Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs	(revision 7412)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs	(revision 7415)
@@ -29,4 +29,5 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common;
 
 namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
@@ -51,4 +52,19 @@
       get { return (LookupParameter<DoubleMatrix>)Parameters["Weights"]; }
     }
+    public LookupParameter<DoubleMatrix> InstallationCostsParameter {
+      get { return (LookupParameter<DoubleMatrix>)Parameters["InstallationCosts"]; }
+    }
+    public LookupParameter<DoubleArray> DemandsParameter {
+      get { return (LookupParameter<DoubleArray>)Parameters["Demands"]; }
+    }
+    public LookupParameter<DoubleArray> CapacitiesParameter {
+      get { return (LookupParameter<DoubleArray>)Parameters["Capacities"]; }
+    }
+    public LookupParameter<DoubleValue> TransportationCostsParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["TransportationCosts"]; }
+    }
+    public LookupParameter<DoubleValue> OverbookedCapacityPenaltyParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["OverbookedCapacityPenalty"]; }
+    }
     public ScopeTreeLookupParameter<IntegerVector> AssignmentParameter {
       get { return (ScopeTreeLookupParameter<IntegerVector>)Parameters["Assignment"]; }
@@ -56,4 +72,13 @@
     public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
       get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> FlowDistanceQualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["FlowDistanceQuality"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> InstallationQualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["InstallationQuality"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> OverbookedCapacityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["OverbookedCapacity"]; }
     }
     public LookupParameter<GQAPAssignment> BestSolutionParameter {
@@ -86,7 +111,15 @@
       Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem."));
       Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances between the locations."));
-      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights between the facilities."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights between the equipments."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("InstallationCosts", "The cost of installing equipment x at location y."));
+      Parameters.Add(new LookupParameter<DoubleArray>("Demands", "The demands of the equipments."));
+      Parameters.Add(new LookupParameter<DoubleArray>("Capacities", "The capacities at the locations."));
+      Parameters.Add(new LookupParameter<DoubleValue>("TransportationCosts", "The transportation cost represents the flow-unit per distance-unit cost factor. This value can also be set to 1 if these costs are factored into the weights matrix already."));
+      Parameters.Add(new LookupParameter<DoubleValue>("OverbookedCapacityPenalty", "The multiplier for the constraint violation when added to the quality."));
       Parameters.Add(new ScopeTreeLookupParameter<IntegerVector>("Assignment", "The GQAP solutions from which the best solution should be analyzed."));
       Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the GQAP solutions which should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("FlowDistanceQuality", "The flow-distance qualities of the GQAP solutions which should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("InstallationQuality", "The installation qualities of the GQAP solutions which should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("OverbookedCapacity", "The overbooked capacities of the GQAP solutions which should be analyzed."));
       Parameters.Add(new LookupParameter<GQAPAssignment>("BestSolution", "The best GQAP solution."));
       Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the best GQAP solution should be stored."));
@@ -109,39 +142,56 @@
 
     public override IOperation Apply() {
-      DoubleMatrix distances = DistancesParameter.ActualValue;
-      DoubleMatrix weights = WeightsParameter.ActualValue;
-      ItemArray<IntegerVector> assignments = AssignmentParameter.ActualValue;
-      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
-      ResultCollection results = ResultsParameter.ActualValue;
-      bool max = MaximizationParameter.ActualValue.Value;
-      DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue;
-
-      var sorted = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).ToArray();
-      if (max) sorted = sorted.Reverse().ToArray();
-      int i = sorted.First().index;
-
-      if (bestKnownQuality == null
-          || max && qualities[i].Value > bestKnownQuality.Value
-          || !max && qualities[i].Value < bestKnownQuality.Value) {
-        // if there isn't a best-known quality or we improved the best-known quality we'll add the current solution as best-known
-        BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[i].Value);
-        BestKnownSolutionParameter.ActualValue = (IntegerVector)assignments[i].Clone();
+      var assignments = AssignmentParameter.ActualValue;
+      var qualities = QualityParameter.ActualValue;
+      var equipmentNames = EquipmentNamesParameter.ActualValue;
+      var locationNames = LocationNamesParameter.ActualValue;
+      var flowDistanceQualities = FlowDistanceQualityParameter.ActualValue;
+      var installationQualities = InstallationQualityParameter.ActualValue;
+      var overbookedCapacities = OverbookedCapacityParameter.ActualValue;
+      var distances = DistancesParameter.ActualValue;
+      var weights = WeightsParameter.ActualValue;
+      var installationCosts = InstallationCostsParameter.ActualValue;
+      var demands = DemandsParameter.ActualValue;
+      var capacities = CapacitiesParameter.ActualValue;
+      var transportationCosts = TransportationCostsParameter.ActualValue;
+      var overbookedCapacityPenalty = OverbookedCapacityPenaltyParameter.ActualValue;
+      var results = ResultsParameter.ActualValue;
+      var maximization = MaximizationParameter.ActualValue.Value;
+      var bestKnownQuality = BestKnownQualityParameter.ActualValue;
+
+      int bestIndex;
+      var tmp = qualities.Select((x, index) => new { Index = index, Value = x.Value });
+      if (maximization) bestIndex = tmp.SelectMax(x => x.Value).Index;
+      else bestIndex = tmp.SelectMin(x => x.Value).Index;
+
+      if (bestKnownQuality == null || HasSolutionImproved(bestKnownQuality.Value, qualities[bestIndex].Value, maximization)) {
+        BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[bestIndex].Value);
+        BestKnownSolutionParameter.ActualValue = (IntegerVector)assignments[bestIndex].Clone();
       }
 
       GQAPAssignment assignment = BestSolutionParameter.ActualValue;
       if (assignment == null) {
-        StringArray equipmentNames = EquipmentNamesParameter.ActualValue;
-        StringArray locationNames = LocationNamesParameter.ActualValue;
-        assignment = new GQAPAssignment(weights, (IntegerVector)assignments[i].Clone(), new DoubleValue(qualities[i].Value), equipmentNames, locationNames);
+        assignment = new GQAPAssignment((IntegerVector)assignments[bestIndex].Clone(), (DoubleValue)qualities[bestIndex].Clone(),
+          equipmentNames, locationNames, distances, weights, installationCosts, demands, capacities, transportationCosts,
+          overbookedCapacityPenalty, flowDistanceQualities[bestIndex], installationQualities[bestIndex], overbookedCapacities[bestIndex]);
         assignment.Distances = distances;
         BestSolutionParameter.ActualValue = assignment;
         results.Add(new Result("Best GQAP Solution", assignment));
       } else {
-        if (max && assignment.Quality.Value < qualities[i].Value ||
-          !max && assignment.Quality.Value > qualities[i].Value) {
+        if (HasSolutionImproved(assignment.Quality.Value, qualities[bestIndex].Value, maximization)) {
+          assignment.Assignment = (IntegerVector)assignments[bestIndex].Clone();
+          assignment.Quality = (DoubleValue)qualities[bestIndex].Clone();
+          assignment.EquipmentNames = equipmentNames;
+          assignment.LocationNames = locationNames;
           assignment.Distances = distances;
           assignment.Weights = weights;
-          assignment.Assignment = (IntegerVector)assignments[i].Clone();
-          assignment.Quality.Value = qualities[i].Value;
+          assignment.InstallationCosts = installationCosts;
+          assignment.Demands = demands;
+          assignment.Capacities = capacities;
+          assignment.TransportationCosts = transportationCosts;
+          assignment.OverbookedCapacityPenalty = overbookedCapacityPenalty;
+          assignment.FlowDistanceQuality = (DoubleValue)flowDistanceQualities[bestIndex].Clone();
+          assignment.InstallationQuality = (DoubleValue)installationQualities[bestIndex].Clone();
+          assignment.OverbookedCapacity = (DoubleValue)overbookedCapacities[bestIndex].Clone();
         }
       }
@@ -149,4 +199,8 @@
       return base.Apply();
     }
+
+    private static bool HasSolutionImproved(double oldQuality, double quality, bool maximization) {
+      return maximization && oldQuality < quality || !maximization && oldQuality > quality;
+    }
   }
 }
