Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.Designer.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.Designer.cs	(revision 7436)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.Designer.cs	(revision 7437)
@@ -56,4 +56,8 @@
       chartArea1.AxisX.Title = "FlowDistanceQuality";
       chartArea1.AxisY.Title = "InstallationQuality";
+      chartArea1.CursorX.IsUserEnabled = true;
+      chartArea1.CursorX.IsUserSelectionEnabled = true;
+      chartArea1.CursorY.IsUserEnabled = true;
+      chartArea1.CursorY.IsUserSelectionEnabled = true;
       chartArea1.Name = "ChartArea1";
       this.paretoFrontChart.ChartAreas.Add(chartArea1);
@@ -72,4 +76,5 @@
       this.paretoFrontChart.TabIndex = 0;
       this.paretoFrontChart.Text = "Pareto Front";
+      this.paretoFrontChart.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.paretoFrontChart_MouseDoubleClick);
       // 
       // messageLabel
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.cs	(revision 7436)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.cs	(revision 7437)
@@ -22,5 +22,7 @@
 using System;
 using System.ComponentModel;
+using System.Linq;
 using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
 using HeuristicLab.Collections;
 using HeuristicLab.Core.Views;
@@ -83,6 +85,8 @@
           if (Content == null) return;
           foreach (var solution in Content.Solutions) {
-            if (solution.OverbookedCapacity.Value <= 0.0)
+            if (solution.OverbookedCapacity.Value <= 0.0) {
               paretoFrontChart.Series[0].Points.AddXY(solution.FlowDistanceQuality.Value, solution.InstallationQuality.Value);
+              paretoFrontChart.Series[0].Points.Last().Tag = solution;
+            }
           }
         } finally {
@@ -92,4 +96,18 @@
       }
     }
+
+    private void paretoFrontChart_MouseDoubleClick(object sender, MouseEventArgs e) {
+      HitTestResult h = paretoFrontChart.HitTest(e.X, e.Y, ChartElementType.DataPoint);
+      if (h.ChartElementType == ChartElementType.DataPoint) {
+        var solution = (GQAPSolution)((DataPoint)h.Object).Tag;
+        var assignment = new GQAPAssignment(solution.Assignment, solution.Quality, solution.FlowDistanceQuality, solution.InstallationQuality, solution.OverbookedCapacity, Content.EquipmentNames, Content.LocationNames, Content.Distances, Content.Weights, Content.InstallationCosts, Content.Demands, Content.Capacities, Content.TransportationCosts, Content.OverbookedCapacityPenalty);
+
+        var view = MainFormManager.MainForm.ShowContent(assignment);
+        if (view != null) {
+          view.ReadOnly = this.ReadOnly;
+          view.Locked = this.Locked;
+        }
+      }
+    }
   }
 }
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs	(revision 7436)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs	(revision 7437)
@@ -165,5 +165,5 @@
       GQAPAssignment assignment = BestSolutionParameter.ActualValue;
       if (assignment == null) {
-        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 = new GQAPAssignment((IntegerVector)assignments[bestIndex].Clone(), (DoubleValue)qualities[bestIndex].Clone(), flowDistanceQualities[bestIndex], installationQualities[bestIndex], overbookedCapacities[bestIndex], equipmentNames, locationNames, distances, weights, installationCosts, demands, capacities, transportationCosts, overbookedCapacityPenalty);
         assignment.Distances = distances;
         BestSolutionParameter.ActualValue = assignment;
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/GQAPPopulationDiversityAnalyzer.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/GQAPPopulationDiversityAnalyzer.cs	(revision 7437)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/GQAPPopulationDiversityAnalyzer.cs	(revision 7437)
@@ -0,0 +1,79 @@
+﻿#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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Analyzers {
+  [Item("GQAPPopulationDiversityAnalyzer", "Analyzes the population diversity.")]
+  [StorableClass]
+  public class GQAPPopulationDiversityAnalyzer : PopulationDiversityAnalyzer<IntegerVector>, IAssignmentsAwareGQAPOperator, IQualitiesAwareGQAPOperator {
+
+    public IScopeTreeLookupParameter<IntegerVector> AssignmentParameter {
+      get { return SolutionParameter; }
+    }
+    public new ILookupParameter<BoolValue> MaximizationParameter {
+      get { return MaximizationParameter; }
+    }
+    public new IScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return QualityParameter; }
+    }
+    public IScopeTreeLookupParameter<DoubleValue> FlowDistanceQualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["FlowDistanceQuality"]; }
+    }
+    public IScopeTreeLookupParameter<DoubleValue> InstallationQualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["InstallationQuality"]; }
+    }
+    public IScopeTreeLookupParameter<DoubleValue> OverbookedCapacityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["OverbookedCapacity"]; }
+    }
+
+    [StorableConstructor]
+    protected GQAPPopulationDiversityAnalyzer(bool deserializing) : base(deserializing) { }
+    protected GQAPPopulationDiversityAnalyzer(GQAPPopulationDiversityAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public GQAPPopulationDiversityAnalyzer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("FlowDistanceQuality", GQAPEvaluator.FlowDistanceQualityDescription));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("InstallationQuality", GQAPEvaluator.InstallationQualityDescription));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("OverbookedCapacity", GQAPEvaluator.OverbookedCapacityDescription));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPPopulationDiversityAnalyzer(this, cloner);
+    }
+
+    protected override double[,] CalculateSimilarities(IntegerVector[] solutions) {
+      double[,] result = new double[solutions.Length, solutions.Length];
+      for (int i = 0; i < solutions.Length - 1; i++)
+        for (int j = i + 1; j < solutions.Length; j++) {
+          result[i, j] = IntegerVectorEqualityComparer.GetSimilarity(solutions[i], solutions[j]);
+          result[j, i] = result[i, j];
+        }
+      return result;
+    }
+  }
+}
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/GQAPSolutionArchiveAnalyzer.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/GQAPSolutionArchiveAnalyzer.cs	(revision 7436)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/GQAPSolutionArchiveAnalyzer.cs	(revision 7437)
@@ -178,5 +178,5 @@
             && front[i].InstallationQuality.Value > front[j].InstallationQuality.Value) {
             front.RemoveAt(i);
-            j = i + 1;
+            j = i;
           }
         }
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs	(revision 7436)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs	(revision 7437)
@@ -160,6 +160,8 @@
       this.solution = new GQAPSolution(assignment, quality, flowDistanceQuality, installationQuality, overbookedCapacity);
     }
