Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/BoundedIntegerVectorCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/BoundedIntegerVectorCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/BoundedIntegerVectorCrossover.cs	(revision 17175)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [Item("BoundedIntegerVectorCrossover", "Base class for bounded crossovers.")]
+  [StorableType("90834C8F-461F-4A94-A7CB-25C8D1063604")]
+  public abstract class BoundedIntegerVectorCrossover : IntegerVectorCrossover, IBoundedIntegerVectorOperator {
+
+    public IValueLookupParameter<IntMatrix> BoundsParameter {
+      get { return (IValueLookupParameter<IntMatrix>)Parameters["Bounds"]; }
+    }
+
+    [StorableConstructor]
+    protected BoundedIntegerVectorCrossover(StorableConstructorFlag _) : base(_) { }
+    protected BoundedIntegerVectorCrossover(BoundedIntegerVectorCrossover original, Cloner cloner) : base(original, cloner) { }
+    public BoundedIntegerVectorCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntMatrix>("Bounds", "The bounds matrix can contain one row for each dimension with three columns specifying minimum (inclusive), maximum (exclusive), and step size. If less rows are given the matrix is cycled."));
+    }
+
+    protected sealed override IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents) {
+      if (BoundsParameter.ActualValue == null) throw new InvalidOperationException(Name + ": Bounds are not defined!");
+      return CrossBounded(random, parents, BoundsParameter.ActualValue);
+    }
+
+    protected abstract IntegerVector CrossBounded(IRandom random, ItemArray<IntegerVector> parents, IntMatrix bounds);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/BoundedIntegerVectorManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/BoundedIntegerVectorManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/BoundedIntegerVectorManipulator.cs	(revision 17175)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [Item("BoundedIntegerVectorManipulator", "Base class for bounded integer vector manipulators.")]
+  [StorableType("A2B6079B-19AC-4518-91FB-8BEDFC8C776F")]
+  public abstract class BoundedIntegerVectorManipulator : IntegerVectorManipulator, IBoundedIntegerVectorOperator {
+
+    public IValueLookupParameter<IntMatrix> BoundsParameter {
+      get { return (IValueLookupParameter<IntMatrix>)Parameters["Bounds"]; }
+    }
+
+    [StorableConstructor]
+    protected BoundedIntegerVectorManipulator(StorableConstructorFlag _) : base(_) { }
+    protected BoundedIntegerVectorManipulator(BoundedIntegerVectorManipulator original, Cloner cloner) : base(original, cloner) { }
+    public BoundedIntegerVectorManipulator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntMatrix>("Bounds", "The bounds matrix can contain one row for each dimension with three columns specifying minimum (inclusive), maximum (exclusive), and step size. If less rows are given the matrix is cycled."));
+    }
+
+    protected sealed override void Manipulate(IRandom random, IntegerVector integerVector) {
+      if (BoundsParameter.ActualValue == null) throw new InvalidOperationException("BoundedIntegerVectorManipulator: Parameter " + BoundsParameter.ActualName + " could not be found.");
+      ManipulateBounded(random, integerVector, BoundsParameter.ActualValue);
+    }
+
+    protected abstract void ManipulateBounded(IRandom random, IntegerVector integerVector, IntMatrix bounds);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Creators/UniformRandomIntegerVectorCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Creators/UniformRandomIntegerVectorCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Creators/UniformRandomIntegerVectorCreator.cs	(revision 17175)
@@ -0,0 +1,68 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Generates a new random integer vector with each element uniformly distributed in a specified range.
+  /// </summary>
+  [Item("UniformRandomIntegerVectorCreator", "An operator which creates a new random int vector with each element uniformly distributed in a specified range.")]
+  [StorableType("23B6374A-EE3B-4487-B728-635395D5F1B7")]
+  public class UniformRandomIntegerVectorCreator : IntegerVectorCreator {
+    [StorableConstructor]
+    protected UniformRandomIntegerVectorCreator(StorableConstructorFlag _) : base(_) { }
+    protected UniformRandomIntegerVectorCreator(UniformRandomIntegerVectorCreator original, Cloner cloner) : base(original, cloner) { }
+    public UniformRandomIntegerVectorCreator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new UniformRandomIntegerVectorCreator(this, cloner);
+    }
+
+    /// <summary>
+    /// Generates a new random integer vector with the given <paramref name="length"/>.
+    /// </summary>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="length">The length of the int vector.</param>
+    /// <param name="bounds">A matrix containing the inclusive lower and inclusive upper bound in the first and second column and a step size in the third column.
+    /// Each line represents the bounds for a certain dimension. If fewer lines are given, the lines are cycled.</param>
+    /// <returns>The newly created integer vector.</returns>
+    public static IntegerVector Apply(IRandom random, int length, IntMatrix bounds) {
+      var result = new IntegerVector(length);
+      result.Randomize(random, bounds);
+      return result;
+    }
+
+    /// <summary>
+    /// Forwards the call to <see cref="Apply(IRandom, int, int, int)"/>.
+    /// </summary>
+    /// <param name="random">The pseudo random number generator to use.</param>
+    /// <param name="length">The length of the int vector.</param>
+    /// <param name="bounds">Contains in each row for each dimension minimum (inclusive), maximum (inclusive), and step size.</param>
+    /// <returns>The newly created int vector.</returns>
+    protected override IntegerVector Create(IRandom random, IntValue length, IntMatrix bounds) {
+      return Apply(random, length.Value, bounds);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/DiscreteCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/DiscreteCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/DiscreteCrossover.cs	(revision 17175)
@@ -0,0 +1,80 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Discrete crossover for integer vectors.
+  /// </summary>
+  /// 
+  /// It is implemented as described in Gwiazda, T.D. 2006. Genetic algorithms reference Volume I Crossover for single-objective numerical optimization problems, p.17.
+  /// </remarks>
+  [Item("DiscreteCrossover", "Discrete crossover for integer vectors. It is implemented as described in Gwiazda, T.D. 2006. Genetic algorithms reference Volume I Crossover for single-objective numerical optimization problems, p.17.")]
+  [StorableType("64C79AA5-1D77-4CF4-A19B-9646F270E4D8")]
+  public class DiscreteCrossover : IntegerVectorCrossover {
+    [StorableConstructor]
+    protected DiscreteCrossover(StorableConstructorFlag _) : base(_) { }
+    protected DiscreteCrossover(DiscreteCrossover original, Cloner cloner) : base(original, cloner) { }
+    public DiscreteCrossover() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DiscreteCrossover(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs a discrete crossover operation of any number of given parents.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown when the vectors of the parents are of different length or when there are less than 2 parents.</exception>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="parents">The list of parents for the crossover operation.</param>
+    /// <returns>The newly created integer vector, resulting from the crossover operation.</returns>
+    public static IntegerVector Apply(IRandom random, ItemArray<IntegerVector> parents) {
+      if (parents.Length < 2) throw new ArgumentException("DiscreteCrossover: There are less than two parents to cross.");
+      int length = parents[0].Length;
+
+      for (int i = 0; i < parents.Length; i++) {
+        if (parents[i].Length != length)
+          throw new ArgumentException("DiscreteCrossover: The parents' vectors are of different length.", "parents");
+      }
+
+      var result = new IntegerVector(length);
+      for (int i = 0; i < length; i++) {
+        result[i] = parents[random.Next(parents.Length)][i];
+      }
+
+      return result;
+    }
+
+    /// <summary>
+    /// Performs a discrete crossover operation for any number of given parent integer vectors.
+    /// </summary>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="parents">An array containing integer vectors that should be crossed.</param>
+    /// <returns>The newly created integer vector, resulting from the crossover operation.</returns>
+    protected override IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents) {
+      return Apply(random, parents);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/MultiIntegerVectorCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/MultiIntegerVectorCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/MultiIntegerVectorCrossover.cs	(revision 17175)
@@ -0,0 +1,108 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [Item("MultiIntegerVectorCrossover", "Randomly selects and applies one of its crossovers every time it is called.")]
+  [StorableType("EC482D88-4258-48D3-BCD2-C6FC013C8FED")]
+  public class MultiIntegerVectorCrossover : StochasticMultiBranch<IIntegerVectorCrossover>, IIntegerVectorCrossover, IStochasticOperator, IBoundedIntegerVectorOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    public IValueLookupParameter<IntMatrix> BoundsParameter {
+      get { return (IValueLookupParameter<IntMatrix>)Parameters["Bounds"]; }
+    }
+
+    public ILookupParameter<ItemArray<IntegerVector>> ParentsParameter {
+      get { return (ILookupParameter<ItemArray<IntegerVector>>)Parameters["Parents"]; }
+    }
+
+    public ILookupParameter<IntegerVector> ChildParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Child"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiIntegerVectorCrossover(StorableConstructorFlag _) : base(_) { }
+    protected MultiIntegerVectorCrossover(MultiIntegerVectorCrossover original, Cloner cloner) : base(original, cloner) { }
+    public MultiIntegerVectorCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntMatrix>("Bounds", "The bounds matrix can contain one row for each dimension with three columns specifying minimum (inclusive), maximum (exclusive), and step size. If less rows are given the matrix is cycled."));
+      Parameters.Add(new ScopeTreeLookupParameter<IntegerVector>("Parents", "The parent integer vector which should be crossed."));
+      ParentsParameter.ActualName = "IntegerVector";
+      Parameters.Add(new LookupParameter<IntegerVector>("Child", "The child integer vector resulting from the crossover."));
+      ChildParameter.ActualName = "IntegerVector";
+
+      foreach (Type type in ApplicationManager.Manager.GetTypes(typeof(IIntegerVectorCrossover))) {
+        if (!typeof(MultiOperator<IIntegerVectorCrossover>).IsAssignableFrom(type))
+          Operators.Add((IIntegerVectorCrossover)Activator.CreateInstance(type), true);
+      }
+
+      SelectedOperatorParameter.ActualName = "SelectedCrossoverOperator";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiIntegerVectorCrossover(this, cloner);
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IIntegerVectorCrossover>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeCrossovers();
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IIntegerVectorCrossover>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeCrossovers();
+    }
+
+    private void ParameterizeCrossovers() {
+      foreach (IIntegerVectorCrossover crossover in Operators.OfType<IIntegerVectorCrossover>()) {
+        crossover.ChildParameter.ActualName = ChildParameter.Name;
+        crossover.ParentsParameter.ActualName = ParentsParameter.Name;
+      }
+      foreach (IStochasticOperator crossover in Operators.OfType<IStochasticOperator>()) {
+        crossover.RandomParameter.ActualName = RandomParameter.Name;
+      }
+      foreach (IBoundedIntegerVectorOperator crossover in Operators.OfType<IBoundedIntegerVectorOperator>()) {
+        crossover.BoundsParameter.ActualName = BoundsParameter.Name;
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one integer vector crossover to choose from.");
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedAverageCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedAverageCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedAverageCrossover.cs	(revision 17175)
@@ -0,0 +1,91 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Rounded average crossover for integer vectors.
+  /// </summary>
+  [Item("RoundedAverageCrossover", "Average crossover for integer vectors.")]
+  [StorableType("6899DA13-4004-4E22-99B5-46FE6E3418FA")]
+  public class RoundedAverageCrossover : BoundedIntegerVectorCrossover, IBoundedIntegerVectorOperator {
+
+    [StorableConstructor]
+    protected RoundedAverageCrossover(StorableConstructorFlag _) : base(_) { }
+    protected RoundedAverageCrossover(RoundedAverageCrossover original, Cloner cloner) : base(original, cloner) { }
+    public RoundedAverageCrossover() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RoundedAverageCrossover(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs an average crossover of the two given parent integer vectors.
+    /// The average is rounded and mapped to the nearest valid value (e.g. if step size is > 1)
+    /// </summary>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="parents">The parents for crossover.</param>
+    /// <param name="bounds">The bounds matrix that contains for each dimension one row with minimum (inclusive), maximum (exclusive), and step size columns.
+    /// If the number of rows is smaller than the number of dimensions the matrix is cycled.</param>
+    /// <returns>The newly created integer vector, resulting from the single point crossover.</returns>
+    public static IntegerVector Apply(IRandom random, ItemArray<IntegerVector> parents, IntMatrix bounds) {
+      int length = parents[0].Length, parentsCount = parents.Length;
+      if (parents.Length < 2) throw new ArgumentException("RoundedAverageCrossover: The number of parents is less than 2.", "parents");
+      if (bounds == null || bounds.Rows < 1 || bounds.Columns < 2) throw new ArgumentException("AverageCrossover: Invalid bounds specified.", "bounds");
+
+      var result = new IntegerVector(length);
+      try {
+        double avg;
+        for (int i = 0; i < length; i++) {
+          avg = 0;
+          for (int j = 0; j < parentsCount; j++)
+            avg += parents[j][i];
+          avg /= parentsCount;
+          int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1;
+          if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2];
+          max = FloorFeasible(min, max, step, max - 1);
+          result[i] = RoundFeasible(min, max, step, avg);
+        }
+      } catch (IndexOutOfRangeException) {
+        throw new ArgumentException("RoundedAverageCrossover: The parents' vectors are of different length.", "parents");
+      }
+
+      return result;
+    }
+
+    /// <summary>
+    /// Performs an average crossover between two parent integer vectors.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown if there are not exactly two parents.</exception>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="parents">An array containing the two integer vectors that should be crossed.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <returns>The newly created integer vector, resulting from the average crossover.</returns>
+    protected override IntegerVector CrossBounded(IRandom random, ItemArray<IntegerVector> parents, IntMatrix bounds) {
+      return Apply(random, parents, bounds);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedBlendAlphaBetaCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedBlendAlphaBetaCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedBlendAlphaBetaCrossover.cs	(revision 17175)
@@ -0,0 +1,164 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Blend alpha-beta crossover for integer vectors (BLX-a-b). Creates a new offspring by selecting a 
+  /// random value from the interval between the two alleles of the parent solutions and rounds the
+  /// result to the nearest feasible value. The interval is increased in both directions as follows:
+  /// Into the direction of the 'better' solution by the factor alpha, into the direction of the
+  /// 'worse' solution by the factor beta.
+  /// </summary>
+  [Item("RoundedBlendAlphaBetaCrossover", "The rounded blend alpha beta crossover (BLX-a-b) for integer vectors is similar to the blend alpha crossover (BLX-a), but distinguishes between the better and worse of the parents. The interval from which to choose the new offspring can be extended beyond the better parent by specifying a higher alpha value, and beyond the worse parent by specifying a higher beta value. The new offspring is sampled uniformly in the extended range and rounded to the next feasible integer.")]
+  [StorableType("E9786DA1-C713-44EA-AD2A-BBE371712BA2")]
+  public class RoundedBlendAlphaBetaCrossover : BoundedIntegerVectorCrossover, ISingleObjectiveOperator {
+    /// <summary>
+    /// Whether the problem is a maximization or minimization problem.
+    /// </summary>
+    public ValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    /// <summary>
+    /// The quality of the parents.
+    /// </summary>
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    /// <summary>
+    /// The Alpha parameter controls the extension of the range beyond the better parent. The value must be >= 0 and does not depend on Beta.
+    /// </summary>
+    public ValueLookupParameter<DoubleValue> AlphaParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["Alpha"]; }
+    }
+    /// <summary>
+    /// The Beta parameter controls the extension of the range beyond the worse parent. The value must be >= 0 and does not depend on Alpha.
+    /// </summary>
+    public ValueLookupParameter<DoubleValue> BetaParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["Beta"]; }
+    }
+
+    [StorableConstructor]
+    protected RoundedBlendAlphaBetaCrossover(StorableConstructorFlag _) : base(_) { }
+    protected RoundedBlendAlphaBetaCrossover(RoundedBlendAlphaBetaCrossover original, Cloner cloner) : base(original, cloner) { }
+    /// <summary>
+    /// Initializes a new instance of <see cref="RoundedBlendAlphaBetaCrossover"/> with four additional parameters
+    /// (<c>Maximization</c>, <c>Quality</c>, <c>Alpha</c> and <c>Beta</c>).
+    /// </summary>
+    public RoundedBlendAlphaBetaCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "Whether the problem is a maximization problem or not."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The quality values of the parents."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Alpha", "The Alpha parameter controls the extension of the range beyond the better parent. The value must be >= 0 and does not depend on Beta.", new DoubleValue(0.75)));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Beta", "The Beta parameter controls the extension of the range beyond the worse parent. The value must be >= 0 and does not depend on Alpha.", new DoubleValue(0.25)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RoundedBlendAlphaBetaCrossover(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs the rounded blend alpha beta crossover (BLX-a-b) on two parent vectors.
+    /// </summary>
+    /// <exception cref="ArgumentException">
+    /// Thrown when either:<br/>
+    /// <list type="bullet">
+    /// <item><description>The length of <paramref name="betterParent"/> and <paramref name="worseParent"/> is not equal.</description></item>
+    /// <item><description>The parameter <paramref name="alpha"/> is smaller than 0.</description></item>
+    /// <item><description>The parameter <paramref name="beta"/> is smaller than 0.</description></item>
+    /// </list>
+    /// </exception>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="betterParent">The better of the two parents with regard to their fitness.</param>
+    /// <param name="worseParent">The worse of the two parents with regard to their fitness.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <param name="alpha">The parameter alpha.</param>
+    /// <param name="beta">The parameter beta.</param>
+    /// <returns>The integer vector that results from the crossover.</returns>
+    public static IntegerVector Apply(IRandom random, IntegerVector betterParent, IntegerVector worseParent, IntMatrix bounds, DoubleValue alpha, DoubleValue beta) {
+      if (betterParent.Length != worseParent.Length) throw new ArgumentException("RoundedBlendAlphaBetaCrossover: The parents' vectors are of different length.", "betterParent");
+      if (alpha.Value < 0) throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Parameter alpha must be greater or equal to 0.", "alpha");
+      if (beta.Value < 0) throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Parameter beta must be greater or equal to 0.", "beta");
+      if (bounds == null || bounds.Rows < 1 || bounds.Columns < 2) throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Invalid bounds specified.", "bounds");
+
+      int length = betterParent.Length;
+      double min, max, d;
+      var result = new IntegerVector(length);
+      int minBound, maxBound, step = 1;
+      for (int i = 0; i < length; i++) {
+        minBound = bounds[i % bounds.Rows, 0];
+        maxBound = bounds[i % bounds.Rows, 1];
+        if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2];
+        maxBound = FloorFeasible(minBound, maxBound, step, maxBound - 1);
+
+        d = Math.Abs(betterParent[i] - worseParent[i]);
+        if (betterParent[i] <= worseParent[i]) {
+          min = FloorFeasible(minBound, maxBound, step, betterParent[i] - d * alpha.Value);
+          max = CeilingFeasible(minBound, maxBound, step, worseParent[i] + d * beta.Value);
+        } else {
+          min = FloorFeasible(minBound, maxBound, step, worseParent[i] - d * beta.Value);
+          max = CeilingFeasible(minBound, maxBound, step, betterParent[i] + d * alpha.Value);
+        }
+        result[i] = RoundFeasible(minBound, maxBound, step, min + random.NextDouble() * (max - min));
+      }
+      return result;
+    }
+
+    /// <summary>
+    /// Checks if the number of parents is equal to 2, if all parameters are available and forwards the call to <see cref="Apply(IRandom, IntegerVector, IntegerVector, IntMatrix, DoubleValue, DoubleValue)"/>.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown when the number of parents is not equal to 2.</exception>
+    /// <exception cref="InvalidOperationException">
+    /// Thrown when either:<br/>
+    /// <list type="bullet">
+    /// <item><description>Maximization parameter could not be found.</description></item>
+    /// <item><description>Quality parameter could not be found or the number of quality values is not equal to the number of parents.</description></item>
+    /// <item><description>Alpha parameter could not be found.</description></item>
+    /// <item><description>Beta parameter could not be found.</description></item>
+    /// </list>
+    /// </exception>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="parents">The collection of parents (must be of size 2).</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <returns>The integer vector that results from the crossover.</returns>
+    protected override IntegerVector CrossBounded(IRandom random, ItemArray<IntegerVector> parents, IntMatrix bounds) {
+      if (parents.Length != 2) throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Number of parents is not equal to 2.", "parents");
+      if (MaximizationParameter.ActualValue == null) throw new InvalidOperationException("RoundedBlendAlphaBetaCrossover: Parameter " + MaximizationParameter.ActualName + " could not be found.");
+      if (QualityParameter.ActualValue == null || QualityParameter.ActualValue.Length != parents.Length) throw new InvalidOperationException("RoundedBlendAlphaBetaCrossover: Parameter " + QualityParameter.ActualName + " could not be found, or not in the same quantity as there are parents.");
+      if (AlphaParameter.ActualValue == null || BetaParameter.ActualValue == null) throw new InvalidOperationException("RoundedBlendAlphaBetaCrossover: Parameter " + AlphaParameter.ActualName + " or paramter " + BetaParameter.ActualName + " could not be found.");
+
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+      if (maximization && qualities[0].Value >= qualities[1].Value || !maximization && qualities[0].Value <= qualities[1].Value)
+        return Apply(random, parents[0], parents[1], bounds, AlphaParameter.ActualValue, BetaParameter.ActualValue);
+      else {
+        return Apply(random, parents[1], parents[0], bounds, AlphaParameter.ActualValue, BetaParameter.ActualValue);
+      }
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedBlendAlphaCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedBlendAlphaCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedBlendAlphaCrossover.cs	(revision 17175)
@@ -0,0 +1,121 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Rounded blend alpha crossover for integer vectors (BLX-a). Creates a new offspring by selecting a random value 
+  /// from the interval between the two alleles of the parent solutions and rounding the result to the next feasible
+  /// integer. The interval is increased in both directions by the factor alpha.
+  /// </summary>
+  [Item("RoundedBlendAlphaCrossover", "The rounded blend alpha crossover (BLX-a) for integer vectors creates new offspring by sampling a new value in the range [min_i - d * alpha, max_i + d * alpha) at each position i and rounding the result to the next feasible integer. Here min_i and max_i are the smaller and larger value of the two parents at position i and d is max_i - min_i.")]
+  [StorableType("F371B342-7D0C-4ED9-8F3F-A641E82DC8F1")]
+  public class RoundedBlendAlphaCrossover : BoundedIntegerVectorCrossover {
+    /// <summary>
+    /// The alpha parameter specifies how much the interval between the parents should be extended to the left and right.
+    /// The value of this parameter also determines the name of the operator: BLX-0.0 for example means alpha is set to 0.
+    /// When Alpha is 0, then the offspring will only be chosen in between the parents, the bigger alpha is the more it will be possible to choose
+    /// values left and right of the min and max value for each gene.
+    /// </summary>
+    public ValueLookupParameter<DoubleValue> AlphaParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["Alpha"]; }
+    }
+
+    [StorableConstructor]
+    protected RoundedBlendAlphaCrossover(StorableConstructorFlag _) : base(_) { }
+    protected RoundedBlendAlphaCrossover(RoundedBlendAlphaCrossover original, Cloner cloner) : base(original, cloner) { }
+    /// <summary>
+    /// Initializes a new instance of <see cref="RoundedBlendAlphaCrossover"/> with one parameter (<c>Alpha</c>).
+    /// </summary>
+    public RoundedBlendAlphaCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Alpha", "The Alpha parameter controls the extension of the range beyond the two parents. It must be >= 0. A value of 0.5 means that half the range is added to both sides of the intervals.", new DoubleValue(0.5)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RoundedBlendAlphaCrossover(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs the rounded blend alpha crossover (BLX-a) of two integer vectors.<br/>
+    /// It creates new offspring by sampling a new value in the range [min_i - d * alpha, max_i + d * alpha) at each position i
+    /// and rounding the result to the next integer.
+    /// Here min_i and max_i are the smaller and larger value of the two parents at position i and d is max_i - min_i.
+    /// </summary>
+    /// <exception cref="ArgumentException">
+    /// Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are of different length or<br/>
+    /// when <paramref name="alpha"/> is less than 0.
+    /// </exception>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="parent1">The first parent for the crossover operation.</param>
+    /// <param name="parent2">The second parent for the crossover operation.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <param name="alpha">The alpha value for the crossover.</param>
+    /// <returns>The newly created integer vector resulting from the crossover operation.</returns>
+    public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2, IntMatrix bounds, DoubleValue alpha) {
+      if (parent1.Length != parent2.Length) throw new ArgumentException("RoundedBlendAlphaCrossover: The parents' vectors are of different length.", "parent1");
+      if (alpha.Value < 0) throw new ArgumentException("RoundedBlendAlphaCrossover: Paramter alpha must be greater or equal than 0.", "alpha");
+      if (bounds == null || bounds.Rows < 1 || bounds.Columns < 2) throw new ArgumentException("RoundedBlendAlphaCrossover: Invalid bounds specified.", "bounds");
+
+      int length = parent1.Length;
+      var result = new IntegerVector(length);
+      double max = 0, min = 0, d = 0, resMin = 0, resMax = 0;
+      int minBound, maxBound, step = 1;
+
+      for (int i = 0; i < length; i++) {
+        minBound = bounds[i % bounds.Rows, 0];
+        maxBound = bounds[i % bounds.Rows, 1];
+        if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2];
+        maxBound = FloorFeasible(minBound, maxBound, step, maxBound - 1);
+
+        max = Math.Max(parent1[i], parent2[i]);
+        min = Math.Min(parent1[i], parent2[i]);
+        d = Math.Abs(max - min);
+        resMin = FloorFeasible(minBound, maxBound, step, min - d * alpha.Value);
+        resMax = CeilingFeasible(minBound, maxBound, step, max + d * alpha.Value);
+
+        result[i] = RoundFeasible(minBound, maxBound, step, resMin + random.NextDouble() * Math.Abs(resMax - resMin));
+      }
+      return result;
+    }
+
+    /// <summary>
+    /// Checks that the number of parents is equal to 2 and forwards the call to <see cref="Apply(IRandom, RealVector, RealVector, DoubleValue)"/>.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown when the number of parents is not equal to 2.</exception>
+    /// <exception cref="InvalidOperationException">Thrown when the parameter alpha could not be found.</exception>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="parents">The collection of parents (must be of size 2).</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <returns>The integer vector resulting from the crossover operation.</returns>
+    protected override IntegerVector CrossBounded(IRandom random, ItemArray<IntegerVector> parents, IntMatrix bounds) {
+      if (parents.Length != 2) throw new ArgumentException("RoundedBlendAlphaCrossover: The number of parents is not equal to 2", "parents");
+      if (AlphaParameter.ActualValue == null) throw new InvalidOperationException("RoundedBlendAlphaCrossover: Parameter " + AlphaParameter.ActualName + " could not be found.");
+      return Apply(random, parents[0], parents[1], bounds, AlphaParameter.ActualValue);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedHeuristicCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedHeuristicCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedHeuristicCrossover.cs	(revision 17175)
@@ -0,0 +1,127 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Heuristic crossover for integer vectors: Calculates the vector from the worse to the better parent and adds that to the better parent weighted with a factor in the interval [0;1).
+  /// The result is then rounded to the next feasible integer.
+  /// The idea is that going further in direction from the worse to the better leads to even better solutions (naturally this depends on the fitness landscape).
+  /// </summary>
+  [Item("RoundedHeuristicCrossover", "The heuristic crossover produces offspring that extend the better parent in direction from the worse to the better parent.")]
+  [StorableType("94963FD3-4092-4B76-88E0-5FE5AC2DA9E2")]
+  public class RoundedHeuristicCrossover : BoundedIntegerVectorCrossover, ISingleObjectiveOperator {
+    /// <summary>
+    /// Whether the problem is a maximization or minimization problem.
+    /// </summary>
+    public ValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    /// <summary>
+    /// The quality of the parents.
+    /// </summary>
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    [StorableConstructor]
+    protected RoundedHeuristicCrossover(StorableConstructorFlag _) : base(_) { }
+    protected RoundedHeuristicCrossover(RoundedHeuristicCrossover original, Cloner cloner) : base(original, cloner) { }
+    /// <summary>
+    /// Initializes a new instance of <see cref="RoundedHeuristicCrossover"/> with two variable infos
+    /// (<c>Maximization</c> and <c>Quality</c>).
+    /// </summary>
+    public RoundedHeuristicCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "Whether the problem is a maximization problem or not."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The quality values of the parents."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RoundedHeuristicCrossover(this, cloner);
+    }
+
+    /// <summary>
+    /// Perfomrs a heuristic crossover on the two given parents.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown when two parents are not of the same length.</exception>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="betterParent">The first parent for the crossover operation.</param>
+    /// <param name="worseParent">The second parent for the crossover operation.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <returns>The newly created integer vector, resulting from the heuristic crossover.</returns>
+    public static IntegerVector Apply(IRandom random, IntegerVector betterParent, IntegerVector worseParent, IntMatrix bounds) {
+      if (betterParent.Length != worseParent.Length)
+        throw new ArgumentException("HeuristicCrossover: the two parents are not of the same length");
+
+      int length = betterParent.Length;
+      var result = new IntegerVector(length);
+      double factor = random.NextDouble();
+
+      int min, max, step = 1;
+      for (int i = 0; i < length; i++) {
+        min = bounds[i % bounds.Rows, 0];
+        max = bounds[i % bounds.Rows, 1];
+        if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2];
+        max = FloorFeasible(min, max, step, max - 1);
+        result[i] = RoundFeasible(min, max, step, betterParent[i] + factor * (betterParent[i] - worseParent[i]));
+      }
+      return result;
+    }
+
+    /// <summary>
+    /// Performs a heuristic crossover operation for two given parent integer vectors.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown when the number of parents is not equal to 2.</exception>
+    /// <exception cref="InvalidOperationException">
+    /// Thrown when either:<br/>
+    /// <list type="bullet">
+    /// <item><description>Maximization parameter could not be found.</description></item>
+    /// <item><description>Quality parameter could not be found or the number of quality values is not equal to the number of parents.</description></item>
+    /// </list>
+    /// </exception>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="parents">An array containing the two real vectors that should be crossed.</param>
+    /// /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <returns>The newly created integer vector, resulting from the crossover operation.</returns>
+    protected override IntegerVector CrossBounded(IRandom random, ItemArray<IntegerVector> parents, IntMatrix bounds) {
+      if (parents.Length != 2) throw new ArgumentException("RoundedHeuristicCrossover: The number of parents is not equal to 2");
+
+      if (MaximizationParameter.ActualValue == null) throw new InvalidOperationException("RoundedHeuristicCrossover: Parameter " + MaximizationParameter.ActualName + " could not be found.");
+      if (QualityParameter.ActualValue == null || QualityParameter.ActualValue.Length != parents.Length) throw new InvalidOperationException("RoundedHeuristicCrossover: Parameter " + QualityParameter.ActualName + " could not be found, or not in the same quantity as there are parents.");
+
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+
+      if (maximization && qualities[0].Value >= qualities[1].Value || !maximization && qualities[0].Value <= qualities[1].Value)
+        return Apply(random, parents[0], parents[1], bounds);
+      else
+        return Apply(random, parents[1], parents[0], bounds);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedLocalCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedLocalCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedLocalCrossover.cs	(revision 17175)
@@ -0,0 +1,86 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// The rounded local crossover for integer vectors is similar to the <see cref="UniformArithmeticCrossover"/>, but where the factor alpha is chosen randomly in the interval [0;1) for each position.
+  /// </summary>cribed in Dumitrescu, D. et al. (2000), Evolutionary computation, CRC Press, Boca Raton, FL, p. 194.
+  /// </remarks>
+  [Item("RoundedLocalCrossover", @"The runded local crossover is similar to the arithmetic crossover, but uses a random alpha for each position x = alpha * p1 + (1-alpha) * p2.")]
+  [StorableType("2E21F322-85CD-4B67-AF9C-4119FAABB3C1")]
+  public class RoundedLocalCrossover : BoundedIntegerVectorCrossover {
+    [StorableConstructor]
+    protected RoundedLocalCrossover(StorableConstructorFlag _) : base(_) { }
+    protected RoundedLocalCrossover(RoundedLocalCrossover original, Cloner cloner) : base(original, cloner) { }
+    public RoundedLocalCrossover() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RoundedLocalCrossover(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs a local crossover on the two given parent vectors.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown when two parents are not of the same length.</exception>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="parent1">The first parent for the crossover operation.</param>
+    /// <param name="parent2">The second parent for the crossover operation.</param>
+    /// <returns>The newly created integer vector, resulting from the local crossover.</returns>
+    public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2, IntMatrix bounds) {
+      if (parent1.Length != parent2.Length)
+        throw new ArgumentException("RoundedLocalCrossover: the two parents are not of the same length");
+
+      double factor;
+      int length = parent1.Length;
+      var result = new IntegerVector(length);
+
+      int min, max, step = 1;
+      for (int i = 0; i < length; i++) {
+        min = bounds[i % bounds.Rows, 0];
+        max = bounds[i % bounds.Rows, 1];
+        if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2];
+        max = FloorFeasible(min, max, step, max - 1);
+        factor = random.NextDouble();
+        result[i] = RoundFeasible(min, max, step, (factor * parent1[i]) + ((1 - factor) * parent2[i]));
+      }
+      return result;
+    }
+
+    /// <summary>
+    /// Performs a local crossover operation for two given parent integer vectors.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown if there are not exactly two parents.</exception>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="parents">An array containing the two real vectors that should be crossed.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <returns>The newly created integer vector, resulting from the crossover operation.</returns>
+    protected override IntegerVector CrossBounded(IRandom random, ItemArray<IntegerVector> parents, IntMatrix bounds) {
+      if (parents.Length != 2) throw new ArgumentException("RoundedLocalCrossover: The number of parents is not equal to 2");
+      return Apply(random, parents[0], parents[1], bounds);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedUniformArithmeticCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedUniformArithmeticCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/RoundedUniformArithmeticCrossover.cs	(revision 17175)
@@ -0,0 +1,111 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// The rounded uniform arithmetic crossover (continuous recombination) constructs an offspring by calculating x = alpha * p1 + (1-alpha) * p2 for a position x in the vector with a given probability (otherwise p1 is taken at this position).
+  /// </summary>
+  [Item("RoundedUniformSomePositionsArithmeticCrossover", "The uniform some positions arithmetic crossover (continuous recombination) constructs an offspring by calculating x = alpha * p1 + (1-alpha) * p2 for a position x in the vector with a given probability (otherwise p1 is taken at this position).")]
+  [StorableType("8393AFC2-FAA5-47A8-A1E3-E6DEABE71B2F")]
+  public class RoundedUniformArithmeticCrossover : BoundedIntegerVectorCrossover, IBoundedIntegerVectorOperator {
+
+    /// <summary>
+    /// The alpha parameter needs to be in the interval (0;1) and specifies how close the resulting offspring should be either to parent1 (alpha -> 0) or parent2 (alpha -> 1).
+    /// </summary>
+    public ValueLookupParameter<DoubleValue> AlphaParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["Alpha"]; }
+    }
+    /// <summary>
+    /// The probability in the range (0;1] for each position in the vector to be crossed.
+    /// </summary>
+    public ValueLookupParameter<DoubleValue> ProbabilityParameter {
+      get { return (ValueLookupParameter<DoubleValue>)Parameters["Probability"]; }
+    }
+
+    [StorableConstructor]
+    protected RoundedUniformArithmeticCrossover(StorableConstructorFlag _) : base(_) { }
+    protected RoundedUniformArithmeticCrossover(RoundedUniformArithmeticCrossover original, Cloner cloner) : base(original, cloner) { }
+    /// <summary>
+    /// Initializes a new instance with two parameters (<c>Alpha</c> and <c>Probability</c>).
+    /// </summary>
+    public RoundedUniformArithmeticCrossover()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Alpha", "The alpha value in the range (0;1) that defines whether the point should be close to parent1 (->1) or parent2 (->0)", new DoubleValue(0.5)));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Probability", "The probability for crossing a position in the range (0;1]", new DoubleValue(1)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RoundedUniformArithmeticCrossover(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs the arithmetic crossover on some positions by taking either x = alpha * p1 + (1 - alpha) * p2 or x = p1 depending on the probability for a gene to be crossed.
+    /// </summary>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="parent1">The first parent vector.</param>
+    /// <param name="parent2">The second parent vector.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <param name="alpha">The alpha parameter (<see cref="AlphaParameter"/>).</param>
+    /// <param name="probability">The probability parameter (<see cref="ProbabilityParameter"/>).</param>
+    /// <returns>The vector resulting from the crossover.</returns>
+    public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2, IntMatrix bounds, DoubleValue alpha, DoubleValue probability) {
+      int length = parent1.Length;
+      if (length != parent2.Length) throw new ArgumentException("RoundedUniformArithmeticCrossover: The parent vectors are of different length.", "parent1");
+      if (alpha.Value < 0 || alpha.Value > 1) throw new ArgumentException("RoundedUniformArithmeticCrossover: Parameter alpha must be in the range [0;1]", "alpha");
+      if (probability.Value < 0 || probability.Value > 1) throw new ArgumentException("RoundedUniformArithmeticCrossover: Parameter probability must be in the range [0;1]", "probability");
+
+      var result = new IntegerVector(length);
+      for (int i = 0; i < length; i++) {
+        if (random.NextDouble() < probability.Value) {
+          int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1;
+          if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2];
+          max = FloorFeasible(min, max, step, max - 1);
+          double value = alpha.Value * parent1[i] + (1 - alpha.Value) * parent2[i];
+          result[i] = RoundFeasible(min, max, step, value);
+        } else result[i] = parent1[i];
+      }
+      return result;
+    }
+
+    /// <summary>
+    /// Checks that there are exactly 2 parents, that the alpha and the probability parameter are not null and fowards the call to the static Apply method.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown when there are not exactly two parents.</exception>
+    /// <exception cref="InvalidOperationException">Thrown when either the alpha parmeter or the probability parameter could not be found.</exception>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="parents">The collection of parents (must be of size 2).</param>
+    /// /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <returns>The vector resulting from the crossover.</returns>
+    protected override IntegerVector CrossBounded(IRandom random, ItemArray<IntegerVector> parents, IntMatrix bounds) {
+      if (parents.Length != 2) throw new ArgumentException("RoundedUniformArithmeticCrossover: There must be exactly two parents.", "parents");
+      if (AlphaParameter.ActualValue == null) throw new InvalidOperationException("RoundedUniformArithmeticCrossover: Parameter " + AlphaParameter.ActualName + " could not be found.");
+      if (ProbabilityParameter.ActualValue == null) throw new InvalidOperationException("RoundedUniformArithmeticCrossover: Parameter " + ProbabilityParameter.ActualName + " could not be found.");
+      return Apply(random, parents[0], parents[1], bounds, AlphaParameter.ActualValue, ProbabilityParameter.ActualValue);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/SinglePointCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/SinglePointCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Crossovers/SinglePointCrossover.cs	(revision 17175)
@@ -0,0 +1,83 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Single point crossover for integer vectors.
+  /// </summary>
+  /// <remarks>
+  /// It is implemented as described in Michalewicz, Z. 1999. Genetic Algorithms + Data Structures = Evolution Programs. Third, Revised and Extended Edition, Spring-Verlag Berlin Heidelberg.
+  /// </remarks>
+  [Item("SinglePointCrossover", "Single point crossover for integer vectors. It is implemented as described in Michalewicz, Z. 1999. Genetic Algorithms + Data Structures = Evolution Programs. Third, Revised and Extended Edition, Spring-Verlag Berlin Heidelberg.")]
+  [StorableType("0B985803-CC2D-466B-B5F2-9A1F7C415735")]
+  public class SinglePointCrossover : IntegerVectorCrossover {
+    [StorableConstructor]
+    protected SinglePointCrossover(StorableConstructorFlag _) : base(_) { }
+    protected SinglePointCrossover(SinglePointCrossover original, Cloner cloner) : base(original, cloner) { }
+    public SinglePointCrossover() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SinglePointCrossover(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs a single point crossover at a randomly chosen position of the two 
+    /// given parent integer vectors.
+    /// </summary>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="parent1">The first parent for crossover.</param>
+    /// <param name="parent2">The second parent for crossover.</param>
+    /// <returns>The newly created integer vector, resulting from the single point crossover.</returns>
+    public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2) {
+      if (parent1.Length != parent2.Length)
+        throw new ArgumentException("SinglePointCrossover: The parents are of different length.");
+
+      int length = parent1.Length;
+      int[] result = new int[length];
+      int breakPoint = random.Next(1, length);
+
+      for (int i = 0; i < breakPoint; i++)
+        result[i] = parent1[i];
+      for (int i = breakPoint; i < length; i++)
+        result[i] = parent2[i];
+
+      return new IntegerVector(result);
+    }
+
+    /// <summary>
+    /// Performs a single point crossover at a randomly chosen position of two 
+    /// given parent integer vectors.
+    /// </summary>
+    /// <exception cref="ArgumentException">Thrown if there are not exactly two parents.</exception>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="parents">An array containing the two integer vectors that should be crossed.</param>
+    /// <returns>The newly created integer vector, resulting from the single point crossover.</returns>
+    protected override IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents) {
+      if (parents.Length != 2) throw new ArgumentException("ERROR in SinglePointCrossover: The number of parents is not equal to 2");
+      return Apply(random, parents[0], parents[1]);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/HeuristicLab.Encodings.IntegerVectorEncoding-3.3.csproj
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/HeuristicLab.Encodings.IntegerVectorEncoding-3.3.csproj	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/HeuristicLab.Encodings.IntegerVectorEncoding-3.3.csproj	(revision 17175)
@@ -0,0 +1,259 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Encodings.IntegerVectorEncoding</RootNamespace>
+    <AssemblyName>HeuristicLab.Encodings.IntegerVectorEncoding-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Plugin.cs.frame" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="BoundedIntegerVectorCrossover.cs" />
+    <Compile Include="BoundedIntegerVectorManipulator.cs" />
+    <Compile Include="Creators\UniformRandomIntegerVectorCreator.cs" />
+    <Compile Include="Crossovers\RoundedAverageCrossover.cs" />
+    <Compile Include="Crossovers\DiscreteCrossover.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Crossovers\MultiIntegerVectorCrossover.cs" />
+    <Compile Include="Crossovers\RoundedBlendAlphaBetaCrossover.cs" />
+    <Compile Include="Crossovers\RoundedBlendAlphaCrossover.cs" />
+    <Compile Include="Crossovers\RoundedHeuristicCrossover.cs" />
+    <Compile Include="Crossovers\RoundedLocalCrossover.cs" />
+    <Compile Include="Crossovers\SinglePointCrossover.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Crossovers\RoundedUniformArithmeticCrossover.cs" />
+    <Compile Include="IntegerVectorEncoding.cs" />
+    <Compile Include="IntegerVectorEqualityComparer.cs" />
+    <Compile Include="IntegerVectorOperator.cs" />
+    <Compile Include="Interfaces\IBoundedIntegerVectorOperator.cs" />
+    <Compile Include="Interfaces\IIntegerVectorCreator.cs" />
+    <Compile Include="Interfaces\IIntegerVectorCrossover.cs" />
+    <Compile Include="Interfaces\IIntegerVectorManipulator.cs" />
+    <Compile Include="Interfaces\IIntegerVectorMultiNeighborhoodShakingOperator.cs" />
+    <Compile Include="Interfaces\IIntegerVectorOperator.cs" />
+    <Compile Include="IntegerVectorCrossover.cs" />
+    <Compile Include="IntegerVectorManipulator.cs" />
+    <Compile Include="Interfaces\IIntegerVectorStdDevStrategyParameterCreator.cs" />
+    <Compile Include="Interfaces\IIntegerVectorStdDevStrategyParameterCrossover.cs" />
+    <Compile Include="Interfaces\IIntegerVectorStdDevStrategyParameterManipulator.cs" />
+    <Compile Include="Interfaces\IIntegerVectorStdDevStrategyParameterOperator.cs" />
+    <Compile Include="Manipulators\UniformSomePositionsManipulator.cs" />
+    <Compile Include="Manipulators\RoundedNormalAllPositionsManipulator.cs" />
+    <Compile Include="Manipulators\SelfAdaptiveRoundedNormalAllPositionsManipulator.cs" />
+    <Compile Include="SimilarityCalculators\EuclideanSimilarityCalculator.cs" />
+    <Compile Include="SimilarityCalculators\HammingSimilarityCalculator.cs" />
+    <Compile Include="StrategyParameters\StdDevStrategyVectorCreator.cs" />
+    <Compile Include="StrategyParameters\StdDevStrategyVectorCrossover.cs" />
+    <Compile Include="StrategyParameters\StdDevStrategyVectorManipulator.cs" />
+    <Compile Include="Manipulators\UniformOnePositionManipulator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="IntegerVector.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="IntegerVectorCreator.cs" />
+    <Compile Include="ShakingOperators\IntegerVectorShakingOperator.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Data-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization.Operators-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Optimization.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Parameters-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Persistence-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Persistence-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Random-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Random-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
+      <Project>{14AB8D24-25BC-400C-A846-4627AA945192}</Project>
+      <Name>HeuristicLab.Optimization-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="HEAL.Attic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\bin\HEAL.Attic.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+</PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVector.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVector.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVector.cs	(revision 17175)
@@ -0,0 +1,79 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("2DDD33C1-4732-478B-83B1-17226A8F2B61")]
+  [Item("IntegerVector", "Represents a vector of integer values.")]
+  public class IntegerVector : IntArray {
+    [StorableConstructor]
+    protected IntegerVector(StorableConstructorFlag _) : base(_) { }
+    protected IntegerVector(IntegerVector original, Cloner cloner) : base(original, cloner) { }
+    public IntegerVector() : base() { }
+    public IntegerVector(int length) : base(length) { }
+    public IntegerVector(int length, IRandom random, int min, int max)
+      : this(length) {
+      Randomize(random, min, max);
+    }
+    public IntegerVector(int[] elements) : base(elements) { }
+    public IntegerVector(IntArray elements)
+      : this(elements.Length) {
+      for (int i = 0; i < array.Length; i++)
+        array[i] = elements[i];
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IntegerVector(this, cloner);
+    }
+
+    public virtual void Randomize(IRandom random, int startIndex, int length, int min, int max, int step = 1) {
+      if (length > 0) {
+        int numbers = (int)Math.Floor((max - min) / (double)step);
+        for (int i = startIndex; i < startIndex + length; i++) {
+          array[i] = random.Next(numbers) * step + min;
+        }
+        OnReset();
+      }
+    }
+    public virtual void Randomize(IRandom random, int startIndex, int length, IntMatrix bounds) {
+      if (length > 0) {
+        for (int i = startIndex; i < startIndex + length; i++) {
+          int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1;
+          if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2];
+          int numbers = (int)Math.Floor((max - min) / (double)step);
+          array[i] = random.Next(numbers) * step + min;
+        }
+        OnReset();
+      }
+    }
+    public void Randomize(IRandom random, int min, int max, int step = 1) {
+      Randomize(random, 0, Length, min, max, step);
+    }
+    public void Randomize(IRandom random, IntMatrix bounds) {
+      Randomize(random, 0, Length, bounds);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorCreator.cs	(revision 17175)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// A base class for operators creating int-valued vectors.
+  /// </summary>
+  [Item("IntegerVectorCreator", "A base class for operators creating int-valued vectors.")]
+  [StorableType("3C20D629-EFCB-4A1C-81B4-1DF0942B27F7")]
+  public abstract class IntegerVectorCreator : InstrumentedOperator, IIntegerVectorCreator, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<IntegerVector> IntegerVectorParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["IntegerVector"]; }
+    }
+    public IValueLookupParameter<IntValue> LengthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["Length"]; }
+    }
+    public IValueLookupParameter<IntMatrix> BoundsParameter {
+      get { return (IValueLookupParameter<IntMatrix>)Parameters["Bounds"]; }
+    }
+
+    [StorableConstructor]
+    protected IntegerVectorCreator(StorableConstructorFlag _) : base(_) { }
+    protected IntegerVectorCreator(IntegerVectorCreator original, Cloner cloner) : base(original, cloner) { }
+    protected IntegerVectorCreator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+      Parameters.Add(new LookupParameter<IntegerVector>("IntegerVector", "The vector which should be manipulated."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("Length", "The length of the vector."));
+      Parameters.Add(new ValueLookupParameter<IntMatrix>("Bounds", "The bounds matrix can contain one row for each dimension with three columns specifying minimum (inclusive), maximum (exclusive), and step size. If less rows are given the matrix is cycled."));
+    }
+
+    // BackwardsCompatibility3.3
+    #region Backwards compatible code, remove with 3.4
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("Bounds")) {
+        var min = ((IValueLookupParameter<IntValue>)Parameters["Minimum"]).Value as IntValue;
+        var max = ((IValueLookupParameter<IntValue>)Parameters["Maximum"]).Value as IntValue;
+        Parameters.Remove("Minimum");
+        Parameters.Remove("Maximum");
+        Parameters.Add(new ValueLookupParameter<IntMatrix>("Bounds", "The bounds matrix can contain one row for each dimension with three columns specifying minimum (inclusive), maximum (exclusive), and step size. If less rows are given the matrix is cycled."));
+        if (min != null && max != null) {
+          BoundsParameter.Value = new IntMatrix(new int[,] { { min.Value, max.Value, 1 } });
+        }
+      }
+    }
+    #endregion
+
+    public sealed override IOperation InstrumentedApply() {
+      IntegerVectorParameter.ActualValue = Create(RandomParameter.ActualValue, LengthParameter.ActualValue, BoundsParameter.ActualValue);
+      return base.InstrumentedApply();
+    }
+
+    protected abstract IntegerVector Create(IRandom random, IntValue length, IntMatrix bounds);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorCrossover.cs	(revision 17175)
@@ -0,0 +1,67 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// A base class for operators that perform a crossover of int-valued vectors.
+  /// </summary>
+  [Item("IntegerVectorCrossover", "A base class for operators that perform a crossover of int-valued vectors.")]
+  [StorableType("BE778213-C140-4B1C-A4A4-1D92D0ADAB45")]
+  public abstract class IntegerVectorCrossover : IntegerVectorOperator, IIntegerVectorCrossover, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<ItemArray<IntegerVector>> ParentsParameter {
+      get { return (ScopeTreeLookupParameter<IntegerVector>)Parameters["Parents"]; }
+    }
+    public ILookupParameter<IntegerVector> ChildParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Child"]; }
+    }
+
+    [StorableConstructor]
+    protected IntegerVectorCrossover(StorableConstructorFlag _) : base(_) { }
+    protected IntegerVectorCrossover(IntegerVectorCrossover original, Cloner cloner) : base(original, cloner) { }
+    protected IntegerVectorCrossover()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic crossover operators."));
+      Parameters.Add(new ScopeTreeLookupParameter<IntegerVector>("Parents", "The parent vectors which should be crossed."));
+      ParentsParameter.ActualName = "IntegerVector";
+      Parameters.Add(new LookupParameter<IntegerVector>("Child", "The child vector resulting from the crossover."));
+      ChildParameter.ActualName = "IntegerVector";
+    }
+
+    public sealed override IOperation InstrumentedApply() {
+      ChildParameter.ActualValue = Cross(RandomParameter.ActualValue, ParentsParameter.ActualValue);
+      return base.InstrumentedApply();
+    }
+
+    protected abstract IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorEncoding.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorEncoding.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorEncoding.cs	(revision 17175)
@@ -0,0 +1,283 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [Item("IntegerVectorEncoding", "Describes an integer vector encoding.")]
+  [StorableType("15D6E55E-C39F-4784-8350-14A0FD47CF0E")]
+  public sealed class IntegerVectorEncoding : Encoding<IIntegerVectorCreator> {
+    #region Encoding Parameters
+    [Storable]
+    private IFixedValueParameter<IntValue> lengthParameter;
+    public IFixedValueParameter<IntValue> LengthParameter {
+      get { return lengthParameter; }
+      set {
+        if (value == null) throw new ArgumentNullException("Length parameter must not be null.");
+        if (value.Value == null) throw new ArgumentNullException("Length parameter value must not be null.");
+        if (lengthParameter == value) return;
+
+        if (lengthParameter != null) Parameters.Remove(lengthParameter);
+        lengthParameter = value;
+        Parameters.Add(lengthParameter);
+        OnLengthParameterChanged();
+      }
+    }
+
+    [Storable]
+    private IValueParameter<IntMatrix> boundsParameter;
+    public IValueParameter<IntMatrix> BoundsParameter {
+      get { return boundsParameter; }
+      set {
+        if (value == null) throw new ArgumentNullException("Bounds parameter must not be null.");
+        if (boundsParameter == value) return;
+
+        if (boundsParameter != null) Parameters.Remove(boundsParameter);
+        boundsParameter = value;
+        Parameters.Add(boundsParameter);
+        OnBoundsParameterChanged();
+      }
+    }
+    #endregion
+
+    public int Length {
+      get { return LengthParameter.Value.Value; }
+      set { LengthParameter.Value.Value = value; }
+    }
+    public IntMatrix Bounds {
+      get { return BoundsParameter.Value; }
+      set { BoundsParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    private IntegerVectorEncoding(StorableConstructorFlag _) : base(_) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterParameterEvents();
+      DiscoverOperators();
+    }
+
+    private IntegerVectorEncoding(IntegerVectorEncoding original, Cloner cloner)
+      : base(original, cloner) {
+      lengthParameter = cloner.Clone(original.lengthParameter);
+      boundsParameter = cloner.Clone(original.boundsParameter);
+      RegisterParameterEvents();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new IntegerVectorEncoding(this, cloner); }
+
+
+    public IntegerVectorEncoding() : this("IntegerVector", 10) { }
+    public IntegerVectorEncoding(string name) : this(name, 10) { }
+    public IntegerVectorEncoding(int length) : this("integerVector", length) { }
+    public IntegerVectorEncoding(string name, int length, int min = int.MinValue, int max = int.MaxValue, int? step = null)
+      : base(name) {
+      if (min >= max) throw new ArgumentException("min must be less than max", "min");
+      if (step.HasValue && step.Value <= 0) throw new ArgumentException("step must be greater than zero or null", "step");
+
+      var bounds = new IntMatrix(1, step.HasValue ? 3 : 2);
+      bounds[0, 0] = min;
+      bounds[0, 1] = max;
+      if (step.HasValue) bounds[0, 2] = step.Value;
+
+      lengthParameter = new FixedValueParameter<IntValue>(Name + ".Length", new IntValue(length));
+      boundsParameter = new ValueParameter<IntMatrix>(Name + ".Bounds", bounds);
+      Parameters.Add(lengthParameter);
+      Parameters.Add(boundsParameter);
+
+      SolutionCreator = new UniformRandomIntegerVectorCreator();
+      RegisterParameterEvents();
+      DiscoverOperators();
+    }
+    public IntegerVectorEncoding(string name, int length, IList<int> min, IList<int> max, IList<int> step = null)
+      : base(name) {
+      if (min.Count == 0) throw new ArgumentException("Bounds must be given for the integer parameters.");
+      if (min.Count != max.Count) throw new ArgumentException("min must be of the same length as max", "min");
+      if (step != null && min.Count != step.Count) throw new ArgumentException("step must be of the same length as min or null", "step");
+      if (min.Zip(max, (mi, ma) => mi >= ma).Any(x => x)) throw new ArgumentException("min must be less than max in each dimension", "min");
+
+      var bounds = new IntMatrix(min.Count, step != null ? 3 : 2);
+      for (int i = 0; i < min.Count; i++) {
+        bounds[i, 0] = min[i];
+        bounds[i, 1] = max[i];
+        if (step != null) bounds[i, 2] = step[i];
+      }
+
+      lengthParameter = new FixedValueParameter<IntValue>(Name + ".Length", new IntValue(length));
+      boundsParameter = new ValueParameter<IntMatrix>(Name + ".Bounds", bounds);
+      Parameters.Add(lengthParameter);
+      Parameters.Add(boundsParameter);
+
+      SolutionCreator = new UniformRandomIntegerVectorCreator();
+      RegisterParameterEvents();
+      DiscoverOperators();
+    }
+
+    private void OnLengthParameterChanged() {
+      RegisterLengthParameterEvents();
+      ConfigureOperators(Operators);
+    }
+    private void OnBoundsParameterChanged() {
+      RegisterBoundsParameterEvents();
+      ConfigureOperators(Operators);
+    }
+
+    private void RegisterParameterEvents() {
+      RegisterLengthParameterEvents();
+      RegisterBoundsParameterEvents();
+    }
+    private void RegisterLengthParameterEvents() {
+      LengthParameter.ValueChanged += (o, s) => ConfigureOperators(Operators);
+      LengthParameter.Value.ValueChanged += (o, s) => ConfigureOperators(Operators);
+    }
+    private void RegisterBoundsParameterEvents() {
+      BoundsParameter.ValueChanged += (o, s) => ConfigureOperators(Operators);
+      boundsParameter.Value.ToStringChanged += (o, s) => ConfigureOperators(Operators);
+    }
+
+
+    #region Operator Discovery
+    private static readonly IEnumerable<Type> encodingSpecificOperatorTypes;
+    static IntegerVectorEncoding() {
+      encodingSpecificOperatorTypes = new List<Type>() {
+        typeof (IIntegerVectorOperator),
+        typeof (IIntegerVectorCreator),
+        typeof (IIntegerVectorCrossover),
+        typeof (IIntegerVectorManipulator),
+        typeof (IIntegerVectorStdDevStrategyParameterOperator),
+        typeof (IIntegerVectorMultiNeighborhoodShakingOperator),
+      };
+    }
+    private void DiscoverOperators() {
+      var assembly = typeof(IIntegerVectorOperator).Assembly;
+      var discoveredTypes = ApplicationManager.Manager.GetTypes(encodingSpecificOperatorTypes, assembly, true, false, false);
+      var operators = discoveredTypes.Select(t => (IOperator)Activator.CreateInstance(t));
+      var newOperators = operators.Except(Operators, new TypeEqualityComparer<IOperator>()).ToList();
+
+      ConfigureOperators(newOperators);
+      foreach (var @operator in newOperators)
+        AddOperator(@operator);
+    }
+    #endregion
+
+    public override void ConfigureOperators(IEnumerable<IOperator> operators) {
+      ConfigureBoundedOperators(operators.OfType<IBoundedIntegerVectorOperator>());
+      ConfigureCreators(operators.OfType<IIntegerVectorCreator>());
+      ConfigureCrossovers(operators.OfType<IIntegerVectorCrossover>());
+      ConfigureManipulators(operators.OfType<IIntegerVectorManipulator>());
+      ConfigureShakingOperators(operators.OfType<IIntegerVectorMultiNeighborhoodShakingOperator>());
+      ConfigureStrategyVectorOperator(operators.OfType<IIntegerVectorStdDevStrategyParameterOperator>());
+    }
+
+    #region Specific Operator Wiring
+    private void ConfigureBoundedOperators(IEnumerable<IBoundedIntegerVectorOperator> boundedOperators) {
+      foreach (var boundedOperator in boundedOperators) {
+        boundedOperator.BoundsParameter.ActualName = BoundsParameter.Name;
+      }
+    }
+
+    private void ConfigureCreators(IEnumerable<IIntegerVectorCreator> creators) {
+      foreach (var creator in creators) {
+        creator.IntegerVectorParameter.ActualName = Name;
+        creator.BoundsParameter.ActualName = BoundsParameter.Name;
+        creator.LengthParameter.ActualName = LengthParameter.Name;
+      }
+    }
+
+    private void ConfigureCrossovers(IEnumerable<IIntegerVectorCrossover> crossovers) {
+      foreach (var crossover in crossovers) {
+        crossover.ChildParameter.ActualName = Name;
+        crossover.ParentsParameter.ActualName = Name;
+      }
+    }
+
+    private void ConfigureManipulators(IEnumerable<IIntegerVectorManipulator> manipulators) {
+      foreach (var manipulator in manipulators) {
+        manipulator.IntegerVectorParameter.ActualName = Name;
+        manipulator.IntegerVectorParameter.Hidden = true;
+        var sm = manipulator as ISelfAdaptiveManipulator;
+        if (sm != null) {
+          var p = sm.StrategyParameterParameter as ILookupParameter;
+          if (p != null) {
+            p.ActualName = Name + "Strategy";
+          }
+        }
+      }
+    }
+
+    private void ConfigureShakingOperators(IEnumerable<IIntegerVectorMultiNeighborhoodShakingOperator> shakingOperators) {
+      foreach (var shakingOperator in shakingOperators) {
+        shakingOperator.IntegerVectorParameter.ActualName = Name;
+      }
+    }
+
+    private void ConfigureStrategyVectorOperator(IEnumerable<IIntegerVectorStdDevStrategyParameterOperator> strategyVectorOperators) {
+      var bounds = new DoubleMatrix(Bounds.Rows, Bounds.Columns);
+      for (var i = 0; i < bounds.Rows; i++) {
+        bounds[i, 1] = (int)Math.Ceiling(0.33 * (Bounds[i, 1] - Bounds[i, 0]));
+        bounds[i, 0] = 0;
+        if (bounds.Columns > 2) bounds[i, 2] = Bounds[i, 2];
+      }
+      foreach (var s in strategyVectorOperators) {
+        var c = s as IIntegerVectorStdDevStrategyParameterCreator;
+        if (c != null) {
+          c.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
+          c.LengthParameter.ActualName = Name;
+          c.StrategyParameterParameter.ActualName = Name + "Strategy";
+        }
+        var m = s as IIntegerVectorStdDevStrategyParameterManipulator;
+        if (m != null) {
+          m.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
+          m.StrategyParameterParameter.ActualName = Name + "Strategy";
+        }
+        var mm = s as StdDevStrategyVectorManipulator;
+        if (mm != null) {
+          mm.GeneralLearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * Length));
+          mm.LearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * Math.Sqrt(Length)));
+        }
+        var x = s as IIntegerVectorStdDevStrategyParameterCrossover;
+        if (x != null) {
+          x.ParentsParameter.ActualName = Name + "Strategy";
+          x.StrategyParameterParameter.ActualName = Name + "Strategy";
+        }
+      }
+    }
+    #endregion
+  }
+
+  public static class IndividualExtensionMethods {
+    public static IntegerVector IntegerVector(this Individual individual) {
+      var encoding = individual.GetEncoding<IntegerVectorEncoding>();
+      return individual.IntegerVector(encoding.Name);
+    }
+    public static IntegerVector IntegerVector(this Individual individual, string name) {
+      return (IntegerVector)individual[name];
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorEqualityComparer.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorEqualityComparer.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorEqualityComparer.cs	(revision 17175)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Collections.Generic;
+using HeuristicLab.PluginInfrastructure;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [NonDiscoverableType]
+  [StorableType("33f5a8c1-8230-495f-8b8e-475bf69ac9a4")]
+  public class IntegerVectorEqualityComparer : EqualityComparer<IntegerVector> {
+    public override bool Equals(IntegerVector x, IntegerVector y) {
+      if (ReferenceEquals(x, y)) return true;
+      if (x == null || y == null) return false;
+      if (x.Length != y.Length) return false;
+      for (var i = 0; i < x.Length; i++)
+        if (x[i] != y[i]) return false;
+      return true;
+    }
+
+    public override int GetHashCode(IntegerVector obj) {
+      if (obj == null) throw new ArgumentNullException("obj", "IntegerVectorEqualityComparer: Cannot compute hash value of null.");
+      unchecked {
+        int hash = 17;
+        foreach (var o in obj)
+          hash = hash * 31 + o.GetHashCode();
+        return hash;
+      }
+    }
+
+    public static IEnumerable<int> GetDifferingIndices(IntegerVector a, IntegerVector b) {
+      if (a == null || b == null) throw new ArgumentNullException("arguments must not be null");
+      for (int i = 0; i < a.Length; i++)
+        if (a[i] != b[i]) yield return i;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorManipulator.cs	(revision 17175)
@@ -0,0 +1,61 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// A base class for operators that manipulate int-valued vectors.
+  /// </summary>
+  [Item("IntegerVectorManipulator", "A base class for operators that manipulate int-valued vectors.")]
+  [StorableType("CE399EA5-7FAD-4070-A89D-A0FC3431B02D")]
+  public abstract class IntegerVectorManipulator : IntegerVectorOperator, IIntegerVectorManipulator, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<IntegerVector> IntegerVectorParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["IntegerVector"]; }
+    }
+
+    [StorableConstructor]
+    protected IntegerVectorManipulator(StorableConstructorFlag _) : base(_) { }
+    protected IntegerVectorManipulator(IntegerVectorManipulator original, Cloner cloner) : base(original, cloner) { }
+    protected IntegerVectorManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+      Parameters.Add(new LookupParameter<IntegerVector>("IntegerVector", "The vector which should be manipulated."));
+    }
+
+    public sealed override IOperation InstrumentedApply() {
+      Manipulate(RandomParameter.ActualValue, IntegerVectorParameter.ActualValue);
+      return base.InstrumentedApply();
+    }
+
+    protected abstract void Manipulate(IRandom random, IntegerVector integerVector);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/IntegerVectorOperator.cs	(revision 17175)
@@ -0,0 +1,48 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [Item("IntegerVectorOperator", "Base class for integer vectoro operators.")]
+  [StorableType("6B380738-453C-4E60-B4AB-B3907BB5D9E2")]
+  public abstract class IntegerVectorOperator : InstrumentedOperator, IIntegerVectorOperator {
+
+    [StorableConstructor]
+    protected IntegerVectorOperator(StorableConstructorFlag _) : base(_) { }
+    protected IntegerVectorOperator(IntegerVectorOperator original, Cloner cloner) : base(original, cloner) { }
+    public IntegerVectorOperator() : base() { }
+
+    public static int RoundFeasible(int min, int max, int step, double value) {
+      return Math.Max(min, Math.Min(max, (int)Math.Round((value - min) / (double)step) * step + min));
+    }
+    public static int FloorFeasible(int min, int max, int step, double value) {
+      return Math.Max(min, Math.Min(max, (int)Math.Floor((value - min) / (double)step) * step + min));
+    }
+    public static int CeilingFeasible(int min, int max, int step, double value) {
+      return Math.Max(min, Math.Min(max, (int)Math.Ceiling((value - min) / (double)step) * step + min));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IBoundedIntegerVectorOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IBoundedIntegerVectorOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IBoundedIntegerVectorOperator.cs	(revision 17175)
@@ -0,0 +1,34 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HeuristicLab.Data;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("c39d6a9a-430c-47d8-97d9-8430cb6050ff")]
+  public interface IBoundedIntegerVectorOperator : IIntegerVectorOperator {
+    /// <summary>
+    /// The bounds parameter must contain at least one row and at least two columns. The first two columns specify min and max values, the last column specifies the step size, but is optional (1 is assumed if omitted).
+    /// </summary>
+    IValueLookupParameter<IntMatrix> BoundsParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorCreator.cs	(revision 17175)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("9742b0e1-ab88-474e-b3f7-a2a0c2f77029")]
+  /// <summary>
+  /// An interface which represents an operator for creating vectors of int-valued data.
+  /// </summary>
+  public interface IIntegerVectorCreator : ISolutionCreator, IBoundedIntegerVectorOperator {
+    IValueLookupParameter<IntValue> LengthParameter { get; }
+    ILookupParameter<IntegerVector> IntegerVectorParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorCrossover.cs	(revision 17175)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("b29109e0-1930-429e-bc50-56790b97a7a0")]
+  /// <summary>
+  /// An interface which represents an operator for crossing vectors of int-valued data.
+  /// </summary>
+  public interface IIntegerVectorCrossover : IIntegerVectorOperator, ICrossover {
+    ILookupParameter<ItemArray<IntegerVector>> ParentsParameter { get; }
+    ILookupParameter<IntegerVector> ChildParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorManipulator.cs	(revision 17175)
@@ -0,0 +1,34 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("8c58d54f-5454-4b55-8be8-820ef0ee8687")]
+  /// <summary>
+  /// An interface which represents an operator for manipulating vectors of int-valued data.
+  /// </summary>
+  public interface IIntegerVectorManipulator : IIntegerVectorOperator, IManipulator {
+    ILookupParameter<IntegerVector> IntegerVectorParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorMultiNeighborhoodShakingOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorMultiNeighborhoodShakingOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorMultiNeighborhoodShakingOperator.cs	(revision 17175)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("2b21442c-735f-4df3-a163-4e3147cd11a5")]
+  public interface IIntegerVectorMultiNeighborhoodShakingOperator : IIntegerVectorOperator {
+    ILookupParameter<IntegerVector> IntegerVectorParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorOperator.cs	(revision 17175)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("8caffc56-bdf0-465e-87ba-882441dfbd0d")]
+  /// <summary>
+  /// An interface which represents an operator dealing with vectors of int-valued data.
+  /// </summary>
+  public interface IIntegerVectorOperator : IOperator { }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterCreator.cs	(revision 17175)
@@ -0,0 +1,34 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("24dca301-a0f6-472f-9859-27f292f69458")]
+  public interface IIntegerVectorStdDevStrategyParameterCreator : IIntegerVectorStdDevStrategyParameterOperator, IStrategyParameterCreator {
+    ILookupParameter<DoubleArray> StrategyParameterParameter { get; }
+    IValueLookupParameter<IntValue> LengthParameter { get; }
+    IValueLookupParameter<DoubleMatrix> BoundsParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterCrossover.cs	(revision 17175)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("e8beb5ce-ec96-48b4-aac6-59e73249afef")]
+  public interface IIntegerVectorStdDevStrategyParameterCrossover : IIntegerVectorStdDevStrategyParameterOperator, IStrategyParameterCrossover {
+    ILookupParameter<DoubleArray> StrategyParameterParameter { get; }
+    ILookupParameter<ItemArray<DoubleArray>> ParentsParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterManipulator.cs	(revision 17175)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("c2b76c64-9e5d-4ecb-b692-11cdf697ba02")]
+  public interface IIntegerVectorStdDevStrategyParameterManipulator : IIntegerVectorStdDevStrategyParameterOperator, IStrategyParameterManipulator {
+    ILookupParameter<DoubleArray> StrategyParameterParameter { get; }
+    IValueLookupParameter<DoubleMatrix> BoundsParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Interfaces/IIntegerVectorStdDevStrategyParameterOperator.cs	(revision 17175)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [StorableType("f5dc6e51-c650-4d70-a109-ec94089b9024")]
+  public interface IIntegerVectorStdDevStrategyParameterOperator : IOperator {
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/RoundedNormalAllPositionsManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/RoundedNormalAllPositionsManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/RoundedNormalAllPositionsManipulator.cs	(revision 17175)
@@ -0,0 +1,93 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Manipulates each dimension in the integer vector with the mutation strength given 
+  /// in the sigma parameter vector and rounds the result to the next feasible value.
+  /// </summary>
+  [Item("RoundedNormalAllPositionsManipulator", "This manipulation operator adds a value sigma_i * N_i(0,1) to the current value in each position i given the values for sigma_i in the parameter. The result is rounded to the next feasible value. If there are less elements in Sigma than positions, then Sigma is cycled.")]
+  [StorableType("CDAE115B-1BAD-4CC2-B63E-E3C45955175D")]
+  public class RoundedNormalAllPositionsManipulator : BoundedIntegerVectorManipulator {
+
+    public IValueParameter<DoubleArray> SigmaParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["Sigma"]; }
+    }
+
+    [StorableConstructor]
+    protected RoundedNormalAllPositionsManipulator(StorableConstructorFlag _) : base(_) { }
+    protected RoundedNormalAllPositionsManipulator(RoundedNormalAllPositionsManipulator original, Cloner cloner) : base(original, cloner) { }
+    /// <summary>
+    /// Initializes a new instance of <see cref="RoundedNormalAllPositionsManipulator"/> with one
+    /// parameter (<c>Sigma</c>).
+    /// </summary>
+    public RoundedNormalAllPositionsManipulator()
+      : base() {
+      Parameters.Add(new ValueParameter<DoubleArray>("Sigma", "The vector containing the standard deviations used for manipulating each dimension. If it is only of length one the same sigma will be used for every dimension.", new DoubleArray(new double[] { 1 })));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RoundedNormalAllPositionsManipulator(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs a normally distributed all position manipulation on the given 
+    /// <paramref name="vector"/> and rounds the result to the next feasible value.
+    /// </summary>
+    /// <exception cref="InvalidOperationException">Thrown when the sigma vector is null or of length 0.</exception>
+    /// <param name="sigma">The sigma vector determining the strength of the mutation.</param>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="vector">The integer vector to manipulate.</param>#
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    /// <returns>The manipulated integer vector.</returns>
+    public static void Apply(IRandom random, IntegerVector vector, IntMatrix bounds, DoubleArray sigma) {
+      if (sigma == null || sigma.Length == 0) throw new ArgumentException("RoundedNormalAllPositionsManipulator: Vector containing the standard deviations is not defined.", "sigma");
+      if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) throw new ArgumentException("RoundedNormalAllPositionsManipulator: Invalid bounds specified.", "bounds");
+      var N = new NormalDistributedRandom(random, 0.0, 1.0);
+      for (int i = 0; i < vector.Length; i++) {
+        int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1;
+        if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2];
+
+        double value = vector[i] + N.NextDouble() * sigma[i % sigma.Length];
+        max = FloorFeasible(min, max, step, max - 1);
+        vector[i] = RoundFeasible(min, max, step, value);
+      }
+    }
+
+    /// <summary>
+    /// Retrieves the bounds and forwards the call to the static Apply method.
+    /// </summary>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="vector">The vector of integer values that is manipulated.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    protected override void ManipulateBounded(IRandom random, IntegerVector vector, IntMatrix bounds) {
+      Apply(random, vector, bounds, SigmaParameter.Value);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/SelfAdaptiveRoundedNormalAllPositionsManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/SelfAdaptiveRoundedNormalAllPositionsManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/SelfAdaptiveRoundedNormalAllPositionsManipulator.cs	(revision 17175)
@@ -0,0 +1,104 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Manipulates each dimension in the integer vector with the mutation strength given 
+  /// in the strategy parameter vector.
+  /// </summary>
+  [Item("SelfAdaptiveRoundedNormalAllPositionsManipulator", "This manipulation operator adds a value sigma_i * N(0,1) to the current value in each position i. The resulting value is rounded to the next feasible value. The values for sigma_i are looked up dynamically. If there are less elements in the strategy vector than positions, then the strategy vector is cycled.")]
+  [StorableType("2CD4AE6E-3A73-4514-AB66-4D94C700F779")]
+  public class SelfAdaptiveRoundedNormalAllPositionsManipulator : BoundedIntegerVectorManipulator, ISelfAdaptiveManipulator {
+    public Type StrategyParameterType {
+      get { return typeof(IIntegerVectorStdDevStrategyParameterOperator); }
+    }
+    /// <summary>
+    /// Parameter for the strategy vector.
+    /// </summary>
+    public ILookupParameter<DoubleArray> StrategyParameterParameter {
+      get { return (ILookupParameter<DoubleArray>)Parameters["StrategyParameter"]; }
+    }
+
+    IParameter ISelfAdaptiveManipulator.StrategyParameterParameter {
+      get { return StrategyParameterParameter; }
+    }
+
+    [StorableConstructor]
+    protected SelfAdaptiveRoundedNormalAllPositionsManipulator(StorableConstructorFlag _) : base(_) { }
+    protected SelfAdaptiveRoundedNormalAllPositionsManipulator(SelfAdaptiveRoundedNormalAllPositionsManipulator original, Cloner cloner) : base(original, cloner) { }
+    /// <summary>
+    /// Initializes a new instance of <see cref="SelfAdaptiveRoundedNormalAllPositionsManipulator"/> with one.
+    /// </summary>
+    public SelfAdaptiveRoundedNormalAllPositionsManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleArray>("StrategyParameter", "The vector containing the endogenous strategy parameters."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SelfAdaptiveRoundedNormalAllPositionsManipulator(this, cloner);
+    }
+
+    /// <summary>
+    /// Performs an adaptive normally distributed all position manipulation on the given 
+    /// <paramref name="vector"/> and rounding the results to the next feasible value.
+    /// </summary>
+    /// <exception cref="InvalidOperationException">Thrown when the strategy vector is not
+    /// as long as the vector to get manipulated.</exception>
+    /// <param name="strategyParameters">The strategy vector determining the strength of the mutation.</param>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="vector">The integer vector to manipulate.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    public static void Apply(IRandom random, IntegerVector vector, IntMatrix bounds, DoubleArray strategyParameters) {
+      if (strategyParameters == null || strategyParameters.Length == 0) throw new ArgumentException("SelfAdaptiveRoundedNormalAllPositionsManipulator: Vector containing the standard deviations is not defined.", "sigma");
+      if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) throw new ArgumentException("SelfAdaptiveRoundedNormalAllPositionsManipulator: Invalid bounds specified.", "bounds");
+      var N = new NormalDistributedRandom(random, 0.0, 1.0);
+      if (strategyParameters != null) {
+        for (int i = 0; i < vector.Length; i++) {
+          int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1;
+          if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2];
+
+          int value = (vector[i] + (int)Math.Round((N.NextDouble() * strategyParameters[i % strategyParameters.Length])) - min) / step;
+          max = FloorFeasible(min, max, step, max - 1);
+          vector[i] = RoundFeasible(min, max, step, value);
+        }
+      }
+    }
+
+    /// <summary>
+    /// Checks that the strategy vector is not null and forwards the call to the static Apply method.
+    /// </summary>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="vector">The vector of integer values that is manipulated.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    protected override void ManipulateBounded(IRandom random, IntegerVector vector, IntMatrix bounds) {
+      Apply(random, vector, bounds, StrategyParameterParameter.ActualValue);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/UniformOnePositionManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/UniformOnePositionManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/UniformOnePositionManipulator.cs	(revision 17175)
@@ -0,0 +1,111 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Uniformly distributed change of a single position of an integer vector.
+  /// </summary>
+  /// <remarks>
+  /// It is implemented as described in Michalewicz, Z. 1999. Genetic Algorithms + Data Structures = Evolution Programs. Third, Revised and Extended Edition, Spring-Verlag Berlin Heidelberg.
+  /// </remarks>
+  [Item("UniformOnePositionManipulator", " Uniformly distributed change of a single position of an integer vector. It is implemented as described in Michalewicz, Z. 1999. Genetic Algorithms + Data Structures = Evolution Programs. Third, Revised and Extended Edition, Spring-Verlag Berlin Heidelberg.")]
+  [StorableType("205791F7-231F-4957-B27E-387161BF56F0")]
+  public class UniformOnePositionManipulator : BoundedIntegerVectorManipulator {
+
+    [StorableConstructor]
+    protected UniformOnePositionManipulator(StorableConstructorFlag _) : base(_) { }
+    protected UniformOnePositionManipulator(UniformOnePositionManipulator original, Cloner cloner) : base(original, cloner) { }
+    /// <summary>
+    /// Initializes a new instance of <see cref="UniformOnePositionManipulator"/> with two parameters
+    /// (<c>Minimum</c> and <c>Maximum</c>).
+    /// </summary>
+    public UniformOnePositionManipulator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new UniformOnePositionManipulator(this, cloner);
+    }
+
+    // BackwardsCompatibility3.3
+    #region Backwards compatible code, remove with 3.4
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("Bounds")) {
+        var min = ((IValueLookupParameter<IntValue>)Parameters["Minimum"]).Value as IntValue;
+        var max = ((IValueLookupParameter<IntValue>)Parameters["Maximum"]).Value as IntValue;
+        Parameters.Remove("Minimum");
+        Parameters.Remove("Maximum");
+        Parameters.Add(new ValueLookupParameter<IntMatrix>("Bounds", "The bounds matrix can contain one row for each dimension with three columns specifying minimum (inclusive), maximum (exclusive), and step size. If less rows are given the matrix is cycled."));
+        if (min != null && max != null) {
+          BoundsParameter.Value = new IntMatrix(new int[,] { { min.Value, max.Value, 1 } });
+        }
+      }
+    }
+    #endregion
+
+    /// <summary>
+    /// Changes randomly a single position in the given integer <paramref name="vector"/>.
+    /// </summary>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="vector">The integer vector to manipulate.</param>
+    /// <param name="min">The minimum value of the sampling range for 
+    /// the vector element to change (inclusive).</param>
+    /// <param name="max">The maximum value of the sampling range for
+    /// the vector element to change (exclusive).</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    public static void Apply(IRandom random, IntegerVector vector, IntMatrix bounds) {
+      Manipulate(random, vector, bounds, random.Next(vector.Length));
+    }
+
+    public static void Manipulate(IRandom random, IntegerVector vector, IntMatrix bounds, int index) {
+      if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) throw new ArgumentException("UniformOnePositionManipulator: Invalid bounds specified", "bounds");
+      int min = bounds[index % bounds.Rows, 0], max = bounds[index % bounds.Rows, 1], step = 1;
+      if (min == max) {
+        vector[index] = min;
+      } else {
+        if (bounds.Columns > 2) step = bounds[index % bounds.Rows, 2];
+        // max has to be rounded to the lower feasible value
+        // e.g. min...max / step = 0...100 / 5, max is exclusive so it would be 0..99
+        // but 99 is not a feasible value, so max needs to be adjusted => min = 0, max = 95
+        max = FloorFeasible(min, max, step, max - 1);
+        vector[index] = RoundFeasible(min, max, step, random.Next(min, max));
+      }
+    }
+
+    /// <summary>
+    /// Changes randomly a single position in the given integer <paramref name="vector"/>.
+    /// </summary>
+    /// <remarks>Calls <see cref="Apply"/>.</remarks>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="vector">The integer vector to manipulate.</param>
+    /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param>
+    protected override void ManipulateBounded(IRandom random, IntegerVector vector, IntMatrix bounds) {
+      if (BoundsParameter.ActualValue == null) throw new InvalidOperationException("UniformOnePositionManipulator: Parameter " + BoundsParameter.ActualName + " could not be found.");
+      Apply(random, vector, bounds);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/UniformSomePositionsManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/UniformSomePositionsManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Manipulators/UniformSomePositionsManipulator.cs	(revision 17175)
@@ -0,0 +1,89 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Uniformly distributed change of several, but at least one, positions of an integer vector.
+  /// </summary>
+  /// <remarks>
+  /// It is implemented as described in Michalewicz, Z. 1999. Genetic Algorithms + Data Structures = Evolution Programs. Third, Revised and Extended Edition, Spring-Verlag Berlin Heidelberg.
+  /// </remarks>
+  [Item("UniformSomePositionsManipulator", "Uniformly distributed change of several, but at least one, positions of an integer vector. It is implemented as described in Michalewicz, Z. 1999. Genetic Algorithms + Data Structures = Evolution Programs. Third, Revised and Extended Edition, Spring-Verlag Berlin Heidelberg.")]
+  [StorableType("1A0F372D-7256-41EA-B825-9173BC1E278B")]
+  public class UniformSomePositionsManipulator : BoundedIntegerVectorManipulator {
+
+    public IValueLookupParameter<DoubleValue> ProbabilityParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["Probability"]; }
+    }
+
+    [StorableConstructor]
+    protected UniformSomePositionsManipulator(StorableConstructorFlag _) : base(_) { }
+    protected UniformSomePositionsManipulator(UniformSomePositionsManipulator original, Cloner cloner) : base(original, cloner) { }
+    public UniformSomePositionsManipulator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Probability", "The probability for each dimension to be manipulated.", new DoubleValue(0.5)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new UniformSomePositionsManipulator(this, cloner);
+    }
+
+    /// <summary>
+    /// Changes randomly several, but at least one, positions in the given integer <paramref name="vector"/>, according to the given probabilities.
+    /// </summary>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="vector">The integer vector to manipulate.</param>
+    /// <param name="bounds"> Contains the minimum value (inclusive), maximum value (exclusive), and step size of the sampling range for 
+    /// the vector element to change.</param>
+    /// <param name="probability">The probability for each dimension to be manipulated..</param>
+    public static void Apply(IRandom random, IntegerVector vector, IntMatrix bounds, double probability) {
+      if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) throw new ArgumentException("UniformSomePositionsManipulator: Invalid bounds specified", "bounds");
+      bool atLeastOneManipulated = false;
+      for (int index = 0; index < vector.Length; index++) {
+        if (random.NextDouble() < probability) {
+          atLeastOneManipulated = true;
+          UniformOnePositionManipulator.Manipulate(random, vector, bounds, index);
+        }
+      }
+
+      if (!atLeastOneManipulated) {
+        UniformOnePositionManipulator.Manipulate(random, vector, bounds, random.Next(vector.Length));
+      }
+    }
+
+    /// <summary>
+    /// Changes randomly several, but at least one, positions in the given integer <paramref name="vector"/>.
+    /// </summary>
+    /// <remarks>Calls <see cref="Apply"/>.</remarks>
+    /// <param name="random">A random number generator.</param>
+    /// <param name="vector">The integer vector to manipulate.</param>
+    protected override void ManipulateBounded(IRandom random, IntegerVector vector, IntMatrix bounds) {
+      Apply(random, vector, bounds, ProbabilityParameter.ActualValue.Value);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Plugin.cs.frame
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Plugin.cs.frame	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Plugin.cs.frame	(revision 17175)
@@ -0,0 +1,42 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.PluginInfrastructure;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Plugin class for HeuristicLab.Encodings.IntegerVectorEncoding plugin.
+  /// </summary>
+  [Plugin("HeuristicLab.Encodings.IntegerVectorEncoding", "3.3.15.$WCREV$")]
+  [PluginFile("HeuristicLab.Encodings.IntegerVectorEncoding-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Attic", "1.0")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+  public class HeuristicLabEncodingsIntegerVectorEncodingPlugin : PluginBase {
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Properties/AssemblyInfo.cs.frame	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/Properties/AssemblyInfo.cs.frame	(revision 17175)
@@ -0,0 +1,56 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Encodings.IntegerVectorEncoding")]
+[assembly: AssemblyDescription("HeuristicLab integer vector encoding and related operators")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("B0F88DF0-497D-4038-BCC4-065B278C5D2A")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.15.$WCREV$")]
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/ShakingOperators/IntegerVectorShakingOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/ShakingOperators/IntegerVectorShakingOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/ShakingOperators/IntegerVectorShakingOperator.cs	(revision 17175)
@@ -0,0 +1,99 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// A shaking operator for VNS.
+  /// </summary>
+  [Item("IntegerVectorShakingOperator", "A shaking operator for VNS which uses available manipulation operators to perform the shaking.")]
+  [StorableType("852155D8-B96F-4AAA-A9F9-5358F317C015")]
+  public class IntegerVectorShakingOperator : ShakingOperator<IIntegerVectorManipulator>, IIntegerVectorMultiNeighborhoodShakingOperator, IStochasticOperator, IBoundedIntegerVectorOperator {
+
+    public ILookupParameter<IntegerVector> IntegerVectorParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["IntegerVector"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueLookupParameter<IntMatrix> BoundsParameter {
+      get { return (IValueLookupParameter<IntMatrix>)Parameters["Bounds"]; }
+    }
+
+    [StorableConstructor]
+    protected IntegerVectorShakingOperator(StorableConstructorFlag _) : base(_) { }
+    protected IntegerVectorShakingOperator(IntegerVectorShakingOperator original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IntegerVectorShakingOperator(this, cloner);
+    }
+    public IntegerVectorShakingOperator()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("IntegerVector", "The integer vector to shake."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator that will be used for stochastic shaking operators."));
+      Parameters.Add(new ValueLookupParameter<IntMatrix>("Bounds", "A 2 column matrix specifying the lower and upper bound for each dimension. If there are less rows than dimension the bounds vector is cycled."));
+
+      foreach (IIntegerVectorManipulator shaker in ApplicationManager.Manager.GetInstances<IIntegerVectorManipulator>().OrderBy(x => x.Name))
+        if (!(shaker is ISelfAdaptiveManipulator)) Operators.Add(shaker);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("Bounds"))
+        Parameters.Add(new ValueLookupParameter<IntMatrix>("Bounds", "A 2 column matrix specifying the lower and upper bound for each dimension. If there are less rows than dimension the bounds vector is cycled."));
+      #endregion
+    }
+
+    #region Wiring of some parameters
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IIntegerVectorManipulator>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeOperators(e.Items);
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IIntegerVectorManipulator>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeOperators(e.Items);
+    }
+
+    private void ParameterizeOperators(IEnumerable<IndexedItem<IIntegerVectorManipulator>> items) {
+      if (items.Any()) {
+        foreach (IStochasticOperator op in items.Select(x => x.Value).OfType<IStochasticOperator>())
+          op.RandomParameter.ActualName = RandomParameter.Name;
+        foreach (IIntegerVectorManipulator op in items.Select(x => x.Value).OfType<IIntegerVectorManipulator>())
+          op.IntegerVectorParameter.ActualName = IntegerVectorParameter.Name;
+      }
+    }
+    #endregion
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/SimilarityCalculators/EuclideanSimilarityCalculator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/SimilarityCalculators/EuclideanSimilarityCalculator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/SimilarityCalculators/EuclideanSimilarityCalculator.cs	(revision 17175)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization.Operators;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [Item("Euclidean Similarity Calculator for IntegerVector", "Calculates the solution similarity based on the Euclidean distance and a transformation into (0;1] between two integer vectors.")]
+  [StorableType("479842EF-3426-4355-A064-7B235DC1D5E2")]
+  public sealed class EuclideanSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    protected override bool IsCommutative {
+      get { return true; }
+    }
+
+    [Storable]
+    private double scaling;
+    /// <summary>
+    /// The higher the scaling, the higher the similarity score for solutions of larger Euclidean distance.
+    /// A value of 1 means no scaling is applied. The function for squashing the numbers into (0;1] is
+    /// 1 / (1 + x / scaling) where x is the Euclidean distance.
+    /// </summary>
+    public double Scaling {
+      get { return scaling; }
+      set { scaling = value; }
+    }
+
+    [StorableConstructor]
+    private EuclideanSimilarityCalculator(StorableConstructorFlag _) : base(_) { }
+    private EuclideanSimilarityCalculator(EuclideanSimilarityCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      scaling = original.scaling;
+    }
+    public EuclideanSimilarityCalculator() {
+      scaling = 1;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new EuclideanSimilarityCalculator(this, cloner);
+    }
+
+    public static double CalculateSimilarity(IntegerVector left, IntegerVector right, double scaling = 1.0) {
+      if (left == null || right == null)
+        throw new ArgumentException("Cannot calculate similarity because one or both of the provided solutions is null.");
+      if (left.Length != right.Length)
+        throw new ArgumentException("Cannot calculate similarity because the provided solutions have different lengths.");
+      if (left.Length == 0)
+        throw new ArgumentException("Cannot calculate similarity because solutions are of length 0.");
+      if (scaling <= 0)
+        throw new ArgumentException("Cannot choose a 0 or negative scaling value.");
+      if (ReferenceEquals(left, right)) return 1.0;
+
+      var distance = 0.0;
+      for (int i = 0; i < left.Length; i++)
+        distance += (left[i] - right[i]) * (left[i] - right[i]);
+      return 1.0 / (1.0 + Math.Sqrt(distance) / scaling);
+
+    }
+
+    public override double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution) {
+      var left = leftSolution.Variables[SolutionVariableName].Value as IntegerVector;
+      var right = rightSolution.Variables[SolutionVariableName].Value as IntegerVector;
+
+      return CalculateSimilarity(left, right, Scaling);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/SimilarityCalculators/HammingSimilarityCalculator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/SimilarityCalculators/HammingSimilarityCalculator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/SimilarityCalculators/HammingSimilarityCalculator.cs	(revision 17175)
@@ -0,0 +1,68 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization.Operators;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [Item("Hamming Similarity Calculator for IntegerVector", "Calculates the solution similarity based on the Hamming distance between two integer vectors.")]
+  [StorableType("3784C4BD-8834-4A90-900C-0340C7F7BB47")]
+  public sealed class HammingSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    protected override bool IsCommutative {
+      get { return true; }
+    }
+
+    [StorableConstructor]
+    private HammingSimilarityCalculator(StorableConstructorFlag _) : base(_) { }
+    private HammingSimilarityCalculator(HammingSimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
+    public HammingSimilarityCalculator() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new HammingSimilarityCalculator(this, cloner);
+    }
+
+    public static double CalculateSimilarity(IntegerVector left, IntegerVector right) {
+      if (left == null || right == null)
+        throw new ArgumentException("Cannot calculate similarity because one or both of the provided solutions is null.");
+      if (left.Length != right.Length)
+        throw new ArgumentException("Cannot calculate similarity because the provided solutions have different lengths.");
+      if (left.Length == 0)
+        throw new ArgumentException("Cannot calculate similarity because solutions are of length 0.");
+      if (ReferenceEquals(left, right)) return 1.0;
+
+      double similarity = 0.0;
+      for (int i = 0; i < left.Length; i++)
+        if (left[i] == right[i]) similarity++;
+      return similarity / left.Length;
+
+    }
+
+    public override double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution) {
+      var left = leftSolution.Variables[SolutionVariableName].Value as IntegerVector;
+      var right = rightSolution.Variables[SolutionVariableName].Value as IntegerVector;
+
+      return CalculateSimilarity(left, right);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/StrategyParameters/StdDevStrategyVectorCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/StrategyParameters/StdDevStrategyVectorCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/StrategyParameters/StdDevStrategyVectorCreator.cs	(revision 17175)
@@ -0,0 +1,78 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [Item("StdDevStrategyVectorCreator", "Creates the endogeneous strategy parameters.")]
+  [StorableType("3357CE2D-EC8C-4DD7-B51A-FA72D558EA91")]
+  public class StdDevStrategyVectorCreator : SingleSuccessorOperator, IStochasticOperator, IIntegerVectorStdDevStrategyParameterCreator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<DoubleArray> StrategyParameterParameter {
+      get { return (ILookupParameter<DoubleArray>)Parameters["StrategyParameter"]; }
+    }
+    public IValueLookupParameter<IntValue> LengthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["Length"]; }
+    }
+    public IValueLookupParameter<DoubleMatrix> BoundsParameter {
+      get { return (IValueLookupParameter<DoubleMatrix>)Parameters["Bounds"]; }
+    }
+
+    [StorableConstructor]
+    protected StdDevStrategyVectorCreator(StorableConstructorFlag _) : base(_) { }
+    protected StdDevStrategyVectorCreator(StdDevStrategyVectorCreator original, Cloner cloner) : base(original, cloner) { }
+    public StdDevStrategyVectorCreator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<DoubleArray>("StrategyParameter", "The crossed strategy parameter."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("Length", "The length of the vector."));
+      Parameters.Add(new ValueLookupParameter<DoubleMatrix>("Bounds", "A 2 column matrix specifying the lower and upper bound for each dimension. If there are less rows than dimension the bounds vector is cycled.", new DoubleMatrix(new double[,] { { 0, 5 } })));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StdDevStrategyVectorCreator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      StrategyParameterParameter.ActualValue = Randomize(RandomParameter.ActualValue, LengthParameter.ActualValue.Value, BoundsParameter.ActualValue);
+      return base.Apply();
+    }
+
+    private DoubleArray Randomize(IRandom random, int length, DoubleMatrix bounds) {
+      var result = new DoubleArray(length);
+      for (int i = 0; i < length; i++) {
+        result[i] = random.NextDouble() * bounds[i % bounds.Rows, 1] - bounds[i % bounds.Rows, 0];
+      }
+      return result;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/StrategyParameters/StdDevStrategyVectorCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/StrategyParameters/StdDevStrategyVectorCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/StrategyParameters/StdDevStrategyVectorCrossover.cs	(revision 17175)
@@ -0,0 +1,79 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  [Item("StdDevStrategyVectorCrossover", "Crosses the strategy vector by using intermediate recombination (average crossover).")]
+  [StorableType("27583F67-4C80-4059-B4F9-80587C0DFB13")]
+  public class StdDevStrategyVectorCrossover : SingleSuccessorOperator, IStochasticOperator, IIntegerVectorStdDevStrategyParameterCrossover {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<ItemArray<DoubleArray>> ParentsParameter {
+      get { return (ILookupParameter<ItemArray<DoubleArray>>)Parameters["ParentStrategyParameter"]; }
+    }
+    public ILookupParameter<DoubleArray> StrategyParameterParameter {
+      get { return (ILookupParameter<DoubleArray>)Parameters["StrategyParameter"]; }
+    }
+
+    [StorableConstructor]
+    protected StdDevStrategyVectorCrossover(StorableConstructorFlag _) : base(_) { }
+    protected StdDevStrategyVectorCrossover(StdDevStrategyVectorCrossover original, Cloner cloner) : base(original, cloner) { }
+    public StdDevStrategyVectorCrossover()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>("ParentStrategyParameter", "The strategy parameters to cross."));
+      Parameters.Add(new LookupParameter<DoubleArray>("StrategyParameter", "The crossed strategy parameter."));
+      ParentsParameter.ActualName = "StrategyParameter";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StdDevStrategyVectorCrossover(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      StrategyParameterParameter.ActualValue = Average(RandomParameter.ActualValue, ParentsParameter.ActualValue);
+      return base.Apply();
+    }
+
+    private DoubleArray Average(IRandom random, ItemArray<DoubleArray> parents) {
+      int length = parents[0].Length;
+      var result = new DoubleArray(length);
+      for (int i = 0; i < length; i++) {
+        for (int p = 0; p < parents.Length; p++) {
+          result[i] += parents[p][i];
+        }
+        result[i] /= parents.Length;
+      }
+      return result;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/StrategyParameters/StdDevStrategyVectorManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/StrategyParameters/StdDevStrategyVectorManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Encodings.IntegerVectorEncoding/3.3/StrategyParameters/StdDevStrategyVectorManipulator.cs	(revision 17175)
@@ -0,0 +1,113 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Encodings.IntegerVectorEncoding {
+  /// <summary>
+  /// Mutates the endogenous strategy parameters.
+  /// </summary>
+  [Item("StdDevStrategyVectorManipulator", "Mutates the endogenous strategy parameters.")]
+  [StorableType("8DEED222-E816-4B80-B3F9-0A799EC40C4E")]
+  public class StdDevStrategyVectorManipulator : SingleSuccessorOperator, IStochasticOperator, IIntegerVectorStdDevStrategyParameterManipulator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<DoubleArray> StrategyParameterParameter {
+      get { return (ILookupParameter<DoubleArray>)Parameters["StrategyParameter"]; }
+    }
+    public IValueLookupParameter<DoubleValue> GeneralLearningRateParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["GeneralLearningRate"]; }
+    }
+    public IValueLookupParameter<DoubleValue> LearningRateParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["LearningRate"]; }
+    }
+    public IValueLookupParameter<DoubleMatrix> BoundsParameter {
+      get { return (IValueLookupParameter<DoubleMatrix>)Parameters["Bounds"]; }
+    }
+
+    [StorableConstructor]
+    protected StdDevStrategyVectorManipulator(StorableConstructorFlag _) : base(_) { }
+    protected StdDevStrategyVectorManipulator(StdDevStrategyVectorManipulator original, Cloner cloner) : base(original, cloner) { }
+    public StdDevStrategyVectorManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<DoubleArray>("StrategyParameter", "The strategy parameter to manipulate."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("GeneralLearningRate", "The general learning rate (tau0)."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("LearningRate", "The learning rate (tau)."));
+      Parameters.Add(new ValueLookupParameter<DoubleMatrix>("Bounds", "A 2 column matrix specifying the lower and upper bound for each dimension. If there are less rows than dimension the bounds vector is cycled.", new DoubleMatrix(new double[,] { { 0, 5 } })));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StdDevStrategyVectorManipulator(this, cloner);
+    }
+
+    /// <summary>
+    /// Mutates the endogenous strategy parameters.
+    /// </summary>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="vector">The strategy vector to manipulate.</param>
+    /// <param name="generalLearningRate">The general learning rate dampens the mutation over all dimensions.</param>
+    /// <param name="learningRate">The learning rate dampens the mutation in each dimension.</param>
+    /// <param name="bounds">The minimal and maximal value for each component, bounds are cycled if the length of bounds is smaller than the length of vector</param>
+    public static void Apply(IRandom random, DoubleArray vector, double generalLearningRate, double learningRate, DoubleMatrix bounds) {
+      NormalDistributedRandom N = new NormalDistributedRandom(random, 0.0, 1.0);
+      double generalMultiplier = Math.Exp(generalLearningRate * N.NextDouble());
+      for (int i = 0; i < vector.Length; i++) {
+        double change = vector[i] * generalMultiplier * Math.Exp(learningRate * N.NextDouble());
+        if (bounds != null) {
+          double min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1];
+          if (min == max) vector[i] = min;
+          else {
+            if (change < min || change > max) change = Math.Max(min, Math.Min(max, change));
+            vector[i] = change;
+          }
+        }
+      }
+    }
+    /// <summary>
+    /// Mutates the endogenous strategy parameters.
+    /// </summary>
+    /// <remarks>Calls <see cref="OperatorBase.Apply"/> of base class <see cref="OperatorBase"/>.</remarks>
+    /// <inheritdoc select="returns"/>
+    public override IOperation Apply() {
+      var strategyParams = StrategyParameterParameter.ActualValue;
+      if (strategyParams != null) { // only apply if there is a strategy vector
+        IRandom random = RandomParameter.ActualValue;
+        double tau0 = GeneralLearningRateParameter.ActualValue.Value;
+        double tau = LearningRateParameter.ActualValue.Value;
+        Apply(random, strategyParams, tau0, tau, BoundsParameter.ActualValue);
+      }
+      return base.Apply();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.OptimizationExpertSystem.Common/3.3/HeuristicLab.OptimizationExpertSystem.Common-3.3.csproj
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.OptimizationExpertSystem.Common/3.3/HeuristicLab.OptimizationExpertSystem.Common-3.3.csproj	(revision 16958)
+++ branches/2457_ExpertSystem/HeuristicLab.OptimizationExpertSystem.Common/3.3/HeuristicLab.OptimizationExpertSystem.Common-3.3.csproj	(revision 17175)
@@ -151,4 +151,5 @@
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
+    <Reference Include="System.IO.Compression" />
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Xml.Linq" />
Index: branches/2457_ExpertSystem/HeuristicLab.OptimizationExpertSystem.Common/3.3/KnowledgeCenter.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.OptimizationExpertSystem.Common/3.3/KnowledgeCenter.cs	(revision 16958)
+++ branches/2457_ExpertSystem/HeuristicLab.OptimizationExpertSystem.Common/3.3/KnowledgeCenter.cs	(revision 17175)
@@ -24,7 +24,9 @@
 using System.Drawing;
 using System.IO;
+using System.IO.Compression;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
+using HEAL.Attic;
 using HeuristicLab.Algorithms.DataAnalysis;
 using HeuristicLab.Analysis;
@@ -296,5 +298,5 @@
 
     private static readonly HashSet<string> InterestingValueNames = new HashSet<string>() {
-      "QualityPerEvaluations", "Problem Name", "Problem Type", "Algorithm Name", "Algorithm Type", "Maximization", "BestKnownQuality"
+      "QualityPerEvaluations", "QualityPerClock", "Problem Name", "Problem Type", "Algorithm Name", "Algorithm Type", "Maximization", "BestKnownQuality"
     };
 
@@ -517,10 +519,21 @@
 
           IItem bkParam;
-          if (!prob.Parameters.TryGetValue("BestKnownQuality", out bkParam) || !(bkParam is DoubleValue)) {
-            var list = kvp.Value.SelectMany(x => x.Value)
-              .Where(x => x.Results.ContainsKey("QualityPerEvaluations"))
-              .Select(x => ((IndexedDataTable<double>)x.Results["QualityPerEvaluations"]).Rows.First().Values.Last().Item2);
-            if (!list.Any()) continue;
-            bkParam = new DoubleValue(maximization ? list.Max() : list.Min());
+          if (!prob.Parameters.TryGetValue("BestKnownQuality", out bkParam) || !(bkParam is DoubleValue) || double.IsNaN(((DoubleValue)bkParam).Value)) {
+            var best = double.NaN;
+            foreach (var x in kvp.Value.SelectMany(x => x.Value)) {
+              double? lastVal = null;
+              if (x.Results.TryGetValue("QualityPerEvaluations", out var item)) {
+                lastVal = ((IndexedDataTable<double>)item).Rows.FirstOrDefault()?.Values.LastOrDefault()?.Item2;
+              }
+              if (x.Results.TryGetValue("QualityPerClock", out item)) {
+                lastVal = ((IndexedDataTable<double>)item).Rows.FirstOrDefault()?.Values.LastOrDefault()?.Item2;
+              }
+              if (lastVal.HasValue && (double.IsNaN(best)
+                || maximization && best < lastVal.Value
+                || !maximization && best > lastVal.Value))
+                best = lastVal.Value;
+            }
+            if (double.IsNaN(best)) continue;
+            bkParam = new DoubleValue(best);
             prob.Parameters["BestKnownQuality"] = bkParam;
           }
@@ -600,36 +613,40 @@
       var total = hashSet.Count;
       try {
-        var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "HeuristicLab.OKB", "cache", "runs");
-        Parallel.ForEach(Directory.EnumerateDirectories(path).Select((d, i) => new { Index = i, Directory = d }).GroupBy(x => x.Index / 100), new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount },
-          (folderGroup) => {
-          var localRunList = new List<Tuple<long, long, IRun>>();
-          foreach (var runPath in folderGroup.Select(x => x.Directory)) {
-            long runId;
-            var runFolder = new DirectoryInfo(runPath).Name;
-            if (!long.TryParse(runFolder, out runId) || !hashSet.Contains(runId)) continue;
-            var runFilePath = Directory.EnumerateFiles(runPath).Single();
-            var runFileName = Path.GetFileNameWithoutExtension(runFilePath);
-            long algId;
-            if (!long.TryParse(runFileName, out algId)) continue;
-            IRun run = null;
-            try {
-              using (var file = File.OpenRead(runFilePath))
-                run = XmlParser.Deserialize<IRun>(file);
-            } catch {
-              File.Delete(runFilePath);
-              Directory.Delete(runPath);
-            }
-            if (run != null) localRunList.Add(Tuple.Create(algId, runId, run));
-          }
-          lock (runList) {
-            foreach (var r in localRunList) {
-              hashSet.Remove(r.Item2);
-              algorithmId2RunMapping.Add(r.Item1, r.Item3);
-              runList.Add(r.Item3);
-            }
-            progress.Message = string.Format("Retrieved {0} of {1} from cache", runList.Count, total);
-            progress.ProgressValue = (double)runList.Count / total;
-          }
-        });
+        var updateCount = 0;
+        var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "HeuristicLab.OKB", "cache", "runsperalg");
+        Parallel.ForEach(Directory.EnumerateFiles(path), new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount },
+          (algPath) => {
+            var serializer = new ProtoBufSerializer();
+            var algId = long.Parse(Path.GetFileName(algPath));
+            using (var stream = File.Open(algPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) {
+              using (var archive = new ZipArchive(stream, ZipArchiveMode.Read)) {
+                foreach (var entry in archive.Entries) {
+                  var runId = long.Parse(entry.Name);
+                  var useEntry = false;
+                  lock (hashSet) {
+                    useEntry = hashSet.Remove(runId);
+                  }
+                  if (useEntry) {
+                    //using (var df = new DeflateStream(entry.Open(), CompressionMode.Decompress)) {
+                      var run = (Tuple<long, long, IRun>)serializer.Deserialize(entry.Open());
+                      if (run.Item1 != algId || run.Item2 != runId) {
+                        lock (hashSet) hashSet.Add(runId);
+                        continue;
+                      }
+                      lock (runList) {
+                        algorithmId2RunMapping.Add(algId, run.Item3);
+                        runList.Add(run.Item3);
+                        updateCount++;
+                        if (total < 100 || updateCount % (total / 100) == 0) {
+                          progress.Message = string.Format("Retrieved {0} of {1} from cache", updateCount, total);
+                          progress.ProgressValue = (double)runList.Count / total;
+                        }
+                      }
+                    //}
+                  }
+                }
+              }
+            }
+          });
       } catch { }
       return hashSet.ToList();
@@ -638,11 +655,18 @@
     private void SaveToCache(IEnumerable<Tuple<long, long, IRun>> runs) {
       try {
-        var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "HeuristicLab.OKB", "cache", "runs");
+        var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "HeuristicLab.OKB", "cache", "runsperalg");
         if (!Directory.Exists(path)) Directory.CreateDirectory(path);
-        foreach (var r in runs) {
-          var runPath = Path.Combine(path, r.Item2.ToString());
-          if (!Directory.Exists(runPath)) Directory.CreateDirectory(runPath);
-          using (var file = File.Open(Path.Combine(runPath, r.Item1.ToString()), FileMode.Create, FileAccess.ReadWrite)) {
-            XmlGenerator.Serialize(r.Item3, file);
+        var serializer = new ProtoBufSerializer();
+        foreach (var runsOfAlg in runs.GroupBy(x => x.Item1)) {
+          var runPath = Path.Combine(path, runsOfAlg.Key.ToString());
+          using (var stream = File.Open(runPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) {
+            using (var archive = new ZipArchive(stream, ZipArchiveMode.Update)) {
+              foreach (var run in runsOfAlg) {
+                var entry = archive.CreateEntry(run.Item2.ToString(), CompressionLevel.NoCompression);
+                using (var entrystream = entry.Open()) {
+                  serializer.Serialize(run, entrystream, disposeStream: false);
+                }
+              }
+            }
           }
         }
@@ -764,6 +788,19 @@
       var target = GetTarget(((DoubleValue)problemInstance.Parameters["BestKnownQuality"]).Value, MinimumTarget.Value, Maximization);
       return knowledgeBase.Where(x => ((StringValue)x.Parameters["Problem Name"]).Value == ((StringValue)problemInstance.Parameters["Problem Name"]).Value)
-                          .GroupBy(x => algorithmId2AlgorithmInstanceMapping.GetByFirst(algorithmId2RunMapping.GetBySecond(x).Single()))
-                          .ToDictionary(x => x.Key, x => ExpectedRuntimeHelper.CalculateErt(x.ToList(), "QualityPerEvaluations", target, Maximization).ExpectedRuntime);
+                          .Select(x => {
+                            IItem item = null;
+                            if (x.Results.TryGetValue("QualityPerEvaluations", out item)) {
+                              var idt = (IndexedDataTable<double>)item;
+                              return Tuple.Create(x, idt.Rows.First().Values.AsEnumerable());
+                            }
+                            if (x.Results.TryGetValue("QualityPerClock", out item)) {
+                              var idt = (IndexedDataTable<double>)item;
+                              return Tuple.Create(x, idt.Rows.First().Values.AsEnumerable());
+                            }
+                            return null;
+                          })
+                          .Where(x => x != null)
+                          .GroupBy(x => algorithmId2AlgorithmInstanceMapping.GetByFirst(algorithmId2RunMapping.GetBySecond(x.Item1).Single()))
+                          .ToDictionary(x => x.Key, x => ExpectedRuntimeHelper.CalculateErt(x.Select(y => y.Item2), target, Maximization).ExpectedRuntime);
     }
 
@@ -772,6 +809,19 @@
       var target = GetTarget(((DoubleValue)problemInstance.Parameters["BestKnownQuality"]).Value, MinimumTarget.Value, Maximization);
       return knowledgeBase.Where(x => ((StringValue)x.Parameters["Problem Name"]).Value == ((StringValue)problemInstance.Parameters["Problem Name"]).Value)
-                          .GroupBy(x => algorithmId2AlgorithmInstanceMapping.GetByFirst(algorithmId2RunMapping.GetBySecond(x).Single()))
-                          .ToDictionary(x => x.Key, x => Math.Log10(ExpectedRuntimeHelper.CalculateErt(x.ToList(), "QualityPerEvaluations", target, Maximization).ExpectedRuntime));
+                          .Select(x => {
+                            IItem item = null;
+                            if (x.Results.TryGetValue("QualityPerEvaluations", out item)) {
+                              var idt = (IndexedDataTable<double>)item;
+                              return Tuple.Create(x, idt.Rows.First().Values.AsEnumerable());
+                            }
+                            if (x.Results.TryGetValue("QualityPerClock", out item)) {
+                              var idt = (IndexedDataTable<double>)item;
+                              return Tuple.Create(x, idt.Rows.First().Values.AsEnumerable());
+                            }
+                            return null;
+                          })
+                          .Where(x => x != null)
+                          .GroupBy(x => algorithmId2AlgorithmInstanceMapping.GetByFirst(algorithmId2RunMapping.GetBySecond(x.Item1).Single()))
+                          .ToDictionary(x => x.Key, x => Math.Log10(ExpectedRuntimeHelper.CalculateErt(x.Select(y => y.Item2), target, Maximization).ExpectedRuntime));
     }
 
@@ -871,6 +921,19 @@
         result[problemMap[pr.Key]] = new Dictionary<long, int>();
 
-        var values = pr.GroupBy(x => algorithmId2RunMapping.GetBySecond(x).Single())
-                       .ToDictionary(x => x.Key, x => Math.Log10(ExpectedRuntimeHelper.CalculateErt(x.ToList(), "QualityPerEvaluations", GetTarget(bkq, target, max), max).ExpectedRuntime));
+        var values = pr.Select(x => {
+                          IItem item = null;
+                          if (x.Results.TryGetValue("QualityPerEvaluations", out item)) {
+                            var idt = (IndexedDataTable<double>)item;
+                            return Tuple.Create(x, idt.Rows.First().Values.AsEnumerable());
+                          }
+                          if (x.Results.TryGetValue("QualityPerClock", out item)) {
+                            var idt = (IndexedDataTable<double>)item;
+                            return Tuple.Create(x, idt.Rows.First().Values.AsEnumerable());
+                          }
+                          return null;
+                        })
+                       .Where(x => x != null)
+                       .GroupBy(x => algorithmId2RunMapping.GetBySecond(x.Item1).Single())
+                       .ToDictionary(x => x.Key, x => Math.Log10(ExpectedRuntimeHelper.CalculateErt(x.Select(y => y.Item2), GetTarget(bkq, target, max), max).ExpectedRuntime));
         var ranks = ClusteringHelper<long>.Cluster(nClasses, values, x => double.IsInfinity(x.Value))
           .GetByCluster().ToList();
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/CplexContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/CplexContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/CplexContext.cs	(revision 17175)
@@ -0,0 +1,46 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.CPLEX {
+  [Item("CPLEX Context", "A context for CPLEX solvers.")]
+  [StorableType("9A91A380-A6C3-4294-80D7-163AA13D600B")]
+  public class CplexContext : SingleSolutionContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+    
+    [StorableConstructor]
+    protected CplexContext(StorableConstructorFlag _) : base(_) { }
+    protected CplexContext(CplexContext original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public CplexContext() : base() { }
+    public CplexContext(string name) : base(name) { }
+    public CplexContext(string name, ParameterCollection parameters) : base(name, parameters) { }
+    public CplexContext(string name, string description) : base(name, description) { }
+    public CplexContext(string name, string description, ParameterCollection parameters) : base(name, description, parameters) { }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CplexContext(this, cloner);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/CplexSolver.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/CplexSolver.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/CplexSolver.cs	(revision 17175)
@@ -0,0 +1,123 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using ILOG.CPLEX;
+using ILOG.OPL;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.CPLEX {
+  [Item("CPLEX Solver (GQAP)", "Base class")]
+  [StorableType("09AC71C5-20C7-4AC0-9E5A-405BA5075552")]
+  public abstract class CplexSolver : ContextAlgorithm<CplexContext, IntegerVectorEncoding> {
+    public override bool SupportsPause {
+      get { return false; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [StorableConstructor]
+    protected CplexSolver(StorableConstructorFlag _) : base(_) { }
+    protected CplexSolver(CplexSolver original, Cloner cloner)
+    : base(original, cloner) {
+    }
+    public CplexSolver() {
+      Problem = new GQAP();
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      var factory = new OplFactory();
+      var cplex = factory.CreateCplex();
+      cplex.Use(new LogCallback(this, cancellationToken));
+      cplex.SetParam(Cplex.DoubleParam.TiLim, MaximumRuntime.TotalSeconds);
+      cplex.SetParam(Cplex.IntParam.Threads, 1);
+      var dataSource = new GQAPDataSource(factory, Problem.ProblemInstance);
+      using (var settings = factory.CreateOplSettings(factory.CreateOplErrorHandler()))
+      using (var opl = GetModel(factory, settings, cplex)) {
+        opl.AddDataSource(dataSource);
+        opl.Generate();
+        if (cplex.Solve()) {
+          var obj = cplex.ObjValue;
+          if (double.IsNaN(Context.BestQuality) || obj < Context.BestQuality)
+            Context.BestQuality = obj;
+          IResult result;
+          if (Results.TryGetValue("BestQuality", out result))
+            ((DoubleValue)result.Value).Value = Context.BestQuality;
+          else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+
+          Context.RunOperator(Analyzer, CancellationToken.None);
+        }
+        cplex.End();
+      }
+      Context.RunOperator(Analyzer, CancellationToken.None);
+    }
+
+    protected abstract OplModel GetModel(OplFactory factory, OplSettings settings, Cplex cplex);
+  }
+
+  public class LogCallback : Cplex.MIPInfoCallback {
+    private CplexSolver algorithm;
+    private CancellationToken token;
+    private double prev;
+
+
+    public LogCallback(CplexSolver algorithm, CancellationToken token) {
+      this.algorithm = algorithm;
+      this.token = token;
+      prev = double.NaN;
+    }
+
+    protected override void Main() {
+      if (HasIncumbent()) {
+        var val = GetIncumbentObjValue();
+        if (val >= prev) return;
+        algorithm.Context.Iterations++;
+        algorithm.Context.BestQuality = val;
+        IResult result;
+        if (algorithm.Results.TryGetValue("Iterations", out result))
+          ((IntValue)result.Value).Value = algorithm.Context.Iterations;
+        else algorithm.Results.Add(new Result("Iterations", new IntValue(algorithm.Context.Iterations)));
+        if (algorithm.Results.TryGetValue("BestQuality", out result))
+          ((DoubleValue)result.Value).Value = algorithm.Context.BestQuality;
+        else algorithm.Results.Add(new Result("BestQuality", new DoubleValue(algorithm.Context.BestQuality)));
+        algorithm.Context.RunOperator(algorithm.Analyzer, CancellationToken.None);
+        prev = val;
+        if (val.IsAlmost(algorithm.Problem.BestKnownQuality))
+          Abort();
+      }
+      if (token.IsCancellationRequested) Abort();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/GQAP-FY.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/GQAP-FY.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/GQAP-FY.cs	(revision 17175)
@@ -0,0 +1,101 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using ILOG.CPLEX;
+using ILOG.OPL;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.CPLEX {
+  [Item("FY-Linearization CPLEX (GQAP)", "")]
+  [StorableType("C10D185E-B007-4C9F-9EFC-6EE1D44A3DE1")]
+  [Creatable(CreatableAttribute.Categories.Algorithms)]
+  public sealed class GQAP_FY : CplexSolver {
+    
+    [StorableConstructor]
+    private GQAP_FY(StorableConstructorFlag _) : base(_) { }
+    private GQAP_FY(GQAP_FY original, Cloner cloner)
+    : base(original, cloner) {
+    }
+    public GQAP_FY() {
+
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAP_FY(this, cloner);
+    }
+
+    protected override OplModel GetModel(OplFactory factory, OplSettings settings, Cplex cplex) {
+      using (var modelSource = factory.CreateOplModelSourceFromString(model, "gqap_fy"))
+      using (var def = factory.CreateOplModelDefinition(modelSource, settings))
+        return factory.CreateOplModel(def, cplex);
+    }
+
+    private const string model = @"/*********************************************
+ * OPL 12.7.0.0 Model
+ * Author: Andreas Beham
+ * Creation Date: 31.10.2017 at 14:30:01
+ *********************************************/
+
+int EQUIPMENTS = ...;
+int LOCATIONS = ...;
+float TC = ...;
+
+range N = 1..EQUIPMENTS;
+range M = 1..LOCATIONS;
+
+float weights[N][N] = ...;
+float distances[M][M] = ...;
+float install[N][M] = ...;
+float demands[N] = ...;
+float capacities[M] = ...;
+
+dvar int+ x[N][M] in 0..1;
+dvar float+ z[N][M][N][M] in 0..1;
+
+dexpr float installCosts = sum(i in N, k in M) x[i][k] * install[i][k];
+dexpr float flowCosts = TC * sum(i in 1..EQUIPMENTS-1, k in M, j in N, h in M: j > i)
+  (weights[i][j] * distances[k][h] + weights[j][i] * distances[h][k]) * z[i][k][j][h];
+
+minimize installCosts + flowCosts;
+  
+subject to {
+
+forall (i in N)
+  AllAssigned:
+  sum(k in M) x[i][k] == 1;
+
+forall (k in M)
+  Capacity:
+  sum(i in N) x[i][k] * demands[i] <= capacities[k];
+
+forall (i in 1..EQUIPMENTS-1, k in M, j in N: j > i)
+  sum(h in M) z[i][k][j][h] == x[i][k];
+
+forall (i in 1..EQUIPMENTS-1, j in N, h in M: j > i)
+  sum(k in M) z[i][k][j][h] == x[j][h];
+ 
+}
+
+";
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/GQAP-KB.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/GQAP-KB.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/GQAP-KB.cs	(revision 17175)
@@ -0,0 +1,99 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using ILOG.CPLEX;
+using ILOG.OPL;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.CPLEX {
+  [Item("KB-Linearization CPLEX (GQAP)", "")]
+  [StorableType("649D3DB6-3E54-46E7-BB12-5F26417D6E40")]
+  [Creatable(CreatableAttribute.Categories.Algorithms)]
+  public sealed class GQAP_KB : CplexSolver {
+    
+    [StorableConstructor]
+    private GQAP_KB(StorableConstructorFlag _) : base(_) { }
+    private GQAP_KB(GQAP_KB original, Cloner cloner)
+    : base(original, cloner) {
+    }
+    public GQAP_KB() {
+
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAP_KB(this, cloner);
+    }
+
+    protected override OplModel GetModel(OplFactory factory, OplSettings settings, Cplex cplex) {
+      using (var modelSource = factory.CreateOplModelSourceFromString(model, "gqap_kb"))
+      using (var def = factory.CreateOplModelDefinition(modelSource, settings))
+        return factory.CreateOplModel(def, cplex);
+    }
+
+    private const string model = @"/*********************************************
+ * OPL 12.7.0.0 Model
+ * Author: Andreas Beham
+ * Creation Date: 31.10.2017 at 14:30:01
+ *********************************************/
+
+int EQUIPMENTS = ...;
+int LOCATIONS = ...;
+float TC = ...;
+
+range N = 1..EQUIPMENTS;
+range M = 1..LOCATIONS;
+
+float weights[N][N] = ...;
+float distances[M][M] = ...;
+float install[N][M] = ...;
+float demands[N] = ...;
+float capacities[M] = ...;
+
+float v[i in N][k in M] = sum(j in N, h in M) (weights[i][j] * distances[k][h]);
+
+dvar int+ x[N][M] in 0..1;
+dvar float+ y[N][M];
+
+dexpr float installCosts = sum(i in N, k in M) x[i][k] * install[i][k];
+dexpr float flowCosts = TC * sum(i in N, k in M) y[i][k];
+
+minimize installCosts + flowCosts;
+  
+subject to {
+
+forall (i in N)
+  AllAssigned:
+  sum(k in M) x[i][k] == 1;
+
+forall (k in M)
+  Capacity:
+  sum(i in N) x[i][k] * demands[i] <= capacities[k];
+
+forall (i in N, k in M)
+  v[i][k] * ( x[i][k] - 1 ) + sum(j in N, h in M) (x[j][h] * weights[i][j] * distances[k][h]) <= y[i][k];
+
+}
+
+";
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/GQAPDataSource.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/GQAPDataSource.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/CPLEX/GQAPDataSource.cs	(revision 17175)
@@ -0,0 +1,78 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HeuristicLab.Data;
+using ILOG.OPL;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.CPLEX {
+  public class GQAPDataSource : CustomOplDataSource {
+    protected GQAPInstance Instance { get; set; }
+
+    public GQAPDataSource(OplFactory factory, GQAPInstance instance)
+      : base(factory) {
+      Instance = instance;
+    }
+
+    public override void CustomRead() {
+      NewElement("EQUIPMENTS", () => Add(Instance.Demands.Length));
+      NewElement("LOCATIONS", () => Add(Instance.Capacities.Length));
+      NewElement("TC", () => Add(Instance.TransportationCosts));
+      NewElement("weights", () => Add(Instance.Weights));
+      NewElement("distances", () => Add(Instance.Distances));
+      NewElement("install", () => Add(Instance.InstallationCosts));
+      NewElement("demands", () => Add(Instance.Demands));
+      NewElement("capacities", () => Add(Instance.Capacities));
+    }
+
+    protected void NewElement(string name, Action add) {
+      DataHandler.StartElement(name);
+      add();
+      DataHandler.EndElement();
+    }
+    protected void Add(int value) {
+      DataHandler.AddIntItem(value);
+    }
+    protected void Add(double value) {
+      DataHandler.AddNumItem(value);
+    }
+
+    protected void Add(DoubleArray values) {
+      DataHandler.StartArray();
+      for (var i = 0; i < values.Length; i++) {
+        Add(values[i]);
+      }
+      DataHandler.EndArray();
+    }
+
+    protected void Add(DoubleMatrix values) {
+      DataHandler.StartArray();
+      for (var i = 0; i < values.Rows; i++) {
+        DataHandler.StartArray();
+        for (var j = 0; j < values.Columns; j++) {
+          Add(values[i, j]);
+        }
+        DataHandler.EndArray();
+      }
+      DataHandler.EndArray();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESContext.cs	(revision 17175)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.Evolutionary {
+  [Item("Evolution Strategy (GQAP) Context", "Context for Evolution Strategies (GQAP).")]
+  [StorableType("8A811131-337D-4CF6-A938-FFA08BF50B40")]
+  public sealed class ESContext : PopulationContext<ISingleObjectiveSolutionScope<ESGQAPSolution>> {
+    
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<ESGQAPSolution> bestSolution;
+    public ESGQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IRandom> normalRand;
+    public IRandom NormalRand {
+      get { return normalRand.Value; }
+      set { normalRand.Value = value; }
+    }
+    
+    [StorableConstructor]
+    private ESContext(StorableConstructorFlag _) : base(_) { }
+    private ESContext(ESContext original, Cloner cloner)
+      : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+      normalRand = cloner.Clone(original.normalRand);
+    }
+    public ESContext() : this("Evolution Strategy (GQAP) Context") { }
+    public ESContext(string name) : base(name) {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<ESGQAPSolution>("BestFoundSolution"));
+      Parameters.Add(normalRand = new ValueParameter<IRandom>("NormalRand"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ESContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<ESGQAPSolution> ToScope(ESGQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<ESGQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      scope.Variables.Add(new Variable("StrategyParameter", code.sParam));
+      return scope;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESGQAPSolution.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESGQAPSolution.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESGQAPSolution.cs	(revision 17175)
@@ -0,0 +1,59 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.Evolutionary {
+  [Item("ES-specific GQAP Solution", "GQAP Solution that holds a strategy parameter")]
+  [StorableType("00A9856C-5E25-4F12-B3B0-6A9FF855B8A9")]
+  public class ESGQAPSolution : GQAPSolution {
+
+    [Storable]
+    internal DoubleValue sParam;
+    public double SParam {
+      get { return sParam.Value; }
+      set {
+        if (sParam.Value == value) return;
+        sParam.Value = value;
+        OnPropertyChanged(nameof(SParam));
+      }
+    }
+
+    [StorableConstructor]
+    protected ESGQAPSolution(StorableConstructorFlag _) : base(_) { }
+    protected ESGQAPSolution(ESGQAPSolution original, Cloner cloner)
+    : base(original, cloner) {
+      sParam = cloner.Clone(original.sParam);
+    }
+    public ESGQAPSolution(IntegerVector assignment, Evaluation eval, double sParam)
+      : base(assignment, eval) {
+      this.sParam = new DoubleValue(sParam);
+    }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ESGQAPSolution(this, cloner);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/EvolutionStrategy.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/EvolutionStrategy.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/EvolutionStrategy.cs	(revision 17175)
@@ -0,0 +1,227 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.Evolutionary {
+  [StorableType("d568d524-1f84-461c-adf5-573d8e472063")]
+  public enum ESSelection { Plus = 0, Comma = 1 }
+
+  [Item("Evolution Strategy (GQAP)", "The algorithm implements a simple evolution strategy (ES).")]
+  [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms)]
+  [StorableType("A1590185-F2E3-4163-896E-28EEC93A5CDF")]
+  public sealed class EvolutionStrategy : StochasticAlgorithm<ESContext, IntegerVectorEncoding> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [Storable]
+    private FixedValueParameter<IntValue> lambdaParameter;
+    private IFixedValueParameter<IntValue> LambdaParameter {
+      get { return lambdaParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> muParameter;
+    public IFixedValueParameter<IntValue> MuParameter {
+      get { return muParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<EnumValue<ESSelection>> selectionParameter;
+    public IFixedValueParameter<EnumValue<ESSelection>> SelectionParameter {
+      get { return selectionParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<BoolValue> useRecombinationParameter;
+    public IFixedValueParameter<BoolValue> UseRecombinationParameter {
+      get { return useRecombinationParameter; }
+    }
+
+    public int Lambda {
+      get { return lambdaParameter.Value.Value; }
+      set { lambdaParameter.Value.Value = value; }
+    }
+    public int Mu {
+      get { return muParameter.Value.Value; }
+      set { muParameter.Value.Value = value; }
+    }
+    public ESSelection Selection {
+      get { return selectionParameter.Value.Value; }
+      set { selectionParameter.Value.Value = value; }
+    }
+    public bool UseRecombination {
+      get { return useRecombinationParameter.Value.Value; }
+      set { useRecombinationParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private EvolutionStrategy(StorableConstructorFlag _) : base(_) { }
+    private EvolutionStrategy(EvolutionStrategy original, Cloner cloner)
+      : base(original, cloner) {
+      lambdaParameter = cloner.Clone(original.lambdaParameter);
+      muParameter = cloner.Clone(original.muParameter);
+      selectionParameter = cloner.Clone(original.selectionParameter);
+      useRecombinationParameter = cloner.Clone(original.useRecombinationParameter);
+    }
+    public EvolutionStrategy() {
+      Parameters.Add(lambdaParameter = new FixedValueParameter<IntValue>("Lambda", "(λ) The amount of offspring that are created each generation.", new IntValue(10)));
+      Parameters.Add(muParameter = new FixedValueParameter<IntValue>("Mu", "(μ) The population size.", new IntValue(1)));
+      Parameters.Add(selectionParameter= new FixedValueParameter<EnumValue<ESSelection>>("Selection", "The selection strategy: elitist (plus) or generational (comma).", new EnumValue<ESSelection>(ESSelection.Plus)));
+      Parameters.Add(useRecombinationParameter = new FixedValueParameter<BoolValue>("Use Recombination", "Whether to create an \"intermediate\" solution to perform the mutation from.", new BoolValue(false)));
+
+      Problem = new GQAP();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new EvolutionStrategy(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+
+      Context.NormalRand = new NormalDistributedRandom(Context.Random, 0, 1);
+      Context.Problem = Problem;
+      Context.BestSolution = null;
+      
+      for (var m = 0; m < Mu; m++) {
+        var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length);
+        var eval = Problem.ProblemInstance.Evaluate(assign);
+        Context.EvaluatedSolutions++;
+
+        var min = (1.0 / assign.Length) * 2 - 1; // desired min prob
+        var max = (4.0 / assign.Length) * 2 - 1; // desired max prob
+        min = 0.5 * (Math.Log(1 + min) - Math.Log(1 - min)); // arctanh
+        max = 0.5 * (Math.Log(1 + max) - Math.Log(1 - max));
+        var ind = new ESGQAPSolution(assign, eval, min + Context.Random.NextDouble() * (max - min));
+        var fit = Problem.ProblemInstance.ToSingleObjective(eval);
+        Context.AddToPopulation(Context.ToScope(ind, fit));
+        if (double.IsNaN(Context.BestQuality) || fit < Context.BestQuality) {
+          Context.BestQuality = fit;
+          Context.BestSolution = (ESGQAPSolution)ind.Clone();
+        }
+      }
+
+      Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+      Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+      Results.Add(new Result("BestSolution", Context.BestSolution));
+
+      Context.RunOperator(Analyzer, cancellationToken);
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      var lastUpdate = ExecutionTime;
+      var eq = new IntegerVectorEqualityComparer();
+
+      while (!StoppingCriterion()) {
+        var nextGen = new List<ISingleObjectiveSolutionScope<ESGQAPSolution>>(Lambda);
+
+        for (var l = 0; l < Lambda; l++) {
+          IntegerVector child = null;
+          var sParam = 0.0;
+          if (UseRecombination) {
+            child = DiscreteLocationCrossover.Apply(Context.Random, new ItemArray<IntegerVector>(Context.Population.Select(x => x.Solution.Assignment)), Problem.ProblemInstance.Demands, Problem.ProblemInstance.Capacities);
+            sParam = Context.Population.Select(x => x.Solution.SParam).Average();
+          } else {
+            var m = Context.AtRandomPopulation();
+            child = (IntegerVector)m.Solution.Assignment.Clone();
+            sParam = m.Solution.SParam;
+          }
+          sParam += 0.7071 * Context.NormalRand.NextDouble();
+          RelocateEquipmentManipluator.Apply(Context.Random, child,
+            Problem.ProblemInstance.Capacities.Length, (Math.Tanh(sParam) + 1) / 2.0);
+          var eval = Problem.ProblemInstance.Evaluate(child);
+          Context.EvaluatedSolutions++;
+
+          var offspring = new ESGQAPSolution(child, eval, sParam);
+
+          var fit = Problem.ProblemInstance.ToSingleObjective(offspring.Evaluation);
+          if (Selection == ESSelection.Comma || Context.Population.Select(x => x.Solution.Assignment).All(x => !eq.Equals(child, x)))
+            nextGen.Add(Context.ToScope(offspring, fit));
+
+          if (fit < Context.BestQuality) {
+            Context.BestQuality = fit;
+            Context.BestSolution = (ESGQAPSolution)offspring.Clone();
+          }
+        }
+
+        if (Selection == ESSelection.Comma) {
+          Context.ReplacePopulation(nextGen.OrderBy(x => x.Fitness).Take(Mu));
+        } else if (Selection == ESSelection.Plus) {
+          var best = Context.Population.Concat(nextGen).OrderBy(x => x.Fitness).Take(Mu).ToList();
+          Context.ReplacePopulation(best);
+        } else throw new InvalidOperationException("Unknown Selection strategy: " + Selection);
+
+        IResult result;
+        if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
+        if (Results.TryGetValue("BestQuality", out result))
+          ((DoubleValue)result.Value).Value = Context.BestQuality;
+        else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+        if (Results.TryGetValue("BestSolution", out result))
+          result.Value = Context.BestSolution;
+        else Results.Add(new Result("BestSolution", Context.BestSolution));
+
+        try {
+          Context.RunOperator(Analyzer, cancellationToken);
+        } catch (OperationCanceledException) { }
+
+        Context.Iterations++;
+        if (cancellationToken.IsCancellationRequested) break;
+      }
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/OSGA.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/OSGA.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/OSGA.cs	(revision 17175)
@@ -0,0 +1,227 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 System.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.Evolutionary {
+  [Item("OSGA (GQAP)", "The algorithm implements a strict offspring selection genetic algorithm (OSGA).")]
+  [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms)]
+  [StorableType("3BCF54DD-CECB-4027-AF2F-1764E6318B78")]
+  public sealed class OSGA : StochasticAlgorithm<OSGAContext, IntegerVectorEncoding> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [Storable]
+    private FixedValueParameter<IntValue> populationSizeParameter;
+    public IFixedValueParameter<IntValue> PopulationSizeParameter {
+      get { return populationSizeParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<PercentValue> mutationProbabilityParameter;
+    public IFixedValueParameter<PercentValue> MutationProbabilityParameter {
+      get { return mutationProbabilityParameter; }
+    }
+
+    public int PopulationSize {
+      get { return populationSizeParameter.Value.Value; }
+      set { populationSizeParameter.Value.Value = value; }
+    }
+    public double MutationProbability {
+      get { return mutationProbabilityParameter.Value.Value; }
+      set { mutationProbabilityParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private OSGA(StorableConstructorFlag _) : base(_) { }
+    private OSGA(OSGA original, Cloner cloner)
+      : base(original, cloner) {
+      populationSizeParameter = cloner.Clone(original.populationSizeParameter);
+      mutationProbabilityParameter = cloner.Clone(original.mutationProbabilityParameter);
+    }
+    public OSGA() {
+      Parameters.Add(populationSizeParameter = new FixedValueParameter<IntValue>("Population Size", "(μ) The population size.", new IntValue(500)));
+      Parameters.Add(mutationProbabilityParameter = new FixedValueParameter<PercentValue>("Mutation Probability", "The chance for an offspring to get mutated.", new PercentValue(0.05)));
+
+      Problem = new GQAP();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OSGA(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+      
+      Context.Problem = Problem;
+      Context.BestSolution = null;
+
+      for (var m = 0; m < PopulationSize; m++) {
+        var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length);
+        var eval = Problem.ProblemInstance.Evaluate(assign);
+        Context.EvaluatedSolutions++;
+        
+        var ind = new GQAPSolution(assign, eval);
+        var fit = Problem.ProblemInstance.ToSingleObjective(eval);
+        Context.AddToPopulation(Context.ToScope(ind, fit));
+        if (double.IsNaN(Context.BestQuality) || fit < Context.BestQuality) {
+          Context.BestQuality = fit;
+          Context.BestSolution = (GQAPSolution)ind.Clone();
+        }
+      }
+
+      Context.SelectionPressure = 0;
+      Context.Attempts = 0;
+      Context.NextGeneration = new ItemList<ISingleObjectiveSolutionScope<GQAPSolution>>();
+
+      Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+      Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+      Results.Add(new Result("BestSolution", Context.BestSolution));
+
+      Context.RunOperator(Analyzer, cancellationToken);
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      var lastUpdate = ExecutionTime;
+
+      while (!StoppingCriterion()) {
+        
+        while (!StoppingCriterion() && Context.NextGeneration.Count < PopulationSize
+          && Context.SelectionPressure < 500) {
+
+          var idx1 = Context.Random.Next(PopulationSize);
+          var idx2 = (idx1 + Context.Random.Next(1, PopulationSize)) % PopulationSize;
+
+          var p1 = Context.AtPopulation(idx1);
+          var p2 = Context.AtPopulation(idx2);
+
+          var assign = DiscreteLocationCrossover.Apply(Context.Random,
+            new ItemArray<IntegerVector>(new[] { p1.Solution.Assignment, p2.Solution.Assignment }),
+            Problem.ProblemInstance.Demands, Problem.ProblemInstance.Capacities);
+
+          if (Context.Random.NextDouble() < MutationProbability) {
+            RelocateEquipmentManipluator.Apply(Context.Random, assign, Problem.ProblemInstance.Capacities.Length, 4.0 / assign.Length);
+          }
+
+          var eval = Problem.ProblemInstance.Evaluate(assign);
+          Context.EvaluatedSolutions++;
+
+          var offspring = new GQAPSolution(assign, eval);
+
+          var fit = Problem.ProblemInstance.ToSingleObjective(offspring.Evaluation);
+          if (fit < p1.Fitness && fit < p2.Fitness) { // strict OS
+            Context.NextGeneration.Add(Context.ToScope(offspring, fit));
+
+            if (fit < Context.BestQuality) {
+              Context.BestQuality = fit;
+              Context.BestSolution = (GQAPSolution)offspring.Clone();
+            }
+          }
+
+          Context.SelectionPressure += 1.0 / PopulationSize;
+          Context.Attempts++;
+          if (Context.SelectionPressure > 1
+            && Context.NextGeneration.Count / (double)PopulationSize < Context.SelectionPressure / 500)
+            break;
+          if (cancellationToken.IsCancellationRequested) return;
+        }
+        
+        var restart = Context.NextGeneration.Count < PopulationSize;
+
+        if (restart) {
+          var best = Context.Population.Concat(Context.NextGeneration)
+            .OrderBy(x => x.Fitness).Take(PopulationSize).ToList();
+          Context.ReplacePopulation(best);
+        } else {
+          Context.ReplacePopulation(Context.NextGeneration);
+        }
+        Context.NextGeneration.Clear();
+
+        IResult result;
+        if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
+        if (Results.TryGetValue("BestQuality", out result))
+          ((DoubleValue)result.Value).Value = Context.BestQuality;
+        else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+        if (Results.TryGetValue("BestSolution", out result))
+          result.Value = Context.BestSolution;
+        else Results.Add(new Result("BestSolution", Context.BestSolution));
+
+        try {
+          Context.RunOperator(Analyzer, cancellationToken);
+        } catch (OperationCanceledException) { }
+
+        Context.Iterations++;
+
+        if (restart) {
+          var seed = Context.Population.Select(x => (IntegerVector)x.Solution.Assignment.Clone()).ToList();
+          for (var s = 0; s < seed.Count; s++) {
+            RelocateEquipmentManipluator.Apply(Context.Random, seed[s], Problem.ProblemInstance.Capacities.Length, 0.0);
+            var eval = Problem.ProblemInstance.Evaluate(seed[s]);
+            Context.EvaluatedSolutions++;
+            var fit = Problem.ProblemInstance.ToSingleObjective(eval);
+            Context.NextGeneration.Add(Context.ToScope(new GQAPSolution(seed[s], eval), fit));
+          }
+          Context.ReplacePopulation(Context.NextGeneration);
+          Context.NextGeneration.Clear();
+        }
+        Context.SelectionPressure = 0;
+
+        if (cancellationToken.IsCancellationRequested) break;
+      }
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/OSGAContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/OSGAContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/OSGAContext.cs	(revision 17175)
@@ -0,0 +1,107 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.Evolutionary {
+  [Item("OSGA (GQAP) Context", "Context for OSGA (GQAP).")]
+  [StorableType("65ADDF53-91A6-4C8C-9DDE-B330E87AB32B")]
+  public sealed class OSGAContext : PopulationContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+    
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<ItemList<ISingleObjectiveSolutionScope<GQAPSolution>>> nextGeneration;
+    public ItemList<ISingleObjectiveSolutionScope<GQAPSolution>> NextGeneration {
+      get { return nextGeneration.Value; }
+      set { nextGeneration.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<DoubleValue> selectionPressure;
+    public double SelectionPressure {
+      get { return selectionPressure.Value.Value; }
+      set { selectionPressure.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> attempts;
+    public int Attempts {
+      get { return attempts.Value.Value; }
+      set { attempts.Value.Value = value; }
+    }
+
+    public void SortPopulation() {
+      Scope.SubScopes.Replace(Scope.SubScopes.OfType<ISingleObjectiveSolutionScope<GQAPSolution>>().OrderBy(x => Problem.Maximization ? -x.Fitness : x.Fitness).ToList());
+    }
+    
+    [StorableConstructor]
+    private OSGAContext(StorableConstructorFlag _) : base(_) { }
+    private OSGAContext(OSGAContext original, Cloner cloner)
+      : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+      nextGeneration = cloner.Clone(original.nextGeneration);
+      selectionPressure = cloner.Clone(original.selectionPressure);
+      attempts = cloner.Clone(original.attempts);
+    }
+    public OSGAContext() : this("OSGA (GQAP) Context") { }
+    public OSGAContext(string name) : base(name) {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+      Parameters.Add(nextGeneration = new ValueParameter<ItemList<ISingleObjectiveSolutionScope<GQAPSolution>>>("NextGeneration"));
+      Parameters.Add(selectionPressure = new ValueParameter<DoubleValue>("SelectionPressure", new DoubleValue(0)));
+      Parameters.Add(attempts = new ValueParameter<IntValue>("Attempts", new IntValue(0)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OSGAContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<GQAPSolution> ToScope(GQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<GQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      return scope;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP/GRASP.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP/GRASP.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP/GRASP.cs	(revision 17175)
@@ -0,0 +1,307 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 System.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.GRASP {
+
+  /// <summary>
+  /// This is an implementation of the algorithm described in Mateus, G.R., Resende, M.G.C. & Silva, R.M.A. J Heuristics (2011) 17: 527. https://doi.org/10.1007/s10732-010-9144-0
+  /// </summary>
+  /// <remarks>
+  /// A fine distinction to the described algorithm is that newly found best solutions are always accepted into the elite set. This is reasonable, but not mentioned in the paper by Mateus et al.
+  /// </remarks>
+  [Item("GRASP+PR (GQAP)", "The algorithm implements the Greedy Randomized Adaptive Search Procedure (GRASP) with Path Relinking as described in Mateus, G., Resende, M., and Silva, R. 2011. GRASP with path-relinking for the generalized quadratic assignment problem. Journal of Heuristics 17, Springer Netherlands, pp. 527-565.")]
+  [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms)]
+  [StorableType("F39B6832-67A7-4123-B279-338914599BAB")]
+  public sealed class GRASP : StochasticAlgorithm<GRASPContext, IntegerVectorEncoding> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [Storable]
+    private FixedValueParameter<IntValue> eliteSetSizeParameter;
+    private IFixedValueParameter<IntValue> EliteSetSizeParameter {
+      get { return eliteSetSizeParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> minimiumEliteSetSizeParameter;
+    public IFixedValueParameter<IntValue> MinimumEliteSetSizeParameter {
+      get { return minimiumEliteSetSizeParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> maximumLocalSearchIterationsParameter;
+    public IFixedValueParameter<IntValue> MaximumLocalSearchIterationsParameter {
+      get { return maximumLocalSearchIterationsParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<PercentValue> candidateSizeFactorParameter;
+    public IFixedValueParameter<PercentValue> CandidateSizeFactorParameter {
+      get { return candidateSizeFactorParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> maximumCandidateListSizeParameter;
+    public IFixedValueParameter<IntValue> MaximumCandidateListSizeParameter {
+      get { return maximumCandidateListSizeParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<PercentValue> oneMoveProbabilityParameter;
+    public IFixedValueParameter<PercentValue> OneMoveProbabilityParameter {
+      get { return oneMoveProbabilityParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> minimumDifferenceParameter;
+    public IFixedValueParameter<IntValue> MinimumDifferenceParameter {
+      get { return minimumDifferenceParameter; }
+    }
+    
+    public int EliteSetSize {
+      get { return eliteSetSizeParameter.Value.Value; }
+      set { eliteSetSizeParameter.Value.Value = value; }
+    }
+    public int MinimumEliteSetSize {
+      get { return minimiumEliteSetSizeParameter.Value.Value; }
+      set { minimiumEliteSetSizeParameter.Value.Value = value; }
+    }
+    public int MaximumLocalSearchIterations {
+      get { return maximumLocalSearchIterationsParameter.Value.Value; }
+      set { maximumLocalSearchIterationsParameter.Value.Value = value; }
+    }
+    public double CandidateSizeFactor {
+      get { return candidateSizeFactorParameter.Value.Value; }
+      set { candidateSizeFactorParameter.Value.Value = value; }
+    }
+    public int MaximumCandidateListSize {
+      get { return maximumCandidateListSizeParameter.Value.Value; }
+      set { maximumCandidateListSizeParameter.Value.Value = value; }
+    }
+    public double OneMoveProbability {
+      get { return oneMoveProbabilityParameter.Value.Value; }
+      set { oneMoveProbabilityParameter.Value.Value = value; }
+    }
+    public int MinimumDifference {
+      get { return minimumDifferenceParameter.Value.Value; }
+      set { minimumDifferenceParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private GRASP(StorableConstructorFlag _) : base(_) { }
+    private GRASP(GRASP original, Cloner cloner)
+      : base(original, cloner) {
+      eliteSetSizeParameter = cloner.Clone(original.eliteSetSizeParameter);
+      minimiumEliteSetSizeParameter = cloner.Clone(original.minimiumEliteSetSizeParameter);
+      maximumLocalSearchIterationsParameter = cloner.Clone(original.maximumLocalSearchIterationsParameter);
+      candidateSizeFactorParameter = cloner.Clone(original.candidateSizeFactorParameter);
+      maximumCandidateListSizeParameter = cloner.Clone(original.maximumCandidateListSizeParameter);
+      oneMoveProbabilityParameter = cloner.Clone(original.oneMoveProbabilityParameter);
+      minimumDifferenceParameter = cloner.Clone(original.minimumDifferenceParameter);
+    }
+    public GRASP() {
+      Parameters.Add(eliteSetSizeParameter = new FixedValueParameter<IntValue>("EliteSetSize", "The (maximum) size of the elite set.", new IntValue(10)));
+      Parameters.Add(minimiumEliteSetSizeParameter = new FixedValueParameter<IntValue>("MinimumEliteSetSize", "(ρ) The minimal size of the elite set, before local search and path relinking are applied.", new IntValue(2)));
+      Parameters.Add(maximumLocalSearchIterationsParameter = new FixedValueParameter<IntValue>("MaximumLocalSearchIteration", "The maximum number of iterations that the approximate local search should run", new IntValue(100)));
+      Parameters.Add(candidateSizeFactorParameter = new FixedValueParameter<PercentValue>("CandidateSizeFactor", "(η) Determines the size of the set of feasible moves in each path - relinking step relative to the maximum size.A value of 50 % means that only half of all possible moves are considered each step.", new PercentValue(0.5)));
+      Parameters.Add(maximumCandidateListSizeParameter = new FixedValueParameter<IntValue>("MaximumCandidateListSize", "The maximum number of candidates that should be found in each step.", new IntValue(10)));
+      Parameters.Add(oneMoveProbabilityParameter = new FixedValueParameter<PercentValue>("OneMoveProbability", "The probability for performing a 1-move, which is the opposite of performing a 2-move.", new PercentValue(.5)));
+      Parameters.Add(minimumDifferenceParameter = new FixedValueParameter<IntValue>("MinimumDifference", "The minimum amount of difference between two solutions so that they are both accepted in the elite set.", new IntValue(4)));
+
+      Problem = new GQAP();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GRASP(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+
+      Context.Problem = Problem;
+      Context.BestSolution = null;
+
+      Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+      Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+      Results.Add(new Result("BestSolution", typeof(GQAPSolution)));
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      var eq = new IntegerVectorEqualityComparer();
+      var lastUpdate = ExecutionTime;
+      while (!StoppingCriterion()) { // line 2 in Algorithm 1
+        // next: line 3 in Algorithm 1
+        IntegerVector pi_prime_vec = null;
+        try {
+          pi_prime_vec = GreedyRandomizedSolutionCreator.CreateSolution(Context.Random, Problem.ProblemInstance, 10, true, cancellationToken);
+        } catch (OperationCanceledException) { break; }
+
+        if (Context.PopulationCount >= MinimumEliteSetSize) { // line 4 in Algorithm 1
+          GQAPSolution pi_prime;
+          if (!Problem.ProblemInstance.IsFeasible(pi_prime_vec)) // line 5 in Algorithm 1
+            pi_prime = (GQAPSolution)Context.AtPopulation(Context.Random.Next(Context.PopulationCount)).Solution.Clone(); // line 6 in Algorithm 1
+          else {
+            // This is necessary, because pi_prime has not been evaluated yet and such details are not covered in Algorithm 1
+            pi_prime = Problem.ProblemInstance.ToEvaluatedSolution(pi_prime_vec);
+            Context.EvaluatedSolutions++;
+          }
+
+          ApproxLocalSearch(pi_prime); // line 8 in Algorithm 1
+          var pi_plus = Context.AtPopulation(Context.Random.Next(Context.PopulationCount)); // line 9 in Algorithm 1
+          pi_prime = PathRelinking(pi_prime, pi_plus.Solution); // line 10 in Algorithm 1
+          ApproxLocalSearch(pi_prime); // line 11 in Algorithm 1
+          var fitness = Problem.ProblemInstance.ToSingleObjective(pi_prime.Evaluation);
+          // Book-keeping
+          var newBest = Context.BestQuality > fitness;
+          if (newBest) {
+            Context.BestQuality = fitness;
+            Context.BestSolution = (GQAPSolution)pi_prime.Clone();
+          }
+
+          if (Context.PopulationCount == EliteSetSize) { // line 12 in Algorithm 1
+            double[] similarities = Context.Population.Select(x => HammingSimilarityCalculator.CalculateSimilarity(x.Solution.Assignment, pi_prime.Assignment)).ToArray();
+            // NOTE: In the original paper it is not described that new best solutions are accepted regardless of difference
+            // in this implementation a new best solution is always accepted into the elite set
+            if (newBest || similarities.Max() <= 1.0 - (MinimumDifference / (double)pi_prime.Assignment.Length)) { // cond. 2 of line 13 in Algorithm 1
+              var replacement = Context.Population.Select((v, i) => new { Scope = v, Index = i })
+                                          .Where(x => x.Scope.Fitness >= fitness) // cond. 1 of line 13 in Algorithm 1
+                                          .OrderByDescending(x => similarities[x.Index]) // line 14 in Algorithm 1
+                                          .FirstOrDefault();
+              if (replacement != null) {
+                Context.ReplaceAtPopulation(replacement.Index, Context.ToScope(pi_prime, fitness)); // line 14 in Algorithm 1
+              }
+            }
+            // NOTE: In the original paper it is not described that new best solutions are accepted regardless of difference
+            // in this implementation a new best solution is always accepted into the elite set
+          } else if (newBest || IsSufficientlyDifferent(pi_prime.Assignment)) { // line 17 in Algorithm 1
+            Context.AddToPopulation(Context.ToScope(pi_prime, Problem.ProblemInstance.ToSingleObjective(pi_prime.Evaluation))); // line 18 in Algorithm 1
+          }
+        } else if (Problem.ProblemInstance.IsFeasible(pi_prime_vec) /* cond. 1 of line 21 in Algorithm 1 */
+          && IsSufficientlyDifferent(pi_prime_vec))  /* cond. 2 of line 21 in Algorithm 1 */ {
+          var pi_prime = Problem.ProblemInstance.ToEvaluatedSolution(pi_prime_vec);
+          Context.EvaluatedSolutions++;
+          var fitness = Problem.ProblemInstance.ToSingleObjective(pi_prime.Evaluation);
+          Context.AddToPopulation(Context.ToScope(pi_prime, fitness)); /* line 22 in Algorithm 1 */
+          // Book-keeping
+          if (Context.PopulationCount == 1 || Context.BestQuality > fitness) {
+            Context.BestQuality = fitness;
+            Context.BestSolution = (GQAPSolution)pi_prime.Clone();
+          }
+        } else if (Context.PopulationCount == 0) {
+          // Book-keeping
+          // pi_prime_vec is not feasible, but no other feasible solution has been found so far
+          var eval = Problem.ProblemInstance.Evaluate(pi_prime_vec);
+          Context.EvaluatedSolutions++;
+          var fit = Problem.ProblemInstance.ToSingleObjective(eval);
+          if (double.IsNaN(Context.BestQuality) || fit < Context.BestQuality) {
+            Context.BestQuality = fit;
+            Context.BestSolution = new GQAPSolution(pi_prime_vec, eval);
+          }
+        }
+
+        IResult result;
+        if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
+        if (Results.TryGetValue("BestQuality", out result))
+          ((DoubleValue)result.Value).Value = Context.BestQuality;
+        else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+        if (Results.TryGetValue("BestSolution", out result))
+          result.Value = Context.BestSolution;
+        else Results.Add(new Result("BestSolution", Context.BestSolution));
+
+        try {
+          Context.RunOperator(Analyzer, cancellationToken);
+        } catch (OperationCanceledException) { }
+
+        Context.Iterations++;
+        if (cancellationToken.IsCancellationRequested) break;
+      }
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+
+    private bool IsSufficientlyDifferent(IntegerVector vec) {
+      return Context.Population.All(x =>
+        HammingSimilarityCalculator.CalculateSimilarity(vec, x.Solution.Assignment) <= 1.0 - (MinimumDifference / (double)vec.Length)
+      );
+    }
+
+    private GQAPSolution PathRelinking(GQAPSolution pi_prime, GQAPSolution pi_plus) {
+      // Following code represents line 1 of Algorithm 4
+      IntegerVector source = pi_prime.Assignment, target = pi_plus.Assignment;
+      Evaluation sourceEval = pi_prime.Evaluation, targetEval = pi_plus.Evaluation;
+      var sourceFit = Problem.ProblemInstance.ToSingleObjective(sourceEval);
+      var targetFit = Problem.ProblemInstance.ToSingleObjective(targetEval);
+      if (targetFit < sourceFit) {
+        var h = source;
+        source = target;
+        target = h;
+        var hh = sourceEval;
+        sourceEval = targetEval;
+        targetEval = hh;
+      }
+      int evaluatedSolutions;
+      // lines 2-36 of Algorithm 4 are implemented in the following call
+      var pi_star = GQAPPathRelinking.Apply(Context.Random, source, sourceEval,
+        target, targetEval, Problem.ProblemInstance, CandidateSizeFactor,
+        out evaluatedSolutions);
+      Context.EvaluatedSolutions += evaluatedSolutions;
+      return pi_star;
+    }
+
+    private void ApproxLocalSearch(GQAPSolution pi_prime) {
+      var localSearchEvaluations = 0;
+      ApproximateLocalSearch.Apply(Context.Random, pi_prime, MaximumCandidateListSize,
+        OneMoveProbability, MaximumLocalSearchIterations, Problem.ProblemInstance, out localSearchEvaluations);
+      Context.EvaluatedSolutions += localSearchEvaluations;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP/GRASPContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP/GRASPContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP/GRASPContext.cs	(revision 17175)
@@ -0,0 +1,79 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.GRASP {
+  [Item("GRASP+PR (GQAP) Context", "Context for GRASP+PR (GQAP).")]
+  [StorableType("64A7F8C0-8A38-4293-AC84-CE241EBF6F2C")]
+  public sealed class GRASPContext : PopulationContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+    
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+    
+    public void SortPopulation() {
+      Scope.SubScopes.Replace(Scope.SubScopes.OfType<ISingleObjectiveSolutionScope<GQAPSolution>>().OrderBy(x => Problem.Maximization ? -x.Fitness : x.Fitness).ToList());
+    }
+    
+    [StorableConstructor]
+    private GRASPContext(StorableConstructorFlag _) : base(_) { }
+    private GRASPContext(GRASPContext original, Cloner cloner)
+      : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+    }
+    public GRASPContext() : this("GRASP+PR (GQAP) Context") { }
+    public GRASPContext(string name) : base(name) {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GRASPContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<GQAPSolution> ToScope(GQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<GQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      return scope;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj	(revision 17175)
@@ -0,0 +1,172 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{577239EC-7D7F-4505-A0A4-572E34010DBA}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>false</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <DelaySign>false</DelaySign>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>
+    </AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="HEAL.Attic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HEAL.Attic.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common.Resources-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common.Resources-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Data-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization.Operators-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Optimization.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Parameters-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Persistence-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Persistence-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Random-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Random-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="localsolvernet, Version=7.5.0.0, Culture=neutral, processorArchitecture=AMD64">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\localsolvernet.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="oplall, Version=12.7.0.0, Culture=neutral, PublicKeyToken=7906592bc7cc7340, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\oplall.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Evolutionary\ESContext.cs" />
+    <Compile Include="Evolutionary\ESGQAPSolution.cs" />
+    <Compile Include="Evolutionary\EvolutionStrategy.cs" />
+    <Compile Include="Evolutionary\OSGAContext.cs" />
+    <Compile Include="Evolutionary\OSGA.cs" />
+    <Compile Include="Infrastructure\Algorithms\StochasticAlgorithm.cs" />
+    <Compile Include="Infrastructure\Contexts\StochasticContext.cs" />
+    <Compile Include="Infrastructure\Contexts\BasicContext.cs" />
+    <Compile Include="Infrastructure\Algorithms\ContextAlgorithm.cs" />
+    <Compile Include="GRASP\GRASPContext.cs" />
+    <Compile Include="GRASP\GRASP.cs" />
+    <Compile Include="LAHC\pLAHCContext.cs" />
+    <Compile Include="LAHC\pLAHC.cs" />
+    <Compile Include="LAHC\LAHC.cs" />
+    <Compile Include="LAHC\LAHCContext.cs" />
+    <Compile Include="LocalSearch\LocalSearchContext.cs" />
+    <Compile Include="Infrastructure\Interfaces.cs" />
+    <Compile Include="LocalSearch\IteratedLS.cs" />
+    <Compile Include="LocalSearch\MultistartLS.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="Infrastructure\Contexts\SingleSolutionContext.cs" />
+    <Compile Include="Infrastructure\Contexts\PopulationContext.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Infrastructure\SingleObjectiveSolutionScope.cs" />
+    <Compile Include="RandomSearch\RandomSearchContext.cs" />
+    <Compile Include="RandomSearch\RandomSearch.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425b4-4348-49ed-a457-b7d2c26ddbf9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.IntegerVectorEncoding\3.3\HeuristicLab.Encodings.IntegerVectorEncoding-3.3.csproj">
+      <Project>{ddfb14dd-2a85-493c-a52d-e69729bbaeb0}</Project>
+      <Name>HeuristicLab.Encodings.IntegerVectorEncoding-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
+      <Project>{14ab8d24-25bc-400c-a846-4627aa945192}</Project>
+      <Name>HeuristicLab.Optimization-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.GeneralizedQuadraticAssignment\3.3\HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj">
+      <Project>{c739e6d2-5680-4804-a810-8017da0c238f}</Project>
+      <Name>HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Algorithms/ContextAlgorithm.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Algorithms/ContextAlgorithm.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Algorithms/ContextAlgorithm.cs	(revision 17175)
@@ -0,0 +1,225 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Diagnostics;
+using System.Linq;
+using System.Threading;
+using HEAL.Attic;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [Item("Context-based Algorithm", "Algorithms that make use of contexts to facilitate applying operators.")]
+  [StorableType("F7679602-28B2-495C-AF6C-370EFC7BE38A")]
+  public abstract class ContextAlgorithm<TContext, TEncoding> : BasicAlgorithm
+    where TContext : class, IContext, new()
+    where TEncoding : class, IEncoding {
+
+    public override Type ProblemType {
+      get { return typeof(SingleObjectiveBasicProblem<TEncoding>); }
+    }
+
+    public new SingleObjectiveBasicProblem<TEncoding> Problem {
+      get { return (SingleObjectiveBasicProblem<TEncoding>)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [Storable]
+    private TContext context;
+    public TContext Context {
+      get { return context; }
+    }
+
+    [Storable]
+    private ValueParameter<IAnalyzer> analyzerParameter;
+    public IValueParameter<IAnalyzer> AnalyzerParameter {
+      get { return analyzerParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> maximumIterationsParameter;
+    public IFixedValueParameter<IntValue> MaximumIterationsParameter {
+      get { return maximumIterationsParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> maximumEvaluationsParameter;
+    public IFixedValueParameter<IntValue> MaximumEvaluationsParameter {
+      get { return maximumEvaluationsParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<TimeSpanValue> maximumRuntimeParameter;
+    public IFixedValueParameter<TimeSpanValue> MaximumRuntimeParameter {
+      get { return maximumRuntimeParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<BoolValue> stopAtBestKnownQualityParameter;
+    public IFixedValueParameter<BoolValue> StopAtBestKnownQualityParameter {
+      get { return stopAtBestKnownQualityParameter; }
+    }
+
+    public IAnalyzer Analyzer {
+      get { return analyzerParameter.Value; }
+      set { analyzerParameter.Value = value; }
+    }
+    public int MaximumIterations {
+      get { return maximumIterationsParameter.Value.Value; }
+      set { maximumIterationsParameter.Value.Value = value; }
+    }
+    public int MaximumEvaluations {
+      get { return maximumEvaluationsParameter.Value.Value; }
+      set { maximumEvaluationsParameter.Value.Value = value; }
+    }
+    public TimeSpan MaximumRuntime {
+      get { return maximumRuntimeParameter.Value.Value; }
+      set { maximumRuntimeParameter.Value.Value = value; }
+    }
+    public bool StopAtBestKnownQuality {
+      get { return stopAtBestKnownQualityParameter.Value.Value; }
+      set { stopAtBestKnownQualityParameter.Value.Value = value; }
+    }
+
+    private Stopwatch stopwatch;
+    [Storable]
+    private TimeSpan elapsed;
+    [Storable]
+    private IndexedDataTable<double> qualityPerClock;
+    [Storable]
+    private IndexedDataRow<double> firstHitGraph;
+
+    [StorableConstructor]
+    protected ContextAlgorithm(StorableConstructorFlag _) : base(_) { }
+    protected ContextAlgorithm(ContextAlgorithm<TContext, TEncoding> original, Cloner cloner)
+      : base(original, cloner) {
+      context = cloner.Clone(original.context);
+      analyzerParameter = cloner.Clone(original.analyzerParameter);
+      maximumIterationsParameter = cloner.Clone(original.maximumIterationsParameter);
+      maximumEvaluationsParameter = cloner.Clone(original.maximumEvaluationsParameter);
+      maximumRuntimeParameter = cloner.Clone(original.maximumRuntimeParameter);
+      stopAtBestKnownQualityParameter = cloner.Clone(original.stopAtBestKnownQualityParameter);
+      elapsed = original.elapsed;
+      qualityPerClock = cloner.Clone(original.qualityPerClock);
+      firstHitGraph = cloner.Clone(original.firstHitGraph);
+      if (context != null)
+        context.BestQualityChanged += ContextOnBestQualityChanged;
+    }
+    protected ContextAlgorithm()
+      : base() {
+      Parameters.Add(analyzerParameter = new ValueParameter<IAnalyzer>("Analyzer", "The analyzers that are used to perform an analysis of the solutions.", new MultiAnalyzer()));
+      Parameters.Add(maximumIterationsParameter = new FixedValueParameter<IntValue>("MaximumIterations", "The number of iterations that the algorithm should run or < 1 to ignore.", new IntValue(0)));
+      Parameters.Add(maximumEvaluationsParameter = new FixedValueParameter<IntValue>("MaximumEvaluations", "The number of evaluated solutions that the algorithm should perform or < 1 to ignore.", new IntValue(0)));
+      Parameters.Add(maximumRuntimeParameter = new FixedValueParameter<TimeSpanValue>("MaximumRuntime", "The timespan that the algorithm is allowed to run.", new TimeSpanValue(TimeSpan.FromMinutes(1))));
+      Parameters.Add(stopAtBestKnownQualityParameter = new FixedValueParameter<BoolValue>("StopAtBestKnownQuality", "Whether the algorithm should terminate if the best known quality has been found.", new BoolValue(true)));
+    }
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+      context = new TContext();
+      context.Scope.Variables.Add(new Variable("Results", Results));
+      context.BestQualityChanged += ContextOnBestQualityChanged;
+
+      IExecutionContext ctxt = null;
+      foreach (var item in Problem.ExecutionContextItems)
+        ctxt = new Core.ExecutionContext(ctxt, item, Context.Scope);
+      ctxt = new Core.ExecutionContext(ctxt, this, Context.Scope);
+      context.Parent = ctxt;
+
+      context.Iterations = 0;
+      context.EvaluatedSolutions = 0;
+      context.BestQuality = double.NaN;
+
+      qualityPerClock = new IndexedDataTable<double>("Quality Per Clock");
+      firstHitGraph = new IndexedDataRow<double>("First-hit Graph");
+      qualityPerClock.Rows.Add(firstHitGraph);
+      Results.Add(new Result("QualityPerClock", qualityPerClock));
+
+      elapsed = TimeSpan.Zero;
+      stopwatch = Stopwatch.StartNew();
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      if (stopwatch == null || !stopwatch.IsRunning) stopwatch = Stopwatch.StartNew();
+    }
+
+    private void ContextOnBestQualityChanged(object sender, EventArgs e) {
+      if (double.IsNaN(Context.BestQuality)) return;
+      var newEntry = Tuple.Create((elapsed + stopwatch.Elapsed).TotalSeconds, Context.BestQuality);
+
+      if (firstHitGraph.Values.Count == 0) {
+        firstHitGraph.Values.Add(newEntry); // record the first data
+        firstHitGraph.Values.Add(Tuple.Create(newEntry.Item1, newEntry.Item2)); // last entry records max number of evaluations
+        return;
+      }
+
+      var improvement = firstHitGraph.Values.Last().Item2 != newEntry.Item2;
+      if (improvement) {
+        firstHitGraph.Values[firstHitGraph.Values.Count - 1] = newEntry; // record the improvement
+        firstHitGraph.Values.Add(Tuple.Create(newEntry.Item1, newEntry.Item2)); // last entry records max number of evaluations
+      } else {
+        firstHitGraph.Values[firstHitGraph.Values.Count - 1] = Tuple.Create(newEntry.Item1, newEntry.Item2);
+      }
+    }
+
+    public override void Prepare() {
+      if (context != null) {
+        context.BestQualityChanged -= ContextOnBestQualityChanged;
+        context = null;
+      }
+      base.Prepare();
+    }
+
+    protected override void OnPaused() {
+      elapsed += stopwatch.Elapsed;
+      stopwatch.Reset();
+      if (firstHitGraph.Values.Count > 0)
+        firstHitGraph.Values[firstHitGraph.Values.Count - 1] = Tuple.Create(elapsed.TotalSeconds, Context.BestQuality);
+      base.OnPaused();
+    }
+
+    protected override void OnStopped() {
+      if (stopwatch.IsRunning) {
+        elapsed += stopwatch.Elapsed;
+        stopwatch.Reset();
+        if (firstHitGraph.Values.Count > 0)
+          firstHitGraph.Values[firstHitGraph.Values.Count - 1] = Tuple.Create(elapsed.TotalSeconds, Context.BestQuality);
+      }
+      context = null;
+      // base call must be done last as the results will be cloned and a run is created
+      base.OnStopped();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (context != null) context.BestQualityChanged += ContextOnBestQualityChanged;
+    }
+
+    protected virtual bool StoppingCriterion() {
+      return MaximumIterations > 0 && Context.Iterations > MaximumIterations
+        || MaximumEvaluations > 0 && Context.EvaluatedSolutions > MaximumEvaluations
+        || MaximumRuntime > TimeSpan.Zero && ExecutionTime > MaximumRuntime
+        || StopAtBestKnownQuality && !double.IsNaN(Problem.BestKnownQuality)
+          && Context.BestQuality.IsAlmost(Problem.BestKnownQuality);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Algorithms/StochasticAlgorithm.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Algorithms/StochasticAlgorithm.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Algorithms/StochasticAlgorithm.cs	(revision 17175)
@@ -0,0 +1,82 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [Item("Stochastic Algorithm", "Stochastic context-based algorithms to facilitate applying operators.")]
+  [StorableType("749A9442-BCE6-45A1-8911-159217199013")]
+  public abstract class StochasticAlgorithm<TContext, TEncoding> : ContextAlgorithm<TContext, TEncoding>
+    where TContext : class, IStochasticContext, new()
+    where TEncoding : class, IEncoding {
+    
+    [Storable]
+    private FixedValueParameter<BoolValue> setSeedRandomlyParameter;
+    private IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
+      get { return setSeedRandomlyParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> seedParameter;
+    private IFixedValueParameter<IntValue> SeedParameter {
+      get { return seedParameter; }
+    }
+    
+    public bool SetSeedRandomly {
+      get { return setSeedRandomlyParameter.Value.Value; }
+      set { setSeedRandomlyParameter.Value.Value = value; }
+    }
+    public int Seed {
+      get { return seedParameter.Value.Value; }
+      set { seedParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected StochasticAlgorithm(StorableConstructorFlag _) : base(_) { }
+    protected StochasticAlgorithm(StochasticAlgorithm<TContext, TEncoding> original, Cloner cloner)
+      : base(original, cloner) {
+      setSeedRandomlyParameter = cloner.Clone(original.setSeedRandomlyParameter);
+      seedParameter = cloner.Clone(original.seedParameter);
+    }
+    protected StochasticAlgorithm()
+      : base() {
+      Parameters.Add(setSeedRandomlyParameter = new FixedValueParameter<BoolValue>("SetSeedRandomly", "Whether to overwrite the seed with a random value each time the algorithm is run.", new BoolValue(true)));
+      Parameters.Add(seedParameter = new FixedValueParameter<IntValue>("Seed", "The random seed that is used in the stochastic algorithm", new IntValue(0)));
+    }
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+
+      if (SetSeedRandomly) {
+        var rnd = new System.Random();
+        Seed = rnd.Next();
+      }
+
+      Context.Random = new MersenneTwister((uint)Seed);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/BasicContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/BasicContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/BasicContext.cs	(revision 17175)
@@ -0,0 +1,168 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Collections.Generic;
+using System.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [Item("Basic Context", "A base class for algorithms' contexts.")]
+  [StorableType("633CC9F2-35B9-4193-A022-0D768532937A")]
+  public class BasicContext : ParameterizedNamedItem, IContext {
+
+    private IExecutionContext parent;
+    public IExecutionContext Parent {
+      get { return parent; }
+      set { parent = value; }
+    }
+
+    [Storable]
+    private IScope scope;
+    public IScope Scope {
+      get { return scope; }
+      private set { scope = value; }
+    }
+
+    IKeyedItemCollection<string, IParameter> IExecutionContext.Parameters {
+      get { return Parameters; }
+    }
+
+    [Storable]
+    private IFixedValueParameter<IntValue> iterations;
+    public int Iterations {
+      get { return iterations.Value.Value; }
+      set { iterations.Value.Value = value; }
+    }
+
+    [Storable]
+    private IFixedValueParameter<IntValue> evaluatedSolutions;
+    public int EvaluatedSolutions {
+      get { return evaluatedSolutions.Value.Value; }
+      set { evaluatedSolutions.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<DoubleValue> bestQuality;
+    public double BestQuality {
+      get { return bestQuality.Value.Value; }
+      set {
+        if (bestQuality.Value.Value == value) return;
+        bestQuality.Value.Value = value;
+        OnBestQualityChanged();
+      }
+    }
+
+    [StorableConstructor]
+    protected BasicContext(StorableConstructorFlag _) : base(_) { }
+    protected BasicContext(BasicContext original, Cloner cloner)
+    : base(original, cloner) {
+      scope = cloner.Clone(original.scope);
+      iterations = cloner.Clone(original.iterations);
+      evaluatedSolutions = cloner.Clone(original.evaluatedSolutions);
+      bestQuality = cloner.Clone(original.bestQuality);
+    }
+    protected BasicContext() : base() {
+      scope = new Scope("Global");
+      Parameters.Add(iterations = new FixedValueParameter<IntValue>("Iterations", new IntValue(0)));
+      Parameters.Add(evaluatedSolutions = new FixedValueParameter<IntValue>("EvaluatedSolutions", new IntValue(0)));
+      Parameters.Add(bestQuality = new ValueParameter<DoubleValue>("BestQuality", new DoubleValue(double.NaN)));
+    }
+    protected BasicContext(string name) : base(name) {
+      scope = new Scope("Global");
+      Parameters.Add(iterations = new FixedValueParameter<IntValue>("Iterations", new IntValue(0)));
+      Parameters.Add(evaluatedSolutions = new FixedValueParameter<IntValue>("EvaluatedSolutions", new IntValue(0)));
+      Parameters.Add(bestQuality = new ValueParameter<DoubleValue>("BestQuality", new DoubleValue(double.NaN)));
+    }
+    protected BasicContext(string name, ParameterCollection parameters) : base(name, parameters) {
+      scope = new Scope("Global");
+      Parameters.Add(iterations = new FixedValueParameter<IntValue>("Iterations", new IntValue(0)));
+      Parameters.Add(evaluatedSolutions = new FixedValueParameter<IntValue>("EvaluatedSolutions", new IntValue(0)));
+      Parameters.Add(bestQuality = new ValueParameter<DoubleValue>("BestQuality", new DoubleValue(double.NaN)));
+    }
+    protected BasicContext(string name, string description) : base(name, description) {
+      scope = new Scope("Global");
+      Parameters.Add(iterations = new FixedValueParameter<IntValue>("Iterations", new IntValue(0)));
+      Parameters.Add(evaluatedSolutions = new FixedValueParameter<IntValue>("EvaluatedSolutions", new IntValue(0)));
+      Parameters.Add(bestQuality = new ValueParameter<DoubleValue>("BestQuality", new DoubleValue(double.NaN)));
+    }
+    protected BasicContext(string name, string description, ParameterCollection parameters) : base(name, description, parameters) {
+      scope = new Scope("Global");
+      Parameters.Add(iterations = new FixedValueParameter<IntValue>("Iterations", new IntValue(0)));
+      Parameters.Add(evaluatedSolutions = new FixedValueParameter<IntValue>("EvaluatedSolutions", new IntValue(0)));
+      Parameters.Add(bestQuality = new ValueParameter<DoubleValue>("BestQuality", new DoubleValue(double.NaN)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BasicContext(this, cloner);
+    }
+
+    public void RunOperator(IOperator op, CancellationToken cancellationToken) {
+      var stack = new Stack<IOperation>();
+      stack.Push(((IExecutionContext)this).CreateChildOperation(op, scope));
+
+      while (stack.Count > 0) {
+        cancellationToken.ThrowIfCancellationRequested();
+
+        var next = stack.Pop();
+        if (next is OperationCollection) {
+          var coll = (OperationCollection)next;
+          for (int i = coll.Count - 1; i >= 0; i--)
+            if (coll[i] != null) stack.Push(coll[i]);
+        } else if (next is IAtomicOperation) {
+          var operation = (IAtomicOperation)next;
+          try {
+            next = operation.Operator.Execute((IExecutionContext)operation, cancellationToken);
+          } catch (Exception ex) {
+            stack.Push(operation);
+            if (ex is OperationCanceledException) throw ex;
+            else throw new OperatorExecutionException(operation.Operator, ex);
+          }
+          if (next != null) stack.Push(next);
+        }
+      }
+    }
+
+    public event EventHandler BestQualityChanged;
+    private void OnBestQualityChanged() {
+      BestQualityChanged?.Invoke(this, EventArgs.Empty);
+    }
+
+    #region IExecutionContext members
+    IAtomicOperation IExecutionContext.CreateOperation(IOperator op) {
+      return new Core.ExecutionContext(this, op, Scope);
+    }
+    IAtomicOperation IExecutionContext.CreateOperation(IOperator op, IScope s) {
+      return new Core.ExecutionContext(this, op, s);
+    }
+    IAtomicOperation IExecutionContext.CreateChildOperation(IOperator op) {
+      return new Core.ExecutionContext(this, op, Scope);
+    }
+    IAtomicOperation IExecutionContext.CreateChildOperation(IOperator op, IScope s) {
+      return new Core.ExecutionContext(this, op, s);
+    }
+    #endregion
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/PopulationContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/PopulationContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/PopulationContext.cs	(revision 17175)
@@ -0,0 +1,68 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [Item("Population Context", "A context for population-based algorithms.")]
+  [StorableType("2FF3BB92-80E9-4463-B05A-5D36B76873A6")]
+  public abstract class PopulationContext<TSolutionScope> : StochasticContext
+    where TSolutionScope: class, IScope {
+
+    public IEnumerable<TSolutionScope> Population {
+      get { return Scope.SubScopes.OfType<TSolutionScope>(); }
+    }
+    public void AddToPopulation(TSolutionScope solScope) {
+      Scope.SubScopes.Add(solScope);
+    }
+    public void ReplaceAtPopulation(int index, TSolutionScope solScope) {
+      Scope.SubScopes[index] = solScope;
+    }
+    public void ReplacePopulation(IEnumerable<TSolutionScope> replacement) {
+      Scope.SubScopes.Replace(replacement);
+    }
+    public TSolutionScope AtPopulation(int index) {
+      return Scope.SubScopes[index] as TSolutionScope;
+    }
+    public TSolutionScope AtRandomPopulation() {
+      return Scope.SubScopes[Random.Next(PopulationCount)] as TSolutionScope;
+    }
+    public int PopulationCount {
+      get { return Scope.SubScopes.Count; }
+    }
+
+
+    [StorableConstructor]
+    protected PopulationContext(StorableConstructorFlag _) : base(_) { }
+    protected PopulationContext(PopulationContext<TSolutionScope> original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    protected PopulationContext() : base() { }
+    protected PopulationContext(string name) : base(name) { }
+    protected PopulationContext(string name, ParameterCollection parameters) : base(name, parameters) { }
+    protected PopulationContext(string name, string description) : base(name, description) { }
+    protected PopulationContext(string name, string description, ParameterCollection parameters) : base(name, description, parameters) { }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/SingleSolutionContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/SingleSolutionContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/SingleSolutionContext.cs	(revision 17175)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [Item("Single Solution Context", "A context for single solution algorithms.")]
+  [StorableType("1AE4E4ED-21C5-48E7-833C-58D813557026")]
+  public abstract class SingleSolutionContext<TSolutionScope> : StochasticContext
+    where TSolutionScope: class, IScope {
+    
+    [Storable]
+    private TSolutionScope incumbent;
+    public TSolutionScope Incumbent {
+      get { return incumbent; }
+    }
+
+    public void ReplaceIncumbent(TSolutionScope solScope) {
+      if (incumbent != null) Scope.SubScopes.Remove(incumbent);
+      this.incumbent = solScope;
+      if (incumbent != null) Scope.SubScopes.Add(incumbent);
+    }
+
+
+    [StorableConstructor]
+    protected SingleSolutionContext(StorableConstructorFlag _) : base(_) { }
+    protected SingleSolutionContext(SingleSolutionContext<TSolutionScope> original, Cloner cloner)
+      : base(original, cloner) {
+      incumbent = cloner.Clone(original.incumbent);
+    }
+    protected SingleSolutionContext() : base() { }
+    protected SingleSolutionContext(string name) : base(name) { }
+    protected SingleSolutionContext(string name, ParameterCollection parameters) : base(name, parameters) { }
+    protected SingleSolutionContext(string name, string description) : base(name, description) { }
+    protected SingleSolutionContext(string name, string description, ParameterCollection parameters) : base(name, description, parameters) { }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/StochasticContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/StochasticContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/StochasticContext.cs	(revision 17175)
@@ -0,0 +1,65 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [Item("Stochastic Context", "A base class for stochastic algorithms' contexts.")]
+  [StorableType("9A9B3147-4D77-45E7-9A79-B6393666AB2E")]
+  public class StochasticContext : BasicContext, IStochasticContext {
+    
+    [Storable]
+    private IValueParameter<IRandom> random;
+    public IRandom Random {
+      get { return random.Value; }
+      set { random.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected StochasticContext(StorableConstructorFlag _) : base(_) { }
+    protected StochasticContext(StochasticContext original, Cloner cloner)
+    : base(original, cloner) {
+      random = cloner.Clone(original.random);
+    }
+    protected StochasticContext() : base() {
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
+    }
+    protected StochasticContext(string name) : base(name) {
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
+    }
+    protected StochasticContext(string name, ParameterCollection parameters) : base(name, parameters) {
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
+    }
+    protected StochasticContext(string name, string description) : base(name, description) {
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
+    }
+    protected StochasticContext(string name, string description, ParameterCollection parameters) : base(name, description, parameters) {
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StochasticContext(this, cloner);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Interfaces.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Interfaces.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Interfaces.cs	(revision 17175)
@@ -0,0 +1,45 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [StorableType("2bab7669-028a-4ba8-9c63-60853e15ad47")]
+  public interface ISingleObjectiveSolutionScope<TSolution> : IScope {
+    TSolution Solution { get; set; }
+    double Fitness { get; set; }
+  }
+  [StorableType("0ae52e60-5ea1-428f-99ca-b7b84a79857d")]
+  public interface IContext : IExecutionContext {
+    new IExecutionContext Parent { get; set; }
+    int Iterations { get; set; }
+    int EvaluatedSolutions { get; set; }
+    double BestQuality { get; set; }
+
+    event EventHandler BestQualityChanged;
+  }
+  [StorableType("ab766d45-2dab-4280-9f4e-1531fe9a91cf")]
+  public interface IStochasticContext : IContext {
+    IRandom Random { get; set; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/SingleObjectiveSolutionScope.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/SingleObjectiveSolutionScope.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/SingleObjectiveSolutionScope.cs	(revision 17175)
@@ -0,0 +1,137 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Drawing;
+using HEAL.Attic;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [Item("Solution Scope", "Scope for an individual/solution of a single-objective single-encoded problem.")]
+  [StorableType("C3F4010D-8B4F-4F0E-B99C-1B78AED8F114")]
+  public sealed class SingleObjectiveSolutionScope<T> : NamedItem, ISingleObjectiveSolutionScope<T> where T : class, IItem {
+    public new static Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.OrgChart; }
+    }
+
+    [Storable]
+    private IScope parent;
+    public IScope Parent {
+      get { return parent; }
+      set {
+        if (parent != value) {
+          parent = value;
+        }
+      }
+    }
+
+    [Storable]
+    private VariableCollection variables;
+    public VariableCollection Variables {
+      get { return variables; }
+    }
+
+    [Storable]
+    private ScopeList subScopes;
+    public ScopeList SubScopes {
+      get { return subScopes; }
+    }
+
+    [Storable]
+    private Variable solution;
+    public T Solution {
+      get { return (T)solution.Value; }
+      set { solution.Value = value; }
+    }
+
+    [Storable]
+    private Variable fitness;
+    public double Fitness {
+      get { return ((DoubleValue)fitness.Value).Value; }
+      set { ((DoubleValue)fitness.Value).Value = value; }
+    }
+
+    [StorableConstructor]
+    private SingleObjectiveSolutionScope(StorableConstructorFlag _) : base(_) { }
+    private SingleObjectiveSolutionScope(SingleObjectiveSolutionScope<T> original, Cloner cloner)
+      : base(original, cloner) {
+      // the parent will not be deep-cloned
+      parent = original.parent;
+      variables = cloner.Clone(original.variables);
+      subScopes = cloner.Clone(original.subScopes);
+      foreach (var child in SubScopes)
+        child.Parent = this;
+      solution = cloner.Clone(original.solution);
+      fitness = cloner.Clone(original.fitness);
+
+      RegisterSubScopesEvents();
+    }
+    public SingleObjectiveSolutionScope(T code, string codeName, double fitness, string fitnessName) {
+      this.solution = new Variable(codeName, code);
+      this.fitness = new Variable(fitnessName, new DoubleValue(fitness));
+      variables = new VariableCollection(2) { this.solution, this.fitness };
+      subScopes = new ScopeList(2);
+
+      RegisterSubScopesEvents();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectiveSolutionScope<T>(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterSubScopesEvents();
+    }
+
+    public void Clear() {
+      variables.Clear();
+      subScopes.Clear();
+    }
+
+    #region SubScopes Events
+    private void RegisterSubScopesEvents() {
+      if (subScopes != null) {
+        subScopes.ItemsAdded += SubScopes_ItemsAdded;
+        subScopes.ItemsRemoved += SubScopes_ItemsRemoved;
+        subScopes.ItemsReplaced += SubScopes_ItemsReplaced;
+        subScopes.CollectionReset += SubScopes_CollectionReset;
+      }
+    }
+    private void SubScopes_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IScope>> e) {
+      foreach (var item in e.Items) item.Value.Parent = this;
+    }
+    private void SubScopes_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IScope>> e) {
+      foreach (var item in e.Items) item.Value.Parent = null;
+    }
+    private void SubScopes_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IScope>> e) {
+      foreach (var oldItem in e.OldItems) oldItem.Value.Parent = null;
+      foreach (var item in e.Items) item.Value.Parent = this;
+    }
+    private void SubScopes_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IScope>> e) {
+      foreach (var oldItem in e.OldItems) oldItem.Value.Parent = null;
+      foreach (var item in e.Items) item.Value.Parent = this;
+    }
+    #endregion
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHC.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHC.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHC.cs	(revision 17175)
@@ -0,0 +1,176 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 System.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LAHC {
+  [Item("LAHC (GQAP)", "Late-acceptance hill climber for the GQAP.")]
+  [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
+  [StorableType("41FABEE1-506A-45FE-A6D3-57932036AEC8")]
+  public sealed class LAHC : StochasticAlgorithm<LAHCContext, IntegerVectorEncoding> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [Storable]
+    private FixedValueParameter<IntValue> memorySizeParameter;
+    public IFixedValueParameter<IntValue> MemorySizeParameter {
+      get { return memorySizeParameter; }
+    }
+
+    public int MemorySize {
+      get { return memorySizeParameter.Value.Value; }
+      set { memorySizeParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private LAHC(StorableConstructorFlag _) : base(_) { }
+    private LAHC(LAHC original, Cloner cloner)
+      : base(original, cloner) {
+      memorySizeParameter = cloner.Clone(original.memorySizeParameter);
+    }
+    public LAHC() {
+      Parameters.Add(memorySizeParameter = new FixedValueParameter<IntValue>("MemorySize", "The size of the memory, the shorter the more greedy LAHC performs.", new IntValue(100)));
+
+      Problem = new GQAP();
+    }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LAHC(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken token) {
+      base.Initialize(token);
+
+      Context.Problem = Problem;
+      Context.LastSuccess = 0;
+      
+      var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length);
+      var eval = Problem.ProblemInstance.Evaluate(assign);
+      var fit = Problem.ProblemInstance.ToSingleObjective(eval);
+      Context.EvaluatedSolutions++;
+
+      var candidate = new GQAPSolution(assign, eval);
+      
+      Context.ReplaceIncumbent(Context.ToScope(candidate, fit));
+      Context.BestQuality = fit;
+      Context.BestSolution = (GQAPSolution)candidate.Clone();
+      
+      Context.Memory = new DoubleArray(Enumerable.Repeat(Context.BestQuality, MemorySize).ToArray());
+
+      Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+      Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+      Results.Add(new Result("BestSolution", Context.BestSolution));
+
+      try {
+        Context.RunOperator(Analyzer, token);
+      } catch (OperationCanceledException) { }
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      var lastUpdate = ExecutionTime;
+      while (!StoppingCriterion()) {
+        var move = StochasticNMoveSingleMoveGenerator.GenerateOneMove(Context.Random,
+          Context.Incumbent.Solution.Assignment, Problem.ProblemInstance.Capacities);
+        var moveEval = GQAPNMoveEvaluator.Evaluate(move,
+          Context.Incumbent.Solution.Assignment,
+          Context.Incumbent.Solution.Evaluation, Problem.ProblemInstance);
+        if (Context.Iterations % Problem.ProblemInstance.Demands.Length == 0)
+          Context.EvaluatedSolutions++;
+        var nextFit = Problem.ProblemInstance.ToSingleObjective(moveEval);
+        var nextVec = new IntegerVector(Context.Incumbent.Solution.Assignment);
+        NMoveMaker.Apply(nextVec, move);
+        
+        var v = Context.Iterations % Context.Memory.Length;
+        Context.Iterations++;
+        var prevFit = Context.Memory[v];
+
+        var accept = nextFit <= Context.Incumbent.Fitness
+                  || nextFit <= prevFit;
+
+        if (accept && nextFit < Context.Incumbent.Fitness)
+          Context.LastSuccess = Context.Iterations;
+
+        if (accept) {
+          Context.ReplaceIncumbent(Context.ToScope(new GQAPSolution(nextVec, moveEval), nextFit));
+          if (nextFit < Context.BestQuality) {
+            Context.BestSolution = (GQAPSolution)Context.Incumbent.Solution.Clone();
+            Context.BestQuality = nextFit;
+          }
+        }
+
+        if (Context.Incumbent.Fitness < prevFit)
+          Context.Memory[v] = Context.Incumbent.Fitness;
+
+        IResult result;
+        if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
+        if (Results.TryGetValue("BestQuality", out result))
+          ((DoubleValue)result.Value).Value = Context.BestQuality;
+        else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+        if (Results.TryGetValue("BestSolution", out result))
+          result.Value = Context.BestSolution;
+        else Results.Add(new Result("BestSolution", Context.BestSolution));
+
+        try {
+          Context.RunOperator(Analyzer, cancellationToken);
+        } catch (OperationCanceledException) { }
+
+        if (cancellationToken.IsCancellationRequested) break;
+      }
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHCContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHCContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHCContext.cs	(revision 17175)
@@ -0,0 +1,91 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LAHC {
+  [Item("LAHC Context", "Context for late-acceptance hill climber")]
+  [StorableType("546B6C06-D986-49AA-BDEB-B664D2A9DA8C")]
+  public sealed class LAHCContext : SingleSolutionContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<DoubleArray> memory;
+    public DoubleArray Memory {
+      get { return memory.Value; }
+      set { memory.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> lastSuccess;
+    public int LastSuccess {
+      get { return lastSuccess.Value.Value; }
+      set { lastSuccess.Value.Value = value; }
+    }
+    
+    [StorableConstructor]
+    private LAHCContext(StorableConstructorFlag _) : base(_) { }
+    private LAHCContext(LAHCContext original, Cloner cloner)
+    : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+      memory = cloner.Clone(original.memory);
+      lastSuccess = cloner.Clone(original.lastSuccess);
+    }
+    public LAHCContext() {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+      Parameters.Add(memory = new ValueParameter<DoubleArray>("Memory"));
+      Parameters.Add(lastSuccess = new ValueParameter<IntValue>("LastSuccess"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LAHCContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<GQAPSolution> ToScope(GQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<GQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      return scope;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHC.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHC.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHC.cs	(revision 17175)
@@ -0,0 +1,216 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LAHC {
+  [Item("pLAHC-s (GQAP)", "Parameterless Late-acceptance hill climber for the GQAP.")]
+  [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
+  [StorableType("90A97927-D784-4F73-9215-ADC75A9F6C9D")]
+  public sealed class PLAHCS : StochasticAlgorithm<PLAHCContext, IntegerVectorEncoding> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [Storable]
+    private FixedValueParameter<IntValue> maximumExponentParameter;
+    public IFixedValueParameter<IntValue> MaximumExponentParameter {
+      get { return maximumExponentParameter; }
+    }
+
+    [Storable]
+    private FixedValueParameter<IntValue> minimumSprintIterationsParameter;
+    public IFixedValueParameter<IntValue> MinimumSprintIterationsParameter {
+      get { return minimumSprintIterationsParameter; }
+    }
+
+    public int MaximumExponent {
+      get { return maximumExponentParameter.Value.Value; }
+      set { maximumExponentParameter.Value.Value = value; }
+    }
+
+    public int MinimumSprintIterations {
+      get { return minimumSprintIterationsParameter.Value.Value; }
+      set { minimumSprintIterationsParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private PLAHCS(StorableConstructorFlag _) : base(_) { }
+    private PLAHCS(PLAHCS original, Cloner cloner)
+      : base(original, cloner) {
+      maximumExponentParameter = cloner.Clone(original.maximumExponentParameter);
+      minimumSprintIterationsParameter = cloner.Clone(original.minimumSprintIterationsParameter);
+    }
+    public PLAHCS() {
+      Parameters.Add(maximumExponentParameter = new FixedValueParameter<IntValue>("MaximumExponent", "The maximum power to which memory sizes should be tried (2^x). Do not set higher than 31", new IntValue(24)));
+      Parameters.Add(minimumSprintIterationsParameter = new FixedValueParameter<IntValue>("MinimumSprintIterations", "The minimum amount of iterations per sprint.", new IntValue(100000)));
+
+      Problem = new GQAP();
+    }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PLAHCS(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken token) {
+      base.Initialize(token);
+
+      Context.Problem = Problem;
+      Context.LastSuccess = 0;
+
+      var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length);
+      var eval = Problem.ProblemInstance.Evaluate(assign);
+      var fit = Problem.ProblemInstance.ToSingleObjective(eval);
+      Context.EvaluatedSolutions++;
+
+      var candidate = new GQAPSolution(assign, eval);
+
+      Context.ReplaceIncumbent(Context.ToScope(candidate, fit));
+      Context.BestQuality = fit;
+      Context.BestSolution = (GQAPSolution)candidate.Clone();
+
+      Context.BestList = new ItemList<DoubleValue>(new[] { new DoubleValue(Context.BestQuality) });
+
+      Results.Add(new Result("Sprint Iterations", new IntValue(Context.SprintIterations)));
+      Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+      Results.Add(new Result("CurrentMemorySize", new IntValue(0)));
+
+      try {
+        Context.RunOperator(Analyzer, token);
+      } catch (OperationCanceledException) { }
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      var lastUpdate = ExecutionTime;
+      for (var i = 0; i <= MaximumExponent; i++) {
+        var l = (int)Math.Pow(2, i);
+        var memory = new double[l];
+        for (var vv = 0; vv < l; vv++)
+          memory[vv] = Context.BestList[Context.BestList.Count - 1 - (vv % Context.BestList.Count)].Value;
+        Array.Sort(memory);
+        Context.Memory = new DoubleArray(memory);
+        if (i > 0) Context.ReplaceIncumbent(Context.ToScope((GQAPSolution)Context.BestSolution.Clone(), Context.BestQuality));
+        IResult memorySizeResult;
+        if (Results.TryGetValue("CurrentMemorySize", out memorySizeResult))
+          ((IntValue)memorySizeResult.Value).Value = Context.Memory.Length;
+        else Results.Add(new Result("CurrentMemorySize", new IntValue(Context.Memory.Length)));
+
+        Context.SprintIterations = 0;
+        while (!StoppingCriterion()
+          && (Context.SprintIterations < MinimumSprintIterations
+          || (Context.SprintIterations - Context.LastSuccess) < Context.SprintIterations * 0.02)) {
+
+          var move = StochasticNMoveSingleMoveGenerator.GenerateOneMove(Context.Random,
+            Context.Incumbent.Solution.Assignment, Problem.ProblemInstance.Capacities);
+          var moveEval = GQAPNMoveEvaluator.Evaluate(move,
+            Context.Incumbent.Solution.Assignment,
+            Context.Incumbent.Solution.Evaluation, Problem.ProblemInstance);
+          if (Context.SprintIterations % Problem.ProblemInstance.Demands.Length == 0)
+            Context.EvaluatedSolutions++;
+          var nextFit = Problem.ProblemInstance.ToSingleObjective(moveEval);
+          var nextVec = new IntegerVector(Context.Incumbent.Solution.Assignment);
+          NMoveMaker.Apply(nextVec, move);
+
+          var v = Context.Iterations % Context.Memory.Length;
+          Context.Iterations++;
+          Context.SprintIterations++;
+          var prevFit = Context.Memory[v];
+
+          var accept = nextFit <= Context.Incumbent.Fitness
+                    || nextFit <= prevFit;
+
+          if (accept && nextFit < Context.Incumbent.Fitness)
+            Context.LastSuccess = Context.SprintIterations;
+
+          if (accept) {
+            Context.ReplaceIncumbent(Context.ToScope(new GQAPSolution(nextVec, moveEval), nextFit));
+            if (nextFit < Context.BestQuality) {
+              Context.BestSolution = (GQAPSolution)Context.Incumbent.Solution.Clone();
+              Context.BestQuality = nextFit;
+              Context.BestList.Add(new DoubleValue(Context.BestQuality));
+            }
+          }
+
+          if (Context.Incumbent.Fitness < prevFit)
+            Context.Memory[v] = Context.Incumbent.Fitness;
+
+          IResult result;
+          if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+            if (Results.TryGetValue("Iterations", out result))
+              ((IntValue)result.Value).Value = Context.Iterations;
+            else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+            if (Results.TryGetValue("Sprint Iterations", out result))
+              ((IntValue)result.Value).Value = Context.SprintIterations;
+            else Results.Add(new Result("Total Iterations", new IntValue(Context.SprintIterations)));
+            if (Results.TryGetValue("EvaluatedSolutions", out result))
+              ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+            else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+            lastUpdate = ExecutionTime;
+          }
+          if (Results.TryGetValue("BestQuality", out result))
+            ((DoubleValue)result.Value).Value = Context.BestQuality;
+          else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+          if (Results.TryGetValue("BestSolution", out result))
+            result.Value = Context.BestSolution;
+          else Results.Add(new Result("BestSolution", Context.BestSolution));
+
+          try {
+            Context.RunOperator(Analyzer, cancellationToken);
+          } catch (OperationCanceledException) { }
+
+          if (cancellationToken.IsCancellationRequested) break;
+        }
+        if (StoppingCriterion() || cancellationToken.IsCancellationRequested) break;
+      }
+
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("Sprint Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.SprintIterations;
+      else Results.Add(new Result("Sprint Iterations", new IntValue(Context.SprintIterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHCContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHCContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHCContext.cs	(revision 17175)
@@ -0,0 +1,109 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LAHC {
+  [Item("pLAHC-s Context", "Context for parameterless late-acceptance hill climber with seeding.")]
+  [StorableType("3C550AB5-8FEC-42DA-9200-ABC98A1C20EA")]
+  public sealed class PLAHCContext : SingleSolutionContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> sprintIterations;
+    public int SprintIterations {
+      get { return sprintIterations.Value.Value; }
+      set { sprintIterations.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<DoubleArray> memory;
+    public DoubleArray Memory {
+      get { return memory.Value; }
+      set { memory.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> lastSuccess;
+    public int LastSuccess {
+      get { return lastSuccess.Value.Value; }
+      set { lastSuccess.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<ItemList<DoubleValue>> bestList;
+    public ItemList<DoubleValue> BestList {
+      get { return bestList.Value; }
+      set { bestList.Value = value; }
+    }
+    
+    [StorableConstructor]
+    private PLAHCContext(StorableConstructorFlag _) : base(_) { }
+    private PLAHCContext(PLAHCContext original, Cloner cloner)
+    : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+      sprintIterations = cloner.Clone(original.sprintIterations);
+      memory = cloner.Clone(original.memory);
+      lastSuccess = cloner.Clone(original.lastSuccess);
+      bestList = cloner.Clone(original.bestList);
+    }
+    public PLAHCContext() {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+      Parameters.Add(sprintIterations = new ValueParameter<IntValue>("SprintIterations"));
+      Parameters.Add(memory = new ValueParameter<DoubleArray>("Memory"));
+      Parameters.Add(lastSuccess = new ValueParameter<IntValue>("LastSuccess"));
+      Parameters.Add(bestList = new ValueParameter<ItemList<DoubleValue>>("BestList"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PLAHCContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<GQAPSolution> ToScope(GQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<GQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      return scope;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/IteratedLS.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/IteratedLS.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/IteratedLS.cs	(revision 17175)
@@ -0,0 +1,161 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LocalSearch {
+  [Item("Iterated Local Search (GQAP)", "Iterated local search for the GQAP.")]
+  [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
+  [StorableType("2C8EE433-B133-4382-8B4F-4EFFA536D759")]
+  public sealed class IteratedLS : StochasticAlgorithm<LocalSearchContext, IntegerVectorEncoding> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [Storable]
+    private IFixedValueParameter<PercentValue> perturbationStrengthParameter;
+    public IFixedValueParameter<PercentValue> PerturbationStrengthParameter {
+      get { return perturbationStrengthParameter; }
+    }
+
+    public double PerturbationStrength {
+      get { return perturbationStrengthParameter.Value.Value; }
+      set { perturbationStrengthParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private IteratedLS(StorableConstructorFlag _) : base(_) { }
+    private IteratedLS(IteratedLS original, Cloner cloner)
+      : base(original, cloner) {
+      perturbationStrengthParameter = cloner.Clone(original.perturbationStrengthParameter);
+    }
+    public IteratedLS() {
+      Parameters.Add(perturbationStrengthParameter = new FixedValueParameter<PercentValue>("PerturbationStrength", "The expected length of the random walk relative to the size of the solution vector.", new PercentValue(0.5)));
+
+      Problem = new GQAP();
+    }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new IteratedLS(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken token) {
+      base.Initialize(token);
+
+      Context.Problem = Problem;
+      Context.BestSolution = null;
+
+      var assign = GreedyRandomizedSolutionCreator.CreateSolution(Context.Random, Problem.ProblemInstance, 10, true, token);
+      var eval = Problem.ProblemInstance.Evaluate(assign);
+      var fit = Problem.ProblemInstance.ToSingleObjective(eval);
+      Context.EvaluatedSolutions++;
+
+      var candidate = new GQAPSolution(assign, eval);
+      var lsevaluations = 0;
+      OneOptLocalSearch.Apply(Context.Random, candidate, Problem.ProblemInstance, out lsevaluations);
+      Context.EvaluatedSolutions += lsevaluations;
+
+      Context.ReplaceIncumbent(Context.ToScope(candidate, fit));
+      Context.BestQuality = fit;
+      Context.BestSolution = (GQAPSolution)candidate.Clone();
+
+      Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+      Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+      Results.Add(new Result("BestSolution", Context.BestSolution));
+
+      try {
+        Context.RunOperator(Analyzer, token);
+      } catch (OperationCanceledException) { }
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      var lastUpdate = ExecutionTime;
+
+      while (!StoppingCriterion()) {
+        var lsevaluations = 0;
+        var candidate = (GQAPSolution)Context.Incumbent.Solution.Clone();
+        RelocateEquipmentManipluator.Apply(Context.Random, candidate.Assignment, Problem.ProblemInstance.Capacities.Length, 1.0 / (PerturbationStrength * candidate.Assignment.Length));
+        candidate.Evaluation = Problem.ProblemInstance.Evaluate(candidate.Assignment);
+        Context.EvaluatedSolutions++;
+        OneOptLocalSearch.Apply(Context.Random, candidate, Problem.ProblemInstance, out lsevaluations);
+        Context.EvaluatedSolutions += lsevaluations;
+
+        var candidateFit = Problem.ProblemInstance.ToSingleObjective(candidate.Evaluation);
+        if (candidateFit < Context.Incumbent.Fitness) {
+          Context.ReplaceIncumbent(Context.ToScope(candidate, candidateFit));
+          Context.BestQuality = candidateFit;
+          Context.BestSolution = (GQAPSolution)candidate.Clone();
+        }
+
+        IResult result;
+        if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
+        if (Results.TryGetValue("BestQuality", out result))
+          ((DoubleValue)result.Value).Value = Context.BestQuality;
+        else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+        if (Results.TryGetValue("BestSolution", out result))
+          result.Value = Context.BestSolution;
+        else Results.Add(new Result("BestSolution", Context.BestSolution));
+
+        try {
+          Context.RunOperator(Analyzer, cancellationToken);
+        } catch (OperationCanceledException) { }
+
+        Context.Iterations++;
+        if (cancellationToken.IsCancellationRequested) break;
+      }
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/LocalSearchContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/LocalSearchContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/LocalSearchContext.cs	(revision 17175)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LocalSearch {
+  [Item("Local Search Context", "Context for local search algorithms.")]
+  [StorableType("1AD51259-7DDB-43C1-A4A0-9E8B652988B1")]
+  public sealed class LocalSearchContext : SingleSolutionContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+    
+    [StorableConstructor]
+    private LocalSearchContext(StorableConstructorFlag _) : base(_) { }
+    private LocalSearchContext(LocalSearchContext original, Cloner cloner)
+    : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+    }
+    public LocalSearchContext() {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LocalSearchContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<GQAPSolution> ToScope(GQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<GQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      return scope;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/MultistartLS.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/MultistartLS.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/MultistartLS.cs	(revision 17175)
@@ -0,0 +1,126 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LocalSearch {
+  [Item("Multi-start Local Search (GQAP)", "Multi-start local search for the GQAP.")]
+  [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
+  [StorableType("DA79118A-BA6B-4A0F-81E6-752D750BF7F4")]
+  public sealed class MultistartLS : StochasticAlgorithm<LocalSearchContext, IntegerVectorEncoding> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [StorableConstructor]
+    private MultistartLS(StorableConstructorFlag _) : base(_) { }
+    private MultistartLS(MultistartLS original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public MultistartLS() {
+
+      Problem = new GQAP();
+    }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultistartLS(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken token) {
+      base.Initialize(token);
+
+      Context.Problem = Problem;
+      Context.BestSolution = null;
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      var lastUpdate = ExecutionTime;
+
+      while (!StoppingCriterion()) {
+        var lsevaluations = 0;
+        var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length);
+        var eval = Problem.ProblemInstance.Evaluate(assign);
+        Context.EvaluatedSolutions++;
+
+        var candidate = new GQAPSolution(assign, eval);
+        OneOptLocalSearch.Apply(Context.Random, candidate, Problem.ProblemInstance, out lsevaluations);
+        Context.EvaluatedSolutions += lsevaluations;
+
+        var candidateFit = Problem.ProblemInstance.ToSingleObjective(candidate.Evaluation);
+        if (Context.Incumbent == null || candidateFit < Context.Incumbent.Fitness) {
+          Context.ReplaceIncumbent(Context.ToScope(candidate, candidateFit));
+          Context.BestQuality = candidateFit;
+          Context.BestSolution = (GQAPSolution)candidate.Clone();
+        }
+
+        IResult result;
+        if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
+        if (Results.TryGetValue("BestQuality", out result))
+          ((DoubleValue)result.Value).Value = Context.BestQuality;
+        else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+        if (Results.TryGetValue("BestSolution", out result))
+          result.Value = Context.BestSolution;
+        else Results.Add(new Result("BestSolution", Context.BestSolution));
+
+        try {
+          Context.RunOperator(Analyzer, cancellationToken);
+        } catch (OperationCanceledException) { }
+
+        Context.Iterations++;
+        if (cancellationToken.IsCancellationRequested) break;
+      }
+
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/GQAPBinarySolver.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/GQAPBinarySolver.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/GQAPBinarySolver.cs	(revision 17175)
@@ -0,0 +1,232 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using localsolver;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LocalSolverNet {
+  [Item("LocalSolver Binary (GQAP)", "LocalSolver algorithm solving the GQAP using 0-1 decision variables")]
+  [StorableType("E9040268-4240-4EF7-8E9A-6991D0831D06")]
+  [Creatable(CreatableAttribute.Categories.Algorithms)]
+  public sealed class GQAPBinarySolver : ContextAlgorithm<LocalSolverContext, IntegerVectorEncoding> {
+    public override bool SupportsPause {
+      get { return false; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    // LS Program variables
+    private LSExpression[][] x;
+    private LSExpression[] equipmentsOnLocations;
+    private LSExpression obj;
+    private LocalSolver localSolver;
+
+
+    [StorableConstructor]
+    private GQAPBinarySolver(StorableConstructorFlag _) : base(_) { }
+    private GQAPBinarySolver(GQAPBinarySolver original, Cloner cloner)
+    : base(original, cloner) {
+    }
+    public GQAPBinarySolver() {
+      Problem = new GQAP();
+      MaximumEvaluationsParameter.Hidden = true;
+      MaximumIterationsParameter.Hidden = true;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPBinarySolver(this, cloner);
+    }
+
+    private double prevObj;
+    private DateTime lastUpdate;
+    private CancellationToken token;
+
+    private void LocalSolverOnIterationTicked(LocalSolver ls, LSCallbackType type) {
+      IResult result;
+      Context.Iterations++;
+      if ((DateTime.UtcNow - lastUpdate) > TimeSpan.FromSeconds(1)) {
+        if (Results.TryGetValue("Iterations", out result))
+          ((IntValue)result.Value).Value = Context.Iterations;
+        else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+        lastUpdate = DateTime.UtcNow;
+      }
+
+      if (token.IsCancellationRequested) localSolver.Stop();
+
+      var curObj = obj.GetDoubleValue();
+
+      if (curObj >= prevObj) return;
+      UpdateSolution(curObj);
+
+      Context.RunOperator(Analyzer, CancellationToken.None);
+
+      if (StoppingCriterion()) localSolver.Stop();
+    }
+
+    private void UpdateSolution(double obj) {
+      IResult result;
+      prevObj = obj;
+      Context.BestQuality = obj;
+
+      if (Results.TryGetValue("BestQuality", out result))
+        ((DoubleValue)result.Value).Value = Context.BestQuality;
+      else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+
+      var locations = Problem.ProblemInstance.Capacities.Length;
+      var best = new int[Problem.ProblemInstance.Demands.Length];
+      for (var i = 0; i < best.Length; i++) {
+        for (var j = 0; j < locations; j++) {
+          if (x[i][j].GetIntValue() == 1) {
+            best[i] = j;
+            break;
+          }
+        }
+      }
+      var bestVec = new IntegerVector(best);
+      var eval = Problem.ProblemInstance.Evaluate(bestVec);
+      Context.BestSolution = new GQAPSolution(bestVec, eval);
+
+      var scope = Context.ToScope(new GQAPSolution(new IntegerVector(best), (Evaluation)eval.Clone()), Problem.ProblemInstance.ToSingleObjective(eval));
+      Context.ReplaceIncumbent(scope);
+
+      if (Results.TryGetValue("BestSolution", out result))
+        result.Value = Context.BestSolution;
+      else Results.Add(new Result("BestSolution", Context.BestSolution));
+    }
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+
+      prevObj = double.MaxValue;
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      token = cancellationToken;
+      lastUpdate = DateTime.UtcNow.AddSeconds(-1);
+      localSolver = new LocalSolver();
+
+      // Declares the optimization model
+      LSModel model = localSolver.GetModel();
+
+      var data = Problem.ProblemInstance;
+
+      // x[f,l] = 1 if equipments f is on location l, 0 otherwise
+      x = new LSExpression[data.Demands.Length][];
+      for (int f = 0; f < data.Demands.Length; f++) {
+        x[f] = new LSExpression[data.Capacities.Length];
+        for (int l = 0; l < data.Capacities.Length; l++) {
+          x[f][l] = model.Bool();
+        }
+      }
+
+      // All equipments are installed in exactly 1 location
+      for (int f = 0; f < data.Demands.Length; f++) {
+        LSExpression nbLocationsAssigned = model.Sum();
+        for (int l = 0; l < data.Capacities.Length; l++) {
+          nbLocationsAssigned.AddOperand(x[f][l]);
+        }
+        model.Constraint(nbLocationsAssigned == 1);
+      }
+
+      // All locations contain not more equipments than there is capacity for
+      for (int l = 0; l < data.Capacities.Length; l++) {
+        LSExpression assignedDemand = model.Sum();
+        for (int f = 0; f < data.Demands.Length; f++) {
+          assignedDemand.AddOperand(x[f][l] * data.Demands[f]);
+        }
+        model.Constraint(assignedDemand <= data.Capacities[l]);
+      }
+
+      // Index of the assigned location of equipment f
+      equipmentsOnLocations = new LSExpression[data.Demands.Length];
+      for (int f = 0; f < data.Demands.Length; f++) {
+        equipmentsOnLocations[f] = model.Sum();
+        for (int l = 0; l < data.Capacities.Length; l++) {
+          equipmentsOnLocations[f].AddOperand(l * x[f][l]);
+        }
+      }
+
+      // Create distances as an array to be accessed by an at operator
+      var distancesJagged = new double[data.Capacities.Length][];
+      for (var i = 0; i < data.Capacities.Length; i++) {
+        distancesJagged[i] = new double[data.Capacities.Length];
+        for (var j = 0; j < data.Capacities.Length; j++)
+          distancesJagged[i][j] = data.Distances[i, j];
+      }
+      var installJagged = new double[data.Demands.Length][];
+      for (var i = 0; i < data.Demands.Length; i++) {
+        installJagged[i] = new double[data.Capacities.Length];
+        for (var j = 0; j < data.Capacities.Length; j++)
+          installJagged[i][j] = data.InstallationCosts[i, j];
+      }
+      LSExpression distancesArray = model.Array(distancesJagged);
+      LSExpression installCostsArray = model.Array(installJagged);
+
+      // Minimize the sum of product distance*flow
+      obj = model.Sum();
+      for (int f1 = 0; f1 < data.Demands.Length; f1++) {
+        for (int f2 = 0; f2 < data.Demands.Length; f2++) {
+          obj.AddOperand(data.TransportationCosts * data.Weights[f1, f2] * distancesArray[equipmentsOnLocations[f1], equipmentsOnLocations[f2]]);
+        }
+        obj.AddOperand(installCostsArray[f1, equipmentsOnLocations[f1]]);
+      }
+
+      model.Minimize(obj);
+
+      try {
+        model.Close();
+
+        // Parameterizes the solver.
+        LSPhase phase = localSolver.CreatePhase();
+        phase.SetTimeLimit((int)Math.Ceiling(MaximumRuntime.TotalSeconds));
+
+        localSolver.AddCallback(LSCallbackType.IterationTicked, LocalSolverOnIterationTicked);
+
+        localSolver.Solve();
+
+        var curObj = obj.GetDoubleValue();
+        if (curObj < prevObj)
+          UpdateSolution(curObj);
+
+        localSolver.RemoveCallback(LSCallbackType.IterationTicked, LocalSolverOnIterationTicked);
+      } finally {
+        localSolver.Dispose();
+      }
+
+      Context.RunOperator(Analyzer, CancellationToken.None);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/GQAPIntegerSolver.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/GQAPIntegerSolver.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/GQAPIntegerSolver.cs	(revision 17175)
@@ -0,0 +1,204 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using localsolver;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LocalSolverNet {
+  [Item("LocalSolver Integer (GQAP)", "LocalSolver algorithm solving the GQAP using integer decision variables")]
+  [StorableType("6D0D77CE-A8DE-41EA-9674-A1D59782D03B")]
+  [Creatable(CreatableAttribute.Categories.Algorithms)]
+  public sealed class GQAPIntegerSolver : ContextAlgorithm<LocalSolverContext, IntegerVectorEncoding> {
+    public override bool SupportsPause {
+      get { return false; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    // LS Program variables
+    private LSExpression[] x;
+    private LSExpression obj;
+    private LocalSolver localSolver;
+
+
+    [StorableConstructor]
+    private GQAPIntegerSolver(StorableConstructorFlag _) : base(_) { }
+    private GQAPIntegerSolver(GQAPIntegerSolver original, Cloner cloner)
+    : base(original, cloner) {
+    }
+    public GQAPIntegerSolver() {
+      Problem = new GQAP();
+      MaximumEvaluationsParameter.Hidden = true;
+      MaximumIterationsParameter.Hidden = true;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPIntegerSolver(this, cloner);
+    }
+
+    private double prevObj;
+    private DateTime lastUpdate;
+    private CancellationToken token;
+
+    private void LocalSolverOnIterationTicked(LocalSolver ls, LSCallbackType type) {
+      IResult result;
+      Context.Iterations++;
+      if ((DateTime.UtcNow - lastUpdate) > TimeSpan.FromSeconds(1)) {
+        if (Results.TryGetValue("Iterations", out result))
+          ((IntValue)result.Value).Value = Context.Iterations;
+        else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+        lastUpdate = DateTime.UtcNow;
+      }
+
+      if (token.IsCancellationRequested) localSolver.Stop();
+
+      var curObj = obj.GetDoubleValue();
+
+      if (curObj >= prevObj) return;
+      UpdateSolution(curObj);
+
+      Context.RunOperator(Analyzer, CancellationToken.None);
+
+      if (StoppingCriterion()) localSolver.Stop();
+    }
+
+    private void UpdateSolution(double obj) {
+      IResult result;
+      prevObj = obj;
+      Context.BestQuality = obj;
+
+      if (Results.TryGetValue("BestQuality", out result))
+        ((DoubleValue)result.Value).Value = Context.BestQuality;
+      else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+
+      var locations = Problem.ProblemInstance.Capacities.Length;
+      var best = new int[Problem.ProblemInstance.Demands.Length];
+      for (var i = 0; i < best.Length; i++) {
+        best[i] = (int)x[i].GetIntValue();
+      }
+      var bestVec = new IntegerVector(best);
+      var eval = Problem.ProblemInstance.Evaluate(bestVec);
+      Context.BestSolution = new GQAPSolution(bestVec, eval);
+
+      var scope = Context.ToScope(new GQAPSolution(new IntegerVector(best), (Evaluation)eval.Clone()), Problem.ProblemInstance.ToSingleObjective(eval));
+      Context.ReplaceIncumbent(scope);
+
+      if (Results.TryGetValue("BestSolution", out result))
+        result.Value = Context.BestSolution;
+      else Results.Add(new Result("BestSolution", Context.BestSolution));
+    }
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+
+      prevObj = double.MaxValue;
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      token = cancellationToken;
+      lastUpdate = DateTime.UtcNow.AddSeconds(-1);
+      localSolver = new LocalSolver();
+
+      // Declares the optimization model
+      LSModel model = localSolver.GetModel();
+
+      var data = Problem.ProblemInstance;
+
+      // x[f] = location l, f ... facility/equipment
+      x = new LSExpression[data.Demands.Length];
+      for (int f = 0; f < data.Demands.Length; f++) {
+        x[f] = model.Int(0, data.Capacities.Length - 1);
+      }
+
+      // All locations contain not more equipments than there is capacity for
+      for (int l = 0; l < data.Capacities.Length; l++) {
+        var util = model.Sum();
+        for (var f = 0; f < data.Demands.Length; f++)
+          util.AddOperand((x[f] == l) * data.Demands[f]);
+        model.Constraint(util <= data.Capacities[l]);
+      }
+
+      // Create distances as an array to be accessed by an at operator
+      var distancesJagged = new double[data.Capacities.Length][];
+      for (var i = 0; i < data.Capacities.Length; i++) {
+        distancesJagged[i] = new double[data.Capacities.Length];
+        for (var j = 0; j < data.Capacities.Length; j++)
+          distancesJagged[i][j] = data.Distances[i, j];
+      }
+      var installJagged = new double[data.Demands.Length][];
+      for (var i = 0; i < data.Demands.Length; i++) {
+        installJagged[i] = new double[data.Capacities.Length];
+        for (var j = 0; j < data.Capacities.Length; j++)
+          installJagged[i][j] = data.InstallationCosts[i, j];
+      }
+      LSExpression distancesArray = model.Array(distancesJagged);
+      LSExpression installCostsArray = model.Array(installJagged);
+
+      // Minimize the sum of product distance*flow
+      obj = model.Sum();
+      for (int f1 = 0; f1 < data.Demands.Length; f1++) {
+        for (int f2 = 0; f2 < data.Demands.Length; f2++) {
+          obj.AddOperand(data.TransportationCosts * data.Weights[f1, f2] * distancesArray[x[f1], x[f2]]);
+        }
+        obj.AddOperand(installCostsArray[f1, x[f1]]);
+      }
+
+      model.Minimize(obj);
+
+      try {
+        model.Close();
+
+        // Parameterizes the solver.
+        LSPhase phase = localSolver.CreatePhase();
+        phase.SetTimeLimit((int)Math.Ceiling(MaximumRuntime.TotalSeconds));
+
+        localSolver.AddCallback(LSCallbackType.IterationTicked, LocalSolverOnIterationTicked);
+
+        localSolver.Solve();
+
+        var curObj = obj.GetDoubleValue();
+        if (curObj < prevObj)
+          UpdateSolution(curObj);
+
+        localSolver.RemoveCallback(LSCallbackType.IterationTicked, LocalSolverOnIterationTicked);
+      } finally {
+        localSolver.Dispose();
+      }
+
+      Context.RunOperator(Analyzer, CancellationToken.None);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/GQAPListSolver.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/GQAPListSolver.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/GQAPListSolver.cs	(revision 17175)
@@ -0,0 +1,224 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using localsolver;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LocalSolverNet {
+  [Item("LocalSolver List (GQAP)", "LocalSolver algorithm solving the GQAP using list decision variables")]
+  [StorableType("BBB27FAA-DCFD-4DB4-A465-4A02E1A0EDA9")]
+  [Creatable(CreatableAttribute.Categories.Algorithms)]
+  public sealed class GQAPListSolver : ContextAlgorithm<LocalSolverContext, IntegerVectorEncoding> {
+    public override bool SupportsPause {
+      get { return false; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    // LS Program variables
+    private LSExpression[] x;
+    private LSExpression obj;
+    private LocalSolver localSolver;
+
+
+    [StorableConstructor]
+    private GQAPListSolver(StorableConstructorFlag _) : base(_) { }
+    private GQAPListSolver(GQAPListSolver original, Cloner cloner)
+    : base(original, cloner) {
+    }
+    public GQAPListSolver() {
+      Problem = new GQAP();
+      MaximumEvaluationsParameter.Hidden = true;
+      MaximumIterationsParameter.Hidden = true;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPListSolver(this, cloner);
+    }
+
+    private double prevObj;
+    private DateTime lastUpdate;
+    private CancellationToken token;
+
+    private void LocalSolverOnIterationTicked(LocalSolver ls, LSCallbackType type) {
+      IResult result;
+      Context.Iterations++;
+      if ((DateTime.UtcNow - lastUpdate) > TimeSpan.FromSeconds(1)) {
+        if (Results.TryGetValue("Iterations", out result))
+          ((IntValue)result.Value).Value = Context.Iterations;
+        else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+        lastUpdate = DateTime.UtcNow;
+      }
+
+      if (token.IsCancellationRequested) localSolver.Stop();
+
+      var curObj = obj.GetDoubleValue();
+
+      if (curObj >= prevObj) return;
+      UpdateSolution(curObj);
+
+      Context.RunOperator(Analyzer, CancellationToken.None);
+
+      if (StoppingCriterion()) localSolver.Stop();
+    }
+
+    private void UpdateSolution(double obj) {
+      IResult result;
+      prevObj = obj;
+      Context.BestQuality = obj;
+
+      if (Results.TryGetValue("BestQuality", out result))
+        ((DoubleValue)result.Value).Value = Context.BestQuality;
+      else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+
+      var locations = Problem.ProblemInstance.Capacities.Length;
+      var best = new int[Problem.ProblemInstance.Demands.Length];
+      for (var j = 0; j < locations; j++) {
+        var xcol = x[j].GetCollectionValue();
+        for (var i = 0; i < xcol.Count(); i++) {
+          var equip = xcol.Get(i);
+          best[equip] = j;
+        }
+      }
+      var bestVec = new IntegerVector(best);
+      var eval = Problem.ProblemInstance.Evaluate(bestVec);
+      Context.BestSolution = new GQAPSolution(bestVec, eval);
+
+      var scope = Context.ToScope(new GQAPSolution(new IntegerVector(best), (Evaluation)eval.Clone()), Problem.ProblemInstance.ToSingleObjective(eval));
+      Context.ReplaceIncumbent(scope);
+
+      if (Results.TryGetValue("BestSolution", out result))
+        result.Value = Context.BestSolution;
+      else Results.Add(new Result("BestSolution", Context.BestSolution));
+    }
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+
+      prevObj = double.MaxValue;
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      token = cancellationToken;
+      lastUpdate = DateTime.UtcNow.AddSeconds(-1);
+      localSolver = new LocalSolver();
+
+      // Declares the optimization model
+      var model = localSolver.GetModel();
+
+      var data = Problem.ProblemInstance;
+
+      x = new LSExpression[data.Capacities.Length];
+      // x[f,l] = 1 if equipments f is on location l, 0 otherwise
+      for (int r = 0; r < data.Capacities.Length; r++) {
+        x[r] = model.List(data.Demands.Length);
+      }
+
+      // All equipments are installed in exactly 1 location
+      model.Constraint(model.Partition(x));
+
+      var demandsArray = model.Array(data.Demands);
+
+      // Create distances as an array to be accessed by an at operator
+      var weightsJagged = new double[data.Demands.Length][];
+      for (var i = 0; i < data.Demands.Length; i++) {
+        weightsJagged[i] = new double[data.Demands.Length];
+        for (var j = 0; j < data.Demands.Length; j++) {
+          weightsJagged[i][j] = data.Weights[i, j];
+        }
+      }
+      var distancesJagged = new double[data.Capacities.Length][];
+      for (var i = 0; i < data.Capacities.Length; i++) {
+        distancesJagged[i] = new double[data.Capacities.Length];
+        for (var j = 0; j < data.Capacities.Length; j++)
+          distancesJagged[i][j] = data.Distances[i, j];
+      }
+      var installJagged = new double[data.Demands.Length][];
+      for (var i = 0; i < data.Demands.Length; i++) {
+        installJagged[i] = new double[data.Capacities.Length];
+        for (var j = 0; j < data.Capacities.Length; j++)
+          installJagged[i][j] = data.InstallationCosts[i, j];
+      }
+      var weightsArray = model.Array(weightsJagged);
+      var distancesArray = model.Array(distancesJagged);
+      var installCostsArray = model.Array(installJagged);
+
+      obj = model.Sum();
+      // All locations contain not more equipments than there is capacity for
+      for (int l = 0; l < data.Capacities.Length; l++) {
+        var c = model.Count(x[l]);
+        var demandSelector = model.Function(i => demandsArray[x[l][i]]);
+        var assignedDemand = model.Sum(model.Range(0, c), demandSelector);
+        model.Constraint(assignedDemand <= data.Capacities[l]);
+
+        var installCostSelector = model.Function(i => installCostsArray[x[l][i], l]);
+        var installCosts = model.Sum(model.Range(0, c), installCostSelector);
+        obj.AddOperand(installCosts);
+        
+        // Flow to other equipments
+        for (int k = 0; k < data.Capacities.Length; k++) {
+          var kc = model.Count(x[k]);
+          var flowCostSelector = model.Function(j => model.Sum(model.Range(0, c), model.Function(i => weightsArray[x[l][i], x[k][j]] * distancesArray[l, k] * data.TransportationCosts)));
+          obj.AddOperand(model.Sum(model.Range(0, kc), flowCostSelector));
+        }
+      }
+
+      model.Minimize(this.obj);
+
+      try {
+        model.Close();
+
+        // Parameterizes the solver.
+        LSPhase phase = localSolver.CreatePhase();
+        phase.SetTimeLimit((int)Math.Ceiling(MaximumRuntime.TotalSeconds));
+
+        localSolver.AddCallback(LSCallbackType.IterationTicked, LocalSolverOnIterationTicked);
+
+        localSolver.Solve();
+
+        var curObj = this.obj.GetDoubleValue();
+        if (curObj < prevObj)
+          UpdateSolution(curObj);
+
+        localSolver.RemoveCallback(LSCallbackType.IterationTicked, LocalSolverOnIterationTicked);
+      } finally {
+        localSolver.Dispose();
+      }
+
+      Context.RunOperator(Analyzer, CancellationToken.None);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/LocalSolverContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/LocalSolverContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSolverNet/LocalSolverContext.cs	(revision 17175)
@@ -0,0 +1,89 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LocalSolverNet {
+  [Item("LocalSolver Context", "A context for CPLEX solvers.")]
+  [StorableType("DAE4D0C7-AFE1-4FCF-9DD5-899E4DC4FD9E")]
+  public class LocalSolverContext : SingleSolutionContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected LocalSolverContext(StorableConstructorFlag _) : base(_) { }
+    protected LocalSolverContext(LocalSolverContext original, Cloner cloner)
+      : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+    }
+    public LocalSolverContext() : base() {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+    }
+    public LocalSolverContext(string name) : base(name) {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+    }
+    public LocalSolverContext(string name, ParameterCollection parameters) : base(name, parameters) {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+    }
+    public LocalSolverContext(string name, string description) : base(name, description) {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+    }
+    public LocalSolverContext(string name, string description, ParameterCollection parameters) : base(name, description, parameters) {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+    }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LocalSolverContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<GQAPSolution> ToScope(GQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<GQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      return scope;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Plugin.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Plugin.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Plugin.cs	(revision 17175)
@@ -0,0 +1,46 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [Plugin("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms", "3.3.14.1")]
+  [PluginFile("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Analysis", "3.3")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.IntegerVectorEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.GeneralizedQuadraticAssignment", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Instances", "3.3")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+  //[PluginDependency("CPLEX Transport", "12.7.0")]
+  //[PluginDependency("LocalSolver 7.5 Transport", "7.5")]
+  public class Plugin : PluginBase {
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Properties/AssemblyInfo.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Properties/AssemblyInfo.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Properties/AssemblyInfo.cs	(revision 17175)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2017 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("577239ec-7d7f-4505-a0a4-572e34010dba")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.14.1")]
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/RandomSearch/RandomSearch.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/RandomSearch/RandomSearch.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/RandomSearch/RandomSearch.cs	(revision 17175)
@@ -0,0 +1,121 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Threading;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.RandomSearch {
+  [Item("Random Search (GQAP)", "Random search for the GQAP.")]
+  [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
+  [StorableType("D6ED1A84-BBCD-4163-96A7-47F3DCACBE49")]
+  public sealed class RandomSearch : StochasticAlgorithm<RandomSearchContext, IntegerVectorEncoding> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [StorableConstructor]
+    private RandomSearch(StorableConstructorFlag _) : base(_) { }
+    private RandomSearch(RandomSearch original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public RandomSearch() {
+      Problem = new GQAP();
+    }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RandomSearch(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken token) {
+      base.Initialize(token);
+
+      Context.Problem = Problem;
+      Context.BestSolution = null;
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      base.Run(cancellationToken);
+      var lastUpdate = ExecutionTime;
+
+      while (!StoppingCriterion()) {
+        var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length);
+        var eval = Problem.ProblemInstance.Evaluate(assign);
+        var candidate = new GQAPSolution(assign, eval);
+        Context.EvaluatedSolutions++;
+
+        var candidateFit = Problem.ProblemInstance.ToSingleObjective(candidate.Evaluation);
+        if (Context.Incumbent == null || candidateFit < Context.Incumbent.Fitness) {
+          Context.ReplaceIncumbent(Context.ToScope(candidate, candidateFit));
+          Context.BestQuality = candidateFit;
+          Context.BestSolution = (GQAPSolution)candidate.Clone();
+        }
+
+        IResult result;
+        if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
+        if (Results.TryGetValue("BestQuality", out result))
+          ((DoubleValue)result.Value).Value = Context.BestQuality;
+        else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+        if (Results.TryGetValue("BestSolution", out result))
+          result.Value = Context.BestSolution;
+        else Results.Add(new Result("BestSolution", Context.BestSolution));
+
+        try {
+          Context.RunOperator(Analyzer, cancellationToken);
+        } catch (OperationCanceledException) { }
+
+        Context.Iterations++;
+        if (cancellationToken.IsCancellationRequested) break;
+      }
+
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/RandomSearch/RandomSearchContext.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/RandomSearch/RandomSearchContext.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/RandomSearch/RandomSearchContext.cs	(revision 17175)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.RandomSearch {
+  [Item("Random Search Context", "Context for random search algorithms.")]
+  [StorableType("49827D3F-3668-44C8-888B-5F5EB6769652")]
+  public sealed class RandomSearchContext : SingleSolutionContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+    
+    [StorableConstructor]
+    private RandomSearchContext(StorableConstructorFlag _) : base(_) { }
+    private RandomSearchContext(RandomSearchContext original, Cloner cloner)
+    : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+    }
+    public RandomSearchContext() {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RandomSearchContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<GQAPSolution> ToScope(GQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<GQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      return scope;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/GeneralizedQAPLIBInstanceDescriptor.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/GeneralizedQAPLIBInstanceDescriptor.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/GeneralizedQAPLIBInstanceDescriptor.cs	(revision 17175)
@@ -0,0 +1,37 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Problems.Instances;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances {
+  internal class GeneralizedQAPLIBInstanceDescriptor : IDataDescriptor {
+    public string Name { get; internal set; }
+    public string Description { get; internal set; }
+
+    internal string InstanceIdentifier { get; set; }
+
+    internal GeneralizedQAPLIBInstanceDescriptor(string name, string description, string instanceIdentifier) {
+      this.Name = name;
+      this.Description = description;
+      this.InstanceIdentifier = instanceIdentifier;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/GeneralizedQAPLIBInstanceProvider.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/GeneralizedQAPLIBInstanceProvider.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/GeneralizedQAPLIBInstanceProvider.cs	(revision 17175)
@@ -0,0 +1,118 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.Instances.CordeauGQAP;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances {
+  public class GeneralizedQAPLIBInstanceProvider : ProblemInstanceProvider<GQAPData> {
+    public override string Name {
+      get { return "Generalized QAPLIB"; }
+    }
+
+    public override string Description {
+      get { return "GQAP instances based on flow and distance matrices from QAPLIB instances."; }
+    }
+
+    public override Uri WebLink {
+      get { return null; }
+    }
+
+    public override string ReferencePublication {
+      get { return null; }
+    }
+
+    private const string FileName = "Data";
+
+    public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
+      var instanceArchiveName = GetResourceName(FileName + @"\.zip");
+      if (String.IsNullOrEmpty(instanceArchiveName)) yield break;
+
+      using (var instanceStream = new ZipArchive(GetType().Assembly.GetManifestResourceStream(instanceArchiveName), ZipArchiveMode.Read)) {
+        foreach (var entry in instanceStream.Entries.Select(x => x.Name).OrderBy(x => x)) {
+          yield return new GeneralizedQAPLIBInstanceDescriptor(Path.GetFileNameWithoutExtension(entry), GetDescription(), entry);
+        }
+      }
+    }
+
+    public override GQAPData LoadData(IDataDescriptor id) {
+      var descriptor = (GeneralizedQAPLIBInstanceDescriptor)id;
+      var instanceArchiveName = GetResourceName(FileName + @"\.zip");
+      using (var instancesZipFile = new ZipArchive(GetType().Assembly.GetManifestResourceStream(instanceArchiveName), ZipArchiveMode.Read)) {
+        var entry = instancesZipFile.GetEntry(descriptor.InstanceIdentifier);
+        using (var stream = entry.Open()) {
+          var parser = new CordeauGQAPParser();
+          parser.Parse(stream);
+          var instance = Load(parser);
+
+          instance.Name = id.Name;
+          instance.Description = id.Description;
+
+          return instance;
+        }
+      }
+    }
+
+    public override bool CanImportData {
+      get { return true; }
+    }
+    public override GQAPData ImportData(string path) {
+      var parser = new CordeauGQAPParser();
+      parser.Parse(path);
+      var instance = Load(parser);
+
+      instance.Name = Path.GetFileName(path);
+      instance.Description = "Loaded from file \"" + path + "\" on " + DateTime.Now.ToString();
+
+      return instance;
+    }
+
+    private GQAPData Load(CordeauGQAPParser parser) {
+      var instance = new GQAPData();
+      instance.BestKnownQuality = parser.BestKnownQuality;
+      instance.Equipments = parser.Equipments;
+      instance.Locations = parser.Locations;
+      instance.Demands = parser.Demands;
+      instance.Capacities = parser.Capacities;
+      instance.Weights = parser.Weights;
+      instance.Distances = parser.Distances;
+      instance.InstallationCosts = parser.InstallationCosts;
+      instance.TransportationCosts = parser.TransportationCosts;
+      return instance;
+    }
+
+    private string GetDescription() {
+      return "Embedded instance of plugin version " + Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyFileVersionAttribute), true).Cast<AssemblyFileVersionAttribute>().First().Version + ".";
+    }
+
+    protected virtual string GetResourceName(string fileName) {
+      return Assembly.GetExecutingAssembly().GetManifestResourceNames()
+              .Where(x => Regex.Match(x, @".*\.Data\." + fileName).Success).SingleOrDefault();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances-3.3.csproj
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances-3.3.csproj	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances-3.3.csproj	(revision 17175)
@@ -0,0 +1,85 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances.CordeauGQAP-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Problems.Instances.CordeauGQAP-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.IO.Compression" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Data\Data.zip" />
+    <None Include="HeuristicLab.snk" />
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="GeneralizedQAPLIBInstanceDescriptor.cs" />
+    <Compile Include="GeneralizedQAPLIBInstanceProvider.cs" />
+    <Compile Include="Plugin.cs" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Plugin.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Plugin.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Plugin.cs	(revision 17175)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances {
+  [Plugin("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances", "3.3.14.0")]
+  [PluginFile("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Instances", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Instances.CordeauGQAP", "3.3")]
+  public class Plugin : PluginBase {
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Plugin.cs.frame
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Plugin.cs.frame	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Plugin.cs.frame	(revision 17175)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances {
+  [Plugin("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances", "3.3.14.0")]
+  [PluginFile("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Instances", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Instances.CordeauGQAP", "3.3")]
+  public class Plugin : PluginBase {
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Properties/AssemblyInfo.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Properties/AssemblyInfo.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Properties/AssemblyInfo.cs	(revision 17175)
@@ -0,0 +1,55 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0eb9ab8e-d0d2-4a63-9353-bd5ce57dbdfe")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.0.0")]
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Properties/AssemblyInfo.cs.frame	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances/3.3/Properties/AssemblyInfo.cs.frame	(revision 17175)
@@ -0,0 +1,55 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0eb9ab8e-d0d2-4a63-9353-bd5ce57dbdfe")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.0.0")]
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.Designer.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.Designer.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.Designer.cs	(revision 17175)
@@ -0,0 +1,108 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views {
+  partial class GQAPAssignmentArchiveView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
+      this.paretoFrontChart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      this.messageLabel = new System.Windows.Forms.Label();
+      ((System.ComponentModel.ISupportInitialize)(this.paretoFrontChart)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // paretoFrontChart
+      // 
+      chartArea1.AxisX.Title = "FlowDistanceQuality";
+      chartArea1.AxisY.Title = "InstallationQuality";
+      chartArea1.CursorX.IsUserSelectionEnabled = true;
+      chartArea1.CursorY.IsUserSelectionEnabled = true;
+      chartArea1.Name = "ChartArea1";
+      this.paretoFrontChart.ChartAreas.Add(chartArea1);
+      this.paretoFrontChart.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.paretoFrontChart.Location = new System.Drawing.Point(0, 0);
+      this.paretoFrontChart.Name = "paretoFrontChart";
+      series1.ChartArea = "ChartArea1";
+      series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Point;
+      series1.MarkerSize = 10;
+      series1.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Cross;
+      series1.Name = "ParetoFront";
+      series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Double;
+      series1.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Double;
+      this.paretoFrontChart.Series.Add(series1);
+      this.paretoFrontChart.Size = new System.Drawing.Size(460, 362);
+      this.paretoFrontChart.TabIndex = 0;
+      this.paretoFrontChart.Text = "Pareto Front";
+      this.paretoFrontChart.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.paretoFrontChart_MouseDoubleClick);
+      // 
+      // messageLabel
+      // 
+      this.messageLabel.Anchor = System.Windows.Forms.AnchorStyles.None;
+      this.messageLabel.AutoSize = true;
+      this.messageLabel.Location = new System.Drawing.Point(128, 151);
+      this.messageLabel.Name = "messageLabel";
+      this.messageLabel.Size = new System.Drawing.Size(209, 13);
+      this.messageLabel.TabIndex = 1;
+      this.messageLabel.Text = "Feasible solutions have not been found yet";
+      // 
+      // GQAPAssignmentArchiveView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.messageLabel);
+      this.Controls.Add(this.paretoFrontChart);
+      this.Name = "GQAPAssignmentArchiveView";
+      this.Size = new System.Drawing.Size(460, 362);
+      ((System.ComponentModel.ISupportInitialize)(this.paretoFrontChart)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private Visualization.ChartControlsExtensions.EnhancedChart paretoFrontChart;
+    private System.Windows.Forms.Label messageLabel;
+
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.cs	(revision 17175)
@@ -0,0 +1,113 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.ComponentModel;
+using System.Linq;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Collections;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views {
+  [View("GQAPAssignmentArchiveView")]
+  [Content(typeof(GQAPAssignmentArchive), IsDefaultView = true)]
+  public partial class GQAPAssignmentArchiveView : ItemView {
+    public new GQAPAssignmentArchive Content {
+      get { return (GQAPAssignmentArchive)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public GQAPAssignmentArchiveView() {
+      InitializeComponent();
+    }
+
+    #region Register Content Events
+    protected override void DeregisterContentEvents() {
+      Content.PropertyChanged -= new PropertyChangedEventHandler(Content_PropertyChanged);
+      Content.Solutions.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<GQAPSolution>>(ContentSolutions_Changed);
+      Content.Solutions.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<GQAPSolution>>(ContentSolutions_Changed);
+      Content.Solutions.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<GQAPSolution>>(ContentSolutions_Changed);
+      base.DeregisterContentEvents();
+    }
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.PropertyChanged += new PropertyChangedEventHandler(Content_PropertyChanged);
+      Content.Solutions.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<GQAPSolution>>(ContentSolutions_Changed);
+      Content.Solutions.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<GQAPSolution>>(ContentSolutions_Changed);
+      Content.Solutions.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<GQAPSolution>>(ContentSolutions_Changed);
+    }
+
+    private void ContentSolutions_Changed(object sender, CollectionItemsChangedEventArgs<IndexedItem<GQAPSolution>> e) {
+      UpdateParetoFront();
+    }
+
+    private void Content_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      UpdateParetoFront();
+    }
+    #endregion
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      UpdateParetoFront();
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+    }
+
+    private void UpdateParetoFront() {
+      if (InvokeRequired) Invoke((Action)UpdateParetoFront);
+      else {
+        paretoFrontChart.Series[0].Points.SuspendUpdates();
+        try {
+          paretoFrontChart.Series[0].Points.Clear();
+          if (Content == null) return;
+          foreach (var solution in Content.Solutions) {
+            if (solution.Evaluation.ExcessDemand <= 0.0) {
+              paretoFrontChart.Series[0].Points.AddXY(solution.Evaluation.FlowCosts, solution.Evaluation.InstallationCosts);
+              paretoFrontChart.Series[0].Points.Last().Tag = solution;
+            }
+          }
+        } finally {
+          paretoFrontChart.Series[0].Points.ResumeUpdates();
+          messageLabel.Visible = paretoFrontChart.Series[0].Points.Count == 0;
+        }
+      }
+    }
+
+    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, Content.ProblemInstance, solution.Evaluation);
+
+        var view = MainFormManager.MainForm.ShowContent(assignment);
+        if (view != null) {
+          view.ReadOnly = this.ReadOnly;
+          view.Locked = this.Locked;
+        }
+      }
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.resx
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.resx	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentArchiveView.resx	(revision 17175)
@@ -0,0 +1,120 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.Designer.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.Designer.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.Designer.cs	(revision 17175)
@@ -0,0 +1,268 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views {
+  partial class GQAPAssignmentView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.assignmentTreeView = new System.Windows.Forms.TreeView();
+      this.label1 = new System.Windows.Forms.Label();
+      this.qualityLabel = new System.Windows.Forms.Label();
+      this.assignmentGroupBox = new System.Windows.Forms.GroupBox();
+      this.assignmentSplitContainer = new System.Windows.Forms.SplitContainer();
+      this.assignmentView = new HeuristicLab.Data.Views.StringConvertibleArrayView();
+      this.characteristicsGroupBox = new System.Windows.Forms.GroupBox();
+      this.label7 = new System.Windows.Forms.Label();
+      this.overbookedCapacityLabel = new System.Windows.Forms.Label();
+      this.label5 = new System.Windows.Forms.Label();
+      this.installationQualityLabel = new System.Windows.Forms.Label();
+      this.label3 = new System.Windows.Forms.Label();
+      this.flowDistanceQualityLabel = new System.Windows.Forms.Label();
+      this.recalculateButton = new System.Windows.Forms.Button();
+      this.assignmentGroupBox.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.assignmentSplitContainer)).BeginInit();
+      this.assignmentSplitContainer.Panel1.SuspendLayout();
+      this.assignmentSplitContainer.Panel2.SuspendLayout();
+      this.assignmentSplitContainer.SuspendLayout();
+      this.characteristicsGroupBox.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // assignmentTreeView
+      // 
+      this.assignmentTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.assignmentTreeView.Location = new System.Drawing.Point(0, 0);
+      this.assignmentTreeView.Margin = new System.Windows.Forms.Padding(3, 6, 3, 3);
+      this.assignmentTreeView.Name = "assignmentTreeView";
+      this.assignmentTreeView.Size = new System.Drawing.Size(78, 337);
+      this.assignmentTreeView.TabIndex = 3;
+      this.assignmentTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.assignmentTreeView_AfterSelect);
+      this.assignmentTreeView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.assignmentTreeView_MouseUp);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(6, 19);
+      this.label1.Margin = new System.Windows.Forms.Padding(3);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(42, 13);
+      this.label1.TabIndex = 0;
+      this.label1.Text = "Quality:";
+      // 
+      // qualityLabel
+      // 
+      this.qualityLabel.AutoSize = true;
+      this.qualityLabel.Location = new System.Drawing.Point(91, 19);
+      this.qualityLabel.Margin = new System.Windows.Forms.Padding(3);
+      this.qualityLabel.Name = "qualityLabel";
+      this.qualityLabel.Size = new System.Drawing.Size(10, 13);
+      this.qualityLabel.TabIndex = 4;
+      this.qualityLabel.Text = "-";
+      // 
+      // assignmentGroupBox
+      // 
+      this.assignmentGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.assignmentGroupBox.Controls.Add(this.assignmentSplitContainer);
+      this.assignmentGroupBox.Location = new System.Drawing.Point(217, 3);
+      this.assignmentGroupBox.Name = "assignmentGroupBox";
+      this.assignmentGroupBox.Size = new System.Drawing.Size(240, 356);
+      this.assignmentGroupBox.TabIndex = 5;
+      this.assignmentGroupBox.TabStop = false;
+      this.assignmentGroupBox.Text = "Assignment";
+      // 
+      // assignmentSplitContainer
+      // 
+      this.assignmentSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.assignmentSplitContainer.Location = new System.Drawing.Point(3, 16);
+      this.assignmentSplitContainer.Name = "assignmentSplitContainer";
+      // 
+      // assignmentSplitContainer.Panel1
+      // 
+      this.assignmentSplitContainer.Panel1.Controls.Add(this.assignmentTreeView);
+      // 
+      // assignmentSplitContainer.Panel2
+      // 
+      this.assignmentSplitContainer.Panel2.Controls.Add(this.assignmentView);
+      this.assignmentSplitContainer.Size = new System.Drawing.Size(234, 337);
+      this.assignmentSplitContainer.SplitterDistance = 78;
+      this.assignmentSplitContainer.TabIndex = 4;
+      // 
+      // assignmentView
+      // 
+      this.assignmentView.Caption = "StringConvertibleArray View";
+      this.assignmentView.Content = null;
+      this.assignmentView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.assignmentView.Location = new System.Drawing.Point(0, 0);
+      this.assignmentView.Name = "assignmentView";
+      this.assignmentView.ReadOnly = false;
+      this.assignmentView.Size = new System.Drawing.Size(152, 337);
+      this.assignmentView.TabIndex = 0;
+      // 
+      // characteristicsGroupBox
+      // 
+      this.characteristicsGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left)));
+      this.characteristicsGroupBox.Controls.Add(this.recalculateButton);
+      this.characteristicsGroupBox.Controls.Add(this.label7);
+      this.characteristicsGroupBox.Controls.Add(this.overbookedCapacityLabel);
+      this.characteristicsGroupBox.Controls.Add(this.label5);
+      this.characteristicsGroupBox.Controls.Add(this.installationQualityLabel);
+      this.characteristicsGroupBox.Controls.Add(this.label3);
+      this.characteristicsGroupBox.Controls.Add(this.flowDistanceQualityLabel);
+      this.characteristicsGroupBox.Controls.Add(this.label1);
+      this.characteristicsGroupBox.Controls.Add(this.qualityLabel);
+      this.characteristicsGroupBox.Location = new System.Drawing.Point(3, 3);
+      this.characteristicsGroupBox.Name = "characteristicsGroupBox";
+      this.characteristicsGroupBox.Size = new System.Drawing.Size(208, 356);
+      this.characteristicsGroupBox.TabIndex = 6;
+      this.characteristicsGroupBox.TabStop = false;
+      this.characteristicsGroupBox.Text = "Characteristics";
+      // 
+      // label7
+      // 
+      this.label7.AutoSize = true;
+      this.label7.Location = new System.Drawing.Point(6, 76);
+      this.label7.Margin = new System.Windows.Forms.Padding(3);
+      this.label7.Name = "label7";
+      this.label7.Size = new System.Drawing.Size(71, 13);
+      this.label7.TabIndex = 0;
+      this.label7.Text = "Overbooking:";
+      // 
+      // overbookedCapacityLabel
+      // 
+      this.overbookedCapacityLabel.AutoSize = true;
+      this.overbookedCapacityLabel.Location = new System.Drawing.Point(91, 76);
+      this.overbookedCapacityLabel.Margin = new System.Windows.Forms.Padding(3);
+      this.overbookedCapacityLabel.Name = "overbookedCapacityLabel";
+      this.overbookedCapacityLabel.Size = new System.Drawing.Size(10, 13);
+      this.overbookedCapacityLabel.TabIndex = 4;
+      this.overbookedCapacityLabel.Text = "-";
+      // 
+      // label5
+      // 
+      this.label5.AutoSize = true;
+      this.label5.Location = new System.Drawing.Point(6, 57);
+      this.label5.Margin = new System.Windows.Forms.Padding(3);
+      this.label5.Name = "label5";
+      this.label5.Size = new System.Drawing.Size(60, 13);
+      this.label5.TabIndex = 0;
+      this.label5.Text = "Installation:";
+      // 
+      // installationQualityLabel
+      // 
+      this.installationQualityLabel.AutoSize = true;
+      this.installationQualityLabel.Location = new System.Drawing.Point(91, 57);
+      this.installationQualityLabel.Margin = new System.Windows.Forms.Padding(3);
+      this.installationQualityLabel.Name = "installationQualityLabel";
+      this.installationQualityLabel.Size = new System.Drawing.Size(10, 13);
+      this.installationQualityLabel.TabIndex = 4;
+      this.installationQualityLabel.Text = "-";
+      // 
+      // label3
+      // 
+      this.label3.AutoSize = true;
+      this.label3.Location = new System.Drawing.Point(6, 38);
+      this.label3.Margin = new System.Windows.Forms.Padding(3);
+      this.label3.Name = "label3";
+      this.label3.Size = new System.Drawing.Size(79, 13);
+      this.label3.TabIndex = 0;
+      this.label3.Text = "Flow/Distance:";
+      // 
+      // flowDistanceQualityLabel
+      // 
+      this.flowDistanceQualityLabel.AutoSize = true;
+      this.flowDistanceQualityLabel.Location = new System.Drawing.Point(91, 38);
+      this.flowDistanceQualityLabel.Margin = new System.Windows.Forms.Padding(3);
+      this.flowDistanceQualityLabel.Name = "flowDistanceQualityLabel";
+      this.flowDistanceQualityLabel.Size = new System.Drawing.Size(10, 13);
+      this.flowDistanceQualityLabel.TabIndex = 4;
+      this.flowDistanceQualityLabel.Text = "-";
+      // 
+      // recalculateButton
+      // 
+      this.recalculateButton.Location = new System.Drawing.Point(9, 95);
+      this.recalculateButton.Name = "recalculateButton";
+      this.recalculateButton.Size = new System.Drawing.Size(193, 23);
+      this.recalculateButton.TabIndex = 5;
+      this.recalculateButton.Text = "Recalculate";
+      this.recalculateButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+      this.recalculateButton.UseVisualStyleBackColor = true;
+      this.recalculateButton.Click += new System.EventHandler(this.recalculateButton_Click);
+      // 
+      // GQAPAssignmentView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.characteristicsGroupBox);
+      this.Controls.Add(this.assignmentGroupBox);
+      this.Name = "GQAPAssignmentView";
+      this.Size = new System.Drawing.Size(460, 362);
+      this.assignmentGroupBox.ResumeLayout(false);
+      this.assignmentSplitContainer.Panel1.ResumeLayout(false);
+      this.assignmentSplitContainer.Panel2.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.assignmentSplitContainer)).EndInit();
+      this.assignmentSplitContainer.ResumeLayout(false);
+      this.characteristicsGroupBox.ResumeLayout(false);
+      this.characteristicsGroupBox.PerformLayout();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.TreeView assignmentTreeView;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.Label qualityLabel;
+    private System.Windows.Forms.GroupBox assignmentGroupBox;
+    private System.Windows.Forms.GroupBox characteristicsGroupBox;
+    private System.Windows.Forms.Label label3;
+    private System.Windows.Forms.Label flowDistanceQualityLabel;
+    private System.Windows.Forms.Label label7;
+    private System.Windows.Forms.Label overbookedCapacityLabel;
+    private System.Windows.Forms.Label label5;
+    private System.Windows.Forms.Label installationQualityLabel;
+    private System.Windows.Forms.SplitContainer assignmentSplitContainer;
+    private Data.Views.StringConvertibleArrayView assignmentView;
+    private System.Windows.Forms.Button recalculateButton;
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs	(revision 17175)
@@ -0,0 +1,303 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using HeuristicLab.Common.Resources;
+using HeuristicLab.Core.Views;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views {
+  [View("GQAPAssignmentView")]
+  [Content(typeof(GQAPAssignment), IsDefaultView = true)]
+  public partial class GQAPAssignmentView : ItemView {
+    private static readonly double BrightnessLevel = 0.5;
+
+    public new GQAPAssignment Content {
+      get { return (GQAPAssignment)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public GQAPAssignmentView() {
+      InitializeComponent();
+      recalculateButton.Text = string.Empty;
+      recalculateButton.Image = VSImageLibrary.Refresh;
+    }
+
+    #region Register Content Events
+    protected override void DeregisterContentEvents() {
+      DeregisterSolutionEvents();
+      Content.PropertyChanged -= Content_PropertyChanged;
+      base.DeregisterContentEvents();
+    }
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.PropertyChanged += Content_PropertyChanged;
+      RegisterSolutionEvents();
+    }
+
+    private void DeregisterSolutionEvents() {
+      if (Content.Solution != null) Content.Solution.PropertyChanged -= Content_SolutionPropertyChanged;
+    }
+    private void RegisterSolutionEvents() {
+      if (Content.Solution != null) Content.Solution.PropertyChanged += Content_SolutionPropertyChanged;
+    }
+    #endregion
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      UpdateEvaluation();
+      UpdateAssignment();
+      if (Content != null && Content.Solution != null) assignmentView.Content = Content.Solution.Assignment;
+      else assignmentView.Content = null;
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      recalculateButton.Enabled = Content != null && Content.Solution != null && !Locked && !ReadOnly;
+    }
+
+    #region Content Event Handlers
+    private void Content_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      switch (e.PropertyName) {
+        case nameof(Content.Solution): RegisterSolutionEvents(); UpdateEvaluation(); UpdateAssignment(); break;
+        case nameof(Content.ProblemInstance): UpdateEvaluation(); UpdateAssignment(); break;
+        default: break;
+      }
+      SetEnabledStateOfControls();
+    }
+
+    private void Content_SolutionPropertyChanged(object sender, PropertyChangedEventArgs e) {
+      switch (e.PropertyName) {
+        case nameof(Content.Solution.Assignment): UpdateAssignment(); break;
+        case nameof(Content.Solution.Evaluation): UpdateEvaluation(); break;
+        default: break;
+      }
+    }
+
+    private void Content_Assignment_ToStringChanged(object sender, EventArgs e) {
+      UpdateAssignment();
+    }
+    #endregion
+
+    #region Event Handlers
+    private void assignmentTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
+      if (Content != null && Content.Solution != null) {
+        assignmentTreeView.BeginUpdate();
+        try {
+          if (assignmentTreeView.SelectedNode == null) {
+            ColorByInstallationCosts();
+          } else {
+            var equipmentNode = (assignmentTreeView.SelectedNode as EquipmentNode);
+            if (equipmentNode != null) {
+              ColorByWeight(equipmentNode);
+            }
+            var locationNode = (assignmentTreeView.SelectedNode as LocationNode);
+            if (locationNode != null) {
+              ColorByWeight(locationNode);
+            }
+          }
+        } finally { assignmentTreeView.EndUpdate(); }
+      }
+    }
+
+    private void assignmentTreeView_MouseUp(object sender, MouseEventArgs e) {
+      var hit = assignmentTreeView.HitTest(e.X, e.Y);
+      if (hit.Node == null || hit.Location == TreeViewHitTestLocations.None || hit.Location == TreeViewHitTestLocations.RightOfLabel) {
+        assignmentTreeView.SelectedNode = null;
+        ColorByInstallationCosts();
+      }
+    }
+    #endregion
+
+    #region Helpers
+    private void UpdateEvaluation() {
+      if (InvokeRequired) Invoke((Action)UpdateEvaluation);
+      else {
+        if (Content == null || Content.Solution == null) {
+          qualityLabel.Text = "-";
+          flowDistanceQualityLabel.Text = "-";
+          installationQualityLabel.Text = "-";
+          overbookedCapacityLabel.Text = "-";
+        } else {
+          qualityLabel.Text = Content.ProblemInstance.ToSingleObjective(Content.Solution.Evaluation).ToString();
+          flowDistanceQualityLabel.Text = Content.Solution.Evaluation.FlowCosts.ToString();
+          installationQualityLabel.Text = Content.Solution.Evaluation.InstallationCosts.ToString();
+          overbookedCapacityLabel.Text = Content.Solution.Evaluation.ExcessDemand.ToString();
+        }
+      }
+    }
+
+    private void UpdateAssignment() {
+      if (InvokeRequired) Invoke((Action)UpdateAssignment);
+      else {
+        assignmentTreeView.Nodes.Clear();
+        if (Content != null && Content.Solution != null) {
+          IntegerVector assignment = Content.Solution.Assignment;
+          Dictionary<int, TreeNode> locationNodes = new Dictionary<int, TreeNode>();
+          for (int i = 0; i < assignment.Length; i++) {
+            if (!locationNodes.ContainsKey(assignment[i])) {
+              string locationName = assignment[i].ToString();
+              if (Content.ProblemInstance.LocationNames != null && Content.ProblemInstance.LocationNames.Length > assignment[i])
+                locationName = Content.ProblemInstance.LocationNames[assignment[i]];
+              locationNodes.Add(assignment[i], new LocationNode(assignment[i], locationName));
+            }
+            string equipmentName = i.ToString();
+            if (Content.ProblemInstance.EquipmentNames != null && Content.ProblemInstance.EquipmentNames.Length > i)
+              equipmentName = Content.ProblemInstance.EquipmentNames[i];
+            locationNodes[assignment[i]].Nodes.Add(new EquipmentNode(i, equipmentName));
+          }
+
+          assignmentTreeView.BeginUpdate();
+          try {
+            foreach (var node in locationNodes.OrderBy(x => x.Key).Select(x => x.Value)) {
+              assignmentTreeView.Nodes.Add(node);
+              node.Expand();
+            }
+            ColorByInstallationCosts();
+          } finally { assignmentTreeView.EndUpdate(); }
+        }
+      }
+    }
+
+    private void ColorByInstallationCosts() {
+      var installationCosts = new Dictionary<EquipmentNode, double>();
+      foreach (var node in GetAllSubNodes(assignmentTreeView.Nodes).OfType<EquipmentNode>()) {
+        int location = Content.Solution.Assignment[node.Equipment];
+        installationCosts[node] = Content.ProblemInstance.InstallationCosts[node.Equipment, location];
+      }
+      double max = installationCosts.Values.Max();
+      foreach (var kvp in installationCosts) {
+        if (max == 0) {
+          kvp.Key.BackColor = assignmentTreeView.BackColor;
+          kvp.Key.ForeColor = assignmentTreeView.ForeColor;
+        } else {
+          int colorComponent = (int)(255 * Math.Pow((max - kvp.Value) / max, 2));
+          kvp.Key.BackColor = Color.FromArgb(255, colorComponent, colorComponent);
+          if (kvp.Key.BackColor.GetBrightness() < BrightnessLevel) kvp.Key.ForeColor = Color.White;
+          else kvp.Key.ForeColor = Color.Black;
+        }
+      }
+    }
+
+    private void ColorByWeight(EquipmentNode selectedNode) {
+      int equipment = selectedNode.Equipment;
+      double rowSum = 0, colSum = 0;
+      for (int i = 0; i < Content.ProblemInstance.Weights.Columns; i++)
+        if (i != equipment) rowSum += Content.ProblemInstance.Weights[equipment, i];
+      for (int i = 0; i < Content.ProblemInstance.Weights.Rows; i++)
+        if (i != equipment) colSum += Content.ProblemInstance.Weights[i, equipment];
+
+      var otherEquipments = GetAllSubNodes(assignmentTreeView.Nodes)
+        .OfType<EquipmentNode>()
+        .Where(x => x != selectedNode);
+
+      selectedNode.BackColor = assignmentTreeView.BackColor;
+      selectedNode.ForeColor = assignmentTreeView.ForeColor;
+      foreach (var other in otherEquipments) {
+        if (rowSum == 0 && colSum == 0) {
+          other.BackColor = assignmentTreeView.BackColor;
+          other.ForeColor = assignmentTreeView.ForeColor;
+        } else {
+          double rowInvProportion = rowSum == 0 ? 1.0 : (rowSum - Content.ProblemInstance.Weights[equipment, other.Equipment]) / rowSum;
+          double colInvProportion = colSum == 0 ? 1.0 : (colSum - Content.ProblemInstance.Weights[other.Equipment, equipment]) / colSum;
+          int colorComponent = (int)(255 * Math.Pow(Math.Min(rowInvProportion, colInvProportion), 2));
+          other.BackColor = Color.FromArgb(colorComponent, 255, colorComponent);
+          if (other.BackColor.GetBrightness() < BrightnessLevel) other.ForeColor = Color.White;
+          else other.ForeColor = Color.Black;
+        }
+      }
+    }
+
+    private void ColorByWeight(LocationNode selectedNode) {
+      var equipments = new HashSet<int>(Content.Solution.Assignment.Select((v, i) => new { Index = i, Value = v })
+        .Where(x => x.Value == selectedNode.Location).Select(x => x.Index));
+      var rowSums = new Dictionary<int, double>(equipments.Count);
+      var colSums = new Dictionary<int, double>(equipments.Count);
+      foreach (var e in equipments) {
+        rowSums[e] = 0;
+        colSums[e] = 0;
+        for (int i = 0; i < Content.ProblemInstance.Weights.Columns; i++) {
+          if (!equipments.Contains(i)) rowSums[e] += Content.ProblemInstance.Weights[e, i];
+          if (!equipments.Contains(i)) colSums[e] += Content.ProblemInstance.Weights[i, e];
+        }
+      }
+      var equipmentNodes = GetAllSubNodes(assignmentTreeView.Nodes)
+        .OfType<EquipmentNode>();
+
+      var relevantEquipments = new HashSet<int>(equipments.Where(x => rowSums[x] > 0 || colSums[x] > 0));
+      foreach (var other in equipmentNodes) {
+        if (!relevantEquipments.Any() || equipments.Contains(other.Equipment)) {
+          other.BackColor = assignmentTreeView.BackColor;
+          other.ForeColor = assignmentTreeView.ForeColor;
+        } else {
+          double rowInvProportion = relevantEquipments.Min(x => rowSums[x] == 0 ? 1.0 : (rowSums[x] - Content.ProblemInstance.Weights[x, other.Equipment]) / rowSums[x]);
+          double colInvProportion = relevantEquipments.Min(x => colSums[x] == 0 ? 1.0 : (colSums[x] - Content.ProblemInstance.Weights[other.Equipment, x]) / colSums[x]);
+          int colorComponent = (int)(255 * Math.Pow(Math.Min(rowInvProportion, colInvProportion), 2));
+          other.BackColor = Color.FromArgb(colorComponent, 255, colorComponent);
+          if (other.BackColor.GetBrightness() < BrightnessLevel) other.ForeColor = Color.White;
+          else other.ForeColor = Color.Black;
+        }
+      }
+    }
+
+    private IEnumerable<TreeNode> GetAllSubNodes(TreeNodeCollection nodes) {
+      foreach (TreeNode node in nodes) {
+        yield return node;
+        foreach (TreeNode subNode in GetAllSubNodes(node.Nodes))
+          yield return subNode;
+      }
+    }
+    #endregion
+
+    #region Helper Classes
+    private class LocationNode : TreeNode {
+      public int Location { get; set; }
+
+      public LocationNode() : base() { }
+      public LocationNode(int location, string name)
+        : base(name) {
+        Location = location;
+      }
+    }
+
+    private class EquipmentNode : TreeNode {
+      public int Equipment { get; set; }
+
+      public EquipmentNode() : base() { }
+      public EquipmentNode(int equipment, string name)
+        : base(name) {
+        Equipment = equipment;
+      }
+    }
+    #endregion
+
+    private void recalculateButton_Click(object sender, EventArgs e) {
+      Content.Solution.Evaluation = Content.ProblemInstance.Evaluate(Content.Solution.Assignment);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.resx
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.resx	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.resx	(revision 17175)
@@ -0,0 +1,120 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views-3.3.csproj
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views-3.3.csproj	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views-3.3.csproj	(revision 17175)
@@ -0,0 +1,167 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{BFAAC00C-B884-458D-BD74-98C94BFAFA41}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common.Resources-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common.Resources-3-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Core.Views-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core.Views-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Data-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Data.Views-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Data.Views-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.MainForm-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.MainForm-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.MainForm.WindowsForms-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.MainForm.WindowsForms-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Parameters-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Visualization.ChartControlsExtensions-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Visualization.ChartControlsExtensions-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Windows.Forms.DataVisualization" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="GQAPAssignmentArchiveView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="GQAPAssignmentArchiveView.Designer.cs">
+      <DependentUpon>GQAPAssignmentArchiveView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="GQAPAssignmentView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="GQAPAssignmentView.Designer.cs">
+      <DependentUpon>GQAPAssignmentView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Plugin.cs" />
+    <None Include="Plugin.cs.frame" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.IntegerVectorEncoding\3.3\HeuristicLab.Encodings.IntegerVectorEncoding-3.3.csproj">
+      <Project>{ddfb14dd-2a85-493c-a52d-e69729bbaeb0}</Project>
+      <Name>HeuristicLab.Encodings.IntegerVectorEncoding-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.GeneralizedQuadraticAssignment\3.3\HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj">
+      <Project>{C739E6D2-5680-4804-A810-8017DA0C238F}</Project>
+      <Name>HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="GQAPAssignmentArchiveView.resx">
+      <DependentUpon>GQAPAssignmentArchiveView.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="GQAPAssignmentView.resx">
+      <DependentUpon>GQAPAssignmentView.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd</PreBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/Plugin.cs.frame
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/Plugin.cs.frame	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/Plugin.cs.frame	(revision 17175)
@@ -0,0 +1,41 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views {
+  [Plugin("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views", "3.3.15.$WCREV$")]
+  [PluginFile("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Core.Views", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Data.Views", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.IntegerVectorEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm.WindowsForms", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.GeneralizedQuadraticAssignment", "3.3")]
+  [PluginDependency("HeuristicLab.Visualization.ChartControlsExtensions", "3.3")]
+  public class HeuristicLabProblemsGeneralizedQuadraticAssignmentViewsPlugin : PluginBase {
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/Properties/AssemblyInfo.cs.frame	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/Properties/AssemblyInfo.cs.frame	(revision 17175)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a1b78104-1257-482e-a9ed-6c03a49593d3")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.15.$WCREV$")]
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluation/Evaluation.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluation/Evaluation.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluation/Evaluation.cs	(revision 17175)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAP Evaluation", "Class that contains the results of evaluating a solution to the GQAP.")]
+  [StorableType("765222A4-9184-42FF-9413-886BC9B2EF03")]
+  public class Evaluation : Item {
+
+    /// <summary>
+    /// The solution is feasible if there is no excess demand
+    /// </summary>
+    public bool IsFeasible { get { return ExcessDemand <= double.Epsilon; } }
+
+    /// <summary>
+    /// The amount of demand that exceeds the respective capacities
+    /// </summary>
+    [Storable]
+    public double ExcessDemand { get; private set; }
+    /// <summary>
+    /// The amount of slack at each location, is negative in case of excess demand.
+    /// </summary>
+    /// <remarks>
+    /// Slack.Select(x => x &lt; 0 ? -x : 0).Sum() is equivalent to <see cref="ExcessDemand"/>.
+    /// </remarks>
+    [Storable]
+    private double[] slack;
+    public IReadOnlyList<double> Slack {
+      get { return slack; }
+    }
+    /// <summary>
+    /// The quadratic part of the fitness function that represents the flow or transportation costs.
+    /// </summary>
+    [Storable]
+    public double FlowCosts { get; private set; }
+    /// <summary>
+    /// The linear part of the fitness function that represents the installation costs.
+    /// </summary>
+    [Storable]
+    public double InstallationCosts { get; private set; }
+    
+    [StorableConstructor]
+    protected Evaluation(StorableConstructorFlag _) : base(_) { }
+    protected Evaluation(Evaluation original, Cloner cloner)
+      : base(original, cloner) {
+      ExcessDemand = original.ExcessDemand;
+      if (original.slack != null)
+        slack = original.slack.ToArray();
+      FlowCosts = original.FlowCosts;
+      InstallationCosts = original.InstallationCosts;
+    }
+    public Evaluation(double flowCosts, double installationCosts, double excessDemand, double[] slack) {
+      FlowCosts = flowCosts;
+      InstallationCosts = installationCosts;
+      ExcessDemand = excessDemand;
+      this.slack = slack;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Evaluation(this, cloner);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluation/GQAPNMoveEvaluator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluation/GQAPNMoveEvaluator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluation/GQAPNMoveEvaluator.cs	(revision 17175)
@@ -0,0 +1,136 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("N-Move Evaluator", "Evaluates an N-Move.")]
+  [StorableType("EB4CCB5D-8FAC-4DFD-944E-1AC418AAE091")]
+  public class GQAPNMoveEvaluator : SingleSuccessorOperator, IGQAPNMoveEvaluator,
+    IQualityAwareGQAPOperator, IProblemInstanceAwareGQAPOperator, IAssignmentAwareGQAPOperator {
+
+    #region Parameter Descriptions
+    public static readonly string MoveQualityDescription = "The quality of the move if it would be applied.";
+    public static readonly string MoveEvaluationDescription = "The results of evaluating the move.";
+    #endregion
+
+    #region Parameter Properties
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<Evaluation> MoveEvaluationParameter {
+      get { return (ILookupParameter<Evaluation>)Parameters["MoveEvaluation"]; }
+    }
+    public ILookupParameter<NMove> MoveParameter {
+      get { return (ILookupParameter<NMove>)Parameters["Move"]; }
+    }
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<Evaluation> EvaluationParameter {
+      get { return (ILookupParameter<Evaluation>)Parameters["Evaluation"]; }
+    }
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected GQAPNMoveEvaluator(StorableConstructorFlag _) : base(_) { }
+    protected GQAPNMoveEvaluator(GQAPNMoveEvaluator original, Cloner cloner) : base(original, cloner) { }
+    public GQAPNMoveEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<NMove>("Move", GQAPNMoveGenerator.MoveDescription));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", ""));
+      Parameters.Add(new LookupParameter<Evaluation>("Evaluation", GQAP.EvaluationDescription));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", MoveQualityDescription));
+      Parameters.Add(new LookupParameter<Evaluation>("MoveEvaluation", MoveEvaluationDescription));
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPNMoveEvaluator(this, cloner);
+    }
+
+    public static Evaluation Evaluate(NMove move, IntegerVector assignment, Evaluation evaluation, GQAPInstance problemInstance) {
+      int moves = move.N;
+      var excessDemand = evaluation.ExcessDemand;
+      var flowCosts = evaluation.FlowCosts;
+      var installationCosts = evaluation.InstallationCosts;
+      var slack = evaluation.Slack.ToArray();
+
+      foreach (var equip in move.Indices) {
+        int newLoc = move.Reassignments[equip] - 1; // locations are given 1-based
+        int oldLoc = assignment[equip];
+        var equipDemand = problemInstance.Demands[equip];
+        installationCosts -= problemInstance.InstallationCosts[equip, oldLoc];
+        installationCosts += problemInstance.InstallationCosts[equip, newLoc];
+        for (int j = 0; j < assignment.Length; j++) {
+          var reassignedLoc = move.Reassignments[j] - 1; // 0 indicates that this equipment is not reassigned
+          if (reassignedLoc < 0) {
+            flowCosts += problemInstance.Weights[equip, j] * problemInstance.Distances[newLoc, assignment[j]];
+            flowCosts -= problemInstance.Weights[equip, j] * problemInstance.Distances[oldLoc, assignment[j]];
+            flowCosts += problemInstance.Weights[j, equip] * problemInstance.Distances[assignment[j], newLoc];
+            flowCosts -= problemInstance.Weights[j, equip] * problemInstance.Distances[assignment[j], oldLoc];
+          } else {
+            flowCosts += problemInstance.Weights[equip, j] * problemInstance.Distances[newLoc, reassignedLoc];
+            flowCosts -= problemInstance.Weights[equip, j] * problemInstance.Distances[oldLoc, assignment[j]];
+          }
+        }
+        slack[oldLoc] += equipDemand;
+        if (slack[oldLoc] < equipDemand)
+          excessDemand -= Math.Min(equipDemand, equipDemand - slack[oldLoc]);
+        slack[newLoc] -= equipDemand;
+        if (slack[newLoc] < 0)
+          excessDemand += Math.Min(equipDemand, -slack[newLoc]);
+      }
+
+      return new Evaluation(flowCosts, installationCosts, excessDemand, slack);
+    }
+
+    public override IOperation Apply() {
+      var problemInstance = ProblemInstanceParameter.ActualValue;
+      var evaluation = EvaluationParameter.ActualValue;
+
+      var moveEvaluation = Evaluate(MoveParameter.ActualValue,
+               AssignmentParameter.ActualValue,
+               evaluation,
+               problemInstance);
+
+      MoveEvaluationParameter.ActualValue = moveEvaluation;
+      MoveQualityParameter.ActualValue = new DoubleValue(problemInstance.ToSingleObjective(moveEvaluation));
+      return base.Apply();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAP.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAP.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAP.cs	(revision 17175)
@@ -0,0 +1,494 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.Instances;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("Generalized Quadratic Assignment Problem (GQAP)", "The Generalized Quadratic Assignment Problem (GQAP) is a generalization of the QAP in that it allows to assign multiple facilities (here called equipment) to a single location. The problem is described in Lee, C.G., and Ma, Z. 2003. The Generalized Quadratic Assignment Problem. Technical Report M5S 3G8, University of Toronto, Canada.")]
+  [Creatable(CreatableAttribute.Categories.CombinatorialProblems)]
+  [StorableType("20DC9B2F-F667-425E-A235-B0192CCB1BF4")]
+  public sealed class GQAP : SingleObjectiveBasicProblem<IntegerVectorEncoding>,
+    IProblemInstanceConsumer<QAPData>,
+    IProblemInstanceConsumer<CTAPData>,
+    IProblemInstanceConsumer<TSPData>,
+    IProblemInstanceConsumer<ATSPData>,
+    IProblemInstanceConsumer<GQAPData> {
+
+    public override bool Maximization { get { return false; } }
+
+    [Storable]
+    private bool initialized; // ABE: helper variable that defines if the constructor has completed
+
+    #region Parameter Descriptions
+    public static readonly string BestKnownQualityDescription = "The best known quality (if available).";
+    public static readonly string BestKnownSolutionDescription = "The best known solution (if available).";
+    public static readonly string BestKnownSolutionsDescription = "Contains an archive of best-known solutions regarding flow-distance quality and installation quality.";
+    public static readonly string ProblemInstanceDescription = "The problem instance that is to be solved.";
+    public static readonly string EvaluationDescription = "The evaluation result of a solution to the GQAP.";
+    #endregion
+
+    #region Parameter Properties
+    public OptionalValueParameter<GQAPAssignment> BestKnownSolutionParameter {
+      get { return (OptionalValueParameter<GQAPAssignment>)Parameters["BestKnownSolution"]; }
+    }
+    public OptionalValueParameter<GQAPAssignmentArchive> BestKnownSolutionsParameter {
+      get { return (OptionalValueParameter<GQAPAssignmentArchive>)Parameters["BestKnownSolutions"]; }
+    }
+    public IValueParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (IValueParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+    #endregion
+
+    #region Properties
+    public GQAPAssignment BestKnownSolution {
+      get { return BestKnownSolutionParameter.Value; }
+      set { BestKnownSolutionParameter.Value = value; }
+    }
+    public GQAPAssignmentArchive BestKnownSolutions {
+      get { return BestKnownSolutionsParameter.Value; }
+      set { BestKnownSolutionsParameter.Value = value; }
+    }
+    public GQAPInstance ProblemInstance {
+      get { return ProblemInstanceParameter.Value; }
+      set { ProblemInstanceParameter.Value = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private GQAP(StorableConstructorFlag _) : base(_) { }
+    private GQAP(GQAP original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+      initialized = original.initialized;
+    }
+    public GQAP() : base() {
+      Encoding = new IntegerVectorEncoding("Assignment");
+      Parameters.Add(new OptionalValueParameter<GQAPAssignment>("BestKnownSolution", BestKnownSolutionDescription, null) { GetsCollected = false });
+      Parameters.Add(new OptionalValueParameter<GQAPAssignmentArchive>("BestKnownSolutions", BestKnownSolutionsDescription, null) { GetsCollected = false });
+      Parameters.Add(new ValueParameter<GQAPInstance>("ProblemInstance", "The problem instance that is to be solved.", new GQAPInstance()) { GetsCollected = false });
+
+      InitializeOperators();
+      RegisterEventHandlers();
+      initialized = true;
+      Parameterize();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAP(this, cloner);
+    }
+
+    public override double Evaluate(Individual individual, IRandom random = null) {
+      var assignment = individual.IntegerVector();
+      var evaluation = ProblemInstance.Evaluate(assignment);
+      individual["Evaluation"] = evaluation;
+      return ProblemInstance.ToSingleObjective(evaluation);
+    }
+
+    public double Evaluate(IntegerVector assignment) {
+      var evaluation = ProblemInstance.Evaluate(assignment);
+      return ProblemInstance.ToSingleObjective(evaluation);
+    }
+
+    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
+      AnalyzeBestSolution(results, GetBestIndividual(individuals, qualities));
+      AnalyzeParetoArchive(results,
+        individuals.Select(i => Tuple.Create((IntegerVector)i.IntegerVector().Clone(),
+        (Evaluation)i["Evaluation"])));
+    }
+
+    private void AnalyzeBestSolution(ResultCollection results, Tuple<Individual, double> best) {
+      var bestVector = best.Item1.IntegerVector();
+      var bestEvaluation = (Evaluation)best.Item1["Evaluation"];
+
+      IResult bestResult;
+      if (!results.TryGetValue("Best Solution", out bestResult)) {
+        bestResult = new Result("Best Solution", typeof(GQAPAssignment));
+        results.Add(bestResult);
+      }
+      var item = bestResult.Value as GQAPAssignment;
+      if (item == null) bestResult.Value = new GQAPAssignment((IntegerVector)bestVector.Clone(), ProblemInstance, bestEvaluation);
+      else if (ProblemInstance.ToSingleObjective(bestEvaluation)
+        < ProblemInstance.ToSingleObjective(item.Solution.Evaluation)) {
+        item.ProblemInstance = ProblemInstance;
+        item.Solution = new GQAPSolution((IntegerVector)bestVector.Clone(), bestEvaluation);
+      }
+    }
+
+    private void AnalyzeParetoArchive(ResultCollection results, IEnumerable<Tuple<IntegerVector, Evaluation>> solutions) {
+      IResult archiveResult;
+      if (!results.TryGetValue("Solution Archive", out archiveResult)) {
+        archiveResult = new Result("Solution Archive", typeof(GQAPAssignmentArchive));
+        results.Add(archiveResult);
+      }
+      var archive = archiveResult.Value as GQAPAssignmentArchive;
+      if (archive == null) {
+        archive = new GQAPAssignmentArchive(ProblemInstance);
+        archiveResult.Value = archive;
+      } else archive.ProblemInstance = ProblemInstance;
+      
+      var combinedArchive = solutions
+        .Select(x => new GQAPSolution(x.Item1, x.Item2))
+        .Concat(archive.Solutions);
+      archive.Solutions = GetFeasibleParetoFront(combinedArchive);
+      
+      if (BestKnownSolutions == null) {
+        BestKnownSolutions = archive;
+      } else {
+        var combinedArchive2 = solutions
+        .Select(x => new GQAPSolution(x.Item1, x.Item2))
+        .Concat(BestKnownSolutions.Solutions);
+        BestKnownSolutions.Solutions = GetFeasibleParetoFront(combinedArchive2);
+      }
+    }
+
+    #region Problem Instance Loading
+    public void Load(QAPData data) {
+      Name = data.Name;
+      Description = data.Description;
+
+      var weights = new DoubleMatrix(data.Weights);
+      var distances = new DoubleMatrix(data.Distances);
+      var installationCosts = new DoubleMatrix(weights.Rows, distances.Columns); // all zero
+      var capacities = new DoubleArray(Enumerable.Range(0, distances.Rows).Select(x => 1.0).ToArray());
+      var demands = new DoubleArray(Enumerable.Range(0, weights.Rows).Select(x => 1.0).ToArray());
+
+      Load(demands, capacities, weights, distances, installationCosts, new DoubleValue(1));
+      EvaluateAndLoadAssignment(data.BestKnownAssignment);
+    }
+
+    public void Load(CTAPData data) {
+      Name = data.Name;
+      Description = data.Description;
+
+      var capacities = new DoubleArray(data.MemoryCapacities);
+      var demands = new DoubleArray(data.MemoryRequirements);
+      var weights = new DoubleMatrix(data.CommunicationCosts);
+      var installationCosts = new DoubleMatrix(data.ExecutionCosts.Transpose());
+      var distances = new DoubleMatrix(capacities.Length, capacities.Length);
+      for (int i = 0; i < capacities.Length - 1; i++)
+        for (int j = i + 1; j < capacities.Length; j++) {
+          distances[i, j] = 1;
+        }
+
+      Load(demands, capacities, weights, distances, installationCosts, new DoubleValue(1));
+      EvaluateAndLoadAssignment(data.BestKnownAssignment);
+    }
+
+    public void Load(TSPData data) {
+      if (data.Dimension > 1000)
+        throw new System.IO.InvalidDataException("Instances with more than 1000 cities are not supported.");
+
+      Name = data.Name;
+      Description = data.Description;
+
+      var capacities = new DoubleArray(data.Dimension);
+      var demands = new DoubleArray(data.Dimension);
+      for (int i = 0; i < data.Dimension; i++) {
+        capacities[i] = 1;
+        demands[i] = 1;
+      }
+      var installationCosts = new DoubleMatrix(data.Dimension, data.Dimension);
+      var weights = new DoubleMatrix(data.Dimension, data.Dimension);
+      for (int i = 0; i < data.Dimension; i++)
+        weights[i, (i + 1) % data.Dimension] = 1;
+      var distances = new DoubleMatrix(data.GetDistanceMatrix());
+
+      Load(demands, capacities, weights, distances, installationCosts, new DoubleValue(1));
+      EvaluateAndLoadAssignment(data.BestKnownTour);
+    }
+
+    public void Load(ATSPData data) {
+      Name = data.Name;
+      Description = data.Description;
+
+      var capacities = new DoubleArray(data.Dimension);
+      var demands = new DoubleArray(data.Dimension);
+      for (int i = 0; i < data.Dimension; i++) {
+        capacities[i] = 1;
+        demands[i] = 1;
+      }
+      var installationCosts = new DoubleMatrix(data.Dimension, data.Dimension);
+      var weights = new DoubleMatrix(data.Dimension, data.Dimension);
+      for (int i = 0; i < data.Dimension; i++)
+        weights[i, (i + 1) % data.Dimension] = 1;
+      var distances = new DoubleMatrix(data.Distances);
+
+      Load(demands, capacities, weights, distances, installationCosts, new DoubleValue(1));
+      EvaluateAndLoadAssignment(data.BestKnownTour);
+    }
+
+    public void Load(GQAPData data) {
+      Name = data.Name;
+      Description = data.Description;
+
+      var capacities = new DoubleArray(data.Capacities);
+      var demands = new DoubleArray(data.Demands);
+      var installationCosts = new DoubleMatrix(data.InstallationCosts);
+      var weights = new DoubleMatrix(data.Weights);
+      var distances = new DoubleMatrix(data.Distances);
+      var transportationCosts = new DoubleValue(data.TransportationCosts);
+
+      Load(demands, capacities, weights, distances, installationCosts, transportationCosts);
+      EvaluateAndLoadAssignment(data.BestKnownAssignment);
+
+      if (data.BestKnownAssignment == null && data.BestKnownQuality.HasValue) {
+        BestKnownQuality = data.BestKnownQuality.Value;
+      }
+    }
+
+    public void Load(DoubleArray demands, DoubleArray capacities,
+      DoubleMatrix weights, DoubleMatrix distances, DoubleMatrix installationCosts,
+      DoubleValue transportationCosts) {
+      if (weights == null || weights.Rows == 0)
+        throw new System.IO.InvalidDataException(
+@"The given instance does not contain weights!");
+      if (weights.Rows != weights.Columns)
+        throw new System.IO.InvalidDataException(
+@"The weights matrix of the given instance contains
+an unequal number of rows and columns.");
+      if (distances == null || distances.Rows == 0)
+        throw new System.IO.InvalidDataException(
+@"The given instance does not contain distances!");
+      if (distances.Rows != distances.Columns)
+        throw new System.IO.InvalidDataException(
+@"The distances matrix of the given instance contains
+an unequal number of rows and columns.");
+      if (installationCosts == null || installationCosts.Rows == 0)
+        throw new System.IO.InvalidDataException(
+@"The given instance does not contain installation costs!");
+      if (installationCosts.Rows != weights.Rows
+        || installationCosts.Columns != distances.Columns)
+        throw new System.IO.InvalidDataException(
+@"The installation costs matrix of the given instance
+contains different number of rows than given in the
+weights matrix and a different number of columns than
+given in the distances matrix.");
+      if (capacities == null || capacities.Length == 0)
+        throw new System.IO.InvalidDataException(
+@"The given instance does not contain capacities!");
+      if (capacities.Length != distances.Rows)
+        throw new System.IO.InvalidDataException(
+@"The given instance contains a different number of
+capacities than rows given in the distances matrix.");
+      if (demands == null || demands.Length == 0)
+        throw new System.IO.InvalidDataException(
+@"The given instance does not contain demands!");
+      if (demands.Length != weights.Rows)
+        throw new System.IO.InvalidDataException(
+@"The given instance contains a different number of
+demands than rows given in the weights matrix.");
+      if (transportationCosts == null)
+        throw new System.IO.InvalidDataException(
+@"The given instance does not contain transportation costs.");
+
+      ProblemInstance = new GQAPInstance() {
+        Weights = weights,
+        Distances = distances,
+        InstallationCosts = installationCosts,
+        Capacities = capacities,
+        Demands = demands,
+        TransportationCosts = transportationCosts.Value
+      };
+      BestKnownQualityParameter.Value = null;
+      BestKnownSolution = null;
+      BestKnownSolutions = null;
+      ProblemInstance.CalculatePenaltyLevel();
+    }
+    private void EvaluateAndLoadAssignment(int[] vector) {
+      if (vector == null || vector.Length == 0) return;
+      EvaluateAndLoadAssignment(new IntegerVector(vector));
+    }
+    public void EvaluateAndLoadAssignment(IntegerVector assignment) {
+      if (!ProblemInstance.IsValid()) {
+        BestKnownQualityParameter.Value = null;
+        BestKnownSolution = null;
+        BestKnownSolutions = null;
+        return;
+      }
+      var evaluation = ProblemInstance.Evaluate(assignment);
+      var quality = ProblemInstance.ToSingleObjective(evaluation);
+      
+      BestKnownSolution = new GQAPAssignment((IntegerVector)assignment.Clone(), ProblemInstance, evaluation);
+      BestKnownQuality = quality;
+      BestKnownSolutions = new GQAPAssignmentArchive(ProblemInstance);
+      BestKnownSolutions.Solutions.Add(new GQAPSolution((IntegerVector)assignment.Clone(), evaluation));
+    }
+    #endregion
+
+    #region Events
+    protected override void OnOperatorsChanged() {
+      base.OnOperatorsChanged();
+      if (!initialized) return;
+      Parameterize();
+    }
+    protected override void OnEncodingChanged() {
+      base.OnEncodingChanged();
+      if (!initialized) return;
+      Parameterize();
+    }
+    #endregion
+
+    #region Helpers
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      ProblemInstanceParameter.ValueChanged += ProblemInstanceParameterOnValueChanged;
+      ProblemInstance.CapacitiesParameter.ValueChanged += ProblemInstanceCapacitiesParameterOnValueChanged;
+      ProblemInstance.DemandsParameter.ValueChanged += ProblemInstanceDemandsParameterOnValueChanged;
+      ProblemInstance.Capacities.Reset += ProblemInstanceCapacitiesOnReset;
+      ProblemInstance.Demands.Reset += ProblemInstanceDemandsOnReset;
+    }
+
+    private void ProblemInstanceParameterOnValueChanged(object sender, EventArgs e) {
+      ProblemInstance.CapacitiesParameter.ValueChanged += ProblemInstanceCapacitiesParameterOnValueChanged;
+      ProblemInstance.Capacities.Reset += ProblemInstanceCapacitiesOnReset;
+      ProblemInstance.DemandsParameter.ValueChanged += ProblemInstanceDemandsParameterOnValueChanged;
+      ProblemInstance.Demands.Reset += ProblemInstanceDemandsOnReset;
+      UpdateEncoding();
+    }
+    private void ProblemInstanceCapacitiesParameterOnValueChanged(object sender, EventArgs e) {
+      ProblemInstance.Capacities.Reset += ProblemInstanceCapacitiesOnReset;
+      UpdateEncoding();
+    }
+    private void ProblemInstanceDemandsParameterOnValueChanged(object sender, EventArgs e) {
+      ProblemInstance.Demands.Reset += ProblemInstanceDemandsOnReset;
+      UpdateEncoding();
+    }
+    private void ProblemInstanceDemandsOnReset(object sender, EventArgs e) {
+      UpdateEncoding();
+    }
+    private void ProblemInstanceCapacitiesOnReset(object sender, EventArgs e) {
+      UpdateEncoding();
+    }
+
+    private void UpdateEncoding() {
+      Encoding.Length = ProblemInstance.Demands.Length;
+      Encoding.Bounds = new IntMatrix(new int[,] { { 0, ProblemInstance.Capacities.Length } });
+    }
+
+    private void InitializeOperators() {
+      Operators.RemoveAll(x => x is ISingleObjectiveMoveOperator);
+      Operators.RemoveAll(x => x is SingleObjectiveImprover);
+      Operators.AddRange(ApplicationManager.Manager.GetInstances<IGQAPOperator>());
+      Operators.AddRange(ApplicationManager.Manager.GetInstances<IGQAPMoveEvaluator>());
+      Operators.Add(new HammingSimilarityCalculator() { SolutionVariableName = Encoding.Name, QualityVariableName = Evaluator.QualityParameter.ActualName });
+      Operators.Add(new QualitySimilarityCalculator() { SolutionVariableName = Encoding.Name, QualityVariableName = Evaluator.QualityParameter.ActualName });
+      
+      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
+    }
+
+    private void Parameterize() {
+      var operators = Operators.Union(new IOperator[] { SolutionCreator, Evaluator }).ToArray();
+      Encoding.ConfigureOperators(operators.OfType<IOperator>());
+      foreach (var op in operators.OfType<IAssignmentAwareGQAPOperator>()) {
+        op.AssignmentParameter.ActualName = Encoding.Name;
+        op.AssignmentParameter.Hidden = true;
+      }
+      foreach (var op in operators.OfType<IBestKnownQualityAwareGQAPOperator>()) {
+        op.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
+        op.BestKnownQualityParameter.Hidden = true;
+      }
+      foreach (var op in operators.OfType<IBestKnownSolutionAwareGQAPOperator>()) {
+        op.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
+        op.BestKnownSolutionParameter.Hidden = true;
+      }
+      foreach (var op in operators.OfType<IBestKnownSolutionsAwareGQAPOperator>()) {
+        op.BestKnownSolutionsParameter.ActualName = BestKnownSolutionsParameter.Name;
+        op.BestKnownSolutionsParameter.Hidden = true;
+      }
+      foreach (var op in operators.OfType<IGQAPCrossover>()) {
+        op.ParentsParameter.ActualName = Encoding.Name;
+        op.ParentsParameter.Hidden = true;
+        op.ChildParameter.ActualName = Encoding.Name;
+        op.ChildParameter.Hidden = true;
+      }
+      var moveEvaluator = operators.OfType<IGQAPMoveEvaluator>().FirstOrDefault();
+      foreach (var op in operators.OfType<IGQAPMoveEvaluator>()) { // synchronize all move evaluators
+        if (moveEvaluator != null) {
+          op.MoveQualityParameter.ActualName = moveEvaluator.MoveQualityParameter.ActualName;
+          op.MoveQualityParameter.Hidden = true;
+          op.MoveEvaluationParameter.ActualName = "MoveEvaluation";
+          op.MoveEvaluationParameter.Hidden = true;
+        }
+      }
+      foreach (var op in operators.OfType<IMoveQualityAwareGQAPOperator>()) {
+        if (moveEvaluator != null) {
+          op.MoveQualityParameter.ActualName = moveEvaluator.MoveQualityParameter.ActualName;
+          op.MoveQualityParameter.Hidden = true;
+          op.MoveEvaluationParameter.ActualName = "MoveEvaluation";
+          op.MoveEvaluationParameter.Hidden = true;
+        }
+      }
+      foreach (var op in operators.OfType<IProblemInstanceAwareGQAPOperator>()) {
+        op.ProblemInstanceParameter.ActualName = ProblemInstanceParameter.Name;
+        op.ProblemInstanceParameter.Hidden = true;
+      }
+      foreach (var op in operators.OfType<IQualitiesAwareGQAPOperator>()) {
+        op.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        op.QualityParameter.Hidden = true;
+        op.EvaluationParameter.ActualName = "Evaluation";
+        op.EvaluationParameter.Hidden = true;
+      }
+      foreach (var op in operators.OfType<IQualityAwareGQAPOperator>()) {
+        op.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        op.QualityParameter.Hidden = true;
+        op.EvaluationParameter.ActualName = "Evaluation";
+        op.EvaluationParameter.Hidden = true;
+      }
+    }
+    #endregion
+
+    public static ItemList<GQAPSolution> GetFeasibleParetoFront(IEnumerable<GQAPSolution> solutions) {
+      var front = new ItemList<GQAPSolution>(solutions.Where(x => x.Evaluation.IsFeasible));
+
+      for (int i = 0; i < front.Count - 1; i++) {
+        for (int j = i + 1; j < front.Count; j++) {
+          if (front[i].Evaluation.FlowCosts <= front[j].Evaluation.FlowCosts
+            && front[i].Evaluation.InstallationCosts <= front[j].Evaluation.InstallationCosts) {
+            front.RemoveAt(j);
+            j--;
+          } else if (front[i].Evaluation.FlowCosts >= front[j].Evaluation.FlowCosts
+            && front[i].Evaluation.InstallationCosts >= front[j].Evaluation.InstallationCosts) {
+            front.RemoveAt(i);
+            j = i;
+          }
+        }
+      }
+      return front;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs	(revision 17175)
@@ -0,0 +1,86 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("Generalized QAP Assignment", "Represents the solution as well as the problem parameters of a GQAP instance.")]
+  [StorableType("8DAC9356-54EE-4EDC-9AB4-0DA47F111920")]
+  public sealed class GQAPAssignment : Item, INotifyPropertyChanged {
+
+    [Storable]
+    private GQAPSolution solution;
+    public GQAPSolution Solution {
+      get { return solution; }
+      set {
+        if (solution == value) return;
+        solution = value;
+        OnPropertyChanged(nameof(Solution));
+      }
+    }
+
+    [Storable]
+    private GQAPInstance problemInstance;
+    public GQAPInstance ProblemInstance {
+      get { return problemInstance; }
+      set {
+        if (problemInstance == value) return;
+        problemInstance = value;
+        OnPropertyChanged(nameof(ProblemInstance));
+      }
+    }
+
+    [StorableConstructor]
+    private GQAPAssignment(StorableConstructorFlag _) : base(_) { }
+    private GQAPAssignment(GQAPAssignment original, Cloner cloner)
+      : base(original, cloner) {
+      solution = cloner.Clone(original.solution);
+      problemInstance = cloner.Clone(original.problemInstance);
+    }
+    public GQAPAssignment(IntegerVector assignment, GQAPInstance problemInstance)
+      : this(assignment, problemInstance, problemInstance.Evaluate(assignment)) { }
+    public GQAPAssignment(IntegerVector assignment, GQAPInstance problemInstance, Evaluation evaluation)
+      : base() {
+      this.solution = new GQAPSolution(assignment, evaluation);
+      this.problemInstance = problemInstance;
+    }
+    public GQAPAssignment(GQAPSolution solution, GQAPInstance problemInstance)
+      : base() {
+      this.solution = solution;
+      this.problemInstance = problemInstance;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPAssignment(this, cloner);
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    private void OnPropertyChanged(string propertyName) {
+      var handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignmentArchive.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignmentArchive.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignmentArchive.cs	(revision 17175)
@@ -0,0 +1,81 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAPAssignmentArchive", "Stores the pareto front of assignments.")]
+  [StorableType("EA3C4BB4-322B-47EB-8A04-95DADA3D2C02")]
+  public sealed class GQAPAssignmentArchive : Item, INotifyPropertyChanged {
+
+    [Storable]
+    private ItemList<GQAPSolution> solutions;
+    public ItemList<GQAPSolution> Solutions {
+      get { return solutions; }
+      set {
+        if (solutions == value) return;
+        solutions = value;
+        OnPropertyChanged(nameof(Solutions));
+      }
+    }
+
+    [Storable]
+    private GQAPInstance problemInstance;
+    public GQAPInstance ProblemInstance {
+      get { return problemInstance; }
+      set {
+        if (problemInstance == value) return;
+        problemInstance = value;
+        OnPropertyChanged(nameof(ProblemInstance));
+      }
+    }
+
+    [StorableConstructor]
+    private GQAPAssignmentArchive(StorableConstructorFlag _) : base(_) { }
+    private GQAPAssignmentArchive(GQAPAssignmentArchive original, Cloner cloner)
+      : base(original, cloner) {
+      solutions = cloner.Clone(original.solutions);
+      problemInstance = cloner.Clone(original.problemInstance);
+    }
+    public GQAPAssignmentArchive()
+      : base() {
+      this.solutions = new ItemList<GQAPSolution>();
+    }
+    public GQAPAssignmentArchive(GQAPInstance problemInstance)
+      : this() {
+      this.problemInstance = problemInstance;
+    }
+
+    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/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPInstance.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPInstance.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPInstance.cs	(revision 17175)
@@ -0,0 +1,274 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAP Instance", "Instance of a generalized quadratic assignment problem.")]
+  [StorableType("54208525-4EF6-404F-AF4A-52927104C563")]
+  public class GQAPInstance : ParameterizedNamedItem {
+    public static readonly string WeightsDescription = "The weights matrix describes the flows between the equipments.";
+    public static readonly string DistancesDescription = "The distances matrix describes the distances between the locations at which the equipment can be installed.";
+    public static readonly string InstallationCostsDescription = "The installation costs matrix describes the installation costs of installing equipment i at location j";
+    public static readonly string DemandsDescription = "The demands vector describes the space requirements of the equipments.";
+    public static readonly string CapacitiesDescription = "The capacities vector describes the available space at the locations.";
+    public static readonly string TransportationCostsDescription = "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.";
+    public static readonly string EquipmentNamesDescription = "Optional: A list of names that describes the equipments.";
+    public static readonly string LocationNamesDescription = "Optional: A list of names that describes the locations.";
+    public static readonly string PenaltyLevelDescription = "The quality that an infeasible solution cannot surpass.";
+
+
+    #region Parameter Properties
+    [Storable]
+    private ValueParameter<DoubleMatrix> weightsParam;
+    public IValueParameter<DoubleMatrix> WeightsParameter {
+      get { return weightsParam; }
+    }
+    [Storable]
+    private ValueParameter<DoubleMatrix> distancesParam;
+    public IValueParameter<DoubleMatrix> DistancesParameter {
+      get { return distancesParam; }
+    }
+    [Storable]
+    private ValueParameter<DoubleMatrix> installCostsParam;
+    public IValueParameter<DoubleMatrix> InstallationCostsParameter {
+      get { return installCostsParam; }
+    }
+    [Storable]
+    private ValueParameter<DoubleArray> demandsParam;
+    public IValueParameter<DoubleArray> DemandsParameter {
+      get { return demandsParam; }
+    }
+    [Storable]
+    private ValueParameter<DoubleArray> capacitiesParam;
+    public IValueParameter<DoubleArray> CapacitiesParameter {
+      get { return capacitiesParam; }
+    }
+    [Storable]
+    private FixedValueParameter<DoubleValue> transportationCostsParam;
+    public IFixedValueParameter<DoubleValue> TransportationCostsParameter {
+      get { return transportationCostsParam; }
+    }
+    [Storable]
+    private FixedValueParameter<DoubleValue> penaltyLevelParam;
+    public IFixedValueParameter<DoubleValue> PenaltyLevelParameter {
+      get { return penaltyLevelParam; }
+    }
+    [Storable]
+    private OptionalValueParameter<StringArray> equipmentNamesParam;
+    public OptionalValueParameter<StringArray> EquipmentNamesParameter {
+      get { return equipmentNamesParam; }
+    }
+    [Storable]
+    private OptionalValueParameter<StringArray> locationNamesParam;
+    public OptionalValueParameter<StringArray> LocationNamesParameter {
+      get { return locationNamesParam; }
+    }
+    #endregion
+
+    #region Properties
+    public DoubleMatrix Weights {
+      get { return WeightsParameter.Value; }
+      set { WeightsParameter.Value = value; }
+    }
+    public DoubleMatrix Distances {
+      get { return DistancesParameter.Value; }
+      set { DistancesParameter.Value = value; }
+    }
+    public DoubleMatrix InstallationCosts {
+      get { return InstallationCostsParameter.Value; }
+      set { InstallationCostsParameter.Value = value; }
+    }
+    public DoubleArray Demands {
+      get { return DemandsParameter.Value; }
+      set { DemandsParameter.Value = value; }
+    }
+    public DoubleArray Capacities {
+      get { return CapacitiesParameter.Value; }
+      set { CapacitiesParameter.Value = value; }
+    }
+    public double TransportationCosts {
+      get { return TransportationCostsParameter.Value.Value; }
+      set { TransportationCostsParameter.Value.Value = value; }
+    }
+    public double PenaltyLevel {
+      get { return PenaltyLevelParameter.Value.Value; }
+      set { PenaltyLevelParameter.Value.Value = value; }
+    }
+    public StringArray EquipmentNames {
+      get { return EquipmentNamesParameter.Value; }
+      set { EquipmentNamesParameter.Value = value; }
+    }
+    public StringArray LocationNames {
+      get { return LocationNamesParameter.Value; }
+      set { LocationNamesParameter.Value = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected GQAPInstance(StorableConstructorFlag _) : base(_) { }
+    protected GQAPInstance(GQAPInstance original, Cloner cloner)
+      : base(original, cloner) {
+      weightsParam = cloner.Clone(original.weightsParam);
+      distancesParam = cloner.Clone(original.distancesParam);
+      installCostsParam = cloner.Clone(original.installCostsParam);
+      transportationCostsParam = cloner.Clone(original.transportationCostsParam);
+      penaltyLevelParam = cloner.Clone(original.penaltyLevelParam);
+      demandsParam = cloner.Clone(original.demandsParam);
+      capacitiesParam = cloner.Clone(original.capacitiesParam);
+      equipmentNamesParam = cloner.Clone(original.equipmentNamesParam);
+      locationNamesParam = cloner.Clone(original.locationNamesParam);
+    }
+    public GQAPInstance() {
+      Parameters.Add(weightsParam = new ValueParameter<DoubleMatrix>("Weights", WeightsDescription, new DoubleMatrix()) { GetsCollected = false });
+      Parameters.Add(distancesParam = new ValueParameter<DoubleMatrix>("Distances", DistancesDescription, new DoubleMatrix()) { GetsCollected = false });
+      Parameters.Add(installCostsParam = new ValueParameter<DoubleMatrix>("InstallationCosts", InstallationCostsDescription, new DoubleMatrix()) { GetsCollected = false });
+      Parameters.Add(transportationCostsParam = new FixedValueParameter<DoubleValue>("TransportationCosts", TransportationCostsDescription, new DoubleValue(1)));
+      Parameters.Add(penaltyLevelParam = new FixedValueParameter<DoubleValue>("PenaltyLevel", PenaltyLevelDescription, new DoubleValue(0)));
+      Parameters.Add(demandsParam = new ValueParameter<DoubleArray>("Demands", DemandsDescription, new DoubleArray()) { GetsCollected = false });
+      Parameters.Add(capacitiesParam = new ValueParameter<DoubleArray>("Capacities", CapacitiesDescription, new DoubleArray()) { GetsCollected = false });
+      Parameters.Add(equipmentNamesParam = new OptionalValueParameter<StringArray>("EquipmentNames", EquipmentNamesDescription, null) { GetsCollected = false });
+      Parameters.Add(locationNamesParam = new OptionalValueParameter<StringArray>("LocationNames", LocationNamesDescription, null) { GetsCollected = false });
+
+      weightsParam.ReactOnValueToStringChangedAndValueItemImageChanged = false;
+      distancesParam.ReactOnValueToStringChangedAndValueItemImageChanged = false;
+      installCostsParam.ReactOnValueToStringChangedAndValueItemImageChanged = false;
+      demandsParam.ReactOnValueToStringChangedAndValueItemImageChanged = false;
+      capacitiesParam.ReactOnValueToStringChangedAndValueItemImageChanged = false;
+
+      Weights = new DoubleMatrix(5, 5);
+      Weights[0, 0] = Weights[1, 1] = Weights[2, 2] = Weights[3, 3] = Weights[4, 4] = 0;
+      Weights[0, 1] = Weights[1, 0] = Weights[0, 2] = Weights[2, 0] = Weights[0, 3] = Weights[3, 0] = Weights[0, 4] = Weights[4, 0] = 10;
+      Weights[1, 2] = Weights[2, 1] = Weights[1, 3] = Weights[3, 1] = Weights[1, 4] = Weights[4, 1] = 5;
+      Weights[2, 3] = Weights[3, 2] = Weights[2, 4] = Weights[4, 2] = 7.5;
+      Weights[3, 4] = Weights[4, 3] = 2.5;
+
+      Distances = new DoubleMatrix(3, 3);
+      Distances[0, 0] = Distances[1, 1] = Distances[2, 2] = 0;
+      Distances[0, 1] = Distances[1, 0] = Distances[1, 2] = Distances[2, 1] = 1;
+      Distances[0, 2] = Distances[2, 0] = 2;
+
+      InstallationCosts = new DoubleMatrix(5, 3);
+
+      Demands = new DoubleArray(5);
+      Demands[0] = 2; Demands[1] = 1; Demands[2] = 3; Demands[3] = 1; Demands[4] = 1;
+
+      Capacities = new DoubleArray(3);
+      Capacities[0] = 4; Capacities[1] = 1; Capacities[2] = 4;
+
+      TransportationCosts = 1;
+
+      CalculatePenaltyLevel();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPInstance(this, cloner);
+    }
+
+    public Evaluation Evaluate(IntegerVector assignment) {
+      var evaluation = EvaluateIntegerVector(assignment, Demands, Capacities,
+        InstallationCosts, Weights, Distances);
+      return evaluation;
+    }
+
+    public double EvaluateSingleObjective(IntegerVector assignment) {
+      return ToSingleObjective(Evaluate(assignment));
+    }
+
+    public static Evaluation EvaluateIntegerVector(IntegerVector assignment,
+      DoubleArray demands, DoubleArray capacities, DoubleMatrix installCosts,
+      DoubleMatrix weights, DoubleMatrix distances) {
+      var flowDistanceQuality = 0.0;
+      var installationQuality = 0.0;
+      var overbookedCapacity = 0.0;
+      int len = assignment.Length;
+      var slack = capacities.ToArray();
+
+      for (int i = 0; i < len; i++) {
+        var assignI = assignment[i];
+        installationQuality += installCosts[i, assignI];
+        for (int j = 0; j < len; j++) {
+          flowDistanceQuality += weights[i, j] * distances[assignI, assignment[j]];
+        }
+        if (slack[assignI] < 0) overbookedCapacity += demands[i];
+        else if (slack[assignI] < demands[i]) overbookedCapacity += (demands[i] - slack[assignI]);
+        slack[assignI] -= demands[i];
+      }
+      return new Evaluation(flowDistanceQuality, installationQuality, overbookedCapacity, slack);
+    }
+
+    public GQAPSolution ToEvaluatedSolution(IntegerVector assignment) {
+      var evaluation = EvaluateIntegerVector(assignment, Demands, Capacities,
+InstallationCosts, Weights, Distances);
+      return new GQAPSolution(assignment, evaluation);
+    }
+
+    public bool IsFeasible(IntegerVector assignment) {
+      int len = assignment.Length;
+      var utilization = new double[Capacities.Length];
+      for (var equip = 0; equip < len; equip++) {
+        var loc = assignment[equip];
+        utilization[loc] += Demands[equip];
+        if (utilization[loc] > Capacities[loc])
+          return false;
+      }
+      return true;
+    }
+
+    public double ToSingleObjective(Evaluation fitness) {
+      return fitness.IsFeasible
+        ? fitness.InstallationCosts + TransportationCosts * fitness.FlowCosts
+        : PenaltyLevel + fitness.ExcessDemand;
+    }
+
+    public double[] ToMultiObjectiveStrict(Evaluation fitness) {
+      return fitness.IsFeasible
+        ? new double[] { fitness.InstallationCosts, TransportationCosts * fitness.FlowCosts }
+        : new double[] { PenaltyLevel + fitness.ExcessDemand, PenaltyLevel + fitness.ExcessDemand };
+    }
+
+    public double[] ToMultiObjectiveRelaxed(Evaluation fitness) {
+      return new double[] {
+        fitness.InstallationCosts,
+        TransportationCosts * fitness.FlowCosts,
+        fitness.ExcessDemand };
+    }
+
+    public bool IsValid() {
+      return Weights != null && Distances != null && Demands != null && Capacities != null && InstallationCosts != null
+        && Weights.Rows == Weights.Columns && Weights.Rows == InstallationCosts.Rows
+        && Distances.Rows == Distances.Columns && Distances.Rows == InstallationCosts.Columns
+        && Demands.Length == Weights.Rows && Capacities.Length == Distances.Rows;
+    }
+
+    public void CalculatePenaltyLevel() {
+      var flowQuality = Distances.Max() * Weights.Max() * Demands.Length * Demands.Length;
+      var installQuality = InstallationCosts.Max() * Demands.Length;
+      PenaltyLevel = installQuality + TransportationCosts * flowQuality;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPSolution.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPSolution.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPSolution.cs	(revision 17175)
@@ -0,0 +1,79 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAPSolution", "A solution to the Generalized Quadratic Assignment Problem.")]
+  [StorableType("D4CC7924-87BF-4499-9149-D18000AD8151")]
+  public class GQAPSolution : Item, INotifyPropertyChanged {
+
+    [Storable]
+    private IntegerVector assignment;
+    public IntegerVector Assignment {
+      get { return assignment; }
+      set {
+        if (assignment == value) return;
+        assignment = value;
+        OnPropertyChanged(nameof(Assignment));
+      }
+    }
+
+    [Storable]
+    private Evaluation evaluation;
+    public Evaluation Evaluation {
+      get { return evaluation; }
+      set {
+        if (evaluation == value) return;
+        evaluation = value;
+        OnPropertyChanged(nameof(Evaluation));
+      }
+    }
+
+    [StorableConstructor]
+    protected GQAPSolution(StorableConstructorFlag _) : base(_) { }
+    protected GQAPSolution(GQAPSolution original, Cloner cloner)
+      : base(original, cloner) {
+      assignment = cloner.Clone(original.assignment);
+      evaluation = cloner.Clone(original.evaluation);
+    }
+    public GQAPSolution(IntegerVector assignment, Evaluation evaluation)
+      : base() {
+      this.assignment = assignment;
+      this.evaluation = evaluation;
+    }
+
+    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/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 17175)
@@ -0,0 +1,201 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{C739E6D2-5680-4804-A810-8017DA0C238F}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.GeneralizedQuadraticAssignment</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="HEAL.Attic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HEAL.Attic.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common.Resources-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common.Resources-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Data-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Optimization-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization.Operators-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Optimization.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Parameters-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Persistence-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Persistence-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Random-3.3, Version=3.3.0.0">
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Random-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Evaluation\Evaluation.cs" />
+    <Compile Include="Evaluation\GQAPNMoveEvaluator.cs" />
+    <Compile Include="GQAPAssignment.cs" />
+    <Compile Include="GQAPInstance.cs" />
+    <Compile Include="Interfaces\Parameter\IAssignmentAwareGQAPOperator.cs" />
+    <Compile Include="Moves\ExhaustiveOneMoveGenerator.cs" />
+    <Compile Include="Operators\Crossovers\CordeauCrossover.cs" />
+    <Compile Include="Operators\GQAPQualitySimilarityReducer.cs" />
+    <Compile Include="Operators\LocalImprovers\OneOptLocalSearch.cs" />
+    <Compile Include="SolutionCreators\SlackMinimizationSolutionCreator.cs" />
+    <Compile Include="SolutionCreators\RandomButFeasibleSolutionCreator.cs" />
+    <Compile Include="SolutionCreators\GQAPSolutionCreator.cs" />
+    <Compile Include="SolutionCreators\GQAPStochasticSolutionCreator.cs" />
+    <Compile Include="SolutionCreators\GreedyRandomizedSolutionCreator.cs" />
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="GQAP.cs" />
+    <Compile Include="GQAPAssignmentArchive.cs" />
+    <Compile Include="GQAPSolution.cs" />
+    <Compile Include="Interfaces\Parameter\IBestKnownSolutionsAwareGQAPOperator.cs" />
+    <Compile Include="Interfaces\Operator\IGQAPManipulator.cs" />
+    <Compile Include="Interfaces\Parameter\IQualitiesAwareGQAPOperator.cs" />
+    <Compile Include="Interfaces\Parameter\IBestKnownQualityAwareGQAPOperator.cs" />
+    <Compile Include="Interfaces\Parameter\IBestKnownSolutionAwareGQAPOperator.cs" />
+    <Compile Include="Interfaces\Parameter\IMoveQualityAwareGQAPOperator.cs" />
+    <Compile Include="Interfaces\Parameter\IQualityAwareGQAPOperator.cs" />
+    <Compile Include="Interfaces\Parameter\IProblemInstanceAwareGQAPOperator.cs" />
+    <Compile Include="Interfaces\Operator\IGQAPNMoveEvaluator.cs" />
+    <Compile Include="Interfaces\Operator\IGQAPCrossover.cs" />
+    <Compile Include="Interfaces\Operator\IGQAPLocalImprovementOperator.cs" />
+    <Compile Include="Interfaces\Operator\IGQAPMoveEvaluator.cs" />
+    <Compile Include="Interfaces\Operator\IGQAPMoveOperator.cs" />
+    <Compile Include="Interfaces\Operator\IGQAPNMoveOperator.cs" />
+    <Compile Include="Interfaces\Operator\IGQAPOperator.cs" />
+    <Compile Include="Interfaces\Operator\IGQAPSolutionCreator.cs" />
+    <Compile Include="Moves\NMove.cs" />
+    <Compile Include="Moves\GQAPMoveGenerator.cs" />
+    <Compile Include="Moves\GQAPNMoveGenerator.cs" />
+    <Compile Include="Moves\NMoveAbsoluteAttribute.cs" />
+    <Compile Include="Moves\NMoveMaker.cs" />
+    <Compile Include="Moves\NMoveTabuChecker.cs" />
+    <Compile Include="Moves\NMoveTabuMaker.cs" />
+    <Compile Include="Moves\StochasticNMoveMultiMoveGenerator.cs" />
+    <Compile Include="Moves\StochasticNMoveSingleMoveGenerator.cs" />
+    <Compile Include="Operators\Crossovers\DiscreteLocationCrossover.cs" />
+    <Compile Include="Operators\Crossovers\GQAPCrossover.cs" />
+    <Compile Include="Operators\Crossovers\GQAPPathRelinking.cs" />
+    <Compile Include="Operators\Crossovers\MultiGQAPCrossover.cs" />
+    <Compile Include="Operators\LocalImprovers\ApproximateLocalSearch.cs" />
+    <Compile Include="Operators\Manipulators\DemandEquivalentSwapEquipmentManipluator.cs" />
+    <Compile Include="Operators\Manipulators\GQAPManipulator.cs" />
+    <Compile Include="Operators\Manipulators\MultiGQAPManipulator.cs" />
+    <Compile Include="Operators\Manipulators\RelocateEquipmentManipluator.cs" />
+    <Compile Include="Operators\Manipulators\SwapEquipmentManipluator.cs" />
+    <Compile Include="Operators\Manipulators\SwapLocationManipulator.cs" />
+    <Compile Include="Operators\Shakers\NMoveShakingOperator.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.IntegerVectorEncoding\3.3\HeuristicLab.Encodings.IntegerVectorEncoding-3.3.csproj">
+      <Project>{ddfb14dd-2a85-493c-a52d-e69729bbaeb0}</Project>
+      <Name>HeuristicLab.Encodings.IntegerVectorEncoding-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd</PreBuildEvent>
+  </PropertyGroup>
+  <PropertyGroup>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPCrossover.cs	(revision 17175)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("E2FD76F9-82CC-466A-AB42-5B31F02D45FC")]
+  public interface IGQAPCrossover : IGQAPOperator, ICrossover {
+    IScopeTreeLookupParameter<IntegerVector> ParentsParameter { get; }
+    ILookupParameter<IntegerVector> ChildParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPLocalImprovementOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPLocalImprovementOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPLocalImprovementOperator.cs	(revision 17175)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("D22AA954-0957-4F71-9D3C-A614F53A4821")]
+  public interface IGQAPLocalImprovementOperator : ILocalImprovementAlgorithmOperator {
+    ILookupParameter<IntegerVector> AssignmentParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPManipulator.cs	(revision 17175)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("A3C58BBD-1652-456B-AF71-D58F782A47D6")]
+  public interface IGQAPManipulator : IManipulator {
+    ILookupParameter<IntegerVector> AssignmentParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPMoveEvaluator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPMoveEvaluator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPMoveEvaluator.cs	(revision 17175)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("8DE86FE9-07B9-4550-B36C-4DC6B2F58272")]
+  public interface IGQAPMoveEvaluator : IGQAPMoveOperator, ISingleObjectiveMoveEvaluator {
+    ILookupParameter<Evaluation> MoveEvaluationParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPMoveOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPMoveOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPMoveOperator.cs	(revision 17175)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("BB1D416A-CFE4-4CEF-875F-905F38861087")]
+  public interface IGQAPMoveOperator : IMoveOperator {
+    ILookupParameter<IntegerVector> AssignmentParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPNMoveEvaluator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPNMoveEvaluator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPNMoveEvaluator.cs	(revision 17175)
@@ -0,0 +1,26 @@
+﻿using HEAL.Attic;
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("ACEEB42B-09AA-432C-98B4-2C6BBF0D38E5")]
+  public interface IGQAPNMoveEvaluator : IGQAPMoveEvaluator, IGQAPNMoveOperator { }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPNMoveOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPNMoveOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPNMoveOperator.cs	(revision 17175)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("4128D4FF-A36C-4D3F-ADE1-B63407D5C7DE")]
+  public interface IGQAPNMoveOperator : IGQAPMoveOperator {
+    ILookupParameter<NMove> MoveParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPOperator.cs	(revision 17175)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("521D5B7F-85A0-4BE9-89B2-CA0C3B5B9338")]
+  public interface IGQAPOperator : IOperator { }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPSolutionCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPSolutionCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Operator/IGQAPSolutionCreator.cs	(revision 17175)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("02E67D15-F15E-4255-855B-8BA2534E7B2E")]
+  public interface IGQAPSolutionCreator : IIntegerVectorCreator { }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IAssignmentAwareGQAPOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IAssignmentAwareGQAPOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IAssignmentAwareGQAPOperator.cs	(revision 17175)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("1A005153-0B2E-4C8F-993A-F7B03438A359")]
+  public interface IAssignmentAwareGQAPOperator : IGQAPOperator {
+    ILookupParameter<IntegerVector> AssignmentParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IBestKnownQualityAwareGQAPOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IBestKnownQualityAwareGQAPOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IBestKnownQualityAwareGQAPOperator.cs	(revision 17175)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Data;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("91E65BE8-8BFA-440B-A314-0494E70ED558")]
+  public interface IBestKnownQualityAwareGQAPOperator : IGQAPOperator {
+    ILookupParameter<DoubleValue> BestKnownQualityParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IBestKnownSolutionAwareGQAPOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IBestKnownSolutionAwareGQAPOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IBestKnownSolutionAwareGQAPOperator.cs	(revision 17175)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("A90653A3-28DB-49AD-A7D5-07F689116BC6")]
+  public interface IBestKnownSolutionAwareGQAPOperator : IGQAPOperator {
+    ILookupParameter<GQAPAssignment> BestKnownSolutionParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IBestKnownSolutionsAwareGQAPOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IBestKnownSolutionsAwareGQAPOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IBestKnownSolutionsAwareGQAPOperator.cs	(revision 17175)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("C8CCB98C-2792-427C-9C31-289364C4CFF7")]
+  public interface IBestKnownSolutionsAwareGQAPOperator : IGQAPOperator {
+    ILookupParameter<GQAPAssignmentArchive> BestKnownSolutionsParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IMoveQualityAwareGQAPOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IMoveQualityAwareGQAPOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IMoveQualityAwareGQAPOperator.cs	(revision 17175)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Data;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("9CFFCC2B-E7AC-4719-ABA8-4FAAD1EE106F")]
+  public interface IMoveQualityAwareGQAPOperator : IGQAPMoveOperator {
+    ILookupParameter<DoubleValue> MoveQualityParameter { get; }
+    ILookupParameter<Evaluation> MoveEvaluationParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IProblemInstanceAwareGQAPOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IProblemInstanceAwareGQAPOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IProblemInstanceAwareGQAPOperator.cs	(revision 17175)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("5780BD3B-C406-4C0E-96E9-52336301FFA2")]
+  public interface IProblemInstanceAwareGQAPOperator : IGQAPOperator {
+    ILookupParameter<GQAPInstance> ProblemInstanceParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IQualitiesAwareGQAPOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IQualitiesAwareGQAPOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IQualitiesAwareGQAPOperator.cs	(revision 17175)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Data;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("94E6E70C-6BF4-4F57-9D2E-8AC7E5716C34")]
+  public interface IQualitiesAwareGQAPOperator : IGQAPOperator {
+    IScopeTreeLookupParameter<DoubleValue> QualityParameter { get; }
+    IScopeTreeLookupParameter<Evaluation> EvaluationParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IQualityAwareGQAPOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IQualityAwareGQAPOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Interfaces/Parameter/IQualityAwareGQAPOperator.cs	(revision 17175)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Data;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [StorableType("903B1E5E-980E-440D-BFEF-C4EC8E3D01B4")]
+  public interface IQualityAwareGQAPOperator : IGQAPOperator {
+    ILookupParameter<DoubleValue> QualityParameter { get; }
+    ILookupParameter<Evaluation> EvaluationParameter { get; }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/ExhaustiveOneMoveGenerator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/ExhaustiveOneMoveGenerator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/ExhaustiveOneMoveGenerator.cs	(revision 17175)
@@ -0,0 +1,91 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("Exhaustive 1-Move MoveGenerator", "Exhaustively generates all possible 1-moves.")]
+  [StorableType("A200C3BE-D761-4F82-9CA9-44A7BB2AB0DD")]
+  public class ExhaustiveOneMoveGenerator : GQAPNMoveGenerator, IStochasticOperator, IExhaustiveMoveGenerator {
+    
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected ExhaustiveOneMoveGenerator(StorableConstructorFlag _) : base(_) { }
+    protected ExhaustiveOneMoveGenerator(ExhaustiveOneMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public ExhaustiveOneMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator that should be used."));
+      NParameter.Value.Value = 1;
+      NParameter.Hidden = true;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ExhaustiveOneMoveGenerator(this, cloner);
+    }
+
+    public static IEnumerable<NMove> Generate(IntegerVector assignment, GQAPInstance problemInstance) {
+      var equipments = problemInstance.Demands.Length;
+      var locations = problemInstance.Capacities.Length;
+      var tmp = new int[equipments];
+      for (var e = 0; e < equipments; e++) {
+        var indices = new List<int> { e };
+        for (var l = 0; l < locations; l++) {
+          if (assignment[e] == l) continue;
+          var reassign = (int[])tmp.Clone();
+          reassign[e] = l + 1;
+          yield return new NMove(reassign, indices);
+        }
+      }
+    }
+
+    public static IEnumerable<NMove> GenerateAllNxM(GQAPInstance problemInstance) {
+      var equipments = problemInstance.Demands.Length;
+      var locations = problemInstance.Capacities.Length;
+      var tmp = new int[equipments];
+      for (var e = 0; e < equipments; e++) {
+        var indices = new List<int> { e };
+        for (var l = 0; l < locations; l++) {
+          var reassign = (int[])tmp.Clone();
+          reassign[e] = l + 1;
+          yield return new NMove(reassign, indices);
+        }
+      }
+    }
+
+    public override IEnumerable<NMove> GenerateMoves(IntegerVector assignment, int n, GQAPInstance problemInstance) {
+      if (n != 1) throw new ArgumentException("N must be equal to 1 for the exhaustive 1-move generator.");
+      var random = RandomParameter.ActualValue;
+      return Generate(assignment, problemInstance).Shuffle(random);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/GQAPMoveGenerator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/GQAPMoveGenerator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/GQAPMoveGenerator.cs	(revision 17175)
@@ -0,0 +1,55 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAPMoveGenerator", "Base class for move generators for the Generalized Quadratic Assignment Problem.")]
+  [StorableType("4CB9C31B-4ACA-4ED6-8C7E-756319EFB8FF")]
+  public abstract class GQAPMoveGenerator : SingleSuccessorOperator, IMoveGenerator, IGQAPMoveOperator,
+    IProblemInstanceAwareGQAPOperator {
+
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+
+
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    [StorableConstructor]
+    protected GQAPMoveGenerator(StorableConstructorFlag _) : base(_) { }
+    protected GQAPMoveGenerator(GQAPMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public GQAPMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/GQAPNMoveGenerator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/GQAPNMoveGenerator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/GQAPNMoveGenerator.cs	(revision 17175)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("N-Move Generator", "Base class for move operators that generate N-Move moves.")]
+  [StorableType("AC6F4053-7EEF-4125-A6F7-C93A3DC7001A")]
+  public abstract class GQAPNMoveGenerator : GQAPMoveGenerator, IGQAPNMoveOperator {
+
+    #region Parameter Descriptions
+    public static readonly string MoveDescription = "Moves represent changes to the current solution. The n-move changes the assignment of up to or exactly n equipments.";
+    #endregion
+
+    public ILookupParameter<NMove> MoveParameter {
+      get { return (ILookupParameter<NMove>)Parameters["Move"]; }
+    }
+    public IValueLookupParameter<IntValue> NParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["N"]; }
+    }
+
+    [StorableConstructor]
+    protected GQAPNMoveGenerator(StorableConstructorFlag _) : base(_) { }
+    protected GQAPNMoveGenerator(GQAPNMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public GQAPNMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<NMove>("Move", MoveDescription));
+      Parameters.Add(new ValueLookupParameter<IntValue>("N", "The maximum number of equipment(s) that should be moved.", new IntValue(2)));
+    }
+
+    public override IOperation Apply() {
+      List<Scope> scopes = new List<Scope>();
+      int counter = 0;
+      string name = MoveParameter.TranslatedName;
+      foreach (var move in GenerateMoves(AssignmentParameter.ActualValue, NParameter.ActualValue.Value, ProblemInstanceParameter.ActualValue)) {
+        scopes.Add(new Scope(counter.ToString()));
+        scopes.Last().Variables.Add(new Variable(name, move));
+        counter++;
+      }
+      ExecutionContext.Scope.SubScopes.AddRange(scopes);
+      return base.Apply();
+    }
+
+    public abstract IEnumerable<NMove> GenerateMoves(IntegerVector assignment, int n, GQAPInstance problemInstance);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMove.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMove.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMove.cs	(revision 17175)
@@ -0,0 +1,75 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("N-Move", "An N-Move describes the relocation of n equipments to n different locations.")]
+  [StorableType("A3E69FD9-B578-486C-81CE-D1CB65A250CE")]
+  public class NMove : Item {
+    [Storable]
+    private int[] reassignments;
+    /// <summary>
+    /// Contains for each equipment the newly assigned location.
+    /// </summary>
+    /// <remarks>
+    /// Locations are 1-based. A 0 indicates that this equipment is not reassigned.
+    /// </remarks>
+    public IReadOnlyList<int> Reassignments {
+      get { return reassignments; }
+    }
+    [Storable]
+    private List<int> indices;
+    /// <summary>
+    /// Which indices (=equipments) are reassigned.
+    /// </summary>
+    /// <remarks>
+    /// Equipments are 0-based.
+    /// </remarks>
+    public IReadOnlyList<int> Indices {
+      get { return indices; }
+    }
+
+    public int N { get { return Indices.Count; } }
+
+    [StorableConstructor]
+    protected NMove(StorableConstructorFlag _) : base(_) { }
+    protected NMove(NMove original, Cloner cloner)
+      : base(original, cloner) {
+      reassignments = original.reassignments.ToArray();
+      indices = original.indices.ToList();
+    }
+    public NMove(int[] reassignments, List<int> indices)
+      : base() {
+      this.reassignments = reassignments;
+      this.indices = indices;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NMove(this, cloner);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveAbsoluteAttribute.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveAbsoluteAttribute.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveAbsoluteAttribute.cs	(revision 17175)
@@ -0,0 +1,55 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("N-Move Absolute TabuAttribute", "Attribute to determine whether a certain move is tabu.")]
+  [StorableType("39C4AE8F-9FEB-447A-878B-38796B7E8AAF")]
+  public class NMoveAbsoluteTabuAttribute : Item {
+
+    [Storable]
+    public List<Tuple<int, int>> OldAssignments { get; private set; }
+    [Storable]
+    public double MoveQuality { get; private set; }
+
+    [StorableConstructor]
+    protected NMoveAbsoluteTabuAttribute(StorableConstructorFlag _) : base(_) { }
+    protected NMoveAbsoluteTabuAttribute(NMoveAbsoluteTabuAttribute original, Cloner cloner) : base(original, cloner) { }
+    public NMoveAbsoluteTabuAttribute(NMove move, IntegerVector assignment, double moveQuality)
+      : base() {
+      OldAssignments = new List<Tuple<int, int>>(move.N);
+      foreach (var equip in move.Indices)
+        OldAssignments.Add(Tuple.Create(equip, assignment[equip]));
+      MoveQuality = moveQuality;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NMoveAbsoluteTabuAttribute(this, cloner);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveMaker.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveMaker.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveMaker.cs	(revision 17175)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("N-Move Maker", "Performs an N-Move.")]
+  [StorableType("9DAB4C4D-533A-4990-B591-A4C877F0CCE9")]
+  public class NMoveMaker : SingleSuccessorOperator, IQualityAwareGQAPOperator, IMoveQualityAwareGQAPOperator, IGQAPNMoveOperator, IMoveMaker {
+
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public ILookupParameter<NMove> MoveParameter {
+      get { return (ILookupParameter<NMove>)Parameters["Move"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<Evaluation> EvaluationParameter {
+      get { return (ILookupParameter<Evaluation>)Parameters["Evaluation"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<Evaluation> MoveEvaluationParameter {
+      get { return (ILookupParameter<Evaluation>)Parameters["MoveEvaluation"]; }
+    }
+
+    [StorableConstructor]
+    protected NMoveMaker(StorableConstructorFlag _) : base(_) { }
+    protected NMoveMaker(NMoveMaker original, Cloner cloner) : base(original, cloner) { }
+    public NMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<NMove>("Move", GQAPNMoveGenerator.MoveDescription));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", ""));
+      Parameters.Add(new LookupParameter<Evaluation>("Evaluation", GQAP.EvaluationDescription));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", GQAPNMoveEvaluator.MoveQualityDescription));
+      Parameters.Add(new LookupParameter<Evaluation>("MoveEvaluation", GQAPNMoveEvaluator.MoveEvaluationDescription));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NMoveMaker(this, cloner);
+    }
+
+    public static void Apply(IntegerVector vector, NMove move) {
+      for (var i = 0; i < move.N; i++) {
+        var equip = move.Indices[i];
+        vector[equip] = move.Reassignments[equip] - 1; // location is given 1-based in reassignments
+      }
+    }
+
+    public override IOperation Apply() {
+      Apply(AssignmentParameter.ActualValue, MoveParameter.ActualValue);
+      QualityParameter.ActualValue.Value = MoveQualityParameter.ActualValue.Value;
+      EvaluationParameter.ActualValue = MoveEvaluationParameter.ActualValue;
+      return base.Apply();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveTabuChecker.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveTabuChecker.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveTabuChecker.cs	(revision 17175)
@@ -0,0 +1,126 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Moves {
+  [Item("N-Move TabuChecker", "Checks if a certain N-Move is tabu.")]
+  [StorableType("8E122154-5BCE-404A-8AD4-6C30912B3E89")]
+  public class NMoveTabuChecker : SingleSuccessorOperator, ITabuChecker,
+    IGQAPNMoveOperator, IMoveQualityAwareGQAPOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ILookupParameter<NMove> MoveParameter {
+      get { return (ILookupParameter<NMove>)Parameters["Move"]; }
+    }
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public ILookupParameter<ItemList<IItem>> TabuListParameter {
+      get { return (ILookupParameter<ItemList<IItem>>)Parameters["TabuList"]; }
+    }
+    public ILookupParameter<BoolValue> MoveTabuParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["MoveTabu"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<Evaluation> MoveEvaluationParameter {
+      get { return (ILookupParameter<Evaluation>)Parameters["MoveEvaluation"]; }
+    }
+    public IValueParameter<BoolValue> UseAspirationCriterionParameter {
+      get { return (IValueParameter<BoolValue>)Parameters["UseAspirationCriterion"]; }
+    }
+
+    public BoolValue UseAspirationCriterion {
+      get { return UseAspirationCriterionParameter.Value; }
+      set { UseAspirationCriterionParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected NMoveTabuChecker(StorableConstructorFlag _) : base(_) { }
+    protected NMoveTabuChecker(NMoveTabuChecker original, Cloner cloner) : base(original, cloner) { }
+    public NMoveTabuChecker()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", ""));
+      Parameters.Add(new LookupParameter<NMove>("Move", GQAPNMoveGenerator.MoveDescription));
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list contains previous move attributes."));
+      Parameters.Add(new LookupParameter<BoolValue>("MoveTabu", "Declares if a move is tabu or not."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", GQAPNMoveEvaluator.MoveQualityDescription));
+      Parameters.Add(new LookupParameter<Evaluation>("MoveEvaluation", GQAPNMoveEvaluator.MoveEvaluationDescription));
+      Parameters.Add(new ValueParameter<BoolValue>("UseAspirationCriterion", "Whether moves can be aspired.", new BoolValue(true)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NMoveTabuChecker(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      ItemList<IItem> tabuList = TabuListParameter.ActualValue;
+      var move = MoveParameter.ActualValue;
+      var assignment = AssignmentParameter.ActualValue;
+      int length = assignment.Length;
+      double moveQuality = MoveQualityParameter.ActualValue.Value;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+      bool useAspiration = UseAspirationCriterion.Value;
+      
+      bool isTabu = EvaluateTabuState(tabuList, move, assignment, moveQuality, maximization, useAspiration);
+
+      MoveTabuParameter.ActualValue = new BoolValue(isTabu);
+      return base.Apply();
+    }
+
+    private bool EvaluateTabuState(ItemList<IItem> tabuList, NMove move, IntegerVector assignment, double moveQuality, bool maximization, bool useAspiration) {
+      bool isTabu = false;
+      foreach (var t in tabuList) {
+        var attribute = (t as NMoveAbsoluteTabuAttribute);
+        if (attribute == null) continue;
+        if (!useAspiration
+          || maximization && moveQuality <= attribute.MoveQuality
+          || !maximization && moveQuality >= attribute.MoveQuality) {
+          isTabu = true;
+          foreach (var kvp in attribute.OldAssignments) {
+            var assignedLoc = move.Reassignments[kvp.Item1] - 1; // location is given 1-based
+            if (assignedLoc >= 0 && assignedLoc != kvp.Item2) {
+              isTabu = false;
+              break;
+            }
+          }
+        }
+        if (isTabu) break;
+      }
+      return isTabu;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveTabuMaker.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveTabuMaker.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/NMoveTabuMaker.cs	(revision 17175)
@@ -0,0 +1,67 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Moves {
+  [Item("N-Move TabuMaker", "Declares an N-Move tabu.")]
+  [StorableType("BE81C264-2DD8-4A2C-8796-D0D1E121FF53")]
+  public class NMoveTabuMaker : TabuMaker, IGQAPNMoveOperator, IMoveQualityAwareGQAPOperator {
+
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public ILookupParameter<NMove> MoveParameter {
+      get { return (ILookupParameter<NMove>)Parameters["Move"]; }
+    }
+    public ILookupParameter<Evaluation> MoveEvaluationParameter {
+      get { return (ILookupParameter<Evaluation>)Parameters["MoveEvaluation"]; }
+    }
+
+    [StorableConstructor]
+    protected NMoveTabuMaker(StorableConstructorFlag _) : base(_) { }
+    protected NMoveTabuMaker(NMoveTabuMaker original, Cloner cloner) : base(original, cloner) { }
+    public NMoveTabuMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<NMove>("Move", GQAPNMoveGenerator.MoveDescription));
+      Parameters.Add(new LookupParameter<Evaluation>("MoveEvaluation", GQAPNMoveEvaluator.MoveEvaluationDescription));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NMoveTabuMaker(this, cloner);
+    }
+
+    protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality) {
+      var move = MoveParameter.ActualValue;
+      var assignment = AssignmentParameter.ActualValue;
+      double baseQuality = moveQuality;
+      if (maximization && quality > moveQuality || !maximization && quality < moveQuality) baseQuality = quality; // we make an uphill move, the lower bound is the solution quality
+      return new NMoveAbsoluteTabuAttribute(move, assignment, baseQuality);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/StochasticNMoveMultiMoveGenerator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/StochasticNMoveMultiMoveGenerator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/StochasticNMoveMultiMoveGenerator.cs	(revision 17175)
@@ -0,0 +1,66 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("Stochastic N-Move MultiMoveGenerator", "Randomly samples a number of N-Moves.")]
+  [StorableType("EEE53E16-0FB6-4041-A9AC-ECDA5E73A505")]
+  public class StochasticNMoveMultiMoveGenerator : GQAPNMoveGenerator, IStochasticOperator, IMultiMoveGenerator {
+    
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    [StorableConstructor]
+    protected StochasticNMoveMultiMoveGenerator(StorableConstructorFlag _) : base(_) { }
+    protected StochasticNMoveMultiMoveGenerator(StochasticNMoveMultiMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public StochasticNMoveMultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator that should be used."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StochasticNMoveMultiMoveGenerator(this, cloner);
+    }
+
+    public static IEnumerable<NMove> Generate(IRandom random, IntegerVector assignment, int n, GQAPInstance problemInstance, int sampleSize) {
+      for (int i = 0; i < sampleSize; i++)
+        yield return StochasticNMoveSingleMoveGenerator.GenerateUpToN(random, assignment, n, problemInstance.Capacities);
+    }
+
+    public override IEnumerable<NMove> GenerateMoves(IntegerVector assignment, int n, GQAPInstance problemInstance) {
+      return Generate(RandomParameter.ActualValue, assignment, n, problemInstance, SampleSizeParameter.ActualValue.Value);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/StochasticNMoveSingleMoveGenerator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/StochasticNMoveSingleMoveGenerator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/StochasticNMoveSingleMoveGenerator.cs	(revision 17175)
@@ -0,0 +1,108 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("Stochastic N-Move SingleMoveGenerator", "Randomly samples a single N-Move.")]
+  [StorableType("7CC8D0D6-C865-485F-A16A-C2ED764C6AC4")]
+  public class StochasticNMoveSingleMoveGenerator : GQAPNMoveGenerator, IStochasticOperator, ISingleMoveGenerator {
+    
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected StochasticNMoveSingleMoveGenerator(StorableConstructorFlag _) : base(_) { }
+    protected StochasticNMoveSingleMoveGenerator(StochasticNMoveSingleMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public StochasticNMoveSingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator that should be used."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StochasticNMoveSingleMoveGenerator(this, cloner);
+    }
+
+    public static NMove GenerateUpToN(IRandom random, IntegerVector assignment, int n, DoubleArray capacities) {
+      return GenerateExactlyN(random, assignment, random.Next(n) + 1, capacities);
+    }
+
+    public static NMove GenerateOneMove(IRandom random, IntegerVector assignment, DoubleArray capacities) {
+      var locations = capacities.Length;
+      if (locations <= 1) throw new ArgumentException("There must be at least two locations.");
+      var dim = assignment.Length;
+      var equip = random.Next(dim);
+      var equipments = new List<int>(1) { equip };
+
+      var reassignment = new int[dim];
+      reassignment[equip] = 1 + (assignment[equip] + random.Next(1, locations)) % locations;
+
+      return new NMove(reassignment, equipments);
+    }
+
+    public static NMove GenerateTwoMove(IRandom random, IntegerVector assignment, DoubleArray capacities) {
+      var locations = capacities.Length;
+      if (locations <= 1) throw new ArgumentException("There must be at least two locations.");
+      var dim = assignment.Length;
+      var equipments = new List<int>(2) { random.Next(dim) };
+      equipments.Add((equipments[0] + random.Next(1, dim)) % dim);
+
+      var reassignment = new int[dim];
+      for (var i = 0; i < 2; i++) {
+        var equip = equipments[i];
+        reassignment[equip] = 1 + (assignment[equip] + random.Next(1, locations)) % locations;
+      }
+      return new NMove(reassignment, equipments);
+    }
+
+    public static NMove GenerateExactlyN(IRandom random, IntegerVector assignment, int n, DoubleArray capacities) {
+      if (n == 1) return GenerateOneMove(random, assignment, capacities);
+      if (n == 2) return GenerateTwoMove(random, assignment, capacities);
+      var locations = capacities.Length;
+      if (locations <= 1) throw new ArgumentException("There must be at least two locations.");
+      var dim = assignment.Length;
+      var equipments = Enumerable.Range(0, dim).SampleRandomWithoutRepetition(random, n, dim).ToList();
+
+      var reassignment = new int[dim];
+      for (var i = 0; i < n; i++) {
+        var equip = equipments[i];
+        reassignment[equip] = 1 + (assignment[equip] + random.Next(1, locations)) % locations;
+      }
+      return new NMove(reassignment, equipments);
+    }
+
+    public override IEnumerable<NMove> GenerateMoves(IntegerVector assignment, int n, GQAPInstance problemInstance) {
+      yield return GenerateUpToN(RandomParameter.ActualValue, assignment, n, problemInstance.Capacities);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/CordeauCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/CordeauCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/CordeauCrossover.cs	(revision 17175)
@@ -0,0 +1,207 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("CordeauCrossover", "The merge procedure that is described in Cordeau, J.-F., Gaudioso, M., Laporte, G., Moccia, L. 2006. A memetic heuristic for the generalized quadratic assignment problem. INFORMS Journal on Computing, 18, pp. 433–443.")]
+  [StorableType("05D7FC4C-EF71-4118-9FF1-B8B71B501A99")]
+  public class CordeauCrossover : GQAPCrossover,
+    IQualitiesAwareGQAPOperator, IProblemInstanceAwareGQAPOperator {
+    
+    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public IScopeTreeLookupParameter<Evaluation> EvaluationParameter {
+      get { return (IScopeTreeLookupParameter<Evaluation>)Parameters["Evaluation"]; }
+    }
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+
+    [StorableConstructor]
+    protected CordeauCrossover(StorableConstructorFlag _) : base(_) { }
+    protected CordeauCrossover(CordeauCrossover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public CordeauCrossover()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The quality of the parents", 1));
+      Parameters.Add(new ScopeTreeLookupParameter<Evaluation>("Evaluation", GQAP.EvaluationDescription, 1));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The number of evaluated solutions."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CordeauCrossover(this, cloner);
+    }
+
+    public static IntegerVector Apply(IRandom random,
+      IntegerVector parent1, DoubleValue quality1,
+      IntegerVector parent2, DoubleValue quality2,
+      GQAPInstance problemInstance, IntValue evaluatedSolutions) {
+      var distances = problemInstance.Distances;
+      var capacities = problemInstance.Capacities;
+      var demands = problemInstance.Demands;
+
+      var medianDistances = Enumerable.Range(0, distances.Rows).Select(x => distances.GetRow(x).Median()).ToArray();
+
+      int m = capacities.Length;
+      int n = demands.Length;
+      
+      bool onefound = false;
+      double fbest, fbestAttempt = double.MaxValue;
+      IntegerVector bestAttempt = null;
+      IntegerVector result = null;
+
+      fbest = quality1.Value;
+      if (quality1.Value > quality2.Value) {
+        var temp = parent1;
+        parent1 = parent2;
+        parent2 = temp;
+        fbest = quality2.Value;
+      }
+      var cap = new double[m];
+      for (var i = 0; i < m; i++) {
+        int unassigned;
+        Array.Clear(cap, 0, m);
+        var child = Merge(parent1, parent2, distances, demands, medianDistances, m, n, i, cap, out unassigned);
+        if (unassigned > 0)
+          TryRandomAssignment(random, demands, capacities, m, n, cap, child, ref unassigned);
+        if (unassigned == 0) {
+          var childFit = problemInstance.ToSingleObjective(problemInstance.Evaluate(child));
+          evaluatedSolutions.Value++;
+          if (childFit <= fbest) {
+            fbest = childFit;
+            result = child;
+            onefound = true;
+          }
+          if (!onefound && fbestAttempt > childFit) {
+            bestAttempt = child;
+            fbestAttempt = childFit;
+          }
+        }
+      }
+
+      if (!onefound) {
+        var i = random.Next(m);
+        int unassigned;
+        Array.Clear(cap, 0, m);
+        var child = Merge(parent1, parent2, distances, demands, medianDistances, m, n, i, cap, out unassigned);
+        RandomAssignment(random, demands, capacities, m, n, cap, child, ref unassigned);
+
+        var childFit = problemInstance.ToSingleObjective(problemInstance.Evaluate(child));
+        evaluatedSolutions.Value++;
+        if (childFit < fbest) {
+          fbest = childFit;
+          result = child;
+          onefound = true;
+        }
+
+        if (!onefound && fbestAttempt > childFit) {
+          bestAttempt = child;
+          fbestAttempt = childFit;
+        }
+      }
+        /*if (tabufix(&son, 0.5 * sqrt(n * m), round(n * m * log10(n)), &tabufix_it)) {
+          solution_cost(&son);
+          if (son.cost < fbest) {
+            fbest = son.cost;
+            *sptr = son;
+            onefound = TRUE;
+            merge_fixed++;
+          }*/
+      return result ?? bestAttempt;
+    }
+
+    private static IntegerVector Merge(IntegerVector p1, IntegerVector p2,
+      DoubleMatrix distances, DoubleArray demands, double[] mediana,
+      int m, int n, int i, double[] cap, out int unassigned) {
+      unassigned = n;
+      var child = new IntegerVector(n);
+      for (var k = 0; k < n; k++) {
+        child[k] = -1;
+        var ik1 = p1[k];
+        var ik2 = p2[k];
+        if (distances[i, ik1] < mediana[i]) {
+          child[k] = ik1;
+          cap[ik1] += demands[k];
+          unassigned--;
+        } else if (distances[i, ik2] > mediana[i]) {
+          child[k] = ik2;
+          cap[ik2] += demands[k];
+          unassigned--;
+        };
+      }
+      return child;
+    }
+
+    private static bool TryRandomAssignment(IRandom random, DoubleArray demands, DoubleArray capacities, int m, int n, double[] cap, IntegerVector child, ref int unassigned) {
+      var unbiasedOrder = Enumerable.Range(0, n).Shuffle(random).ToList();
+      for (var idx = 0; idx < n; idx++) {
+        var k = unbiasedOrder[idx];
+        if (child[k] < 0) {
+          var feasibleInserts = Enumerable.Range(0, m)
+            .Select((v, i) => new { Pos = i, Slack = capacities[i] - cap[i] })
+            .Where(x => x.Slack >= demands[k]).ToList();
+          if (feasibleInserts.Count == 0) return false;
+          var j = feasibleInserts.SampleRandom(random).Pos;
+          child[k] = j;
+          cap[j] += demands[k];
+          unassigned--;
+        }
+      }
+      return true;
+    }
+
+    private static void RandomAssignment(IRandom random, DoubleArray demands, DoubleArray capacities, int m, int n, double[] cap, IntegerVector child, ref int unassigned) {
+      for (var k = 0; k < n; k++) {
+        if (child[k] < 0) {
+          var j = random.Next(m);
+          child[k] = j;
+          cap[j] += demands[k];
+          unassigned--;
+        }
+      }
+    }
+
+    protected override IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents,
+      GQAPInstance problemInstance) {
+      if (parents == null) throw new ArgumentNullException("parents");
+      if (parents.Length != 2) throw new ArgumentException(Name + " works only with exactly two parents.");
+
+      var qualities = QualityParameter.ActualValue;
+      return Apply(random,
+        parents[0], qualities[0],
+        parents[1], qualities[1],
+        problemInstance,
+        EvaluatedSolutionsParameter.ActualValue);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/DiscreteLocationCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/DiscreteLocationCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/DiscreteLocationCrossover.cs	(revision 17175)
@@ -0,0 +1,128 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("DiscreteLocationCrossover", "Combines the assignment to locations from various parents.")]
+  [StorableType("E001CEB3-DAA4-4AF4-843B-2DD951F0EAA6")]
+  public class DiscreteLocationCrossover : GQAPCrossover {
+
+    [StorableConstructor]
+    protected DiscreteLocationCrossover(StorableConstructorFlag _) : base(_) { }
+    protected DiscreteLocationCrossover(DiscreteLocationCrossover original, Cloner cloner)
+      : base(original, cloner) { }
+    public DiscreteLocationCrossover()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DiscreteLocationCrossover(this, cloner);
+    }
+
+    public static IntegerVector Apply(IRandom random, ItemArray<IntegerVector> parents, DoubleArray demands, DoubleArray capacities) {
+      var locations = capacities.Length;
+      var cap = Math.Max(parents[0].Length / locations, 1);
+      var lookup = new List<int>[parents.Length][];
+      for (var p = 0; p < parents.Length; p++) {
+        lookup[p] = new List<int>[locations];
+        var assign = parents[p];
+        for (var e = 0; e < parents[p].Length; e++) {
+          var loc = assign[e];
+          if (lookup[p][loc] == null) lookup[p][loc] = new List<int>(cap);
+          lookup[p][loc].Add(e);
+        }
+      }
+
+      var slack = capacities.ToArray();
+      IntegerVector child = new IntegerVector(parents[0].Length);
+      var takenEquip = new bool[child.Length];
+      foreach (var loc in Enumerable.Range(0, locations).Shuffle(random)) {
+        int parent = random.Next(parents.Length);
+        if (lookup[parent][loc] == null) {
+          int tmp = parent;
+          do {
+            tmp = (tmp + 1) % parents.Length;
+          } while (tmp != parent && lookup[tmp][loc] == null);
+          if (parent == tmp) continue;
+          else parent = tmp;
+        }
+        foreach (var equip in lookup[parent][loc]) {
+          if (!takenEquip[equip]) {
+            child[equip] = loc;
+            takenEquip[equip] = true;
+            slack[loc] -= demands[equip];
+          }
+        }
+      }
+
+      var order = Enumerable.Range(0, takenEquip.Length)
+        .Where(x => !takenEquip[x])
+        .Shuffle(random); // avoid bias
+      foreach (var e in order) {
+        var assigned = false;
+        // try 1: find a parent where equipment can be assigned feasibly
+        var fallback = -1;
+        var count = 1;
+        foreach (var p in parents.Shuffle(random)) {
+          if (slack[p[e]] >= demands[e]) {
+            child[e] = p[e];
+            slack[child[e]] -= demands[e];
+            assigned = true;
+            break;
+          } else if (random.NextDouble() < 1.0 / count) {
+            fallback = p[e];
+          }
+          count++;
+        }
+        // try 2: find a random feasible location
+        if (!assigned) {
+          var possible = Enumerable.Range(0, locations).Where(x => slack[x] >= demands[e]).ToList();
+          if (possible.Count > 0) {
+            var loc = possible.SampleRandom(random);
+            child[e] = loc;
+            slack[loc] -= demands[e];
+          } else {
+            // otherwise: fallback
+            child[e] = fallback;
+            slack[child[e]] -= demands[e];
+          }
+        }
+      }
+
+      return child;
+    }
+
+    protected override IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents,
+      GQAPInstance problemInstance) {
+      return Apply(random, parents, problemInstance.Demands, problemInstance.Capacities);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPCrossover.cs	(revision 17175)
@@ -0,0 +1,71 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+
+  [Item("GQAPCrossover", "A base class for operators that cross assignment vectors of the GeneralizedQuadraticAssignment problems.")]
+  [StorableType("DC860DB7-FC00-4374-ADC8-71BB4EDFC6E2")]
+  public abstract class GQAPCrossover : SingleSuccessorOperator, IGQAPCrossover, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public IScopeTreeLookupParameter<IntegerVector> ParentsParameter {
+      get { return (ScopeTreeLookupParameter<IntegerVector>)Parameters["Parents"]; }
+    }
+    public ILookupParameter<IntegerVector> ChildParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Child"]; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    [StorableConstructor]
+    protected GQAPCrossover(StorableConstructorFlag _) : base(_) { }
+    protected GQAPCrossover(GQAPCrossover original, Cloner cloner) : base(original, cloner) { }
+    protected GQAPCrossover()
+      : 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"));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic crossover operators."));
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+    }
+
+    public sealed override IOperation Apply() {
+      ChildParameter.ActualValue = Cross(RandomParameter.ActualValue, ParentsParameter.ActualValue, ProblemInstanceParameter.ActualValue);
+      return base.Apply();
+    }
+
+    protected abstract IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents, GQAPInstance problemInstance);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPPathRelinking.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPPathRelinking.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPPathRelinking.cs	(revision 17175)
@@ -0,0 +1,249 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  /// <summary>
+  /// This is an implementation of the algorithm described in Mateus, G.R., Resende, M.G.C. & Silva, R.M.A. J Heuristics (2011) 17: 527. https://doi.org/10.1007/s10732-010-9144-0
+  /// </summary>
+  [Item("GQAPPathRelinking", "Operator that performs path relinking between two solutions. It is described in Mateus, G., Resende, M., and Silva, R. 2011. GRASP with path-relinking for the generalized quadratic assignment problem. Journal of Heuristics 17, Springer Netherlands, pp. 527-565.")]
+  [StorableType("FAE65A24-AE6D-49DD-8A8C-6574D5304E08")]
+  public class GQAPPathRelinking : GQAPCrossover, IQualitiesAwareGQAPOperator {
+
+    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public IScopeTreeLookupParameter<Evaluation> EvaluationParameter {
+      get { return (IScopeTreeLookupParameter<Evaluation>)Parameters["Evaluation"]; }
+    }
+    public IValueParameter<PercentValue> CandidateSizeFactorParameter {
+      get { return (IValueParameter<PercentValue>)Parameters["CandidateSizeFactor"]; }
+    }
+    public IValueLookupParameter<BoolValue> GreedyParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Greedy"]; }
+    }
+
+    [StorableConstructor]
+    protected GQAPPathRelinking(StorableConstructorFlag _) : base(_) { }
+    protected GQAPPathRelinking(GQAPPathRelinking original, Cloner cloner) : base(original, cloner) { }
+    public GQAPPathRelinking()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", ""));
+      Parameters.Add(new ScopeTreeLookupParameter<Evaluation>("Evaluation", GQAP.EvaluationDescription));
+      Parameters.Add(new ValueParameter<PercentValue>("CandidateSizeFactor", "(η) Determines the size of the set of feasible moves in each path-relinking step relative to the maximum size. A value of 50% means that only half of all possible moves are considered each step.", new PercentValue(0.5)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Greedy", "Whether to use a greedy selection strategy or a probabilistic one.", new BoolValue(true)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPPathRelinking(this, cloner);
+    }
+
+    public static GQAPSolution Apply(IRandom random,
+      IntegerVector source, Evaluation sourceEval,
+      IntegerVector target, Evaluation targetEval,
+      GQAPInstance problemInstance, double candidateSizeFactor,
+      out int evaluatedSolutions, bool greedy = true) {
+      evaluatedSolutions = 0;
+      var demands = problemInstance.Demands;
+      var capacities = problemInstance.Capacities;
+      var cmp = new IntegerVectorEqualityComparer();
+      
+      var sFit = problemInstance.ToSingleObjective(sourceEval);
+      var tFit = problemInstance.ToSingleObjective(targetEval);
+      GQAPSolution pi_star = sFit < tFit
+        ? new GQAPSolution((IntegerVector)source.Clone(), (Evaluation)sourceEval.Clone())
+        : new GQAPSolution((IntegerVector)target.Clone(), (Evaluation)targetEval.Clone()); // line 1 of Algorithm 4
+      double pi_star_Fit = problemInstance.ToSingleObjective(pi_star.Evaluation); // line 2 of Algorithm 4
+      
+      var pi_prime = (IntegerVector)source.Clone(); // line 3 of Algorithm 4
+      //var fix = new bool[demands.Length]; // line 3 of Algorithm 4, note that according to the description it is not necessary to track the fixed equipments
+      var nonFix = Enumerable.Range(0, demands.Length).ToList(); // line 3 of Algorithm 4
+      var phi = new List<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target)); // line 4 of Algorithm 4
+
+      var B = new List<GQAPSolution>((int)Math.Ceiling(phi.Count * candidateSizeFactor));
+      var B_fit = new List<double>(B.Capacity);
+      while (phi.Count > 0) { // line 5 of Algorithm 4
+        B.Clear(); // line 6 of Algorithm 4
+        B_fit.Clear(); // line 6 of Algorithm 4 (B is split into two synchronized lists)
+        foreach (var v in phi) { // line 7 of Algorithm 4
+          int oldLocation = pi_prime[v];
+          pi_prime[v] = target[v]; // line 8 of Algorithm 4
+          var pi_dash = MakeFeasible(random, pi_prime, v, nonFix, demands, capacities); // line 9 of Algorithm 4
+          pi_prime[v] = oldLocation; // not mentioned in Algorithm 4, but seems reasonable
+
+          if (problemInstance.IsFeasible(pi_dash)) { // line 10 of Algorithm 4
+            var pi_dash_eval = problemInstance.Evaluate(pi_dash);
+            evaluatedSolutions++;
+            var pi_dash_fit = problemInstance.ToSingleObjective(pi_dash_eval);
+
+            if (B.Any(x => cmp.Equals(x.Assignment, pi_dash))) continue; // cond. 2 of line 12 and cond. 1 of line 16 in Algorithm 4
+
+            if (B.Count >= candidateSizeFactor * phi.Count) { // line 11 of Algorithm 4
+              var replacement = B_fit.Select((val, idx) => new { Index = idx, Fitness = val })
+                                            .Where(x => x.Fitness >= pi_dash_fit) // cond. 1 in line 12 of Algorithm 4
+                                            .Select(x => new { x.Index, x.Fitness, Similarity = HammingSimilarityCalculator.CalculateSimilarity(B[x.Index].Assignment, pi_dash) })
+                                            .ToArray();
+              if (replacement.Length > 0) {
+                var mostSimilar = replacement.MaxItems(x => x.Similarity).SampleRandom(random).Index;
+                B[mostSimilar].Assignment = pi_dash; // line 13 of Algorithm 4
+                B[mostSimilar].Evaluation = pi_dash_eval; // line 13 of Algorithm 4
+                B_fit[mostSimilar] = pi_dash_fit; // line 13 of Algorithm 4
+              }
+            } else { // line 16, condition has been checked above already
+              B.Add(new GQAPSolution(pi_dash, pi_dash_eval)); // line 17 of Algorithm 4
+              B_fit.Add(pi_dash_fit); // line 17 of Algorithm 4
+            }
+          }
+        }
+        if (B.Count > 0) { // line 21 of Algorithm 4
+          GQAPSolution pi;
+          // line 22 of Algorithm 4
+          if (greedy) {
+            pi = B.Select((val, idx) => new { Index = idx, Value = val }).MinItems(x => B_fit[x.Index]).SampleRandom(random).Value;
+          } else {
+            pi = B.SampleProportional(random, 1, B_fit.Select(x => 1.0 / x), false).First();
+          }
+          var diff = IntegerVectorEqualityComparer.GetDifferingIndices(pi.Assignment, target); // line 23 of Algorithm 4
+          var I = phi.Except(diff); // line 24 of Algorithm 4
+          var i = I.SampleRandom(random); // line 25 of Algorithm 4
+          //fix[i] = true; // line 26 of Algorithm 4
+          nonFix.Remove(i); // line 26 of Algorithm 4
+          pi_prime = pi.Assignment; // line 27 of Algorithm 4
+          var fit = problemInstance.ToSingleObjective(pi.Evaluation);
+          if (fit < pi_star_Fit) { // line 28 of Algorithm 4
+            pi_star_Fit = fit; // line 29 of Algorithm 4
+            pi_star = pi; // line 30 of Algorithm 4
+          }
+        } else return pi_star;
+        phi = new List<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target));
+      }
+
+      return pi_star;
+    }
+
+    protected override IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents,
+      GQAPInstance problemInstance) {
+
+      var qualities = QualityParameter.ActualValue;
+      var evaluations = EvaluationParameter.ActualValue;
+      var betterParent = qualities[0].Value <= qualities[1].Value ? 0 : 1;
+      var worseParent = 1 - betterParent;
+      var source = parents[betterParent];
+      var target = parents[worseParent];
+
+      int evaluatedSolution;
+      return Apply(random, source, evaluations[betterParent],
+        target, evaluations[worseParent], problemInstance,
+        CandidateSizeFactorParameter.Value.Value, out evaluatedSolution,
+        GreedyParameter.ActualValue.Value).Assignment;
+    }
+
+    /// <summary>
+    /// Relocates equipments in the same location as <paramref name="equipment"/> to other locations in case the location
+    /// is overutilized.
+    /// </summary>
+    /// <remarks>
+    /// This method is performance critical, called very often and should run as fast as possible.
+    /// </remarks>
+    /// <param name="random">The random number generator.</param>
+    /// <param name="pi">The current solution.</param>
+    /// <param name="equipment">The equipment that was just assigned to a new location.</param>
+    /// <param name="nonFix">The equipments that have not yet been fixed.</param>
+    /// <param name="demands">The demands for all equipments.</param>
+    /// <param name="capacities">The capacities of all locations.</param>
+    /// <param name="maximumTries">The number of tries that should be done in relocating the equipments.</param>
+    /// <returns>A feasible or infeasible solution</returns>
+    private static IntegerVector MakeFeasible(IRandom random, IntegerVector pi, int equipment, List<int> nonFix, DoubleArray demands, DoubleArray capacities, int maximumTries = 1000) {
+      int l = pi[equipment];
+      var slack = ComputeSlack(pi, demands, capacities);
+      if (slack[l] >= 0) // line 1 of Algorithm 5
+        return (IntegerVector)pi.Clone(); // line 2 of Algorithm 5
+
+      IntegerVector pi_prime = null;
+      int k = 0; // line 4 of Algorithm 5
+      var maxSlack = slack.Max(); // line 8-9 of Algorithm 5
+      var slack_prime = (double[])slack.Clone();
+      var maxSlack_prime = maxSlack;
+      // note that FTL can be computed only once for all tries as all tries restart with the same solution
+      var FTL = nonFix.Where(x => x != equipment && pi[x] == l && demands[x] <= maxSlack).ToList(); // line 8-9 of Algorithm 5
+      var FTLweight = FTL.Select(x => demands[x]).ToList();
+      while (k < maximumTries && slack_prime[l] < 0) {  // line 5 of Algorithm 5
+        pi_prime = (IntegerVector)pi.Clone(); // line 6 of Algorithm 5
+        // set T can only shrink and not grow, thus it is created outside the loop and only updated inside
+        var T = new List<int>(FTL); // line 8-9 of Algorithm 5
+        var weightT = new List<double>(FTLweight);
+        do {  // line 7 of Algorithm 5
+          if (T.Count > 0) { // line 10 of Algorithm 5
+            var idx = Enumerable.Range(0, T.Count).SampleProportional(random, 1, weightT, false, false).First(); // line 11 of Algorithm 5
+            int i = T[idx]; // line 11 of Algorithm 5
+            var j = Enumerable.Range(0, capacities.Length)
+              .Where(x => slack_prime[x] >= demands[i]) // line 12 of Algorithm 5
+              .SampleRandom(random);  // line 13 of Algorithm 5
+            pi_prime[i] = j; // line 14 of Algorithm 5
+            T.RemoveAt(idx);
+            weightT.RemoveAt(idx);
+            var recomputeMaxSlack = slack_prime[j] == maxSlack_prime; // efficiency improvement: recompute max slack only if we assign to a location whose slack equals maxSlack
+            slack_prime[j] -= demands[i]; // line 14 of Algorithm 5
+            slack_prime[l] += demands[i]; // line 14 of Algorithm 5
+            if (recomputeMaxSlack) {
+              maxSlack_prime = slack_prime.Max();
+              // T needs to be removed of equipments whose demand is higher than maxSlack only if maxSlack changes
+              for (var h = 0; h < T.Count; h++) {
+                var f = T[h];
+                if (demands[f] > maxSlack_prime) {
+                  T.RemoveAt(h);
+                  weightT.RemoveAt(h);
+                  h--;
+                }
+              }
+            }
+          } else break; // cond. 1 in line 16 of Algorithm 5
+        } while (slack_prime[l] < 0); // cond. 2 in line 16 of Algorithm 5
+        k++; // line 17 of Algorithm 5
+        if (slack_prime[l] < 0) {
+          // reset
+          Array.Copy(slack, slack_prime, slack.Length);
+          maxSlack_prime = maxSlack;
+        }
+      }
+      return pi_prime; // line 19-23 of Algorithm 5
+    }
+
+    private static double[] ComputeSlack(IntegerVector assignment, DoubleArray demands, DoubleArray capacities) {
+      var slack = capacities.ToArray();
+      for (int i = 0; i < assignment.Length; i++) {
+        slack[assignment[i]] -= demands[i];
+      }
+      return slack;
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/MultiGQAPCrossover.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/MultiGQAPCrossover.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/MultiGQAPCrossover.cs	(revision 17175)
@@ -0,0 +1,106 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("MultiGQAPCrossover", "Randomly selects and applies one of its crossovers every time it is called.")]
+  [StorableType("C8AA967E-11CF-48A0-BEC2-71A9ABEB1801")]
+  public class MultiGQAPCrossover : StochasticMultiBranch<IGQAPCrossover>, IGQAPCrossover, IProblemInstanceAwareGQAPOperator, IStochasticOperator {
+    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"]; }
+    }
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiGQAPCrossover(StorableConstructorFlag _) : base(_) { }
+    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"));
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+
+      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.ParentsParameter.Hidden = true;
+        op.ChildParameter.ActualName = ChildParameter.Name;
+        op.ChildParameter.Hidden = true;
+      }
+      foreach (var op in Operators.OfType<IStochasticOperator>()) {
+        op.RandomParameter.ActualName = RandomParameter.Name;
+        op.RandomParameter.Hidden = true;
+      }
+      foreach (var op in Operators.OfType<IProblemInstanceAwareGQAPOperator>()) {
+        op.ProblemInstanceParameter.ActualName = ProblemInstanceParameter.Name;
+        op.ProblemInstanceParameter.Hidden = true;
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one crossover to choose from.");
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPQualitySimilarityReducer.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPQualitySimilarityReducer.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPQualitySimilarityReducer.cs	(revision 17175)
@@ -0,0 +1,124 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Collections.Generic;
+using System.Linq;
+using HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Operators {
+  [Item("GQAPQualitySimilarityReducer", "Reduces two populations two one by using quality and similarity information to obtain a population of high quality, but also diverse solutions.")]
+  [StorableType("3E9B9095-C0FE-4B16-B2FD-9EC349A37CD2")]
+  public class GQAPQualitySimilarityReducer : SingleSuccessorOperator, IQualityAwareGQAPOperator, IAssignmentAwareGQAPOperator, IReducer {
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<Evaluation> EvaluationParameter {
+      get { return (ILookupParameter<Evaluation>)Parameters["Evaluation"]; }
+    }
+    public ILookupParameter<IntValue> MinimumPopulationSizeParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["MinimumPopulationSize"]; }
+    }
+    public ILookupParameter<IntValue> MaximumPopulationSizeParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["MaximumPopulationSize"]; }
+    }
+
+    [StorableConstructor]
+    protected GQAPQualitySimilarityReducer(StorableConstructorFlag _) : base(_) { }
+    protected GQAPQualitySimilarityReducer(GQAPQualitySimilarityReducer original, Cloner cloner) : base(original, cloner) { }
+    public GQAPQualitySimilarityReducer()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", ""));
+      Parameters.Add(new LookupParameter<Evaluation>("Evaluation", GQAP.EvaluationDescription));
+      Parameters.Add(new LookupParameter<IntValue>("MinimumPopulationSize", "The size of the population that should not be undershot."));
+      Parameters.Add(new LookupParameter<IntValue>("MaximumPopulationSize", "The size of the population that should not be surpassed."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GQAPQualitySimilarityReducer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      string vectorName = AssignmentParameter.TranslatedName;
+      string qualityName = QualityParameter.TranslatedName;
+      int populationSize = MaximumPopulationSizeParameter.ActualValue.Value;
+
+      IScope remaining = ExecutionContext.Scope.SubScopes[0];
+      IScope selected = ExecutionContext.Scope.SubScopes[1];
+
+      List<Individual> population =
+        remaining.SubScopes.Select(x => new Individual((IntegerVector)x.Variables[vectorName].Value,
+                                                      ((DoubleValue)x.Variables[qualityName].Value).Value,
+                                                      x)).ToList();
+      HashSet<Individual> candidates = new HashSet<Individual>(
+        selected.SubScopes.Select(x => new Individual((IntegerVector)x.Variables[vectorName].Value,
+                                                     ((DoubleValue)x.Variables[qualityName].Value).Value,
+                                                     x)));
+
+      foreach (var candidate in candidates) {
+        double[] similarities = population.Select(x => HammingSimilarityCalculator.CalculateSimilarity(x.Solution, candidate.Solution)).ToArray();
+        if (!similarities.Any()) {
+          population.Add(candidate);
+          break;
+        }
+        if (similarities.Max() == 1.0) break;
+        if (population.Count < populationSize) {
+          population.Add(candidate);
+        } else {
+          var replacement = population.Select((v, i) => new { V = v, Index = i })
+                                      .Where(x => x.V.Quality > candidate.Quality);
+          if (replacement.Any()) {
+            replacement.OrderBy(x => similarities[x.Index]).ToArray();
+            population.Remove(replacement.Last().V);
+            population.Add(candidate);
+          }
+        }
+      }
+
+      ExecutionContext.Scope.SubScopes.Clear();
+      ExecutionContext.Scope.SubScopes.AddRange(population.Select(x => x.Scope));
+
+      return base.Apply();
+    }
+
+    private class Individual {
+      internal IntegerVector Solution { get; set; }
+      internal double Quality { get; set; }
+      internal IScope Scope { get; set; }
+
+      internal Individual(IntegerVector vector, double quality, IScope scope) {
+        Solution = vector;
+        Quality = quality;
+        Scope = scope;
+      }
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/ApproximateLocalSearch.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/ApproximateLocalSearch.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/ApproximateLocalSearch.cs	(revision 17175)
@@ -0,0 +1,199 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+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;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  /// <summary>
+  /// This is an implementation of the algorithm described in Mateus, G.R., Resende, M.G.C. & Silva, R.M.A. J Heuristics (2011) 17: 527. https://doi.org/10.1007/s10732-010-9144-0
+  /// </summary>
+  [Item("ApproximateLocalSearch", "The approximate local search is described in Mateus, G., Resende, M., and Silva, R. 2011. GRASP with path-relinking for the generalized quadratic assignment problem. Journal of Heuristics 17, Springer Netherlands, pp. 527-565.")]
+  [StorableType("58C75FBC-C586-4048-A60B-DCF967CB2E33")]
+  public class ApproximateLocalSearch : SingleSuccessorOperator, IProblemInstanceAwareGQAPOperator,
+    IQualityAwareGQAPOperator, IGQAPLocalImprovementOperator, IAssignmentAwareGQAPOperator, IStochasticOperator {
+    public IProblem Problem { get; set; }
+    public Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<Evaluation> EvaluationParameter {
+      get { return (ILookupParameter<Evaluation>)Parameters["Evaluation"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumCandidateListSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumCandidateListSize"]; }
+    }
+    public IValueLookupParameter<PercentValue> OneMoveProbabilityParameter {
+      get { return (IValueLookupParameter<PercentValue>)Parameters["OneMoveProbability"]; }
+    }
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    public IValueLookupParameter<BoolValue> GreedyParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Greedy"]; }
+    }
+
+    [StorableConstructor]
+    protected ApproximateLocalSearch(StorableConstructorFlag _) : base(_) { }
+    protected ApproximateLocalSearch(ApproximateLocalSearch original, Cloner cloner) : base(original, cloner) { }
+    public ApproximateLocalSearch()
+      : base() {
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", ""));
+      Parameters.Add(new LookupParameter<Evaluation>("Evaluation", GQAP.EvaluationDescription));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum number of iterations that should be performed."));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The number of evaluated solution equivalents."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumCandidateListSize", "The maximum number of candidates that should be found in each step.", new IntValue(10)));
+      Parameters.Add(new ValueLookupParameter<PercentValue>("OneMoveProbability", "The probability for performing a 1-move, which is the opposite of performing a 2-move.", new PercentValue(.5)));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The result collection that stores the results."));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Greedy", "Whether to use a greedy selection strategy or a probabilistic one.", new BoolValue(true)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ApproximateLocalSearch(this, cloner);
+    }
+
+    public static void Apply(IRandom random, GQAPSolution sol, int maxCLS,
+      double oneMoveProbability, int maximumIterations,
+      GQAPInstance problemInstance, out int evaluatedSolutions, bool greedy = true) {
+      var fit = problemInstance.ToSingleObjective(sol.Evaluation);
+      var eval = sol.Evaluation;
+      Apply(random, sol.Assignment, ref fit, ref eval, maxCLS, oneMoveProbability, maximumIterations, problemInstance,
+        out evaluatedSolutions, greedy);
+      sol.Evaluation = eval;
+    }
+
+    /// <summary>
+    /// </summary>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="assignment">The equipment-location assignment vector.</param>
+    /// <param name="quality">The solution quality.</param>
+    /// <param name="evaluation">The evaluation result of the solution.</param>
+    /// <param name="maxCLS">The maximum number of candidates that should be found in each step.</param>
+    /// <param name="oneMoveProbability">The probability for performing a 1-move, which is the opposite of performing a 2-move.</param>
+    /// <param name="maximumIterations">The maximum number of iterations that should be performed each time the candidate list is generated.</param>
+    /// <param name="problemInstance">The problem instance that contains the data.</param>
+    /// <param name="evaluatedSolutions">The number of evaluated solutions.</param>
+    /// <param name="greedy">Greedy selection performed better in 5 of 8 instances according to the paper</param>
+    public static void Apply(IRandom random, IntegerVector assignment,
+      ref double quality, ref Evaluation evaluation, int maxCLS,
+      double oneMoveProbability, int maximumIterations,
+      GQAPInstance problemInstance, out int evaluatedSolutions, bool greedy = true) {
+      evaluatedSolutions = 0;
+      var capacities = problemInstance.Capacities;
+      var demands = problemInstance.Demands;
+      var evaluations = 0.0;
+      var deltaEvaluationFactor = 1.0 / assignment.Length;
+      while (true) { // line 1 of Algorithm 3
+        var count = 0; // line 2 of Algorithm 3
+        var CLS = new List<Tuple<NMove, double, Evaluation>>(); // line 3 of Algorithm 3
+        do {
+          var move = Move(random, assignment, oneMoveProbability, capacities); // line 4 of Algorithm 3
+
+          var moveEval = GQAPNMoveEvaluator.Evaluate(move, assignment, evaluation, problemInstance);
+          evaluations += move.Indices.Count * deltaEvaluationFactor;
+          double moveQuality = problemInstance.ToSingleObjective(moveEval);
+
+          if (moveEval.ExcessDemand <= 0.0 && moveQuality < quality) { // line 5 of Algorithm 3
+            CLS.Add(Tuple.Create(move, moveQuality, moveEval)); // line 6 of Algorithm 3
+          }
+          count++; // line 8 of Algorithm 3
+        } while (CLS.Count < maxCLS && count < maximumIterations); // line 9 of Algorithm 3
+
+        if (CLS.Count == 0) { // line 10 of Algorithm 3
+          evaluatedSolutions += (int)Math.Ceiling(evaluations);
+          return; // END
+        } else {
+          // line 11 of Algorithm 3
+          Tuple<NMove, double, Evaluation> selected;
+          if (greedy) {
+            selected = CLS.MinItems(x => x.Item2).Shuffle(random).First();
+          } else {
+            selected = CLS.SampleProportional(random, 1, CLS.Select(x => 1.0 / x.Item2), false, false).Single();
+          }
+          NMoveMaker.Apply(assignment, selected.Item1);
+          quality = selected.Item2;
+          evaluation = selected.Item3;
+        }
+      }
+    }
+
+    private static NMove Move(IRandom random, IntegerVector assignment, double oneMoveProbability, DoubleArray capacities) {
+      if (random.NextDouble() < oneMoveProbability)
+        return StochasticNMoveSingleMoveGenerator.GenerateOneMove(random, assignment, capacities);
+      return StochasticNMoveSingleMoveGenerator.GenerateTwoMove(random, assignment, capacities);
+    }
+
+    public override IOperation Apply() {
+      var evaluation = EvaluationParameter.ActualValue;
+      var quality = QualityParameter.ActualValue;
+      var fit = quality.Value;
+      var evaluatedSolutions = 0;
+
+      Apply(RandomParameter.ActualValue,
+        AssignmentParameter.ActualValue,
+        ref fit,
+        ref evaluation,
+        MaximumCandidateListSizeParameter.ActualValue.Value,
+        OneMoveProbabilityParameter.ActualValue.Value,
+        MaximumIterationsParameter.ActualValue.Value,
+        ProblemInstanceParameter.ActualValue,
+        out evaluatedSolutions,
+        GreedyParameter.ActualValue.Value);
+
+      EvaluationParameter.ActualValue = evaluation;
+      quality.Value = fit;
+      EvaluatedSolutionsParameter.ActualValue.Value += evaluatedSolutions;
+      return base.Apply();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/OneOptLocalSearch.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/OneOptLocalSearch.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/OneOptLocalSearch.cs	(revision 17175)
@@ -0,0 +1,174 @@
+﻿
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.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;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("1-opt LocalSearch", "A simple exhaustive 1-change local search.")]
+  [StorableType("C574770B-AB1E-46BE-8B3F-C8C5B2AD3ACF")]
+  public class OneOptLocalSearch : SingleSuccessorOperator, IProblemInstanceAwareGQAPOperator,
+    IQualityAwareGQAPOperator, IGQAPLocalImprovementOperator, IAssignmentAwareGQAPOperator, IStochasticOperator {
+    public IProblem Problem { get; set; }
+    public Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<Evaluation> EvaluationParameter {
+      get { return (ILookupParameter<Evaluation>)Parameters["Evaluation"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    [StorableConstructor]
+    protected OneOptLocalSearch(StorableConstructorFlag _) : base(_) { }
+    protected OneOptLocalSearch(OneOptLocalSearch original, Cloner cloner) : base(original, cloner) { }
+    public OneOptLocalSearch()
+      : base() {
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", ""));
+      Parameters.Add(new LookupParameter<Evaluation>("Evaluation", GQAP.EvaluationDescription));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "This parameter is ignored by the operator.") { Hidden = true });
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The number of evaluated solution equivalents."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The result collection that stores the results."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OneOptLocalSearch(this, cloner);
+    }
+
+    public static void Apply(IRandom random, GQAPSolution sol,
+      GQAPInstance problemInstance, out int evaluatedSolutions) {
+      var fit = problemInstance.ToSingleObjective(sol.Evaluation);
+      var eval = sol.Evaluation;
+      Apply(random, sol.Assignment, ref fit, ref eval, problemInstance, out evaluatedSolutions);
+      sol.Evaluation = eval;
+    }
+
+    /// <summary>
+    /// </summary>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="assignment">The equipment-location assignment vector.</param>
+    /// <param name="quality">The solution quality.</param>
+    /// <param name="evaluation">The evaluation result of the solution.</param>
+    /// <param name="maxCLS">The maximum number of candidates that should be found in each step.</param>
+    /// <param name="oneMoveProbability">The probability for performing a 1-move, which is the opposite of performing a 2-move.</param>
+    /// <param name="maximumIterations">The maximum number of iterations that should be performed each time the candidate list is generated.</param>
+    /// <param name="problemInstance">The problem instance that contains the data.</param>
+    /// <param name="evaluatedSolutions">The number of evaluated solutions.</param>
+    /// <param name="greedy">Greedy selection performed better in 5 of 8 instances according to the paper</param>
+    public static void Apply(IRandom random, IntegerVector assignment,
+      ref double quality, ref Evaluation evaluation,
+      GQAPInstance problemInstance, out int evaluatedSolutions) {
+      evaluatedSolutions = 0;
+      var capacities = problemInstance.Capacities;
+      var demands = problemInstance.Demands;
+      var evaluations = 0.0;
+      var deltaEvaluationFactor = 1.0 / assignment.Length;
+      var change = true;
+      var moves = ExhaustiveOneMoveGenerator.GenerateAllNxM(problemInstance).ToList();
+      var slack = evaluation.Slack.ToList();
+      while (change) {
+        change = false;
+        var feasible = evaluation.IsFeasible;
+        foreach (var move in moves
+            .Where(x => {
+              var equip = x.Indices[0];
+              var assignTo = x.Reassignments[equip] - 1;
+              if (assignTo == assignment[equip]) return false;
+              var dem = problemInstance.Demands[equip];
+              if (feasible) return slack[assignTo] >= dem;
+              return slack[assignTo] - dem > slack[assignment[equip]];
+            })
+            .Shuffle(random)) {
+          var moveEval = GQAPNMoveEvaluator.Evaluate(move, assignment, evaluation, problemInstance);
+          evaluations += deltaEvaluationFactor;
+          var moveQuality = problemInstance.ToSingleObjective(moveEval);
+          if (moveQuality < quality) {
+            NMoveMaker.Apply(assignment, move);
+            quality = moveQuality;
+            evaluation = moveEval;
+            change = true;
+            break;
+          }
+        }
+      }
+      evaluatedSolutions += (int)Math.Ceiling(evaluations);
+    }
+
+    private static NMove Move(IRandom random, IntegerVector assignment, double oneMoveProbability, DoubleArray capacities) {
+      if (random.NextDouble() < oneMoveProbability)
+        return StochasticNMoveSingleMoveGenerator.GenerateOneMove(random, assignment, capacities);
+      return StochasticNMoveSingleMoveGenerator.GenerateTwoMove(random, assignment, capacities);
+    }
+
+    public override IOperation Apply() {
+      var evaluation = EvaluationParameter.ActualValue;
+      var quality = QualityParameter.ActualValue;
+      var fit = quality.Value;
+      var evaluatedSolutions = 0;
+
+      Apply(RandomParameter.ActualValue,
+        AssignmentParameter.ActualValue,
+        ref fit,
+        ref evaluation,
+        ProblemInstanceParameter.ActualValue,
+        out evaluatedSolutions);
+
+      EvaluationParameter.ActualValue = evaluation;
+      quality.Value = fit;
+      EvaluatedSolutionsParameter.ActualValue.Value += evaluatedSolutions;
+      return base.Apply();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/DemandEquivalentSwapEquipmentManipluator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/DemandEquivalentSwapEquipmentManipluator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/DemandEquivalentSwapEquipmentManipluator.cs	(revision 17175)
@@ -0,0 +1,82 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+
+  [Item("DemandEquivalentSwapEquipmentManipluator", "Swaps equipment X from location A with as much equipments from location B that the demand of X is less than or equal to the demand of the swapped equipments in B.")]
+  [StorableType("1FC9A377-D187-414D-9901-D9B26C0BF98E")]
+  public class DemandEquivalentSwapEquipmentManipluator : GQAPManipulator {
+
+    [StorableConstructor]
+    protected DemandEquivalentSwapEquipmentManipluator(StorableConstructorFlag _) : base(_) { }
+    protected DemandEquivalentSwapEquipmentManipluator(DemandEquivalentSwapEquipmentManipluator original, Cloner cloner) : base(original, cloner) { }
+    public DemandEquivalentSwapEquipmentManipluator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DemandEquivalentSwapEquipmentManipluator(this, cloner);
+    }
+
+    public static void Apply(IRandom random, IntegerVector assignment, DoubleArray capacities, DoubleArray demands) {
+      if (assignment.Length < 2) throw new InvalidOperationException("Vector is too small for swap operation.");
+      int equipment1 = random.Next(assignment.Length), equipment2 = random.Next(assignment.Length);
+      int counter = 1;
+      while (assignment[equipment1] == assignment[equipment2] && counter < assignment.Length) {
+        equipment2 = random.Next(assignment.Length);
+        counter++;
+      }
+      if (assignment[equipment1] != assignment[equipment2]) {
+        var groupedLocations = assignment
+              .Select((value, index) => new { Index = index, Value = value })
+              .GroupBy(x => x.Value)
+              .ToDictionary(x => x.Key, y => new HashSet<int>(y.Select(x => x.Index)));
+        double demand = demands[equipment1];
+        int location1 = assignment[equipment1];
+        int location2 = assignment[equipment2];
+
+        assignment[equipment1] = location2;
+        while (demand > 0) {
+          demand -= demands[equipment2];
+          assignment[equipment2] = location1;
+          groupedLocations[location2].Remove(equipment2);
+          if (!groupedLocations[location2].Any()) break;
+          equipment2 = groupedLocations[location2].SampleRandom(random);
+        }
+      }
+    }
+
+    protected override void Manipulate(IRandom random, IntegerVector vector, GQAPInstance problemInstance) {
+      Apply(random, vector, problemInstance.Capacities, problemInstance.Demands);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/GQAPManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/GQAPManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/GQAPManipulator.cs	(revision 17175)
@@ -0,0 +1,67 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAPManipulator", "A base class for operators that manipulate assignment vectors of the GeneralizedQuadraticAssignment problems.")]
+  [StorableType("4AC3D0BB-2BAA-4910-A806-7673BE3E7FEC")]
+  public abstract class GQAPManipulator : SingleSuccessorOperator, IGQAPManipulator, IProblemInstanceAwareGQAPOperator, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected GQAPManipulator(StorableConstructorFlag _) : base(_) { }
+    protected GQAPManipulator(GQAPManipulator original, Cloner cloner) : base(original, cloner) { }
+    protected GQAPManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
+    }
+
+    public sealed override IOperation Apply() {
+      Manipulate(RandomParameter.ActualValue, AssignmentParameter.ActualValue, ProblemInstanceParameter.ActualValue);
+      return base.Apply();
+    }
+
+    protected abstract void Manipulate(IRandom random, IntegerVector integerVector, GQAPInstance problemInstance);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/MultiGQAPManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/MultiGQAPManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/MultiGQAPManipulator.cs	(revision 17175)
@@ -0,0 +1,101 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("MultiGQAPManipulator", "Randomly selects and applies one of its manipulators every time it is called.")]
+  [StorableType("CA2893AC-EECE-4F3A-A12E-81DC838ADC3C")]
+  public class MultiGQAPManipulator : StochasticMultiBranch<IGQAPManipulator>, IGQAPManipulator,
+    IProblemInstanceAwareGQAPOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    public ILookupParameter<IntegerVector> AssignmentParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
+    }
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiGQAPManipulator(StorableConstructorFlag _) : base(_) { }
+    protected MultiGQAPManipulator(MultiGQAPManipulator original, Cloner cloner) : base(original, cloner) { }
+    public MultiGQAPManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+
+      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;
+        op.AssignmentParameter.Hidden = true;
+      }
+      foreach (var op in Operators.OfType<IStochasticOperator>()) {
+        op.RandomParameter.ActualName = RandomParameter.Name;
+        op.RandomParameter.Hidden = true;
+      }
+      foreach (var op in Operators.OfType<IProblemInstanceAwareGQAPOperator>()) {
+        op.ProblemInstanceParameter.ActualName = ProblemInstanceParameter.Name;
+        op.ProblemInstanceParameter.Hidden = true;
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one manipulator to choose from.");
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/RelocateEquipmentManipluator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/RelocateEquipmentManipluator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/RelocateEquipmentManipluator.cs	(revision 17175)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+
+  [Item("RelocateEquipmentManipluator", "Relocates a random equipment from an overstuffed location to a random one with space or a random equipment if constraints are satisfied.")]
+  [StorableType("B696CF26-6654-4CFC-8527-752C9F16F7DD")]
+  public class RelocateEquipmentManipluator : GQAPManipulator {
+    
+    [StorableConstructor]
+    protected RelocateEquipmentManipluator(StorableConstructorFlag _) : base(_) { }
+    protected RelocateEquipmentManipluator(RelocateEquipmentManipluator original, Cloner cloner) : base(original, cloner) { }
+    public RelocateEquipmentManipluator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RelocateEquipmentManipluator(this, cloner);
+    }
+
+    public static void Apply(IRandom random, IntegerVector assignment, int locations, double stopProb) {
+      if (locations < 2) throw new InvalidOperationException("There are not enough locations for relocation operations.");
+
+      var equipments = Enumerable.Range(0, assignment.Length).Shuffle(random);
+      foreach (var equipment in equipments) {
+        var oldLoc = assignment[equipment];
+        assignment[equipment] = (oldLoc + random.Next(1, locations)) % locations;
+        if (random.NextDouble() < stopProb) break;
+      }
+    }
+
+    protected override void Manipulate(IRandom random, IntegerVector vector, GQAPInstance problemInstance) {
+      Apply(random, vector, problemInstance.Capacities.Length, 4.0 / problemInstance.Demands.Length);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/SwapEquipmentManipluator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/SwapEquipmentManipluator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/SwapEquipmentManipluator.cs	(revision 17175)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+
+  [Item("SwapEquipmentManipluator", "Swaps two equipments by placing each in the location of the other.")]
+  [StorableType("FC7FD665-84A3-4BEA-A139-8248120375E0")]
+  public class SwapEquipmentManipluator : GQAPManipulator {
+
+    [StorableConstructor]
+    protected SwapEquipmentManipluator(StorableConstructorFlag _) : base(_) { }
+    protected SwapEquipmentManipluator(SwapEquipmentManipluator original, Cloner cloner) : base(original, cloner) { }
+    public SwapEquipmentManipluator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SwapEquipmentManipluator(this, cloner);
+    }
+
+    public static void Apply(IRandom random, IntegerVector assignment) {
+      if (assignment.Length < 2) throw new InvalidOperationException("Vector is too small for swap operation.");
+      int equipment1 = random.Next(assignment.Length), equipment2 = random.Next(assignment.Length);
+      int counter = 1;
+      while (assignment[equipment1] == assignment[equipment2] && counter < assignment.Length) {
+        equipment2 = random.Next(assignment.Length);
+        counter++;
+      }
+      int location = assignment[equipment1];
+      assignment[equipment1] = assignment[equipment2];
+      assignment[equipment2] = location;
+    }
+
+    protected override void Manipulate(IRandom random, IntegerVector vector, GQAPInstance problemInstance) {
+      Apply(random, vector);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/SwapLocationManipulator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/SwapLocationManipulator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Manipulators/SwapLocationManipulator.cs	(revision 17175)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+
+  [Item("SwapLocationManipluator", "Swaps two locations by exchanging all equipments between the locations.")]
+  [StorableType("F0828F68-42FD-4B3E-9E55-5A7145A442AB")]
+  public class SwapLocationManipluator : GQAPManipulator {
+    
+    [StorableConstructor]
+    protected SwapLocationManipluator(StorableConstructorFlag _) : base(_) { }
+    protected SwapLocationManipluator(SwapLocationManipluator original, Cloner cloner) : base(original, cloner) { }
+    public SwapLocationManipluator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SwapLocationManipluator(this, cloner);
+    }
+
+    public static void Apply(IRandom random, IntegerVector assignment, int locations) {
+      if (assignment.Length < 2) throw new InvalidOperationException("Vector is too small for swap operation.");
+      var groupedLocations = assignment
+        .Select((value, index) => new { Index = index, Value = value })
+        .GroupBy(x => x.Value)
+        .ToDictionary(x => x.Key, y => y.AsEnumerable());
+      if (locations < 2) throw new InvalidOperationException("There doesn't exist more than one location.");
+
+      int location1 = random.Next(locations), location2 = random.Next(locations);
+      while (location1 == location2) location2 = random.Next(locations);
+
+      if (groupedLocations.ContainsKey(location1)) {
+        foreach (var index in groupedLocations[location1])
+          assignment[index.Index] = location2;
+      }
+      if (groupedLocations.ContainsKey(location2)) {
+        foreach (var index in groupedLocations[location2])
+          assignment[index.Index] = location1;
+      }
+    }
+
+    protected override void Manipulate(IRandom random, IntegerVector vector, GQAPInstance problemInstance) {
+      Apply(random, vector, problemInstance.Capacities.Length);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Shakers/NMoveShakingOperator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Shakers/NMoveShakingOperator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Shakers/NMoveShakingOperator.cs	(revision 17175)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Operators {
+  [Item("NMoveShakingOperator", "Performs a number of shaking operations that increase in strength.")]
+  [StorableType("22D9F959-9BAB-497D-B593-FF19BD8CE9AB")]
+  public class NMoveShakingOperator : SingleSuccessorOperator, IProblemInstanceAwareGQAPOperator,
+    IAssignmentAwareGQAPOperator, IMultiNeighborhoodShakingOperator, IStochasticOperator {
+
+
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+    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<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected NMoveShakingOperator(StorableConstructorFlag _) : base(_) { }
+    protected NMoveShakingOperator(NMoveShakingOperator original, Cloner cloner) : base(original, cloner) { }
+    public NMoveShakingOperator() {
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
+      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<IRandom>("Random", "The random number generator to use."));
+    }
+
+    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 = ProblemInstanceParameter.ActualValue.Capacities;
+
+      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();
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Plugin.cs.frame
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Plugin.cs.frame	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Plugin.cs.frame	(revision 17175)
@@ -0,0 +1,44 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Plugin("HeuristicLab.Problems.GeneralizedQuadraticAssignment", "3.3.15.$WCREV$")]
+  [PluginFile("HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Attic", "1.0")]
+  [PluginDependency("HeuristicLab.Analysis", "3.3")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.IntegerVectorEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Instances", "3.3")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+  public class HeuristicLabProblemsGeneralizedQuadraticAssignmentPlugin : PluginBase {
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Properties/AssemblyInfo.cs.frame	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Properties/AssemblyInfo.cs.frame	(revision 17175)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Problems.GeneralizedQuadraticAssignment")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7c14407e-6980-465b-ba3a-4a916d48989b")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.15.$WCREV$")]
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GQAPSolutionCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GQAPSolutionCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GQAPSolutionCreator.cs	(revision 17175)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAPSolutionCreator", "Base class for solution creators of the Generalized Quadratic Assignment Problem.")]
+  [StorableType("1FD56558-5E7C-470C-8E7C-B3CEF7DB1D61")]
+  public abstract class GQAPSolutionCreator : SingleSuccessorOperator, IProblemInstanceAwareGQAPOperator, IGQAPSolutionCreator {
+
+    #region Parameter Descriptions
+    public static readonly string AssignmentDescription = "The vector that encodes the assignment.";
+    #endregion
+
+    public ILookupParameter<IntegerVector> IntegerVectorParameter {
+      get { return (ILookupParameter<IntegerVector>)Parameters["IntegerVector"]; }
+    }
+    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
+      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
+    }
+    public IValueLookupParameter<IntValue> LengthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["Length"]; }
+    }
+    public IValueLookupParameter<IntMatrix> BoundsParameter {
+      get { return (IValueLookupParameter<IntMatrix>)Parameters["Bounds"]; }
+    }
+
+    [StorableConstructor]
+    protected GQAPSolutionCreator(StorableConstructorFlag _) : base(_) { }
+    protected GQAPSolutionCreator(GQAPSolutionCreator original, Cloner cloner)
+      : base(original, cloner) { }
+    public GQAPSolutionCreator()
+      : base() {
+      Parameters.Add(new LookupParameter<IntegerVector>("IntegerVector", AssignmentDescription));
+      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
+      Parameters.Add(new ValueLookupParameter<IntValue>("Length", "The length of the vector.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<IntMatrix>("Bounds", "") { Hidden = true });
+    }
+
+    public override IOperation Apply() {
+      IntegerVectorParameter.ActualValue = CreateSolution(ProblemInstanceParameter.ActualValue);
+      return base.Apply();
+    }
+
+    protected abstract IntegerVector CreateSolution(GQAPInstance problemInstance);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GQAPStochasticSolutionCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GQAPStochasticSolutionCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GQAPStochasticSolutionCreator.cs	(revision 17175)
@@ -0,0 +1,54 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("GQAPStochasticSolutionCreator", "Base class for stochastic solution creators of the Generalized Quadratic Assignment Problem.")]
+  [StorableType("D7789768-032F-4EAB-ADED-FF4DD5A23B99")]
+  public abstract class GQAPStochasticSolutionCreator : GQAPSolutionCreator, IStochasticOperator {
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected GQAPStochasticSolutionCreator(StorableConstructorFlag _) : base(_) { }
+    protected GQAPStochasticSolutionCreator(GQAPStochasticSolutionCreator original, Cloner cloner)
+      : base(original, cloner) { }
+    public GQAPStochasticSolutionCreator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+    }
+
+    protected sealed override IntegerVector CreateSolution(GQAPInstance problemInstance) {
+      return CreateRandomSolution(RandomParameter.ActualValue, problemInstance);
+    }
+
+    protected abstract IntegerVector CreateRandomSolution(IRandom random, GQAPInstance problemInstance);
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs	(revision 17175)
@@ -0,0 +1,228 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  /// <summary>
+  /// This is an implementation of the algorithm described in Mateus, G.R., Resende, M.G.C. & Silva, R.M.A. J Heuristics (2011) 17: 527. https://doi.org/10.1007/s10732-010-9144-0
+  /// </summary>
+  [Item("GreedyRandomizedSolutionCreator", "Creates a solution according to the procedure described in Mateus, G., Resende, M., and Silva, R. 2011. GRASP with path-relinking for the generalized quadratic assignment problem. Journal of Heuristics 17, Springer Netherlands, pp. 527-565.")]
+  [StorableType("44919EFC-AF47-4F0D-8EE4-F5AECBF776CA")]
+  public class GreedyRandomizedSolutionCreator : GQAPStochasticSolutionCreator {
+
+    public IValueLookupParameter<IntValue> MaximumTriesParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTries"]; }
+    }
+    public IValueLookupParameter<BoolValue> CreateMostFeasibleSolutionParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["CreateMostFeasibleSolution"]; }
+    }
+
+    [StorableConstructor]
+    protected GreedyRandomizedSolutionCreator(StorableConstructorFlag _) : base(_) { }
+    protected GreedyRandomizedSolutionCreator(GreedyRandomizedSolutionCreator original, Cloner cloner)
+      : base(original, cloner) { }
+    public GreedyRandomizedSolutionCreator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTries", "The maximum number of tries to create a feasible solution after which an exception is thrown. If it is set to 0 or a negative value there will be an infinite number of attempts.", new IntValue(100000)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("CreateMostFeasibleSolution", "If this is set to true the operator will always succeed, and outputs the solution with the least violation instead of throwing an exception.", new BoolValue(false)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GreedyRandomizedSolutionCreator(this, cloner);
+    }
+
+    public static IntegerVector CreateSolution(IRandom random, GQAPInstance problemInstance,
+      int maximumTries, bool createMostFeasibleSolution, CancellationToken cancelToken) {
+      var weights = problemInstance.Weights;
+      var distances = problemInstance.Distances;
+      var installCosts = problemInstance.InstallationCosts;
+      var demands = problemInstance.Demands;
+      var capacities = problemInstance.Capacities.ToArray();
+      var transportCosts = problemInstance.TransportationCosts;
+      var equipments = demands.Length;
+      var locations = capacities.Length;
+      int tries = 0;
+      var slack = new double[locations];
+      double minViolation = double.MaxValue;
+      int[] assignment = null;
+      int[] bestAssignment = null;
+      var F = new List<int>(equipments); // set of (initially) all facilities / equipments
+      var CF = new List<int>(equipments); // set of chosen facilities / equipments
+      var L = new List<int>(locations); // set of (initially) all locations
+      var CL_list = new List<int>(locations); // list of chosen locations
+      var CL_selected = new bool[locations]; // bool decision if location is chosen
+      var T = new List<int>(equipments); // set of facilities / equpiments that can be assigned to the set of chosen locations (CL)
+      var H = new double[locations]; // proportions for choosing locations in stage 1
+      var W = new double[equipments]; // proportions for choosing facilities in stage 2
+      var Z = new double[locations]; // proportions for choosing locations in stage 2
+      
+      for (var k = 0; k < equipments; k++) {
+        for (var h = 0; h < equipments; h++) {
+          if (k == h) continue;
+          W[k] += weights[k, h];
+        }
+        W[k] *= demands[k];
+      }
+
+      while (maximumTries <= 0 || tries < maximumTries) {
+        cancelToken.ThrowIfCancellationRequested();
+
+        assignment = new int[equipments];
+
+        Array.Copy(capacities, slack, locations); // line 2 of Algorihm 2
+        CF.Clear(); // line 2 of Algorihm 2
+        Array.Clear(CL_selected, 0, locations); // line 2 of Algorihm 2
+        CL_list.Clear(); // line 2 of Algorihm 2
+        T.Clear(); // line 2 of Algorihm 2
+
+        F.Clear(); F.AddRange(Enumerable.Range(0, equipments)); // line 2 of Algorihm 2
+        L.Clear(); L.AddRange(Enumerable.Range(0, locations)); // line 2 of Algorihm 2
+
+        Array.Clear(H, 0, H.Length);
+
+        double threshold = 1.0; // line 3 of Algorithm 2
+        do { // line 4 of Algorithm 2
+          if (L.Count > 0 && random.NextDouble() < threshold) { // line 5 of Algorithm 2
+            // H is the proportion that a location is chosen
+            // The paper doesn't mention what happens if the candidate list CL
+            // does not contain an element in which case according to the formula
+            // all H_k elements would be 0 which would be equal to random selection
+            var HH = L.Select(x => H[x]);
+            int l = L.SampleProportional(random, 1, HH, false, false).Single(); // line 6 of Algorithm 2
+            L.Remove(l); // line 7 of Algorithm 2
+            CL_list.Add(l); // line 7 of Algorithm 2
+            CL_selected[l] = true; // line 7 of Algorithm 2
+            // incrementally updating location weights
+            foreach (var k in L)
+              H[k] += capacities[k] * capacities[l] / distances[k, l];
+
+            T = new List<int>(WhereDemandEqualOrLess(F, GetMaximumSlack(slack, CL_selected), demands)); // line 8 of Algorithm 2
+          }
+          if (T.Count > 0) { // line 10 of Algorithm 2
+            // W is the proportion that an equipment is chosen
+            var WW = T.Select(x => W[x]);
+            var f = T.SampleProportional(random, 1, WW, false, false) // line 11 of Algorithm 2
+              .Single();
+            T.Remove(f); // line 12 of Algorithm 2
+            F.Remove(f); // line 12 of Algorithm 2
+            CF.Add(f); // line 12 of Algorithm 2
+            var R = WhereSlackGreaterOrEqual(CL_list, demands[f], slack).ToList(); // line 13 of Algorithm 2
+            // Z is the proportion that a location is chosen in stage 2
+            var l = R[0];
+            if (R.Count > 1) { // optimization, calculate probabilistic weights only in case |R| > 1
+              Array.Clear(Z, 0, R.Count);
+              var zk = 0;
+              foreach (var k in R) {
+                // d is an increase in fitness if f would be assigned to location k
+                var d = installCosts[f, k];
+                foreach (var i in CF) {
+                  if (assignment[i] == 0) continue; // i is unassigned
+                  var j = assignment[i] - 1;
+                  d += transportCosts * weights[f, i] * distances[k, j];
+                }
+                foreach (var h in CL_list) {
+                  if (k == h) continue;
+                  Z[zk] += slack[k] * capacities[h] / (d * distances[k, h]);
+                }
+                zk++;
+              }
+              l = R.SampleProportional(random, 1, Z.Take(R.Count), false, false).Single(); // line 14 of Algorithm 2
+            }
+            assignment[f] = l + 1; // line 15 of Algorithm 2
+            slack[l] -= demands[f];
+            T = new List<int>(WhereDemandEqualOrLess(F, GetMaximumSlack(slack, CL_selected), demands)); // line 16 of Algorithm 2
+            threshold = 1.0 - (double)T.Count / Math.Max(F.Count, 1.0); // line 17 of Algorithm 2
+          }
+        } while (T.Count > 0 || L.Count > 0); // line 19 of Algorithm 2
+
+        if (maximumTries > 0) tries++;
+
+        if (F.Count == 0) {
+          bestAssignment = assignment.Select(x => x - 1).ToArray();
+          break;
+        } else if (createMostFeasibleSolution) {
+          // complete the solution and remember the one with least violation
+          foreach (var l in L.ToArray()) {
+            CL_list.Add(l);
+            CL_selected[l] = true;
+            L.Remove(l);
+          }
+          while (F.Count > 0) {
+            var f = F.Select((v, i) => new { Index = i, Value = v }).MaxItems(x => demands[x.Value]).SampleRandom(random);
+            var l = CL_list.MaxItems(x => slack[x]).SampleRandom(random);
+            F.RemoveAt(f.Index);
+            assignment[f.Value] = l + 1;
+            slack[l] -= demands[f.Value];
+          }
+          double violation = slack.Select(x => x < 0 ? -x : 0).Sum();
+          if (violation < minViolation) {
+            bestAssignment = assignment.Select(x => x - 1).ToArray();
+            minViolation = violation;
+          }
+        }
+      }
+
+      if (bestAssignment == null)
+        throw new InvalidOperationException(String.Format("No solution could be found in {0} tries.", maximumTries));
+
+      return new IntegerVector(bestAssignment);
+    }
+
+    protected override IntegerVector CreateRandomSolution(IRandom random, GQAPInstance problemInstance) {
+      return CreateSolution(random, problemInstance,
+        MaximumTriesParameter.ActualValue.Value,
+        CreateMostFeasibleSolutionParameter.ActualValue.Value,
+        CancellationToken);
+    }
+
+    private static IEnumerable<int> WhereDemandEqualOrLess(IEnumerable<int> facilities, double maximum, DoubleArray demands) {
+      foreach (int f in facilities) {
+        if (demands[f] <= maximum) yield return f;
+      }
+    }
+
+    private static double GetMaximumSlack(double[] slack, bool[] CL) {
+      var max = double.MinValue;
+      for (var i = 0; i < slack.Length; i++) {
+        if (CL[i] && max < slack[i]) max = slack[i];
+      }
+      return max;
+    }
+
+    private static IEnumerable<int> WhereSlackGreaterOrEqual(IEnumerable<int> locations, double minimum, double[] slack) {
+      foreach (int l in locations) {
+        if (slack[l] >= minimum) yield return l;
+      }
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomButFeasibleSolutionCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomButFeasibleSolutionCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomButFeasibleSolutionCreator.cs	(revision 17175)
@@ -0,0 +1,116 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("RandomButFeasibleSolutionCreator", "Creates a random, but feasible solution to the Generalized Quadratic Assignment Problem.")]
+  [StorableType("3C194DAF-81A9-4FA3-AE7F-45951FC33DE1")]
+  public class RandomFeasibleSolutionCreator : GQAPStochasticSolutionCreator {
+
+    public IValueLookupParameter<IntValue> MaximumTriesParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTries"]; }
+    }
+    public IValueLookupParameter<BoolValue> CreateMostFeasibleSolutionParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["CreateMostFeasibleSolution"]; }
+    }
+
+    [StorableConstructor]
+    protected RandomFeasibleSolutionCreator(StorableConstructorFlag _) : base(_) { }
+    protected RandomFeasibleSolutionCreator(RandomFeasibleSolutionCreator original, Cloner cloner) : base(original, cloner) { }
+    public RandomFeasibleSolutionCreator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTries", "The maximum number of tries to create a feasible solution after which an exception is thrown. If it is set to 0 or a negative value there will be an infinite number of attempts.", new IntValue(100000)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("CreateMostFeasibleSolution", "If this is set to true the operator will always succeed, and outputs the solution with the least violation instead of throwing an exception.", new BoolValue(false)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RandomFeasibleSolutionCreator(this, cloner);
+    }
+
+    public static IntegerVector CreateSolution(IRandom random, GQAPInstance problemInstance,
+      int maximumTries, bool createMostFeasibleSolution, CancellationToken cancel) {
+      var capacities = problemInstance.Capacities;
+      var demands = problemInstance.Demands;
+      IntegerVector result = null;
+      bool isFeasible = false;
+      int counter = 0;
+      double minViolation = double.MaxValue;
+      var slack = new double[capacities.Length];
+      var assignment = new int[demands.Length];
+
+      while (!isFeasible) {
+        cancel.ThrowIfCancellationRequested();
+        if (maximumTries > 0) {
+          counter++;
+          if (counter > maximumTries) {
+            if (createMostFeasibleSolution) break;
+            else throw new InvalidOperationException("A feasible solution could not be obtained after " + maximumTries + " attempts.");
+          }
+        }
+        for (int i = 0; i < capacities.Length; i++) slack[i] = capacities[i];
+        foreach (var equipment in Enumerable.Range(0, demands.Length).Shuffle(random)) {
+          var freeLocations = GetFreeLocations(equipment, demands, slack);
+          assignment[equipment] = freeLocations.SampleRandom(random);
+          slack[assignment[equipment]] -= demands[equipment];
+        }
+        double violation = slack.Select(x => x < 0 ? -x : 0).Sum();
+        isFeasible = violation == 0;
+        if (isFeasible || violation < minViolation) {
+          result = new IntegerVector(assignment);
+          minViolation = violation;
+        }
+      }
+      return result;
+    }
+
+    protected override IntegerVector CreateRandomSolution(IRandom random, GQAPInstance problemInstance) {
+      return CreateSolution(random, problemInstance,
+        MaximumTriesParameter.ActualValue.Value,
+        CreateMostFeasibleSolutionParameter.ActualValue.Value,
+        CancellationToken);
+    }
+
+    private static IEnumerable<int> GetFreeLocations(int equipment, DoubleArray demands, double[] freeCapacities) {
+      var freeLocations = freeCapacities
+        .Select((v, idx) => new KeyValuePair<int, double>(idx, v))
+        .Where(x => x.Value >= demands[equipment]);
+      if (!freeLocations.Any()) {
+        freeLocations = freeCapacities
+          .Select((v, idx) => new KeyValuePair<int, double>(idx, v))
+          .OrderByDescending(x => x.Value)
+          .Take(3); // if there are none, take the three where the free capacity is largest
+      }
+      return freeLocations.Select(x => x.Key);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/SlackMinimizationSolutionCreator.cs
===================================================================
--- branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/SlackMinimizationSolutionCreator.cs	(revision 17175)
+++ branches/2457_ExpertSystem/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/SlackMinimizationSolutionCreator.cs	(revision 17175)
@@ -0,0 +1,181 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
+  [Item("SlackMinimizationSolutionCreator", "A heuristic that creates a solution to the Generalized Quadratic Assignment Problem by minimizing the amount of slack.")]
+  [StorableType("02676A57-A686-4FDB-B912-B3792C749669")]
+  public class SlackMinimizationSolutionCreator : GQAPStochasticSolutionCreator {
+
+    public IValueLookupParameter<IntValue> MaximumTriesParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumTries"]; }
+    }
+    public IValueLookupParameter<BoolValue> CreateMostFeasibleSolutionParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["CreateMostFeasibleSolution"]; }
+    }
+    public IValueLookupParameter<IntValue> DepthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["Depth"]; }
+    }
+    public IValueLookupParameter<IntValue> RandomWalkLengthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["RandomWalkLength"]; }
+    }
+
+    [StorableConstructor]
+    protected SlackMinimizationSolutionCreator(StorableConstructorFlag _) : base(_) { }
+    protected SlackMinimizationSolutionCreator(SlackMinimizationSolutionCreator original, Cloner cloner) : base(original, cloner) { }
+    public SlackMinimizationSolutionCreator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumTries", "The maximum number of tries to create a feasible solution after which an exception is thrown. If it is set to 0 or a negative value there will be an infinite number of attempts to create a feasible solution.", new IntValue(100000)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("CreateMostFeasibleSolution", "If this is set to true the operator will always succeed, and outputs the solution with the least violation instead of throwing an exception.", new BoolValue(false)));
+      Parameters.Add(new ValueLookupParameter<IntValue>("Depth", "How deep the algorithm should look forward.", new IntValue(3)));
+      Parameters.Add(new ValueLookupParameter<IntValue>("RandomWalkLength", "The length of the random walk in the feasible region that is used to diversify the found assignments.", new IntValue(10)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SlackMinimizationSolutionCreator(this, cloner);
+    }
+
+    public static IntegerVector CreateSolution(IRandom random, GQAPInstance problemInstance,
+      int depth, int maximumTries, bool createMostFeasibleSolution, int randomWalkLength, CancellationToken cancel) {
+      var capacities = problemInstance.Capacities;
+      var demands = problemInstance.Demands;
+
+      IntegerVector result = null;
+      bool isFeasible = false;
+      int counter = 0;
+      double minViolation = double.MaxValue;
+      var slack = new double[capacities.Length];
+      var assignment = new Dictionary<int, int>(demands.Length);
+
+      while (!isFeasible) {
+        cancel.ThrowIfCancellationRequested();
+        if (maximumTries > 0) {
+          counter++;
+          if (counter > maximumTries) {
+            if (createMostFeasibleSolution) break;
+            else throw new InvalidOperationException("A feasible solution could not be obtained after " + maximumTries + " attempts.");
+          }
+        }
+        assignment.Clear();
+        for (int i = 0; i < capacities.Length; i++) slack[i] = capacities[i];
+        var remainingEquipment = new HashSet<int>(Enumerable.Range(0, demands.Length));
+        while (remainingEquipment.Any()) {
+          var minimumDemand = remainingEquipment.Min(x => demands[x]);
+          var possibleLocations = Enumerable.Range(0, capacities.Length).Where(x => slack[x] >= minimumDemand);
+          if (!possibleLocations.Any()) break;
+          foreach (var location in possibleLocations.Shuffle(random)) {
+            var group = FindBestGroup(location, slack[location], remainingEquipment, demands, depth);
+            foreach (var eq in group) {
+              remainingEquipment.Remove(eq);
+              assignment[eq] = location;
+              slack[location] -= demands[eq];
+            }
+          }
+        }
+        if (assignment.Count != demands.Length) {
+          // complete the solution
+          while (remainingEquipment.Any()) {
+            var f = remainingEquipment.MaxItems(x => demands[x]).SampleRandom(random);
+            var l = Enumerable.Range(0, capacities.Length).MaxItems(x => slack[x]).SampleRandom(random);
+            remainingEquipment.Remove(f);
+            assignment.Add(f, l);
+            slack[l] -= demands[f];
+          }
+        } else RandomFeasibleWalk(random, assignment, demands, slack, randomWalkLength);
+        double violation = slack.Select(x => x < 0 ? -x : 0).Sum();
+        isFeasible = violation == 0;
+        if (isFeasible || violation < minViolation) {
+          result = new IntegerVector(assignment.OrderBy(x => x.Key).Select(x => x.Value).ToArray());
+          minViolation = violation;
+        }
+      }
+      return result;
+    }
+
+    private static IEnumerable<int> FindBestGroup(int location, double slack, HashSet<int> remainingEquipment, DoubleArray demands, int depth = 3) {
+      var feasibleEquipment = remainingEquipment.Where(x => demands[x] <= slack).ToArray();
+
+      if (!feasibleEquipment.Any()) yield break;
+      if (depth == 0) {
+        var e = feasibleEquipment.MaxItems(x => demands[x]).First();
+        yield return e;
+        yield break;
+      }
+
+      double bestSlack = slack;
+      int bestEquipment = -1;
+      int[] bestColleagues = new int[0];
+      foreach (var e in feasibleEquipment) {
+        remainingEquipment.Remove(e);
+        var colleagues = FindBestGroup(location, slack - demands[e], remainingEquipment, demands, depth - 1).ToArray();
+        var slackWithColleagues = slack - demands[e] - colleagues.Sum(x => demands[x]);
+        if (bestSlack > slackWithColleagues || (bestSlack == slackWithColleagues && colleagues.Length < bestColleagues.Length)) {
+          bestSlack = slackWithColleagues;
+          bestEquipment = e;
+          bestColleagues = colleagues;
+        }
+        remainingEquipment.Add(e);
+      }
+      yield return bestEquipment;
+      foreach (var a in bestColleagues) yield return a;
+    }
+
+    private static void RandomFeasibleWalk(IRandom random, Dictionary<int, int> assignment, DoubleArray demands, double[] slack, int walkLength) {
+      for (int i = 0; i < walkLength; i++) {
+        var equipments = Enumerable.Range(0, demands.Length).Shuffle(random);
+        foreach (var e in equipments) {
+          var partners = Enumerable.Range(0, demands.Length)
+            .Where(x => slack[assignment[x]] + demands[x] - demands[e] >= 0
+                && slack[assignment[e]] + demands[e] - demands[x] >= 0);
+          if (!partners.Any()) continue;
+          var f = partners.SampleRandom(random);
+          int h = assignment[e];
+          assignment[e] = assignment[f];
+          assignment[f] = h;
+          slack[assignment[e]] += demands[f] - demands[e];
+          slack[assignment[f]] += demands[e] - demands[f];
+          break;
+        }
+      }
+    }
+
+    protected override IntegerVector CreateRandomSolution(IRandom random, GQAPInstance problemInstance) {
+      return CreateSolution(random, problemInstance,
+        DepthParameter.ActualValue.Value,
+        MaximumTriesParameter.ActualValue.Value,
+        CreateMostFeasibleSolutionParameter.ActualValue.Value,
+        RandomWalkLengthParameter.ActualValue.Value,
+        CancellationToken);
+    }
+  }
+}
Index: branches/2457_ExpertSystem/PerformanceComparison.sln
===================================================================
--- branches/2457_ExpertSystem/PerformanceComparison.sln	(revision 16958)
+++ branches/2457_ExpertSystem/PerformanceComparison.sln	(revision 17175)
@@ -33,4 +33,14 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WalkExporter", "WalkExporter\WalkExporter.csproj", "{EE6BD7D3-8012-4A5D-ABAE-356B3D1E4573}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3", "HeuristicLab.Problems.GeneralizedQuadraticAssignment\3.3\HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj", "{C739E6D2-5680-4804-A810-8017DA0C238F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances-3.3", "HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances\3.3\HeuristicLab.Problems.GeneralizedQuadraticAssignment.Instances-3.3.csproj", "{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3", "HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms\3.3\HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj", "{577239EC-7D7F-4505-A0A4-572E34010DBA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views-3.3", "HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views\3.3\HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views-3.3.csproj", "{BFAAC00C-B884-458D-BD74-98C94BFAFA41}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Encodings.IntegerVectorEncoding-3.3", "HeuristicLab.Encodings.IntegerVectorEncoding\3.3\HeuristicLab.Encodings.IntegerVectorEncoding-3.3.csproj", "{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}"
 EndProject
 Global
@@ -224,4 +234,64 @@
 		{EE6BD7D3-8012-4A5D-ABAE-356B3D1E4573}.Release|x86.ActiveCfg = Release|Any CPU
 		{EE6BD7D3-8012-4A5D-ABAE-356B3D1E4573}.Release|x86.Build.0 = Release|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Debug|x64.Build.0 = Debug|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Debug|x86.Build.0 = Debug|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Release|x64.ActiveCfg = Release|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Release|x64.Build.0 = Release|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Release|x86.ActiveCfg = Release|Any CPU
+		{C739E6D2-5680-4804-A810-8017DA0C238F}.Release|x86.Build.0 = Release|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Debug|x64.Build.0 = Debug|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Debug|x86.Build.0 = Debug|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Release|x64.ActiveCfg = Release|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Release|x64.Build.0 = Release|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Release|x86.ActiveCfg = Release|Any CPU
+		{0EB9AB8E-D0D2-4A63-9353-BD5CE57DBDFE}.Release|x86.Build.0 = Release|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Debug|x64.Build.0 = Debug|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Debug|x86.Build.0 = Debug|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Release|Any CPU.Build.0 = Release|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Release|x64.ActiveCfg = Release|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Release|x64.Build.0 = Release|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Release|x86.ActiveCfg = Release|Any CPU
+		{577239EC-7D7F-4505-A0A4-572E34010DBA}.Release|x86.Build.0 = Release|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Debug|x64.Build.0 = Debug|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Debug|x86.Build.0 = Debug|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Release|Any CPU.Build.0 = Release|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Release|x64.ActiveCfg = Release|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Release|x64.Build.0 = Release|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Release|x86.ActiveCfg = Release|Any CPU
+		{BFAAC00C-B884-458D-BD74-98C94BFAFA41}.Release|x86.Build.0 = Release|Any CPU
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Debug|x64.ActiveCfg = Debug|x64
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Debug|x64.Build.0 = Debug|x64
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Debug|x86.ActiveCfg = Debug|x86
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Debug|x86.Build.0 = Debug|x86
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Release|x64.ActiveCfg = Release|x64
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Release|x64.Build.0 = Release|x64
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Release|x86.ActiveCfg = Release|x86
+		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
