Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESContext.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESContext.cs	(revision 15562)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESContext.cs	(revision 15563)
@@ -45,4 +45,11 @@
     }
 
+    [Storable]
+    private IValueParameter<IRandom> normalRand;
+    public IRandom NormalRand {
+      get { return normalRand.Value; }
+      set { normalRand.Value = value; }
+    }
+
     public void ReplacePopulation(IEnumerable<ISingleObjectiveSolutionScope<ESGQAPSolution>> replacement) {
       Scope.SubScopes.Replace(replacement);
@@ -55,4 +62,5 @@
       problem = cloner.Clone(original.problem);
       bestSolution = cloner.Clone(original.bestSolution);
+      normalRand = cloner.Clone(original.normalRand);
     }
     public ESContext() : this("Evolution Strategy (GQAP) Context") { }
@@ -60,4 +68,5 @@
       Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
       Parameters.Add(bestSolution = new ValueParameter<ESGQAPSolution>("BestFoundSolution"));
+      Parameters.Add(normalRand = new ValueParameter<IRandom>("NormalRand"));
     }
 
@@ -74,4 +83,5 @@
       scope.Variables.Add(new Variable(name, code.Assignment));
       scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      scope.Variables.Add(new Variable("StrategyParameter", code.sParam));
       return scope;
     }
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESGQAPSolution.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESGQAPSolution.cs	(revision 15562)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/ESGQAPSolution.cs	(revision 15563)
@@ -21,4 +21,5 @@
 
 using HeuristicLab.Common;
+using HeuristicLab.Data;
 using HeuristicLab.Encodings.IntegerVectorEncoding;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -28,10 +29,10 @@
 
     [Storable]