-    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)
+    public GQAPAssignment(IntegerVector assignment, DoubleValue quality, DoubleValue flowDistanceQuality, DoubleValue installationQuality, DoubleValue overbookedCapacity, 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.equipmentNames = equipmentNames;
+      this.locationNames = locationNames;
       this.distances = distances;
       this.weights = weights;
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GeneralizedQuadraticAssignmentProblem.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GeneralizedQuadraticAssignmentProblem.cs	(revision 7436)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GeneralizedQuadraticAssignmentProblem.cs	(revision 7437)
@@ -229,4 +229,5 @@
 
     private void InitializeOperators() {
+      Operators.Clear();
       Operators.Add(new BestGQAPSolutionAnalyzer());
       Operators.Add(new GQAPSolutionArchiveAnalyzer());
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 7436)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 7437)
@@ -38,4 +38,8 @@
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=x86">
+      <SpecificVersion>False</SpecificVersion>
+      <Private>False</Private>
+    </Reference>
     <Reference Include="HeuristicLab.Collections-3.3">
       <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Collections-3.3.dll</HintPath>
@@ -90,4 +94,5 @@
   <ItemGroup>
     <Compile Include="Analyzers\BestGQAPSolutionAnalyzer.cs" />
+    <Compile Include="Analyzers\GQAPPopulationDiversityAnalyzer.cs" />
     <Compile Include="Analyzers\GQAPSolutionArchiveAnalyzer.cs" />
     <Compile Include="Evaluators\GQAPNMoveEvaluator.cs" />
@@ -98,4 +103,5 @@
     <Compile Include="GQAPAssignmentArchive.cs" />
     <Compile Include="GQAPSolution.cs" />
+    <Compile Include="Interfaces\IGQAPManipulator.cs" />
     <Compile Include="Interfaces\IQualitiesAwareGQAPOperator.cs" />
     <Compile Include="Interfaces\IAssignmentsAwareGQAPOperator.cs" />
@@ -130,4 +136,5 @@
     <Compile Include="Moves\StochasticNMoveSingleMoveGenerator.cs" />
     <Compile Include="Operators\ApproximateLocalSearch.cs" />
+    <Compile Include="Operators\MultiGQAPCrossover.cs" />
     <Compile Include="Operators\GQAPPathRelinking.cs" />
     <Compile Include="Operators\GQAPStochasticSolutionCreator.cs" />
@@ -137,4 +144,5 @@
     <Compile Include="Operators\GQAPSolutionCreator.cs" />
     <Compile Include="Operators\GreedyRandomizedSolutionCreator.cs" />
+    <Compile Include="Operators\MultiGQAPManipulator.cs" />
     <Compile Include="Operators\NMoveShakingOperator.cs" />
     <Compile Include="Operators\QualitySimilarityMerger.cs" />
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/IGQAPManipulator.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/IGQAPManipulator.cs	(revision 7437)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/IGQAPManipulator.cs	(revision 7437)
@@ -0,0 +1,26 @@
+﻿#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.Optimization;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  public interface IGQAPManipulator : IAssignmentAwareGQAPOperator, IManipulator { }
+}
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPManipulator.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPManipulator.cs	(revision 7436)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPManipulator.cs	(revision 7437)
@@ -31,5 +31,5 @@
   [Item("GQAPManipulator", "A base class for operators that manipulate assignment vectors of the GeneralizedQuadraticAssignment problems.")]
   [StorableClass]
