Index: branches/GeneralizedQAP/GeneralizedQAP.sln
===================================================================
--- branches/GeneralizedQAP/GeneralizedQAP.sln	(revision 15512)
+++ branches/GeneralizedQAP/GeneralizedQAP.sln	(revision 15553)
@@ -2,5 +2,5 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
-VisualStudioVersion = 15.0.27004.2002
+VisualStudioVersion = 15.0.27130.2010
 MinimumVisualStudioVersion = 10.0.40219.1
 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}"
@@ -18,5 +18,10 @@
 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
+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
 Global
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -100,4 +105,16 @@
 		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Release|x86.ActiveCfg = Release|x86
 		{DDFB14DD-2A85-493C-A52D-E69729BBAEB0}.Release|x86.Build.0 = Release|x86
+		{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
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
@@ -107,3 +124,12 @@
 		SolutionGuid = {B0BBF50B-4E62-4BAB-A730-881208150933}
 	EndGlobalSection
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
 EndGlobal
Index: branches/GeneralizedQAP/HeuristicLab.Algorithms.GRASP/3.3/GRASPWithPathRelinking.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Algorithms.GRASP/3.3/GRASPWithPathRelinking.cs	(revision 15512)
+++ branches/GeneralizedQAP/HeuristicLab.Algorithms.GRASP/3.3/GRASPWithPathRelinking.cs	(revision 15553)
@@ -39,5 +39,5 @@
   /// </summary>
   [Item("GRASP+PR", "The algorithm combines the Greedy Randomized Adaptive Search Procedure (GRASP) with Path Relinking and 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.")]
-  [Creatable("Algorithms")]
+  [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms)]
   [StorableClass]
   public sealed class GRASPWithPathRelinking : HeuristicOptimizationEngineAlgorithm, IStorableContent {
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP.cs	(revision 15553)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP.cs	(revision 15553)
@@ -0,0 +1,339 @@
+﻿#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 HeuristicLab.Analysis;
+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;
+
+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>
+  [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)]
+  [StorableClass]
+  public class GRASP : BasicAlgorithm {
+
+    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 ValueParameter<IAnalyzer> analyzerParameter;
+    public IValueParameter<IAnalyzer> AnalyzerParameter {
+      get { return analyzerParameter; }
+    }
+
+    [Storable]
+    private FixedValueParameter<BoolValue> setSeedRandomlyParameter;
+    private IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
+      get { return setSeedRandomlyParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> seedParameter;
+    private IFixedValueParameter<IntValue> SeedParameter {
+      get { return seedParameter; }
+    }
+    [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> maximumIterationsParameter;
+    public IFixedValueParameter<IntValue> MaximumIterationsParameter {
+      get { return maximumIterationsParameter; }
+    }
+    [Storable]
+    private FixedValueParameter<IntValue> maximumLocalSearchIterationsParameter;
+    public IFixedValueParameter<IntValue> MaximumLocalSearchIterationsParameter {
+      get { return maximumIterationsParameter; }
+    }
+    [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<PercentValue> minimumDifferenceParameter;
+    public IFixedValueParameter<PercentValue> MinimumDifferenceParameter {
+      get { return minimumDifferenceParameter; }
+    }
+    
+    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; }
+    }
+    public int MinimumEliteSetSize {
+      get { return minimiumEliteSetSizeParameter.Value.Value; }
+      set { minimiumEliteSetSizeParameter.Value.Value = value; }
+    }
+    public int EliteSetSize {
+      get { return eliteSetSizeParameter.Value.Value; }
+      set { eliteSetSizeParameter.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 double MinimumDifference {
+      get { return minimumDifferenceParameter.Value.Value; }
+      set { minimumDifferenceParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected GRASP(bool deserializing) : base(deserializing) { }
+    protected GRASP(GRASP original, Cloner cloner)
+      : base(original, cloner) {
+      setSeedRandomlyParameter = cloner.Clone(original.setSeedRandomlyParameter);
+      seedParameter = cloner.Clone(original.seedParameter);
+      analyzerParameter = cloner.Clone(original.analyzerParameter);
+      eliteSetSizeParameter = cloner.Clone(original.eliteSetSizeParameter);
+      minimiumEliteSetSizeParameter = cloner.Clone(original.minimiumEliteSetSizeParameter);
+      maximumIterationsParameter = cloner.Clone(original.maximumIterationsParameter);
+      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);
+      context = cloner.Clone(original.context);
+    }
+    public GRASP() {
+      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)));
+      Parameters.Add(analyzerParameter = new ValueParameter<IAnalyzer>("Analyzer", "The analyzers that are used to perform an analysis of the solutions.", new MultiAnalyzer()));
+      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(maximumIterationsParameter = new FixedValueParameter<IntValue>("MaximumIterations", "The number of iterations that the algorithm should run.", new IntValue(1000)));
+      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<PercentValue>("MinimumDifference", "The minimum amount of difference between two solutions so that they are both accepted in the elite set.", new PercentValue(1e-7)));
+      Problem = new GQAP();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GRASP(this, cloner);
+    }
+
+    public override void Prepare() {
+      base.Prepare();
+      Results.Clear();
+      context = null;
+    }
+
+    [Storable]
+    private GRASPContext context;
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+      context = new GRASPContext();
+      context.Problem = Problem;
+      context.Scope.Variables.Add(new Variable("Results", Results));
+
+      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;
+
+      if (SetSeedRandomly) {
+        var rnd = new System.Random();
+        Seed = rnd.Next();
+      }
+      context.Random = new MersenneTwister((uint)Seed);
+      context.Iterations = 0;
+      context.EvaluatedSolutions = 0;
+      context.BestQuality = double.NaN;
+      context.BestSolution = null;
+
+      context.Initialized = true;
+
+      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)));
+
+      context.RunOperator(analyzerParameter.Value, context.Scope, cancellationToken);
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      var eq = new IntegerVectorEqualityComparer();
+      while (!StoppingCriterion()) { // line 2 in Algorithm 1
+        // next: line 3 in Algorithm 1
+        var pi_prime_vec = GreedyRandomizedSolutionCreator.CreateSolution(context.Random, Problem.ProblemInstance, 1000, false, cancellationToken);
+        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 = context.AtPopulation(context.Random.Next(context.PopulationCount)).Solution; // 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
+          if (context.BestQuality > fitness) {
+            context.BestQuality = fitness;
+            context.BestSolution = (GQAPSolution)pi_prime.Clone();
+          }
+
+          if (context.PopulationCount == EliteSetSize) { // line 12 in Algorithm 1
+            var fit = Problem.ProblemInstance.ToSingleObjective(pi_prime.Evaluation);
+            double[] similarities = context.Population.Select(x => HammingSimilarityCalculator.CalculateSimilarity(x.Solution.Assignment, pi_prime.Assignment)).ToArray();
+            if (similarities.Max() <= 1.0 - MinimumDifference) { // cond. 2 of line 13 in Algorithm 1
+              var replacement = context.Population.Select((v, i) => new { V = v, Index = i })
+                                          .Where(x => x.V.Fitness >= fit).ToArray();
+              if (replacement.Length > 0) { // cond. 1 of line 13 in Algorithm 1
+                // next two lines: line 14 in Algorithm 1
+                replacement = replacement.OrderBy(x => similarities[x.Index]).ToArray();
+                context.ReplaceAtPopulation(replacement.Last().Index, context.ToScope(pi_prime, fit));
+              }
+            }
+          } else if (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();
+          }
+        }
+
+        context.Iterations++;
+
+        IResult result;
+        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)));
+        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));
+
+        context.RunOperator(analyzerParameter.Value, context.Scope, cancellationToken);
+      }
+    }
+
+    private bool IsSufficientlyDifferent(IntegerVector vec) {
+      return context.Population.All(x =>
+        HammingSimilarityCalculator.CalculateSimilarity(x.Solution.Assignment, vec) <= 1.0 - MinimumDifference
+      );
+    }
+
+    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, 1000, Problem.ProblemInstance, out localSearchEvaluations);
+      context.EvaluatedSolutions += localSearchEvaluations;
+    }
+
+    private bool StoppingCriterion() {
+      return context.Iterations > MaximumIterationsParameter.Value.Value;
+    }
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASPContext.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASPContext.cs	(revision 15553)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASPContext.cs	(revision 15553)
@@ -0,0 +1,382 @@
+﻿#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.Runtime.CompilerServices;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.GRASP {
+  [Item("GRASP+PR (GQAP) Context", "Context for GRASP+PR (GQAP).")]
+  [StorableClass]
+  public sealed class GRASPContext : ParameterizedNamedItem, IExecutionContext {
+    
+    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 IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+    public bool Maximization {
+      get { return Problem.Maximization; }
+    }
+
+    [Storable]
+    private IValueParameter<BoolValue> initialized;
+    public bool Initialized {
+      get { return initialized.Value.Value; }
+      set { initialized.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> iterations;
+    public int Iterations {
+      get { return iterations.Value.Value; }
+      set { iterations.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<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 { bestQuality.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> localSearchEvaluations;
+    public int LocalSearchEvaluations {
+      get { return localSearchEvaluations.Value.Value; }
+      set { localSearchEvaluations.Value.Value = value; }
+    }
+    
+    [Storable]
+    private IValueParameter<IRandom> random;
+    public IRandom Random {
+      get { return random.Value; }
+      set { random.Value = value; }
+    }
+
+    public IEnumerable<ISingleObjectiveSolutionScope<GQAPSolution>> Population {
+      get { return scope.SubScopes.OfType<ISingleObjectiveSolutionScope<GQAPSolution>>(); }
+    }
+    public void AddToPopulation(ISingleObjectiveSolutionScope<GQAPSolution> solScope) {
+      scope.SubScopes.Add(solScope);
+    }
+    public void ReplaceAtPopulation(int index, ISingleObjectiveSolutionScope<GQAPSolution> solScope) {
+      scope.SubScopes[index] = solScope;
+    }
+    public ISingleObjectiveSolutionScope<GQAPSolution> AtPopulation(int index) {
+      return scope.SubScopes[index] as ISingleObjectiveSolutionScope<GQAPSolution>;
+    }
+    public void SortPopulation() {
+      scope.SubScopes.Replace(scope.SubScopes.OfType<ISingleObjectiveSolutionScope<GQAPSolution>>().OrderBy(x => Maximization ? -x.Fitness : x.Fitness).ToList());
+    }
+    public int PopulationCount {
+      get { return scope.SubScopes.Count; }
+    }
+    
+    [StorableConstructor]
+    private GRASPContext(bool deserializing) : base(deserializing) { }
+    private GRASPContext(GRASPContext original, Cloner cloner)
+      : base(original, cloner) {
+      scope = cloner.Clone(original.scope);
+      problem = cloner.Clone(original.problem);
+      initialized = cloner.Clone(original.initialized);
+      iterations = cloner.Clone(original.iterations);
+      evaluatedSolutions = cloner.Clone(original.evaluatedSolutions);
+      bestQuality = cloner.Clone(original.bestQuality);
+      bestSolution = cloner.Clone(original.bestSolution);
+      localSearchEvaluations = cloner.Clone(original.localSearchEvaluations);
+      random = cloner.Clone(original.random);
+    }
+    public GRASPContext() : this("GRASP+PR (GQAP) Context") { }
+    public GRASPContext(string name) : base(name) {
+      scope = new Scope("Global");
+
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(initialized = new ValueParameter<BoolValue>("Initialized", new BoolValue(false)));
+      Parameters.Add(iterations = new ValueParameter<IntValue>("Iterations", new IntValue(0)));
+      Parameters.Add(evaluatedSolutions = new ValueParameter<IntValue>("EvaluatedSolutions", new IntValue(0)));
+      Parameters.Add(bestQuality = new ValueParameter<DoubleValue>("BestQuality", new DoubleValue(double.NaN)));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+      Parameters.Add(localSearchEvaluations = new ValueParameter<IntValue>("LocalSearchEvaluations", new IntValue(0)));
+      Parameters.Add(random = new ValueParameter<IRandom>("Random", new MersenneTwister()));
+    }
+
+    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;
+    }
+
+    public double Evaluate(GQAPSolution solution, CancellationToken token) {
+      var solScope = ToScope(solution);
+      Evaluate(solScope, token);
+      return solScope.Fitness;
+    }
+
+    public void Evaluate(ISingleObjectiveSolutionScope<GQAPSolution> solScope, CancellationToken token) {
+      var pdef = Problem as ISingleObjectiveProblemDefinition;
+      if (pdef != null) {
+        var ind = new SingleEncodingIndividual(pdef.Encoding, solScope);
+        solScope.Fitness = pdef.Evaluate(ind, Random);
+      } else {
+        RunOperator(Problem.Evaluator, solScope, token);
+      }
+    }
+
+    public GRASPSolutionContext CreateSingleSolutionContext(ISingleObjectiveSolutionScope<GQAPSolution> solution) {
+      return new GRASPSolutionContext(this, solution);
+    }
+
+    public void IncrementEvaluatedSolutions(int byEvaluations) {
+      if (byEvaluations < 0) throw new ArgumentException("Can only increment and not decrement evaluated solutions.");
+      EvaluatedSolutions += byEvaluations;
+    }
+    
+    private static void ExecuteAlgorithm(IAlgorithm algorithm) {
+      using (var evt = new AutoResetEvent(false)) {
+        EventHandler exeStateChanged = (o, args) => {
+          if (algorithm.ExecutionState != ExecutionState.Started)
+            evt.Set();
+        };
+        algorithm.ExecutionStateChanged += exeStateChanged;
+        if (algorithm.ExecutionState != ExecutionState.Prepared) {
+          algorithm.Prepare(true);
+          evt.WaitOne();
+        }
+        algorithm.Start();
+        evt.WaitOne();
+        algorithm.ExecutionStateChanged -= exeStateChanged;
+      }
+    }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool IsBetter(ISingleObjectiveSolutionScope<GQAPSolution> a, ISingleObjectiveSolutionScope<GQAPSolution> b) {
+      return IsBetter(a.Fitness, b.Fitness);
+    }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool IsBetter(double a, double b) {
+      return double.IsNaN(b) && !double.IsNaN(a)
+        || Maximization && a > b
+        || !Maximization && a < b;
+    }
+
+    #region IExecutionContext members
+    public IAtomicOperation CreateOperation(IOperator op) {
+      return new Core.ExecutionContext(this, op, Scope);
+    }
+
+    public IAtomicOperation CreateOperation(IOperator op, IScope s) {
+      return new Core.ExecutionContext(this, op, s);
+    }
+
+    public IAtomicOperation CreateChildOperation(IOperator op) {
+      return new Core.ExecutionContext(this, op, Scope);
+    }
+
+    public IAtomicOperation CreateChildOperation(IOperator op, IScope s) {
+      return new Core.ExecutionContext(this, op, s);
+    }
+    #endregion
+
+    #region Engine Helper
+    public void RunOperator(IOperator op, IScope scope, CancellationToken cancellationToken) {
+      var stack = new Stack<IOperation>();
+      stack.Push(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);
+        }
+      }
+    }
+    #endregion
+  }
+
+  [Item("GRASP+PR (GQAP) SolutionContext", "SolutionContext for GRASP+PR (GQAP).")]
+  [StorableClass]
+  public sealed class GRASPSolutionContext : ParameterizedNamedItem, IExecutionContext {
+
+    private GRASPContext parent;
+    public IExecutionContext Parent {
+      get { return parent; }
+      set { throw new InvalidOperationException("Cannot set the parent of a single-solution context."); }
+    }
+
+    [Storable]
+    private ISingleObjectiveSolutionScope<GQAPSolution> scope;
+    public IScope Scope {
+      get { return scope; }
+    }
+
+    IKeyedItemCollection<string, IParameter> IExecutionContext.Parameters {
+      get { return Parameters; }
+    }
+
+    public GQAP Problem {
+      get { return parent.Problem; }
+    }
+    public bool Maximization {
+      get { return parent.Maximization; }
+    }
+
+    public double BestQuality {
+      get { return parent.BestQuality; }
+      set { parent.BestQuality = value; }
+    }
+
+    public GQAPSolution BestSolution {
+      get { return parent.BestSolution; }
+      set { parent.BestSolution = value; }
+    }
+
+    public IRandom Random {
+      get { return parent.Random; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> evaluatedSolutions;
+    public int EvaluatedSolutions {
+      get { return evaluatedSolutions.Value.Value; }
+      set { evaluatedSolutions.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> iterations;
+    public int Iterations {
+      get { return iterations.Value.Value; }
+      set { iterations.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private GRASPSolutionContext(bool deserializing) : base(deserializing) { }
+    private GRASPSolutionContext(GRASPSolutionContext original, Cloner cloner)
+      : base(original, cloner) {
+      scope = cloner.Clone(original.scope);
+      evaluatedSolutions = cloner.Clone(original.evaluatedSolutions);
+      iterations = cloner.Clone(original.iterations);
+    }
+    public GRASPSolutionContext(GRASPContext baseContext, ISingleObjectiveSolutionScope<GQAPSolution> solution) {
+      parent = baseContext;
+      scope = solution;
+
+      Parameters.Add(evaluatedSolutions = new ValueParameter<IntValue>("EvaluatedSolutions", new IntValue(0)));
+      Parameters.Add(iterations = new ValueParameter<IntValue>("Iterations", new IntValue(0)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GRASPSolutionContext(this, cloner);
+    }
+
+    public void IncrementEvaluatedSolutions(int byEvaluations) {
+      if (byEvaluations < 0) throw new ArgumentException("Can only increment and not decrement evaluated solutions.");
+      EvaluatedSolutions += byEvaluations;
+    }
+    public double Evaluate(GQAPSolution solution, CancellationToken token) {
+      return parent.Evaluate(solution, token);
+    }
+
+    public void Evaluate(ISingleObjectiveSolutionScope<GQAPSolution> solScope, CancellationToken token) {
+      parent.Evaluate(solScope, token);
+    }
+
+    #region IExecutionContext members
+    public IAtomicOperation CreateOperation(IOperator op) {
+      return new Core.ExecutionContext(this, op, Scope);
+    }
+
+    public IAtomicOperation CreateOperation(IOperator op, IScope s) {
+      return new Core.ExecutionContext(this, op, s);
+    }
+
+    public IAtomicOperation CreateChildOperation(IOperator op) {
+      return new Core.ExecutionContext(this, op, Scope);
+    }
+
+    public IAtomicOperation CreateChildOperation(IOperator op, IScope s) {
+      return new Core.ExecutionContext(this, op, s);
+    }
+    #endregion
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj	(revision 15553)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj	(revision 15553)
@@ -0,0 +1,137 @@
+﻿<?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.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\sources\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\sources\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <DelaySign>false</DelaySign>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="HeuristicLab.Analysis-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Collections-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Common-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Common.Resources-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Common.Resources-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Core-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Data-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization.Operators-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Optimization.Operators-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Parameters-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Persistence-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Persistence-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Random-3.3">
+      <HintPath>..\..\..\..\trunk\sources\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="GRASPContext.cs" />
+    <Compile Include="GRASP.cs" />
+    <Compile Include="Interfaces.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="SingleObjectiveSolutionScope.cs" />
+  </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.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>
+    <None Include="HeuristicLab.snk" />
+  </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/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Interfaces.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Interfaces.cs	(revision 15553)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Interfaces.cs	(revision 15553)
@@ -0,0 +1,31 @@
+﻿#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.Core;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  public interface ISingleObjectiveSolutionScope<TSolution> : IScope {
+    TSolution Solution { get; set; }
+    double Fitness { get; set; }
+
+    void Adopt(ISingleObjectiveSolutionScope<TSolution> orphan);
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Plugin.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Plugin.cs	(revision 15553)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Plugin.cs	(revision 15553)
@@ -0,0 +1,44 @@
+﻿#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")]
+  public class Plugin : PluginBase {
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Properties/AssemblyInfo.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Properties/AssemblyInfo.cs	(revision 15553)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Properties/AssemblyInfo.cs	(revision 15553)
@@ -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/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/SingleObjectiveSolutionScope.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/SingleObjectiveSolutionScope.cs	(revision 15553)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/SingleObjectiveSolutionScope.cs	(revision 15553)
@@ -0,0 +1,142 @@
+﻿#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 HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
+  [Item("Solution Scope", "Scope for an individual/solution of a single-objective single-encoded problem.")]
+  [StorableClass]
+  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(bool deserializing) : base(deserializing) { }
+    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
+
+    public void Adopt(ISingleObjectiveSolutionScope<T> orphan) {
+      Solution = orphan.Solution;
+      Fitness = orphan.Fitness;
+    }
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluation/Evaluation.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluation/Evaluation.cs	(revision 15512)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Evaluation/Evaluation.cs	(revision 15553)
@@ -1,3 +1,24 @@
-﻿using System.Collections.Generic;
+﻿#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 HeuristicLab.Common;
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPInstance.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPInstance.cs	(revision 15512)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPInstance.cs	(revision 15553)
@@ -191,6 +191,7 @@
 
     public Evaluation Evaluate(IntegerVector assignment) {
-      return EvaluateIntegerVector(assignment, Demands, Capacities,
+      var evaluation = EvaluateIntegerVector(assignment, Demands, Capacities,
         InstallationCosts, Weights, Distances);
+      return evaluation;
     }
 
@@ -217,4 +218,22 @@
     }
 
+    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
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPSolution.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPSolution.cs	(revision 15512)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPSolution.cs	(revision 15553)
@@ -36,7 +36,7 @@
       get { return assignment; }
       set {
-        bool changed = (assignment != value);
+        if (assignment == value) return;
         assignment = value;
-        if (changed) OnPropertyChanged("Assignment");
+        OnPropertyChanged(nameof(Assignment));
       }
     }
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 15512)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj	(revision 15553)
@@ -41,6 +41,6 @@
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=x86">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="HeuristicLab.Analysis-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
       <Private>False</Private>
     </Reference>
@@ -69,5 +69,6 @@
       <Private>False</Private>
     </Reference>
-    <Reference Include="HeuristicLab.Optimization.Operators-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+    <Reference Include="HeuristicLab.Optimization.Operators-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Optimization.Operators-3.3.dll</HintPath>
       <Private>False</Private>
     </Reference>
@@ -84,10 +85,10 @@
       <Private>False</Private>
     </Reference>
-    <Reference Include="HeuristicLab.Problems.Instances-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="HeuristicLab.Problems.Instances-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances-3.3.dll</HintPath>
       <Private>False</Private>
     </Reference>
-    <Reference Include="HeuristicLab.Random-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="HeuristicLab.Random-3.3">
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Random-3.3.dll</HintPath>
       <Private>False</Private>
     </Reference>
@@ -170,5 +171,4 @@
     </ProjectReference>
   </ItemGroup>
-  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/StochasticNMoveSingleMoveGenerator.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/StochasticNMoveSingleMoveGenerator.cs	(revision 15512)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Moves/StochasticNMoveSingleMoveGenerator.cs	(revision 15553)
@@ -57,16 +57,55 @@
     }
 
+    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] = ReassignEquipment(random, equip, assignment[equip], 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), -1 };
+      do {
+        equipments[1] = random.Next(dim);
+      } while (equipments[0] == equipments[1]);
+
+      var reassignment = new int[dim];
+      for (var i = 0; i < 2; i++) {
+        var equip = equipments[i];
+        reassignment[equip] = ReassignEquipment(random, equip, assignment[equip], locations);
+      }
+      return new NMove(reassignment, equipments);
+    }
+
     public static NMove GenerateExactlyN(IRandom random, IntegerVector assignment, int n, DoubleArray capacities) {
-      if (capacities.Length <= 1) throw new ArgumentException("There must be at least two locations.");
+      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];
-      var equipments = Enumerable.Range(0, dim).SampleRandomWithoutRepetition(random, n, dim).ToList();
       for (var i = 0; i < n; i++) {
         var equip = equipments[i];
-        do {
-          reassignment[equip] = random.Next(capacities.Length) + 1;
-        } while (reassignment[equip] == assignment[equip] + 1);
+        reassignment[equip] = ReassignEquipment(random, equip, assignment[equip], locations);
       }
       return new NMove(reassignment, equipments);
+    }
+
+    private static int ReassignEquipment(IRandom random, int equip, int prevLocation, int locations) {
+      var newLoc = random.Next(locations) + 1;
+      while (newLoc == prevLocation + 1)
+        newLoc = random.Next(locations) + 1;
+      return newLoc;
     }
 
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPPathRelinking.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPPathRelinking.cs	(revision 15512)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPPathRelinking.cs	(revision 15553)
@@ -61,128 +61,122 @@
     }
 
-    public static IntegerVector Apply(IRandom random, ItemArray<IntegerVector> parents, ItemArray<DoubleValue> qualities,
-      GQAPInstance problemInstance, double candidateSizeFactor) {
-      if (random == null) throw new ArgumentNullException("random", "No IRandom provider is given.");
-      if (parents == null || !parents.Any()) throw new ArgumentException("No parents given for path relinking.", "parents");
-      if (parents.Length != 2) throw new ArgumentException(String.Format("Two parents were expected for path relinking, but {0} was/were given.", parents.Length.ToString()), "parents");
-      if (parents[0].Length != parents[1].Length) throw new ArgumentException("The length of the parents is not equal.", "parents");
-      if (qualities == null || qualities.Length == 0) throw new ArgumentException("The qualities are not given.", "qualities");
-      if (qualities.Length != parents.Length) throw new ArgumentException(String.Format("There are a different number of parents ({0}) than quality values ({1})", parents.Length.ToString(), qualities.Length.ToString()));
-      
-      var source = parents[0];
-      var target = parents[1];
-      IntegerVector result;
-      double resultQuality;
-
-      int betterParent = (qualities[0].Value <= qualities[1].Value) ? 0 : 1;
-
-      result = (IntegerVector)parents[betterParent].Clone();
-      resultQuality = qualities[betterParent].Value;
-
+    public static GQAPSolution Apply(IRandom random,
+      IntegerVector source, Evaluation sourceEval,
+      IntegerVector target, Evaluation targetEval,
+      GQAPInstance problemInstance, double candidateSizeFactor,
+      out int evaluatedSolutions) {
+      evaluatedSolutions = 0;
       var demands = problemInstance.Demands;
       var capacities = problemInstance.Capacities;
-
       var cmp = new IntegerVectorEqualityComparer();
 
-      var pi_prime = (IntegerVector)source.Clone();
-      var fix = new HashSet<int>();
-      var nonFix = new HashSet<int>(Enumerable.Range(0, demands.Length));
-      var phi = new HashSet<int>((IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target)));
+      var sFit = problemInstance.ToSingleObjective(sourceEval);
+      var tFit = problemInstance.ToSingleObjective(targetEval);
+      GQAPSolution pi_star = sFit < tFit ? new GQAPSolution(source, sourceEval) : new GQAPSolution(target, targetEval); // 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 HashSet<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target)); // line 4 of Algorithm 4
 
-      while (phi.Any()) {
-        var B = new List<Tuple<GQAPSolution, double>>();
-        foreach (var v in phi) {
+      while (phi.Count > 0) { // line 5 of Algorithm 4
+        var B = new List<GQAPSolution>((int)Math.Ceiling(phi.Count * candidateSizeFactor)); // line 6 of Algorithm 4
+        var B_fit = new List<double>(B.Capacity); // 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];
-          var pi2 = MakeFeasible(random, pi_prime, v, nonFix, demands, capacities);
-          pi_prime[v] = oldLocation;
+          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
+          var pi_dash_eval = problemInstance.Evaluate(pi_dash);
+          evaluatedSolutions++;
+          var pi_dash_fit = problemInstance.ToSingleObjective(pi_dash_eval);
 
-          var currentEval = problemInstance.Evaluate(pi2);
+          if (problemInstance.IsFeasible(pi_dash)) { // line 10 of Algorithm 4
+            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 (currentEval.ExcessDemand <= 0.0) {
-            var quality = problemInstance.ToSingleObjective(currentEval);
-
-            var solution = new GQAPSolution(pi2, currentEval);
-            if (B.Count >= candidateSizeFactor * phi.Count) {
-              int mostSimilarIndex = -1;
-              double mostSimilarValue = 1.0;
-              for (int i = 0; i < B.Count; i++) {
-                if (quality < B[i].Item2) {
-                  var similarity = HammingSimilarityCalculator.CalculateSimilarity(solution.Assignment, B[i].Item1.Assignment);
-                  if (similarity == 1.0) {
-                    mostSimilarIndex = -1;
-                    break;
-                  } else if (similarity < mostSimilarValue) {
-                    mostSimilarValue = similarity;
-                    mostSimilarIndex = i;
-                  }
-                }
+            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 { Index = x.Index, Fitness = x.Fitness, Similarity = HammingSimilarityCalculator.CalculateSimilarity(B[x.Index].Assignment, pi_dash) })
+                                            .ToArray();
+              if (replacement.Length > 0) {
+                var mostSimilar = replacement.MaxItems(x => x.Similarity).First().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
               }
-              if (mostSimilarIndex >= 0)
-                B[mostSimilarIndex] = Tuple.Create(solution, quality);
-            } else {
-              bool contains = false;
-              foreach (var b in B) {
-                if (cmp.Equals(solution.Assignment, b.Item1.Assignment)) {
-                  contains = true;
-                  break;
-                }
-              }
-              if (!contains) B.Add(Tuple.Create(solution, quality));
+            } 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.Any()) {
-          var pi = B.SampleProportional(random, 1, B.Select(x => 1.0 / x.Item2), false).First();
-          var diff = IntegerVectorEqualityComparer.GetDifferingIndices(pi.Item1.Assignment, target);
-          var I = phi.Except(diff);
-          var i = I.SampleRandom(random);
-          fix.Add(i);
-          nonFix.Remove(i);
-          pi_prime = pi.Item1.Assignment;
-          if (pi.Item2 < resultQuality) {
-            result = pi.Item1.Assignment;
-            resultQuality = pi.Item2;
+        if (B.Count > 0) { // line 21 of Algorithm 4
+          var pi = B.SampleProportional(random, 1, B_fit.Select(x => 1.0 / x), false).First(); // line 22 of Algorithm 4
+          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 result;
+        } else return pi_star ?? new GQAPSolution((IntegerVector)source.Clone(), (Evaluation)sourceEval.Clone());
         phi = new HashSet<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target));
       }
 
-      return result;
+      return pi_star ?? new GQAPSolution((IntegerVector)source.Clone(), (Evaluation)sourceEval.Clone());
     }
 
     protected override IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents,
       GQAPInstance problemInstance) {
-      return Apply(random, parents, QualityParameter.ActualValue, problemInstance,
-        CandidateSizeFactorParameter.Value.Value);
+
+      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).Assignment;
     }
 
-    private static IntegerVector MakeFeasible(IRandom random, IntegerVector assignment, int equipment, HashSet<int> nonFix, DoubleArray demands, DoubleArray capacities, int maximumTries = 1000) {
-      int l = assignment[equipment];
-      var slack = ComputeSlack(assignment, demands, capacities);
-      if (slack[l] >= 0) return (IntegerVector)assignment.Clone();
+    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 new IntegerVector(pi); // line 2 of Algorithm 5
 
-      IntegerVector result = null;
-      int k = 0;
-      while (k < maximumTries && slack[l] < 0) {
-        result = (IntegerVector)assignment.Clone();
-        do {
-          var maxSlack = slack.Max();
-          var T = nonFix.Where(x => x != equipment && assignment[x] == l && demands[x] <= maxSlack);
-          if (T.Any()) {
-            int i = T.SampleProportional(random, 1, T.Select(x => demands[x]), false).First();
-            var j = Enumerable.Range(0, capacities.Length).Where(x => slack[x] >= demands[i]).SampleRandom(random);
-            result[i] = j;
-            slack[j] -= demands[i];
-            slack[l] += demands[i];
-          } else break;
-        } while (slack[l] < 0);
-        k++;
+      IntegerVector pi_prime = null;
+      int k = 0; // line 4 of Algorithm 5
+      while (k < maximumTries && slack[l] < 0) {  // line 5 of Algorithm 5
+        pi_prime = new IntegerVector(pi); // line 6 of Algorithm 5
+        do {  // line 7 of Algorithm 5
+          var maxSlack = slack.Max(); // line 8-9 of Algorithm 5
+          var T = nonFix.Where(x => pi[x] == l && demands[x] <= maxSlack).ToList(); // line 8-9 of Algorithm 5
+          if (T.Count > 0) { // line 10 of Algorithm 5
+            int i = T.SampleProportional(random, 1, T.Select(x => demands[x]), false).First(); // line 11 of Algorithm 5
+            var j = Enumerable.Range(0, capacities.Length)
+              .Where(x => slack[x] >= demands[i]) // line 12 of Algorithm 5
+              .SampleRandom(random);  // line 13 of Algorithm 5
+            pi_prime[i] = j; // line 14 of Algorithm 5
+            slack[j] -= demands[i]; // line 14 of Algorithm 5
+            slack[l] += demands[i]; // line 14 of Algorithm 5
+          } else break; // cond. 1 in line 16 of Algorithm 5
+        } while (slack[l] < 0); // cond. 2 in line 16 of Algorithm 5
+        k++; // line 17 of Algorithm 5
       }
-      return result;
+      return pi_prime; // line 19-23 of Algorithm 5
     }
 
-    private static DoubleArray ComputeSlack(IntegerVector assignment, DoubleArray demands, DoubleArray capacities) {
-      var slack = (DoubleArray)capacities.Clone();
+    private static double[] ComputeSlack(IntegerVector assignment, DoubleArray demands, DoubleArray capacities) {
+      var slack = new double[capacities.Length];
       for (int i = 0; i < assignment.Length; i++) {
         slack[assignment[i]] -= demands[i];
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/ApproximateLocalSearch.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/ApproximateLocalSearch.cs	(revision 15512)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/ApproximateLocalSearch.cs	(revision 15553)
@@ -94,21 +94,33 @@
     }
 
-    /// <summary>
-    /// The implementation differs slightly from Mateus et al. in that the maximumIterations parameter defines a cap
-    /// on the number of steps that the local search can perform. While the maxSampleSize parameter corresponds to
-    /// the maxItr parameter defined by Mateus et al.
-    /// </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="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="oneMoveProbability">The probability for performing a 1-move, which is the opposite of performing a 2-move.</param>
-    public static void Apply(IRandom random, IntegerVector assignment,
-      DoubleValue quality, ref Evaluation evaluation, IntValue maxCLS, IntValue maximumIterations,
-      GQAPInstance problemInstance, IntValue evaluatedSolutions, PercentValue oneMoveProbability) {
+    public static void Apply(IRandom random, GQAPSolution sol, int maxCLS,
+      double oneMoveProbability, int maximumIterations,
+      GQAPInstance problemInstance, out int evaluatedSolutions) {
+      var fit = problemInstance.ToSingleObjective(sol.Evaluation);
+      var eval = sol.Evaluation;
+      Apply(random, sol.Assignment, ref fit, ref eval, maxCLS, oneMoveProbability, maximumIterations, problemInstance,
+        out evaluatedSolutions);
+      sol.Evaluation = eval;
+    }
+
+      /// <summary>
+      /// The implementation differs slightly from Mateus et al. in that the maximumIterations parameter defines a cap
+      /// on the number of steps that the local search can perform. While the maxSampleSize parameter corresponds to
+      /// the maxItr parameter defined by Mateus et al.
+      /// </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>
+      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) {
+      evaluatedSolutions = 0;
       var capacities = problemInstance.Capacities;
       var demands = problemInstance.Demands;
@@ -121,7 +133,7 @@
         do {
           NMove move;
-          if (random.NextDouble() < oneMoveProbability.Value)
-            move = StochasticNMoveSingleMoveGenerator.GenerateExactlyN(random, assignment, 1, capacities);
-          else move = StochasticNMoveSingleMoveGenerator.GenerateExactlyN(random, assignment, 2, capacities);
+          if (random.NextDouble() < oneMoveProbability)
+            move = StochasticNMoveSingleMoveGenerator.GenerateOneMove(random, assignment, capacities);
+          else move = StochasticNMoveSingleMoveGenerator.GenerateTwoMove(random, assignment, capacities);
           
           var moveEval = GQAPNMoveEvaluator.Evaluate(move, assignment, evaluation, problemInstance);
@@ -129,13 +141,13 @@
           double moveQuality = problemInstance.ToSingleObjective(moveEval);
 
-          if (moveEval.ExcessDemand <= 0.0 && moveQuality < quality.Value) {
+          if (moveEval.ExcessDemand <= 0.0 && moveQuality < quality) {
             CLS.Add(Tuple.Create(move, moveQuality, moveEval));
             sum += 1.0 / moveQuality;
           }
           count++;
-        } while (CLS.Count < maxCLS.Value && count < maximumIterations.Value);
+        } while (CLS.Count < maxCLS && count < maximumIterations);
 
         if (CLS.Count == 0) {
-          evaluatedSolutions.Value += (int)Math.Ceiling(evaluations);
+          evaluatedSolutions += (int)Math.Ceiling(evaluations);
           return; // END
         } else {
@@ -150,5 +162,5 @@
           }
           NMoveMaker.Apply(assignment, selected.Item1);
-          quality.Value = selected.Item2;
+          quality = selected.Item2;
           evaluation = selected.Item3;
         }
@@ -158,14 +170,21 @@
     public override IOperation Apply() {
       var evaluation = EvaluationParameter.ActualValue;
+      var quality = QualityParameter.ActualValue;
+      var fit = quality.Value;
+      var evaluatedSolutions = 0;
+
       Apply(RandomParameter.ActualValue,
         AssignmentParameter.ActualValue,
-        QualityParameter.ActualValue,
+        ref fit,
         ref evaluation,
-        MaximumCandidateListSizeParameter.ActualValue,
-        MaximumIterationsParameter.ActualValue,
+        MaximumCandidateListSizeParameter.ActualValue.Value,
+        OneMoveProbabilityParameter.ActualValue.Value,
+        MaximumIterationsParameter.ActualValue.Value,
         ProblemInstanceParameter.ActualValue,
-        EvaluatedSolutionsParameter.ActualValue,
-        OneMoveProbabilityParameter.ActualValue);
+        out evaluatedSolutions);
+
       EvaluationParameter.ActualValue = evaluation;
+      quality.Value = fit;
+      EvaluatedSolutionsParameter.ActualValue.Value += evaluatedSolutions;
       return base.Apply();
     }
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs	(revision 15512)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs	(revision 15553)
@@ -61,49 +61,55 @@
       int maximumTries, bool createMostFeasibleSolution, CancellationToken cancelToken) {
       var demands = problemInstance.Demands;
-      var capacities = problemInstance.Capacities;
+      var capacities = problemInstance.Capacities.ToArray();
+      var equipments = demands.Length;
+      var locations = capacities.Length;
       int tries = 0;
-      var assignment = new Dictionary<int, int>(demands.Length);
-      DoubleArray slack = new DoubleArray(capacities.Length);
+      var assignment = new int[equipments];
+      var slack = new double[locations];
       double minViolation = double.MaxValue;
-      Dictionary<int, int> bestAssignment = null;
-      HashSet<int> CF = new HashSet<int>(), // set of chosen facilities / equipments
-          T = new HashSet<int>(), // set of facilities / equpiments that can be assigned to the set of chosen locations (CL)
-          CL = new HashSet<int>(), // set of chosen locations
-          F = new HashSet<int>(Enumerable.Range(0, demands.Length)), // set of (initially) all facilities / equipments
-          L = new HashSet<int>(Enumerable.Range(0, capacities.Length)); // set of (initially) all locations
-
+      int[] bestAssignment = null;
+      var CF = new bool[equipments]; // set of chosen facilities / equipments
+      var T = new List<int>(equipments); // set of facilities / equpiments that can be assigned to the set of chosen locations (CL)
+      var CL_list = new List<int>(locations); // list of chosen locations
+      var CL_selected = new bool[locations]; // bool decision if location is chosen
+      var F = new List<int>(equipments); // set of (initially) all facilities / equipments
+      var L = new List<int>(locations); // set of (initially) all locations
+      
       while (maximumTries <= 0 || tries < maximumTries) {
         cancelToken.ThrowIfCancellationRequested();
 
-        assignment.Clear();
-        for (int i = 0; i < capacities.Length; i++) slack[i] = capacities[i];
-        CF.Clear();
+        Array.Copy(capacities, slack, locations);
+        Array.Clear(CF, 0, equipments);
+        Array.Clear(CL_selected, 0, locations);
+        CL_list.Clear();
         T.Clear();
-        CL.Clear();
-        F.Clear(); F.UnionWith(Enumerable.Range(0, demands.Length));
-        L.Clear(); L.UnionWith(Enumerable.Range(0, capacities.Length));
+
+        F.Clear(); F.AddRange(Enumerable.Range(0, equipments));
+        L.Clear(); L.AddRange(Enumerable.Range(0, locations));
 
         double threshold = 1.0;
         do {
-          if (L.Any() && random.NextDouble() < threshold) {
+          if (L.Count > 0 && random.NextDouble() < threshold) {
             int l = L.SampleRandom(random);
             L.Remove(l);
-            CL.Add(l);
-            T = new HashSet<int>(WithDemandEqualOrLess(F, GetMaximumSlack(slack, CL), demands));
+            CL_list.Add(l);
+            CL_selected[l] = true;
+            T = new List<int>(WhereDemandEqualOrLess(F, GetMaximumSlack(slack, CL_selected), demands));
           }
-          if (T.Any()) {
-            int f = T.SampleRandom(random);
-            T.Remove(f);
-            F.Remove(f);
-            CF.Add(f);
-            int l = WithSlackGreaterOrEqual(CL, demands[f], slack).SampleRandom(random);
-            assignment.Add(f, l);
+          if (T.Count > 0) {
+            var fidx = Enumerable.Range(0, T.Count).SampleRandom(random);
+            var f = T[fidx];
+            T.RemoveAt(fidx);
+            F.Remove(f); // TODO: slow
+            CF[f] = true;
+            int l = WhereSlackGreaterOrEqual(CL_list, demands[f], slack).SampleRandom(random);
+            assignment[f] = l + 1;
             slack[l] -= demands[f];
-            T = new HashSet<int>(WithDemandEqualOrLess(F, GetMaximumSlack(slack, CL), demands));
+            T = new List<int>(WhereDemandEqualOrLess(F, GetMaximumSlack(slack, CL_selected), demands));
             threshold = 1.0 - (double)T.Count / Math.Max(F.Count, 1.0);
           }
-        } while (T.Any() || L.Any());
+        } while (T.Count > 0 || L.Count > 0);
         if (maximumTries > 0) tries++;
-        if (!F.Any()) {
+        if (F.Count == 0) {
           bestAssignment = assignment;
           break;
@@ -111,18 +117,19 @@
           // complete the solution and remember the one with least violation
           foreach (var l in L.ToArray()) {
-            CL.Add(l);
+            CL_list.Add(l);
+            CL_selected[l] = true;
             L.Remove(l);
           }
-          while (F.Any()) {
-            var f = F.MaxItems(x => demands[x]).SampleRandom(random);
-            var l = CL.MaxItems(x => slack[x]).SampleRandom(random);
-            F.Remove(f);
-            assignment.Add(f, l);
-            slack[l] -= demands[f];
+          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;
-            assignment = new Dictionary<int, int>(demands.Length);
+            assignment = new int[equipments];
             minViolation = violation;
           }
@@ -130,7 +137,8 @@
       }
 
-      if (bestAssignment == null || bestAssignment.Count != demands.Length) throw new InvalidOperationException(String.Format("No solution could be found in {0} tries.", maximumTries));
+      if (bestAssignment == null || bestAssignment.Any(x => x == 0))
+        throw new InvalidOperationException(String.Format("No solution could be found in {0} tries.", maximumTries));
 
-      return new IntegerVector(bestAssignment.OrderBy(x => x.Key).Select(x => x.Value).ToArray());
+      return new IntegerVector(bestAssignment.Select(x => x - 1).ToArray());
     }
 
@@ -142,5 +150,5 @@
     }
 
-    private static IEnumerable<int> WithDemandEqualOrLess(IEnumerable<int> facilities, double maximum, DoubleArray demands) {
+    private static IEnumerable<int> WhereDemandEqualOrLess(IEnumerable<int> facilities, double maximum, DoubleArray demands) {
       foreach (int f in facilities) {
         if (demands[f] <= maximum) yield return f;
@@ -148,9 +156,13 @@
     }
 
-    private static double GetMaximumSlack(DoubleArray slack, HashSet<int> CL) {
-      return slack.Select((val, idx) => new { idx, val }).Where(x => CL.Contains(x.idx)).Select(x => x.val).Max();
+    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> WithSlackGreaterOrEqual(HashSet<int> locations, double minimum, DoubleArray slack) {
+    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/GeneralizedQAP/UnitTests/ApproximateLocalSearchTest.cs
===================================================================
--- branches/GeneralizedQAP/UnitTests/ApproximateLocalSearchTest.cs	(revision 15512)
+++ branches/GeneralizedQAP/UnitTests/ApproximateLocalSearchTest.cs	(revision 15553)
@@ -13,21 +13,21 @@
     [TestMethod]
     public void ApproximateLocalSearchApplyTest() {
-      CollectionAssert.AreEqual(new[] { 0, 3, 4, 2, 2, 0, 4, 3, 2, 0 }, assignment.ToArray());
+      CollectionAssert.AreEqual(new [] { 3, 2, 2, 0, 0, 0, 2, 3, 0, 2 }, assignment.ToArray());
 
       var evaluation = instance.Evaluate(assignment);
-      Assert.AreEqual(7177824, evaluation.FlowCosts);
-      Assert.AreEqual(45, evaluation.InstallationCosts);
+      Assert.AreEqual(3764492, evaluation.FlowCosts);
+      Assert.AreEqual(46, evaluation.InstallationCosts);
       Assert.AreEqual(0, evaluation.ExcessDemand);
 
-      var quality = new DoubleValue(instance.ToSingleObjective(evaluation));
-      Assert.AreEqual(27898616.781881168, quality.Value, 1e-9);
+      var quality = instance.ToSingleObjective(evaluation);
+      Assert.AreEqual(14631771.476177376, quality, 1e-9);
 
-      var evaluatedSolutions = new IntValue(0);
-      ApproximateLocalSearch.Apply(random, assignment, quality,
-        ref evaluation, new IntValue(10), new IntValue(1000), instance,
-        evaluatedSolutions, new PercentValue(0.5));
-      Assert.AreEqual(896, evaluatedSolutions.Value);
-      CollectionAssert.AreEqual(new[] { 2, 0, 0, 3, 3, 1, 0, 0, 2, 0 }, assignment.ToArray());
-      Assert.AreEqual(11733118.305768538, quality.Value, 1e-9);
+      var evaluatedSolutions = 0;
+      ApproximateLocalSearch.Apply(random, assignment, ref quality,
+        ref evaluation, 10, 0.5, 1000, instance,
+        out evaluatedSolutions);
+      Assert.AreEqual(300, evaluatedSolutions);
+      CollectionAssert.AreEqual(new[] { 3, 2, 2, 0, 0, 2, 2, 3, 0, 0 }, assignment.ToArray());
+      Assert.AreEqual(14271146.913257681, quality, 1e-9);
     }
 
