Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs	(revision 7415)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs	(revision 7418)
@@ -130,15 +130,4 @@
     }
 
-    [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserialization() {
-      // BackwardsCompatibility3.3
-      #region Backwards compatible code, remove with 3.4
-      if (!Parameters.ContainsKey("EquipmentNames"))
-        Parameters.Add(new LookupParameter<StringArray>("EquipmentNames", "Optional: A list of names that describes the equipments."));
-      if (!Parameters.ContainsKey("LocationNames"))
-        Parameters.Add(new LookupParameter<StringArray>("LocationNames", "Optional: A list of names that describes the locations."));
-      #endregion
-    }
-
     public override IOperation Apply() {
       var assignments = AssignmentParameter.ActualValue;
@@ -172,14 +161,13 @@
       GQAPAssignment assignment = BestSolutionParameter.ActualValue;
       if (assignment == null) {
-        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 = new GQAPAssignment((IntegerVector)assignments[bestIndex].Clone(), (DoubleValue)qualities[bestIndex].Clone(), flowDistanceQualities[bestIndex], overbookedCapacities[bestIndex], installationQualities[bestIndex], equipmentNames, locationNames, distances, weights, installationCosts, demands, capacities, transportationCosts, overbookedCapacityPenalty);
         assignment.Distances = distances;
         BestSolutionParameter.ActualValue = assignment;
         results.Add(new Result("Best GQAP Solution", assignment));
       } else {
-        if (HasSolutionImproved(assignment.Quality.Value, qualities[bestIndex].Value, maximization)) {
-          assignment.Assignment = (IntegerVector)assignments[bestIndex].Clone();
-          assignment.Quality = (DoubleValue)qualities[bestIndex].Clone();
+        if (HasSolutionImproved(assignment.Solution.Quality.Value, qualities[bestIndex].Value, maximization)) {
+          assignment.Solution = new GQAPSolution((IntegerVector)assignments[bestIndex].Clone(),
+            (DoubleValue)qualities[bestIndex].Clone(), (DoubleValue)flowDistanceQualities[bestIndex].Clone(),
+            (DoubleValue)installationQualities[bestIndex].Clone(), (DoubleValue)overbookedCapacities[bestIndex].Clone());
           assignment.EquipmentNames = equipmentNames;
           assignment.LocationNames = locationNames;
@@ -191,7 +179,4 @@
           assignment.TransportationCosts = transportationCosts;
           assignment.OverbookedCapacityPenalty = overbookedCapacityPenalty;
-          assignment.FlowDistanceQuality = (DoubleValue)flowDistanceQualities[bestIndex].Clone();
-          assignment.InstallationQuality = (DoubleValue)installationQualities[bestIndex].Clone();
-          assignment.OverbookedCapacity = (DoubleValue)overbookedCapacities[bestIndex].Clone();
         }
       }
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/GQAPSolutionArchiveAnalyzer.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/GQAPSolutionArchiveAnalyzer.cs	(revision 7418)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/GQAPSolutionArchiveAnalyzer.cs	(revision 7418)
@@ -0,0 +1,190 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  /// <summary>
+  /// An operator for analyzing the best solution of Generalized Quadratic Assignment Problems.
+  /// </summary>
+  [Item("GeneralizedQAP Solution Archive Analyzer", "An operator for analyzing the archive of found solutions for the GQAP.")]
+  [StorableClass]
+  public sealed class GQAPSolutionArchiveAnalyzer : SingleSuccessorOperator, IAnalyzer {
+
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public LookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (LookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+    public LookupParameter<DoubleMatrix> WeightsParameter {
+      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"]; }
+    }
+    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 {
+      get { return (LookupParameter<GQAPAssignment>)Parameters["BestSolution"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public LookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public LookupParameter<IntegerVector> BestKnownSolutionParameter {
+      get { return (LookupParameter<IntegerVector>)Parameters["BestKnownSolution"]; }
+    }
+    public ILookupParameter<StringArray> EquipmentNamesParameter {
+      get { return (ILookupParameter<StringArray>)Parameters["EquipmentNames"]; }
+    }
+    public ILookupParameter<StringArray> LocationNamesParameter {
+      get { return (ILookupParameter<StringArray>)Parameters["LocationNames"]; }
+    }
+
+    [StorableConstructor]
+    private GQAPSolutionArchiveAnalyzer(bool deserializing) : base(deserializing) { }
+    private GQAPSolutionArchiveAnalyzer(GQAPSolutionArchiveAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPSolutionArchiveAnalyzer(this, cloner);
+    }
+    public GQAPSolutionArchiveAnalyzer()
+      : base() {
+      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 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."));
+      Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this GQAP instance."));
+      Parameters.Add(new LookupParameter<IntegerVector>("BestKnownSolution", "The best known solution of this GQAP instance."));
+      Parameters.Add(new LookupParameter<StringArray>("EquipmentNames", "A list of names that describes the equipments."));
+      Parameters.Add(new LookupParameter<StringArray>("LocationNames", "A list of names that describes the locations."));
+    }
+
+    public override IOperation Apply() {
+      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;
+
+      GQAPAssignmentArchive archive = results.ContainsKey("Solution Archive") ? results["Solution Archive"].Value as GQAPAssignmentArchive : null;
+      if (archive == null) {
+        archive = new GQAPAssignmentArchive(equipmentNames, locationNames, distances, weights, installationCosts, demands, capacities, transportationCosts, overbookedCapacityPenalty);
+        results.Add(new Result("Solution Archive", archive));
+      } else {
+        archive.EquipmentNames = equipmentNames;
+        archive.LocationNames = locationNames;
+        archive.Distances = distances;
+        archive.Weights = weights;
+        archive.InstallationCosts = installationCosts;
+        archive.Demands = demands;
+        archive.Capacities = capacities;
+        archive.TransportationCosts = transportationCosts;
+        archive.OverbookedCapacityPenalty = overbookedCapacityPenalty;
+      }
+
+      ItemList<GQAPSolution> front = new ItemList<GQAPSolution>(archive.Solutions);
+      for (int i = 0; i < assignments.Length; i++) {
+        if (overbookedCapacities[i].Value <= 0.0)
+          front.Add(new GQAPSolution(assignments[i], qualities[i], flowDistanceQualities[i], installationQualities[i], overbookedCapacities[i]));
+      }
+
+      for (int i = 0; i < front.Count - 1; i++) {
+        for (int j = i + 1; j < front.Count; j++) {
+          if (front[i].FlowDistanceQuality.Value < front[j].FlowDistanceQuality.Value
+            && front[i].InstallationQuality.Value < front[j].InstallationQuality.Value) {
+            front.RemoveAt(j);
+            j--;
+          } else if (front[i].FlowDistanceQuality.Value > front[j].FlowDistanceQuality.Value
+            && front[i].InstallationQuality.Value > front[j].InstallationQuality.Value) {
+            front.RemoveAt(i);
+            j = i + 1;
+          }
+        }
+      }
+
+      archive.Solutions = front;
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs	(revision 7415)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs	(revision 7418)
@@ -33,22 +33,11 @@
 
     [Storable]
-    private IntegerVector assignment;
-    public IntegerVector Assignment {
-      get { return assignment; }
+    private GQAPSolution solution;
+    public GQAPSolution Solution {
+      get { return solution; }
       set {
-        bool changed = (assignment != value);
-        assignment = value;
-        if (changed) OnPropertyChanged("Assignment");
-      }
-    }
-
-    [Storable]
-    private DoubleValue quality;
-    public DoubleValue Quality {
-      get { return quality; }
-      set {
-        bool changed = (quality != value);
-        quality = value;
-        if (changed) OnPropertyChanged("Quality");
+        bool changed = (solution != value);
+        solution = value;
+        if (changed) OnPropertyChanged("Solution");
       }
     }
@@ -153,43 +142,8 @@
     }
 
-    [Storable]
-    private DoubleValue flowDistanceQuality;
-    public DoubleValue FlowDistanceQuality {
-      get { return flowDistanceQuality; }
-      set {
-        bool changed = (flowDistanceQuality != value);
-        flowDistanceQuality = value;
-        if (changed) OnPropertyChanged("FlowDistanceQuality");
-      }
-    }
-
-    [Storable]
-    private DoubleValue installationQuality;
-    public DoubleValue InstallationQuality {
-      get { return installationQuality; }
-      set {
-        bool changed = (installationQuality != value);
-        installationQuality = value;
-        if (changed) OnPropertyChanged("InstallationQuality");
-      }
-    }
-
-    [Storable]
-    private DoubleValue overbookedCapacity;
-    public DoubleValue OverbookedCapacity {
-      get { return overbookedCapacity; }
-      set {
-        bool changed = (overbookedCapacity != value);
-        overbookedCapacity = value;
-        if (changed) OnPropertyChanged("OverbookedCapacity");
-      }
-    }
-
     [StorableConstructor]
     private GQAPAssignment(bool deserializing) : base(deserializing) { }
     private GQAPAssignment(GQAPAssignment original, Cloner cloner)
       : base(original, cloner) {
-      assignment = cloner.Clone(original.assignment);
-      quality = cloner.Clone(original.quality);
       equipmentNames = cloner.Clone(original.equipmentNames);
       locationNames = cloner.Clone(original.locationNames);
@@ -201,23 +155,11 @@
       transportationCosts = cloner.Clone(original.transportationCosts);
       overbookedCapacityPenalty = cloner.Clone(original.overbookedCapacityPenalty);
-      flowDistanceQuality = cloner.Clone(original.flowDistanceQuality);
-      installationQuality = cloner.Clone(original.installationQuality);
-      overbookedCapacity = cloner.Clone(original.overbookedCapacity);
     }
-    public GQAPAssignment(IntegerVector assignment, DoubleValue quality)
+    public GQAPAssignment(IntegerVector assignment, DoubleValue quality, DoubleValue flowDistanceQuality, DoubleValue installationQuality, DoubleValue overbookedCapacity)
       : base() {
-      this.assignment = assignment;
-      this.quality = quality;
+      this.solution = new GQAPSolution(assignment, quality, flowDistanceQuality, installationQuality, overbookedCapacity);
     }
-    public GQAPAssignment(IntegerVector assignment, DoubleValue quality, StringArray equipmentNames, StringArray locationNames)
-      : this(assignment, quality) {
-      this.equipmentNames = equipmentNames;
-      this.locationNames = locationNames;
-    }
-    public GQAPAssignment(IntegerVector assignment, DoubleValue quality, StringArray equipmentNames, StringArray locationNames,
-      DoubleMatrix distances, DoubleMatrix weights, DoubleMatrix installationCosts, DoubleArray demands, DoubleArray capacities,
-      DoubleValue transportationCosts, DoubleValue overbookedCapacityPenalty, DoubleValue flowDistanceQuality,
-      DoubleValue installationQuality, DoubleValue overbookedCapacity)
-      : this(assignment, quality, equipmentNames, locationNames) {
+    public GQAPAssignment(IntegerVector assignment, DoubleValue quality, DoubleValue flowDistanceQuality, DoubleValue overbookedCapacity, DoubleValue installationQuality, StringArray equipmentNames, StringArray locationNames, DoubleMatrix distances, DoubleMatrix weights, DoubleMatrix installationCosts, DoubleArray demands, DoubleArray capacities, DoubleValue transportationCosts, DoubleValue overbookedCapacityPenalty)
+      : this(assignment, quality, flowDistanceQuality, installationQuality, overbookedCapacity) {
       this.distances = distances;
       this.weights = weights;
@@ -227,7 +169,4 @@
       this.transportationCosts = transportationCosts;
       this.overbookedCapacityPenalty = overbookedCapacityPenalty;
-      this.flowDistanceQuality = flowDistanceQuality;
-      this.installationQuality = installationQuality;
-      this.overbookedCapacity = overbookedCapacity;
     }
 
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignmentArchive.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignmentArchive.cs	(revision 7418)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignmentArchive.cs	(revision 7418)
@@ -0,0 +1,182 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.ComponentModel;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAPAssignmentArchive", "Stores the pareto front of assignments.")]
+  [StorableClass]
+  public class GQAPAssignmentArchive : Item, INotifyPropertyChanged {
+
+    [Storable]
+    private ItemList<GQAPSolution> solutions;
+    public ItemList<GQAPSolution> Solutions {
+      get { return solutions; }
+      set {
+        bool changed = (solutions != value);
+        solutions = value;
+        if (changed) OnPropertyChanged("Solutions");
+      }
+    }
+
+    [Storable]
+    private StringArray equipmentNames;
+    public StringArray EquipmentNames {
+      get { return equipmentNames; }
+      set {
+        bool changed = (equipmentNames != value);
+        equipmentNames = value;
+        if (changed) OnPropertyChanged("EquipmentNames");
+      }
+    }
+
+    [Storable]
+    private StringArray locationNames;
+    public StringArray LocationNames {
+      get { return locationNames; }
+      set {
+        bool changed = (locationNames != value);
+        locationNames = value;
+        if (changed) OnPropertyChanged("LocationNames");
+      }
+    }
+
+    [Storable]
+    private DoubleMatrix distances;
+    public DoubleMatrix Distances {
+      get { return distances; }
+      set {
+        bool changed = (distances != value);
+        distances = value;
+        if (changed) OnPropertyChanged("Distances");
+      }
+    }
+
+    [Storable]
+    private DoubleMatrix weights;
+    public DoubleMatrix Weights {
+      get { return weights; }
+      set {
+        bool changed = (weights != value);
+        weights = value;
+        if (changed) OnPropertyChanged("Weights");
+      }
+    }
+
+    [Storable]
+    private DoubleMatrix installationCosts;
+    public DoubleMatrix InstallationCosts {
+      get { return installationCosts; }
+      set {
+        bool changed = (installationCosts != value);
+        installationCosts = value;
+        if (changed) OnPropertyChanged("InstallationCosts");
+      }
+    }
+
+    [Storable]
+    private DoubleArray demands;
+    public DoubleArray Demands {
+      get { return demands; }
+      set {
+        bool changed = (demands != value);
+        demands = value;
+        if (changed) OnPropertyChanged("Demands");
+      }
+    }
+
+    [Storable]
+    private DoubleArray capacities;
+    public DoubleArray Capacities {
+      get { return capacities; }
+      set {
+        bool changed = (capacities != value);
+        capacities = value;
+        if (changed) OnPropertyChanged("Capacities");
+      }
+    }
+
+    [Storable]
+    private DoubleValue transportationCosts;
+    public DoubleValue TransportationCosts {
+      get { return transportationCosts; }
+      set {
+        bool changed = (transportationCosts != value);
+        transportationCosts = value;
+        if (changed) OnPropertyChanged("TransportationCosts");
+      }
+    }
+
+    [Storable]
+    private DoubleValue overbookedCapacityPenalty;
+    public DoubleValue OverbookedCapacityPenalty {
+      get { return overbookedCapacityPenalty; }
+      set {
+        bool changed = (overbookedCapacityPenalty != value);
+        overbookedCapacityPenalty = value;
+        if (changed) OnPropertyChanged("OverbookedCapacityPenalty");
+      }
+    }
+
+    [StorableConstructor]
+    private GQAPAssignmentArchive(bool deserializing) : base(deserializing) { }
+    private GQAPAssignmentArchive(GQAPAssignmentArchive original, Cloner cloner)
+      : base(original, cloner) {
+      equipmentNames = cloner.Clone(original.equipmentNames);
+      locationNames = cloner.Clone(original.locationNames);
+      distances = cloner.Clone(original.distances);
+      weights = cloner.Clone(original.weights);
+      installationCosts = cloner.Clone(original.installationCosts);
+      demands = cloner.Clone(original.demands);
+      capacities = cloner.Clone(original.capacities);
+      transportationCosts = cloner.Clone(original.transportationCosts);
+      overbookedCapacityPenalty = cloner.Clone(original.overbookedCapacityPenalty);
+    }
+    public GQAPAssignmentArchive()
+      : base() {
+      this.solutions = new ItemList<GQAPSolution>();
+    }
+    public GQAPAssignmentArchive(StringArray equipmentNames, StringArray locationNames, DoubleMatrix distances, DoubleMatrix weights, DoubleMatrix installationCosts, DoubleArray demands, DoubleArray capacities, DoubleValue transportationCosts, DoubleValue overbookedCapacityPenalty)
+      : this() {
+      this.distances = distances;
+      this.weights = weights;
+      this.installationCosts = installationCosts;
+      this.demands = demands;
+      this.capacities = capacities;
+      this.transportationCosts = transportationCosts;
+      this.overbookedCapacityPenalty = overbookedCapacityPenalty;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPAssignmentArchive(this, cloner);
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    private void OnPropertyChanged(string propertyName) {
+      var handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+    }
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPSolution.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPSolution.cs	(revision 7418)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPSolution.cs	(revision 7418)
@@ -0,0 +1,118 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.ComponentModel;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAPSolution", "A solution to the Generalized Quadratic Assignment Problem.")]
+  [StorableClass]
+  public class GQAPSolution : Item, INotifyPropertyChanged {
+
+    [Storable]
+    private IntegerVector assignment;
+    public IntegerVector Assignment {
+      get { return assignment; }
+      set {
+        bool changed = (assignment != value);
+        assignment = value;
+        if (changed) OnPropertyChanged("Assignment");
+      }
+    }
+
+    [Storable]
+    private DoubleValue quality;
+    public DoubleValue Quality {
+      get { return quality; }
+      set {
+        bool changed = (quality != value);
+        quality = value;
+        if (changed) OnPropertyChanged("Quality");
+      }
+    }
+
+    [Storable]
+    private DoubleValue flowDistanceQuality;
+    public DoubleValue FlowDistanceQuality {
+      get { return flowDistanceQuality; }
+      set {
+        bool changed = (flowDistanceQuality != value);
+        flowDistanceQuality = value;
+        if (changed) OnPropertyChanged("FlowDistanceQuality");
+      }
+    }
+
+    [Storable]
+    private DoubleValue installationQuality;
+    public DoubleValue InstallationQuality {
+      get { return installationQuality; }
+      set {
+        bool changed = (installationQuality != value);
+        installationQuality = value;
+        if (changed) OnPropertyChanged("InstallationQuality");
+      }
+    }
+
+    [Storable]
+    private DoubleValue overbookedCapacity;
+    public DoubleValue OverbookedCapacity {
+      get { return overbookedCapacity; }
+      set {
+        bool changed = (overbookedCapacity != value);
+        overbookedCapacity = value;
+        if (changed) OnPropertyChanged("OverbookedCapacity");
+      }
+    }
+
+    [StorableConstructor]
+    protected GQAPSolution(bool deserializing) : base(deserializing) { }
+    protected GQAPSolution(GQAPSolution original, Cloner cloner)
+      : base(original, cloner) {
+      assignment = cloner.Clone(original.assignment);
+      quality = cloner.Clone(original.quality);
+      flowDistanceQuality = cloner.Clone(original.flowDistanceQuality);
+      installationQuality = cloner.Clone(original.installationQuality);
+      overbookedCapacity = cloner.Clone(original.overbookedCapacity);
+    }
+    public GQAPSolution(IntegerVector assignment, DoubleValue quality, DoubleValue flowDistanceQuality, DoubleValue installationQuality, DoubleValue overbookedCapacity)
+      : base() {
+      this.assignment = assignment;
+      this.quality = quality;
+      this.flowDistanceQuality = flowDistanceQuality;
+      this.installationQuality = installationQuality;
+      this.overbookedCapacity = overbookedCapacity;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPSolution(this, cloner);
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    protected virtual void OnPropertyChanged(string propertyName) {
+      var handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+    }
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GeneralizedQuadraticAssignmentProblem.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GeneralizedQuadraticAssignmentProblem.cs	(revision 7415)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GeneralizedQuadraticAssignmentProblem.cs	(revision 7418)
@@ -116,5 +116,8 @@
 
     public BestGQAPSolutionAnalyzer BestSolutionAnalyzer {
-      get { return Operators.OfType<BestGQAPSolutionAnalyzer>().First(); }
+      get { return Operators.OfType<BestGQAPSolutionAnalyzer>().FirstOrDefault(); }
+    }
+    public GQAPSolutionArchiveAnalyzer SolutionArchiveAnalyzer {
+      get { return Operators.OfType<GQAPSolutionArchiveAnalyzer>().FirstOrDefault(); }
     }
 
@@ -165,5 +168,4 @@
 
       SolutionCreator.AssignmentParameter.ActualName = "Assignment";
-      Parameterize();
 
       InitializeOperators();
@@ -212,4 +214,5 @@
     private void InitializeOperators() {
       Operators.Add(new BestGQAPSolutionAnalyzer());
+      Operators.Add(new GQAPSolutionArchiveAnalyzer());
       Operators.AddRange(ApplicationManager.Manager.GetInstances<IGQAPOperator>());
       Operators.AddRange(ApplicationManager.Manager.GetInstances<IIntegerVectorOperator>());
@@ -263,5 +266,5 @@
       }
       foreach (var op in Operators.OfType<IGQAPManipulator>()) {
-        op.IntegerVectorParameter.ActualName = SolutionCreator.AssignmentParameter.ActualName;
+        op.AssignmentParameter.ActualName = SolutionCreator.AssignmentParameter.ActualName;
       }
       foreach (var op in Operators.OfType<IGQAPMerger>()) {
@@ -305,4 +308,24 @@
         BestSolutionAnalyzer.LocationNamesParameter.ActualName = LocationNamesParameter.Name;
       }
+      if (SolutionArchiveAnalyzer != null) {
+        SolutionArchiveAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+        SolutionArchiveAnalyzer.DistancesParameter.ActualName = DistancesParameter.Name;
+        SolutionArchiveAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
+        SolutionArchiveAnalyzer.InstallationCostsParameter.ActualName = InstallationCostsParameter.Name;
+        SolutionArchiveAnalyzer.DemandsParameter.ActualName = DemandsParameter.Name;
+        SolutionArchiveAnalyzer.CapacitiesParameter.ActualName = CapacitiesParameter.Name;
+        SolutionArchiveAnalyzer.TransportationCostsParameter.ActualName = TransportationCostsParameter.Name;
+        SolutionArchiveAnalyzer.OverbookedCapacityPenaltyParameter.ActualName = OverbookedCapacityPenaltyParameter.Name;
+        SolutionArchiveAnalyzer.AssignmentParameter.ActualName = SolutionCreator.AssignmentParameter.ActualName;
+        SolutionArchiveAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        SolutionArchiveAnalyzer.FlowDistanceQualityParameter.ActualName = Evaluator.FlowDistanceQualityParameter.ActualName;
+        SolutionArchiveAnalyzer.InstallationQualityParameter.ActualName = Evaluator.InstallationQualityParameter.ActualName;
+        SolutionArchiveAnalyzer.OverbookedCapacityParameter.ActualName = Evaluator.OverbookedCapacityParameter.ActualName;
+        SolutionArchiveAnalyzer.ResultsParameter.ActualName = "Results";
+        SolutionArchiveAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
+        SolutionArchiveAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
+        SolutionArchiveAnalyzer.EquipmentNamesParameter.ActualName = EquipmentNamesParameter.Name;
+        SolutionArchiveAnalyzer.LocationNamesParameter.ActualName = LocationNamesParameter.Name;
+      }
     }
     #endregion
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 7415)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 7418)
@@ -70,4 +70,5 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="HeuristicLab.Optimization.Operators-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL" />
     <Reference Include="HeuristicLab.Parameters-3.3">
       <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
@@ -89,4 +90,5 @@
   <ItemGroup>
     <Compile Include="Analyzers\BestGQAPSolutionAnalyzer.cs" />
+    <Compile Include="Analyzers\GQAPSolutionArchiveAnalyzer.cs" />
     <Compile Include="Evaluators\GQAPNMoveEvaluator.cs" />
     <Compile Include="GQAPAssignment.cs" />
@@ -94,5 +96,7 @@
     <Compile Include="Evaluators\GQAPEvaluator.cs" />
     <Compile Include="GeneralizedQuadraticAssignmentProblem.cs" />
+    <Compile Include="GQAPAssignmentArchive.cs" />
     <Compile Include="GQAPIntegerVectorProximityCalculator.cs" />
+    <Compile Include="GQAPSolution.cs" />
     <Compile Include="Interfaces\IGQAPMerger.cs" />
     <Compile Include="Interfaces\IGQAPNMoveEvaluator.cs" />
@@ -122,4 +126,5 @@
     <Compile Include="Operators\GQAPSolutionCreator.cs" />
     <Compile Include="Operators\GreedyRandomizedSolutionCreator.cs" />
+    <Compile Include="Operators\NMoveShakingOperator.cs" />
     <Compile Include="Operators\QualitySimilarityMerger.cs" />
     <Compile Include="Operators\RandomSolutionCreator.cs" />
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/IGQAPManipulator.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/IGQAPManipulator.cs	(revision 7415)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/IGQAPManipulator.cs	(revision 7418)
@@ -27,5 +27,5 @@
   public interface IGQAPManipulator : IGQAPOperator, IManipulator {
     ILookupParameter<IRandom> RandomParameter { get; }
-    ILookupParameter<IntegerVector> IntegerVectorParameter { get; }
+    ILookupParameter<IntegerVector> AssignmentParameter { get; }
   }
 }
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPManipulator.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPManipulator.cs	(revision 7415)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPManipulator.cs	(revision 7418)
@@ -38,5 +38,5 @@
       get { return (LookupParameter<IRandom>)Parameters["Random"]; }
     }
-    public ILookupParameter<IntegerVector> IntegerVectorParameter {
+    public ILookupParameter<IntegerVector> AssignmentParameter {
       get { return (ILookupParameter<IntegerVector>)Parameters["IntegerVector"]; }
     }
@@ -52,5 +52,5 @@
 
     public sealed override IOperation Apply() {
-      Manipulate(RandomParameter.ActualValue, IntegerVectorParameter.ActualValue);
+      Manipulate(RandomParameter.ActualValue, AssignmentParameter.ActualValue);
       return base.Apply();
     }
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/NMoveShakingOperator.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/NMoveShakingOperator.cs	(revision 7418)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/NMoveShakingOperator.cs	(revision 7418)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Operators {
+  [Item("NMoveShakingOperator", "Performs a number of shaking operations that increase in strength.")]
+  [StorableClass]
+  public class NMoveShakingOperator : SingleSuccessorOperator, ILocationAwareGQAPOperator, IGQAPOperator, IMultiNeighborhoodShakingOperator, IStochasticOperator {
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public IValueLookupParameter<IntValue> CurrentNeighborhoodIndexParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["CurrentNeighborhoodIndex"]; }
+    }
+    public ILookupParameter<IntValue> NeighborhoodCountParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["NeighborhoodCount"]; }
+    }
+    public ILookupParameter<DoubleArray> CapacitiesParameter {
+      get { return (ILookupParameter<DoubleArray>)Parameters["Capacities"]; }
+    }
+
+    [StorableConstructor]
+    protected NMoveShakingOperator(bool deserializing) : base(deserializing) { }
+    protected NMoveShakingOperator(NMoveShakingOperator original, Cloner cloner) : base(original, cloner) { }
+    public NMoveShakingOperator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", "The equipment-location assignment vector."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("CurrentNeighborhoodIndex", "The index of the operator that should be applied (k)."));
+      Parameters.Add(new LookupParameter<IntValue>("NeighborhoodCount", "The number of operators that are available."));
+      Parameters.Add(new LookupParameter<DoubleArray>("Capacities", "The capacities vector describes the available space at the locations."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NMoveShakingOperator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var assignment = AssignmentParameter.ActualValue;
+      var capacities = CapacitiesParameter.ActualValue;
+
+      if (NeighborhoodCountParameter.ActualValue == null)
+        NeighborhoodCountParameter.ActualValue = new IntValue(assignment.Length);
+      else NeighborhoodCountParameter.ActualValue.Value = assignment.Length;
+
+      int index = CurrentNeighborhoodIndexParameter.ActualValue.Value;
+
+      var move = StochasticNMoveSingleMoveGenerator.GenerateUpToN(random, assignment, index + 1, capacities);
+      NMoveMaker.Apply(assignment, move);
+
+      return base.Apply();
+    }
+  }
+}