-  public abstract class GQAPManipulator : SingleSuccessorOperator, IAssignmentAwareGQAPOperator, IManipulator, IStochasticOperator {
+  public abstract class GQAPManipulator : SingleSuccessorOperator, IGQAPManipulator, IAssignmentAwareGQAPOperator, IStochasticOperator {
     public override bool CanChangeName {
       get { return false; }
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/MultiGQAPCrossover.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/MultiGQAPCrossover.cs	(revision 7437)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/MultiGQAPCrossover.cs	(revision 7437)
@@ -0,0 +1,93 @@
+﻿#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;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("MultiGQAPCrossover", "Randomly selects and applies one of its crossovers every time it is called.")]
+  [StorableClass]
+  public class MultiGQAPCrossover : StochasticMultiBranch<IGQAPCrossover>, IGQAPCrossover {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    public IScopeTreeLookupParameter<IntegerVector> ParentsParameter {
+      get { return (ScopeTreeLookupParameter<IntegerVector>)Parameters["Parents"]; }
+    }
+    public ILookupParameter<IntegerVector> ChildParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Child"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiGQAPCrossover(bool deserializing) : base(deserializing) { }
+    protected MultiGQAPCrossover(MultiGQAPCrossover original, Cloner cloner) : base(original, cloner) { }
+    public MultiGQAPCrossover()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<IntegerVector>("Parents", "The parent vectors which should be crossed.", "Assignment"));
+      Parameters.Add(new LookupParameter<IntegerVector>("Child", "The child vector resulting from the crossover.", "Assignment"));
+      foreach (Type type in ApplicationManager.Manager.GetTypes(typeof(IGQAPCrossover))) {
+        if (!typeof(MultiOperator<IGQAPCrossover>).IsAssignableFrom(type))
+          Operators.Add((IGQAPCrossover)Activator.CreateInstance(type), true);
+      }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiGQAPCrossover(this, cloner);
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IGQAPCrossover>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      Parameterize();
+    }
+    protected override void Operators_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IGQAPCrossover>> e) {
+      base.Operators_ItemsRemoved(sender, e);
+      Parameterize();
+    }
+
+    private void Parameterize() {
+      foreach (var op in Operators.OfType<IGQAPCrossover>()) {
+        op.ParentsParameter.ActualName = ParentsParameter.Name;
+        op.ChildParameter.ActualName = ChildParameter.Name;
+      }
+      foreach (var op in Operators.OfType<IStochasticOperator>()) {
+        op.RandomParameter.ActualName = RandomParameter.Name;
+      }
+    }
+
+    public override IOperation Apply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one crossover to choose from.");
+      return base.Apply();
+    }
+  }
+}
Index: /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/MultiGQAPManipulator.cs
===================================================================
--- /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/MultiGQAPManipulator.cs	(revision 7437)
+++ /branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/MultiGQAPManipulator.cs	(revision 7437)
@@ -0,0 +1,86 @@
+﻿#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;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("MultiGQAPManipulator", "Randomly selects and applies one of its manipulators every time it is called.")]
+  [StorableClass]
+  public class MultiGQAPManipulator : StochasticMultiBranch<IGQAPManipulator>, IGQAPManipulator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiGQAPManipulator(bool deserializing) : base(deserializing) { }
+    protected MultiGQAPManipulator(MultiGQAPManipulator original, Cloner cloner) : base(original, cloner) { }
+    public MultiGQAPManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      foreach (Type type in ApplicationManager.Manager.GetTypes(typeof(IGQAPManipulator))) {
+        if (!typeof(MultiOperator<IGQAPManipulator>).IsAssignableFrom(type))
+          Operators.Add((IGQAPManipulator)Activator.CreateInstance(type), true);
+      }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiGQAPManipulator(this, cloner);
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IGQAPManipulator>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      Parameterize();
+    }
+    protected override void Operators_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IGQAPManipulator>> e) {
+      base.Operators_ItemsRemoved(sender, e);
+      Parameterize();
+    }
+
+    private void Parameterize() {
+      foreach (var op in Operators.OfType<IGQAPManipulator>())
+        op.AssignmentParameter.ActualName = AssignmentParameter.Name;
+      foreach (var op in Operators.OfType<IStochasticOperator>())
+        op.RandomParameter.ActualName = RandomParameter.Name;
+    }
+
+    public override IOperation Apply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one manipulator to choose from.");
+      return base.Apply();
+    }
+  }
+}