-    private double sParam;
+    internal DoubleValue sParam;
     public double SParam {
-      get { return sParam; }
+      get { return sParam.Value; }
       set {
-        if (sParam == value) return;
-        sParam = value;
+        if (sParam.Value == value) return;
+        sParam.Value = value;
         OnPropertyChanged(nameof(SParam));
       }
@@ -42,9 +43,9 @@
     protected ESGQAPSolution(ESGQAPSolution original, Cloner cloner)
     : base(original, cloner) {
-      sParam = original.sParam;
+      sParam = cloner.Clone(original.sParam);
     }
     public ESGQAPSolution(IntegerVector assignment, Evaluation eval, double sParam)
       : base(assignment, eval) {
-      this.sParam = sParam;
+      this.sParam = new DoubleValue(sParam);
     }
     
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/EvolutionStrategy.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/EvolutionStrategy.cs	(revision 15562)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Evolutionary/EvolutionStrategy.cs	(revision 15563)
@@ -106,8 +106,9 @@
       base.Initialize(cancellationToken);
 
+      Context.NormalRand = new NormalDistributedRandom(Context.Random, 0, 1);
       Context.Problem = Problem;      
       Context.BestQuality = double.NaN;
       Context.BestSolution = null;
-
+      
       for (var m = 0; m < Mu; m++) {
         var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length);
@@ -115,5 +116,5 @@
         Context.EvaluatedSolutions++;
 
-        var ind = new ESGQAPSolution(assign, eval, 1.0 / assign.Length);
+        var ind = new ESGQAPSolution(assign, eval, Context.Random.NextDouble() * 2 - 1);
         var fit = Problem.ProblemInstance.ToSingleObjective(eval);
         Context.AddToPopulation(Context.ToScope(ind, fit));
@@ -133,4 +134,6 @@
 
     protected override void Run(CancellationToken cancellationToken) {
+      var lastUpdate = ExecutionTime;
+
       while (!StoppingCriterion()) {
         var nextGen = new List<ISingleObjectiveSolutionScope<ESGQAPSolution>>(Lambda);
@@ -141,5 +144,5 @@
           var offspring = (ESGQAPSolution)m.Solution.Clone();
           var count = Mutate(m, offspring);
-          offspring.SParam += ((1.0 / count) - offspring.SParam) / 10.0;
+          offspring.SParam += 0.7071 * Context.NormalRand.NextDouble(); //((1.0 / count) - offspring.SParam) / 10.0;
 
           offspring.Evaluation = Problem.ProblemInstance.Evaluate(offspring.Assignment);
@@ -162,10 +165,13 @@
 
         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 (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
         if (Results.TryGetValue("BestQuality", out result))
           ((DoubleValue)result.Value).Value = Context.BestQuality;
@@ -180,7 +186,15 @@
         if (cancellationToken.IsCancellationRequested) break;
       }
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
     }
 
     private int Mutate(ISingleObjectiveSolutionScope<ESGQAPSolution> m, ESGQAPSolution offspring) {
+      var stopProb = (Math.Tanh(m.Solution.SParam) + 1) / 2.0; // squash strategy parameter to ]0;1[
       var offspringFeasible = offspring.Evaluation.IsFeasible;
       double[] slack = null;
@@ -210,5 +224,5 @@
           offspring.Assignment[equip] = newLoc;
         }
-        if (Context.Random.NextDouble() < m.Solution.SParam) break;
+        if (Context.Random.NextDouble() < stopProb) break;
         count++;
       }
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP/GRASP.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP/GRASP.cs	(revision 15562)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/GRASP/GRASP.cs	(revision 15563)
@@ -164,4 +164,5 @@
     protected override void Run(CancellationToken cancellationToken) {
       var eq = new IntegerVectorEqualityComparer();
+      var lastUpdate = ExecutionTime;
       while (!StoppingCriterion()) { // line 2 in Algorithm 1
         // next: line 3 in Algorithm 1
@@ -217,10 +218,13 @@
 
         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 (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
         if (Results.TryGetValue("BestQuality", out result))
           ((DoubleValue)result.Value).Value = Context.BestQuality;
@@ -235,4 +239,11 @@
         if (cancellationToken.IsCancellationRequested) break;
       }
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
     }
 
Index: branches/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 15562)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms-3.3.csproj	(revision 15563)
@@ -110,4 +110,8 @@
     <Compile Include="GRASP\GRASPContext.cs" />
     <Compile Include="GRASP\GRASP.cs" />
+    <Compile Include="LAHC\pLAHCContext.cs" />
+    <Compile Include="LAHC\pLAHC.cs" />
+    <Compile Include="LAHC\LAHC.cs" />
+    <Compile Include="LAHC\LAHCContext.cs" />
     <Compile Include="LocalSearch\LocalSearchContext.cs" />
     <Compile Include="Infrastructure\Interfaces.cs" />
@@ -140,4 +144,5 @@
     <None Include="HeuristicLab.snk" />
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/StochasticContext.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/StochasticContext.cs	(revision 15562)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/Infrastructure/Contexts/StochasticContext.cs	(revision 15563)
@@ -24,5 +24,4 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Random;
 
 namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms {
@@ -43,17 +42,17 @@
     }
     protected StochasticContext() : base() {
-      Parameters.Add(random = new ValueParameter<IRandom>("Random", new MersenneTwister()));
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
     }
     protected StochasticContext(string name) : base(name) {
-      Parameters.Add(random = new ValueParameter<IRandom>("Random", new MersenneTwister()));
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
     }
     protected StochasticContext(string name, ParameterCollection parameters) : base(name, parameters) {
-      Parameters.Add(random = new ValueParameter<IRandom>("Random", new MersenneTwister()));
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
     }
     protected StochasticContext(string name, string description) : base(name, description) {
-      Parameters.Add(random = new ValueParameter<IRandom>("Random", new MersenneTwister()));
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
     }
     protected StochasticContext(string name, string description, ParameterCollection parameters) : base(name, description, parameters) {
-      Parameters.Add(random = new ValueParameter<IRandom>("Random", new MersenneTwister()));
+      Parameters.Add(random = new ValueParameter<IRandom>("Random"));
     }
 
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHC.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHC.cs	(revision 15563)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHC.cs	(revision 15563)
@@ -0,0 +1,171 @@
+﻿#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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LAHC {
+  [Item("LAHC (GQAP)", "Late-acceptance hill climber for the GQAP.")]
+  [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
+  [StorableClass]
+  public sealed class LAHC : StochasticAlgorithm<LAHCContext> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [Storable]
+    private FixedValueParameter<IntValue> memorySizeParameter;
+    public IFixedValueParameter<IntValue> MemorySizeParameter {
+      get { return memorySizeParameter; }
+    }
+
+    public int MemorySize {
+      get { return memorySizeParameter.Value.Value; }
+      set { memorySizeParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private LAHC(bool deserializing) : base(deserializing) { }
+    private LAHC(LAHC original, Cloner cloner)
+      : base(original, cloner) {
+      memorySizeParameter = cloner.Clone(original.memorySizeParameter);
+    }
+    public LAHC() {
+      Parameters.Add(memorySizeParameter = new FixedValueParameter<IntValue>("MemorySize", "The size of the memory, the shorter the more greedy LAHC performs.", new IntValue(100)));
+
+      Problem = new GQAP();
+    }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LAHC(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken token) {
+      base.Initialize(token);
+
+      Context.Problem = Problem;
+      Context.LastSuccess = 0;
+      
+      var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length);
+      var eval = Problem.ProblemInstance.Evaluate(assign);
+      var fit = Problem.ProblemInstance.ToSingleObjective(eval);
+      Context.EvaluatedSolutions++;
+
+      var candidate = new GQAPSolution(assign, eval);
+      
+      Context.ReplaceIncumbent(Context.ToScope(candidate, fit));
+      Context.BestQuality = fit;
+      Context.BestSolution = (GQAPSolution)candidate.Clone();
+      
+      Context.Memory = new DoubleArray(Enumerable.Repeat(Context.BestQuality, MemorySize).ToArray());
+
+      Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+      Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+      Results.Add(new Result("BestSolution", Context.BestSolution));
+
+      Context.RunOperator(Analyzer, Context.Scope, token);
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      var lastUpdate = ExecutionTime;
+      while (!StoppingCriterion()) {
+        var move = StochasticNMoveSingleMoveGenerator.GenerateOneMove(Context.Random,
+          Context.Incumbent.Solution.Assignment, Problem.ProblemInstance.Capacities);
+        var moveEval = GQAPNMoveEvaluator.Evaluate(move,
+          Context.Incumbent.Solution.Assignment,
+          Context.Incumbent.Solution.Evaluation, Problem.ProblemInstance);
+        if (Context.Iterations % Problem.ProblemInstance.Demands.Length == 0)
+          Context.EvaluatedSolutions++;
+        var nextFit = Problem.ProblemInstance.ToSingleObjective(moveEval);
+        var nextVec = new IntegerVector(Context.Incumbent.Solution.Assignment);
+        NMoveMaker.Apply(nextVec, move);
+        
+        var v = Context.Iterations % Context.Memory.Length;
+        Context.Iterations++;
+        var prevFit = Context.Memory[v];
+
+        var accept = nextFit <= Context.Incumbent.Fitness
+                  || nextFit <= prevFit;
+
+        if (accept && nextFit < Context.Incumbent.Fitness)
+          Context.LastSuccess = Context.Iterations;
+
+        if (accept) {
+          Context.ReplaceIncumbent(Context.ToScope(new GQAPSolution(nextVec, moveEval), nextFit));
+          if (nextFit < Context.BestQuality) {
+            Context.BestSolution = (GQAPSolution)Context.Incumbent.Solution.Clone();
+            Context.BestQuality = nextFit;
+          }
+        }
+
+        if (Context.Incumbent.Fitness < prevFit)
+          Context.Memory[v] = Context.Incumbent.Fitness;
+
+        IResult result;
+        if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
+        if (Results.TryGetValue("BestQuality", out result))
+          ((DoubleValue)result.Value).Value = Context.BestQuality;
+        else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+        if (Results.TryGetValue("BestSolution", out result))
+          result.Value = Context.BestSolution;
+        else Results.Add(new Result("BestSolution", Context.BestSolution));
+
+        Context.RunOperator(Analyzer, Context.Scope, cancellationToken);
+        
+        if (cancellationToken.IsCancellationRequested) break;
+      }
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHCContext.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHCContext.cs	(revision 15563)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/LAHCContext.cs	(revision 15563)
@@ -0,0 +1,89 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LAHC {
+  public sealed class LAHCContext : SingleObjectiveSingleSolutionContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<DoubleArray> memory;
+    public DoubleArray Memory {
+      get { return memory.Value; }
+      set { memory.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> lastSuccess;
+    public int LastSuccess {
+      get { return lastSuccess.Value.Value; }
+      set { lastSuccess.Value.Value = value; }
+    }
+    
+    [StorableConstructor]
+    private LAHCContext(bool deserializing) : base(deserializing) { }
+    private LAHCContext(LAHCContext original, Cloner cloner)
+    : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+      memory = cloner.Clone(original.memory);
+      lastSuccess = cloner.Clone(original.lastSuccess);
+    }
+    public LAHCContext() {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+      Parameters.Add(memory = new ValueParameter<DoubleArray>("Memory"));
+      Parameters.Add(lastSuccess = new ValueParameter<IntValue>("LastSuccess"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LAHCContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<GQAPSolution> ToScope(GQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<GQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      return scope;
+    }
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHC.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHC.cs	(revision 15563)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHC.cs	(revision 15563)
@@ -0,0 +1,208 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LAHC {
+  [Item("pLAHC-s (GQAP)", "Parameterless Late-acceptance hill climber for the GQAP.")]
+  [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
+  [StorableClass]
+  public sealed class PLAHCS : StochasticAlgorithm<PLAHCContext> {
+
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public override Type ProblemType {
+      get { return typeof(GQAP); }
+    }
+
+    public new GQAP Problem {
+      get { return (GQAP)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    [Storable]
+    private FixedValueParameter<IntValue> maximumExponentParameter;
+    public IFixedValueParameter<IntValue> MaximumExponentParameter {
+      get { return maximumExponentParameter; }
+    }
+
+    [Storable]
+    private FixedValueParameter<IntValue> minimumSprintIterationsParameter;
+    public IFixedValueParameter<IntValue> MinimumSprintIterationsParameter {
+      get { return minimumSprintIterationsParameter; }
+    }
+
+    public int MaximumExponent {
+      get { return maximumExponentParameter.Value.Value; }
+      set { maximumExponentParameter.Value.Value = value; }
+    }
+
+    public int MinimumSprintIterations {
+      get { return minimumSprintIterationsParameter.Value.Value; }
+      set { minimumSprintIterationsParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private PLAHCS(bool deserializing) : base(deserializing) { }
+    private PLAHCS(PLAHCS original, Cloner cloner)
+      : base(original, cloner) {
+      maximumExponentParameter = cloner.Clone(original.maximumExponentParameter);
+      minimumSprintIterationsParameter = cloner.Clone(original.minimumSprintIterationsParameter);
+    }
+    public PLAHCS() {
+      Parameters.Add(maximumExponentParameter = new FixedValueParameter<IntValue>("MaximumExponent", "The maximum power to which memory sizes should be tried (2^x). Do not set higher than 31", new IntValue(24)));
+      Parameters.Add(minimumSprintIterationsParameter = new FixedValueParameter<IntValue>("MinimumSprintIterations", "The minimum amount of iterations per sprint.", new IntValue(100000)));
+
+      Problem = new GQAP();
+    }
+    
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PLAHCS(this, cloner);
+    }
+
+    protected override void Initialize(CancellationToken token) {
+      base.Initialize(token);
+
+      Context.Problem = Problem;
+      Context.LastSuccess = 0;
+
+      var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length);
+      var eval = Problem.ProblemInstance.Evaluate(assign);
+      var fit = Problem.ProblemInstance.ToSingleObjective(eval);
+      Context.EvaluatedSolutions++;
+
+      var candidate = new GQAPSolution(assign, eval);
+
+      Context.ReplaceIncumbent(Context.ToScope(candidate, fit));
+      Context.BestQuality = fit;
+      Context.BestSolution = (GQAPSolution)candidate.Clone();
+
+      Context.BestList = new ItemList<DoubleValue>(new[] { new DoubleValue(Context.BestQuality) });
+
+      Results.Add(new Result("Sprint Iterations", new IntValue(Context.SprintIterations)));
+      Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+      Results.Add(new Result("CurrentMemorySize", new IntValue(0)));
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      var lastUpdate = ExecutionTime;
+      for (var i = 0; i <= MaximumExponent; i++) {
+        var l = (int)Math.Pow(2, i);
+        var memory = new double[l];
+        for (var vv = 0; vv < l; vv++)
+          memory[vv] = Context.BestList[Context.BestList.Count - 1 - (vv % Context.BestList.Count)].Value;
+        Array.Sort(memory);
+        Context.Memory = new DoubleArray(memory);
+        if (i > 0) Context.ReplaceIncumbent(Context.ToScope((GQAPSolution)Context.BestSolution.Clone(), Context.BestQuality));
+        IResult memorySizeResult;
+        if (Results.TryGetValue("CurrentMemorySize", out memorySizeResult))
+          ((IntValue)memorySizeResult.Value).Value = Context.Memory.Length;
+        else Results.Add(new Result("CurrentMemorySize", new IntValue(Context.Memory.Length)));
+
+        Context.SprintIterations = 0;
+        while (!StoppingCriterion()
+          && (Context.SprintIterations < MinimumSprintIterations
+          || (Context.SprintIterations - Context.LastSuccess) < Context.SprintIterations * 0.02)) {
+
+          var move = StochasticNMoveSingleMoveGenerator.GenerateOneMove(Context.Random,
+            Context.Incumbent.Solution.Assignment, Problem.ProblemInstance.Capacities);
+          var moveEval = GQAPNMoveEvaluator.Evaluate(move,
+            Context.Incumbent.Solution.Assignment,
+            Context.Incumbent.Solution.Evaluation, Problem.ProblemInstance);
+          if (Context.SprintIterations % Problem.ProblemInstance.Demands.Length == 0)
+            Context.EvaluatedSolutions++;
+          var nextFit = Problem.ProblemInstance.ToSingleObjective(moveEval);
+          var nextVec = new IntegerVector(Context.Incumbent.Solution.Assignment);
+          NMoveMaker.Apply(nextVec, move);
+
+          var v = Context.Iterations % Context.Memory.Length;
+          Context.Iterations++;
+          Context.SprintIterations++;
+          var prevFit = Context.Memory[v];
+
+          var accept = nextFit <= Context.Incumbent.Fitness
+                    || nextFit <= prevFit;
+
+          if (accept && nextFit < Context.Incumbent.Fitness)
+            Context.LastSuccess = Context.SprintIterations;
+
+          if (accept) {
+            Context.ReplaceIncumbent(Context.ToScope(new GQAPSolution(nextVec, moveEval), nextFit));
+            if (nextFit < Context.BestQuality) {
+              Context.BestSolution = (GQAPSolution)Context.Incumbent.Solution.Clone();
+              Context.BestQuality = nextFit;
+              Context.BestList.Add(new DoubleValue(Context.BestQuality));
+            }
+          }
+
+          if (Context.Incumbent.Fitness < prevFit)
+            Context.Memory[v] = Context.Incumbent.Fitness;
+
+          IResult result;
+          if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+            if (Results.TryGetValue("Iterations", out result))
+              ((IntValue)result.Value).Value = Context.Iterations;
+            else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+            if (Results.TryGetValue("Sprint Iterations", out result))
+              ((IntValue)result.Value).Value = Context.SprintIterations;
+            else Results.Add(new Result("Total Iterations", new IntValue(Context.SprintIterations)));
+            if (Results.TryGetValue("EvaluatedSolutions", out result))
+              ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+            else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+            lastUpdate = ExecutionTime;
+          }
+          if (Results.TryGetValue("BestQuality", out result))
+            ((DoubleValue)result.Value).Value = Context.BestQuality;
+          else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
+          if (Results.TryGetValue("BestSolution", out result))
+            result.Value = Context.BestSolution;
+          else Results.Add(new Result("BestSolution", Context.BestSolution));
+          Context.RunOperator(Analyzer, Context.Scope, cancellationToken);
+
+          if (cancellationToken.IsCancellationRequested) break;
+        }
+        if (StoppingCriterion() || cancellationToken.IsCancellationRequested) break;
+      }
+
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("Sprint Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.SprintIterations;
+      else Results.Add(new Result("Sprint Iterations", new IntValue(Context.SprintIterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+    }
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHCContext.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHCContext.cs	(revision 15563)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LAHC/pLAHCContext.cs	(revision 15563)
@@ -0,0 +1,107 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LAHC {
+  public sealed class PLAHCContext : SingleObjectiveSingleSolutionContext<ISingleObjectiveSolutionScope<GQAPSolution>> {
+    [Storable]
+    private IValueParameter<GQAP> problem;
+    public GQAP Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<GQAPSolution> bestSolution;
+    public GQAPSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> sprintIterations;
+    public int SprintIterations {
+      get { return sprintIterations.Value.Value; }
+      set { sprintIterations.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<DoubleArray> memory;
+    public DoubleArray Memory {
+      get { return memory.Value; }
+      set { memory.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> lastSuccess;
+    public int LastSuccess {
+      get { return lastSuccess.Value.Value; }
+      set { lastSuccess.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<ItemList<DoubleValue>> bestList;
+    public ItemList<DoubleValue> BestList {
+      get { return bestList.Value; }
+      set { bestList.Value = value; }
+    }
+    
+    [StorableConstructor]
+    private PLAHCContext(bool deserializing) : base(deserializing) { }
+    private PLAHCContext(PLAHCContext original, Cloner cloner)
+    : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      bestSolution = cloner.Clone(original.bestSolution);
+      sprintIterations = cloner.Clone(original.sprintIterations);
+      memory = cloner.Clone(original.memory);
+      lastSuccess = cloner.Clone(original.lastSuccess);
+      bestList = cloner.Clone(original.bestList);
+    }
+    public PLAHCContext() {
+      Parameters.Add(problem = new ValueParameter<GQAP>("Problem"));
+      Parameters.Add(bestSolution = new ValueParameter<GQAPSolution>("BestFoundSolution"));
+      Parameters.Add(sprintIterations = new ValueParameter<IntValue>("SprintIterations"));
+      Parameters.Add(memory = new ValueParameter<DoubleArray>("Memory"));
+      Parameters.Add(lastSuccess = new ValueParameter<IntValue>("LastSuccess"));
+      Parameters.Add(bestList = new ValueParameter<ItemList<DoubleValue>>("BestList"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PLAHCContext(this, cloner);
+    }
+
+    public ISingleObjectiveSolutionScope<GQAPSolution> ToScope(GQAPSolution code, double fitness = double.NaN) {
+      var name = Problem.Encoding.Name;
+      var scope = new SingleObjectiveSolutionScope<GQAPSolution>(code,
+        name + "Solution", fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+      scope.Variables.Add(new Variable(name, code.Assignment));
+      scope.Variables.Add(new Variable("Evaluation", code.Evaluation));
+      return scope;
+    }
+  }
+}
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/IteratedLS.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/IteratedLS.cs	(revision 15562)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/IteratedLS.cs	(revision 15563)
@@ -33,5 +33,5 @@
   [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
   [StorableClass]
-  public sealed class IteratedLS : ContextAlgorithm<LocalSearchContext> {
+  public sealed class IteratedLS : StochasticAlgorithm<LocalSearchContext> {
 
     public override bool SupportsPause {
@@ -92,4 +92,6 @@
 
     protected override void Run(CancellationToken cancellationToken) {
+      var lastUpdate = ExecutionTime;
+
       while (!StoppingCriterion()) {
         var lsevaluations = 0;
@@ -109,10 +111,13 @@
 
         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 (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
         if (Results.TryGetValue("BestQuality", out result))
           ((DoubleValue)result.Value).Value = Context.BestQuality;
@@ -127,4 +132,11 @@
         if (cancellationToken.IsCancellationRequested) break;
       }
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
     }
 
Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/MultistartLS.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/MultistartLS.cs	(revision 15562)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms/3.3/LocalSearch/MultistartLS.cs	(revision 15563)
@@ -33,5 +33,5 @@
   [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
   [StorableClass]
-  public sealed class MultistartLS : ContextAlgorithm<LocalSearchContext> {
+  public sealed class MultistartLS : StochasticAlgorithm<LocalSearchContext> {
 
     public override bool SupportsPause {
@@ -71,4 +71,6 @@
 
     protected override void Run(CancellationToken cancellationToken) {
+      var lastUpdate = ExecutionTime;
+
       while (!StoppingCriterion()) {
         var lsevaluations = 0;
@@ -89,10 +91,13 @@
 
         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 (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) {
+          if (Results.TryGetValue("Iterations", out result))
+            ((IntValue)result.Value).Value = Context.Iterations;
+          else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+          if (Results.TryGetValue("EvaluatedSolutions", out result))
+            ((IntValue)result.Value).Value = Context.EvaluatedSolutions;
+          else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
+          lastUpdate = ExecutionTime;
+        }
         if (Results.TryGetValue("BestQuality", out result))
           ((DoubleValue)result.Value).Value = Context.BestQuality;
@@ -107,4 +112,12 @@
         if (cancellationToken.IsCancellationRequested) break;
       }
+
+      IResult result2;
+      if (Results.TryGetValue("Iterations", out result2))
+        ((IntValue)result2.Value).Value = Context.Iterations;
+      else Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
+      if (Results.TryGetValue("EvaluatedSolutions", out result2))
+        ((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
+      else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
     }
   }
