Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/BinaryMemPR.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/BinaryMemPR.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/BinaryMemPR.cs	(revision 14552)
@@ -38,5 +38,5 @@
   [StorableClass]
   [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 999)]
-  public class BinaryMemPR : MemPRAlgorithm<SingleObjectiveBasicProblem<BinaryVectorEncoding>, BinaryVector, BinaryMemPRPopulationContext, BinaryMemPRSolutionContext> {
+  public class BinaryMemPR : MemPRAlgorithm<ISingleObjectiveHeuristicOptimizationProblem, BinaryVector, BinaryMemPRPopulationContext, BinaryMemPRSolutionContext> {
     [StorableConstructor]
     protected BinaryMemPR(bool deserializing) : base(deserializing) { }
@@ -66,12 +66,4 @@
     }
 
-    protected override ISingleObjectiveSolutionScope<BinaryVector> ToScope(BinaryVector code, double fitness = double.NaN) {
-      var creator = Problem.SolutionCreator as IBinaryVectorCreator;
-      if (creator == null) throw new InvalidOperationException("Can only solve binary encoded problems with MemPR (binary)");
-      return new SingleObjectiveSolutionScope<BinaryVector>(code, creator.BinaryVectorParameter.ActualName, fitness, Problem.Evaluator.QualityParameter.ActualName) {
-        Parent = Context.Scope
-      };
-    }
-
     protected override ISolutionSubspace<BinaryVector> CalculateSubspace(IEnumerable<BinaryVector> solutions, bool inverse = false) {
       var pop = solutions.ToList();
@@ -92,5 +84,5 @@
       var subset = subspace != null ? ((BinarySolutionSubspace)subspace).Subspace : null;
       if (double.IsNaN(scope.Fitness)) {
-        Evaluate(scope, token);
+        Context.Evaluate(scope, token);
         evaluations++;
       }
@@ -104,5 +96,5 @@
       var order = Enumerable.Range(0, N).Where(x => subset == null || subset[x]).Shuffle(Context.Random).ToArray();
 
-      var bound = Problem.Maximization ? Context.Population.Max(x => x.Fitness) : Context.Population.Min(x => x.Fitness);
+      var bound = Context.Maximization ? Context.Population.Max(x => x.Fitness) : Context.Population.Min(x => x.Fitness);
       var range = Math.Abs(bound - Context.LocalOptimaLevel);
       if (range.IsAlmost(0)) range = Math.Abs(bound * 0.05);
@@ -122,5 +114,5 @@
           var before = currentScope.Fitness;
           current[idx] = !current[idx];
-          Evaluate(currentScope, token);
+          Context.Evaluate(currentScope, token);
           evaluations++;
           var after = currentScope.Fitness;
@@ -133,5 +125,5 @@
             }
           }
-          var diff = Problem.Maximization ? after - before : before - after;
+          var diff = Context.Maximization ? after - before : before - after;
           if (diff > 0) moved = true;
           else {
@@ -158,5 +150,5 @@
       var N = p1.Solution.Length;
 
-      var probe = ToScope((BinaryVector)p1.Solution.Clone());
+      var probe = Context.ToScope((BinaryVector)p1.Solution.Clone());
 
       var cache = new HashSet<BinaryVector>(new BinaryVectorEqualityComparer());
@@ -179,5 +171,5 @@
           continue;
         }
-        Evaluate(probe, token);
+        Context.Evaluate(probe, token);
         evaluations++;
         cache.Add(c);
@@ -210,5 +202,5 @@
           var idx = order[i];
           child[idx] = !child[idx]; // move
-          Evaluate(childScope, token);
+          Context.Evaluate(childScope, token);
           evaluations++;
           var s = childScope.Fitness;
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/BinaryMemPRContext.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/BinaryMemPRContext.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/BinaryMemPRContext.cs	(revision 14552)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using HeuristicLab.Algorithms.MemPR.Interfaces;
 using HeuristicLab.Common;
@@ -31,5 +32,5 @@
   [Item("MemPR Population Context (binary)", "MemPR population context for binary encoded problems.")]
   [StorableClass]
-  public sealed class BinaryMemPRPopulationContext : MemPRPopulationContext<SingleObjectiveBasicProblem<BinaryVectorEncoding>, BinaryVector, BinaryMemPRPopulationContext, BinaryMemPRSolutionContext> {
+  public sealed class BinaryMemPRPopulationContext : MemPRPopulationContext<ISingleObjectiveHeuristicOptimizationProblem, BinaryVector, BinaryMemPRPopulationContext, BinaryMemPRSolutionContext> {
 
     [StorableConstructor]
@@ -47,9 +48,17 @@
       return new BinaryMemPRSolutionContext(this, solution);
     }
+
+    public override ISingleObjectiveSolutionScope<BinaryVector> ToScope(BinaryVector code, double fitness = double.NaN) {
+      var creator = Problem.SolutionCreator as IBinaryVectorCreator;
+      if (creator == null) throw new InvalidOperationException("MemPR (binary) context expects a problem with an IBinaryVectorCreator as solution creator.");
+      return new SingleObjectiveSolutionScope<BinaryVector>(code, creator.BinaryVectorParameter.ActualName, fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+    }
   }
 
   [Item("MemPR Solution Context (binary)", "MemPR solution context for binary encoded problems.")]
   [StorableClass]
-  public sealed class BinaryMemPRSolutionContext : MemPRSolutionContext<SingleObjectiveBasicProblem<BinaryVectorEncoding>, BinaryVector, BinaryMemPRPopulationContext, BinaryMemPRSolutionContext>, IBinaryVectorSubspaceContext {
+  public sealed class BinaryMemPRSolutionContext : MemPRSolutionContext<ISingleObjectiveHeuristicOptimizationProblem, BinaryVector, BinaryMemPRPopulationContext, BinaryMemPRSolutionContext>, IBinaryVectorSubspaceContext {
 
     [Storable]
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/LocalSearch/ExhaustiveBitflip.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/LocalSearch/ExhaustiveBitflip.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/LocalSearch/ExhaustiveBitflip.cs	(revision 14552)
@@ -33,5 +33,7 @@
   [Item("Exhaustive Bitflip Local Search (binary)", "", ExcludeGenericTypeInfo = true)]
   [StorableClass]
-  public class ExhaustiveBitflip<TContext> : NamedItem, ILocalSearch<TContext> where TContext : ISingleSolutionHeuristicAlgorithmContext<SingleObjectiveBasicProblem<BinaryVectorEncoding>, BinaryVector> {
+  public class ExhaustiveBitflip<TContext> : NamedItem, ILocalSearch<TContext>
+    where TContext : ISingleSolutionHeuristicAlgorithmContext<ISingleObjectiveHeuristicOptimizationProblem, BinaryVector>,
+                     IEvaluationServiceContext<BinaryVector> {
     
     [StorableConstructor]
@@ -48,9 +50,8 @@
 
     public void Optimize(TContext context) {
-      var evalWrapper = new EvaluationWrapper<BinaryVector>(context.Problem, context.Solution);
       var quality = context.Solution.Fitness;
       try {
         var result = ExhaustiveBitflip.Optimize(context.Random, context.Solution.Solution, ref quality,
-          context.Problem.Maximization, evalWrapper.Evaluate, CancellationToken.None);
+          context.Maximization, context.Evaluate, CancellationToken.None);
         context.IncrementEvaluatedSolutions(result.Item1);
         context.Iterations = result.Item2;
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/LocalSearch/ExhaustiveBitflipSubspace.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/LocalSearch/ExhaustiveBitflipSubspace.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/LocalSearch/ExhaustiveBitflipSubspace.cs	(revision 14552)
@@ -34,5 +34,6 @@
   [StorableClass]
   public class ExhaustiveBitflipSubspace<TContext> : NamedItem, ILocalSearch<TContext>
-      where TContext : ISingleSolutionHeuristicAlgorithmContext<SingleObjectiveBasicProblem<BinaryVectorEncoding>, BinaryVector>, IBinaryVectorSubspaceContext {
+      where TContext : ISingleSolutionHeuristicAlgorithmContext<SingleObjectiveBasicProblem<BinaryVectorEncoding>, BinaryVector>,
+                       IBinaryVectorSubspaceContext, IEvaluationServiceContext<BinaryVector> {
 
     [StorableConstructor]
@@ -49,9 +50,8 @@
 
     public void Optimize(TContext context) {
-      var evalWrapper = new EvaluationWrapper<BinaryVector>(context.Problem, context.Solution);
       var quality = context.Solution.Fitness;
       try {
         var result = ExhaustiveBitflip.Optimize(context.Random, context.Solution.Solution, ref quality,
-          context.Problem.Maximization, evalWrapper.Evaluate, CancellationToken.None, context.Subspace.Subspace);
+          context.Problem.Maximization, context.Evaluate, CancellationToken.None, context.Subspace.Subspace);
         context.IncrementEvaluatedSolutions(result.Item1);
         context.Iterations = result.Item2;
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/LocalSearch/StaticAPI/ExhaustiveBitflip.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/LocalSearch/StaticAPI/ExhaustiveBitflip.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/LocalSearch/StaticAPI/ExhaustiveBitflip.cs	(revision 14552)
@@ -30,6 +30,6 @@
 namespace HeuristicLab.Encodings.Binary.LocalSearch {
   public static class ExhaustiveBitflip {
-    public static Tuple<int, int> Optimize(IRandom random, BinaryVector solution, ref double quality, bool maximization, Func<BinaryVector, double> evalFunc, CancellationToken token, bool[] subspace = null) {
-      if (double.IsNaN(quality)) quality = evalFunc(solution);
+    public static Tuple<int, int> Optimize(IRandom random, BinaryVector solution, ref double quality, bool maximization, Func<BinaryVector, CancellationToken, double> evalFunc, CancellationToken token, bool[] subspace = null) {
+      if (double.IsNaN(quality)) quality = evalFunc(solution, token);
       var improved = false;
       var order = Enumerable.Range(0, solution.Length).Shuffle(random).ToArray();
@@ -47,5 +47,5 @@
           // bitflip the solution
           solution[idx] = !solution[idx];
-          var after = evalFunc(solution);
+          var after = evalFunc(solution, token);
           evaluations++;
           if (FitnessComparer.IsBetter(maximization, after, quality)) {
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/BiasedModelTrainer.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/BiasedModelTrainer.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/BiasedModelTrainer.cs	(revision 14552)
@@ -34,5 +34,5 @@
   [StorableClass]
   public class BiasedModelTrainer<TContext> : ParameterizedNamedItem, ISolutionModelTrainer<TContext>
-    where TContext : IPopulationBasedHeuristicAlgorithmContext<SingleObjectiveBasicProblem<BinaryVectorEncoding>, BinaryVector>, ISolutionModelContext<BinaryVector> {
+    where TContext : IPopulationBasedHeuristicAlgorithmContext<ISingleObjectiveHeuristicOptimizationProblem, BinaryVector>, ISolutionModelContext<BinaryVector> {
     
     [Storable]
@@ -58,5 +58,5 @@
 
     public void TrainModel(TContext context) {
-      context.Model = Trainer.TrainBiased(ModelBias, context.Random, context.Problem.Maximization, context.Population.Select(x => x.Solution), context.Population.Select(x => x.Fitness));
+      context.Model = Trainer.TrainBiased(ModelBias, context.Random, context.Maximization, context.Population.Select(x => x.Solution), context.Population.Select(x => x.Fitness));
     }
   }
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/UnbiasedModelTrainer.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/UnbiasedModelTrainer.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/UnbiasedModelTrainer.cs	(revision 14552)
@@ -32,5 +32,5 @@
   [StorableClass]
   public class UniasedModelTrainer<TContext> : NamedItem, ISolutionModelTrainer<TContext>
-    where TContext : IPopulationBasedHeuristicAlgorithmContext<SingleObjectiveBasicProblem<BinaryVectorEncoding>, BinaryVector>, ISolutionModelContext<BinaryVector> {
+    where TContext : IPopulationBasedHeuristicAlgorithmContext<ISingleObjectiveHeuristicOptimizationProblem, BinaryVector>, ISolutionModelContext<BinaryVector> {
     
     [StorableConstructor]
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/HeuristicLab.Algorithms.MemPR-3.3.csproj
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/HeuristicLab.Algorithms.MemPR-3.3.csproj	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/HeuristicLab.Algorithms.MemPR-3.3.csproj	(revision 14552)
@@ -129,5 +129,4 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Util\CkMeans1D.cs" />
-    <Compile Include="Util\EvaluationWrapper.cs" />
     <Compile Include="Util\FitnessComparer.cs" />
   </ItemGroup>
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Interfaces/Interfaces.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Interfaces/Interfaces.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Interfaces/Interfaces.cs	(revision 14552)
@@ -21,4 +21,5 @@
  
 using System.Collections.Generic;
+using System.Threading;
 using HeuristicLab.Algorithms.MemPR.Binary;
 using HeuristicLab.Algorithms.MemPR.Grouping;
@@ -63,6 +64,7 @@
 
   public interface IHeuristicAlgorithmContext<TProblem, TSolution> : IExecutionContext
-      where TProblem : class, ISingleObjectiveProblemDefinition {
+      where TProblem : class, ISingleObjectiveHeuristicOptimizationProblem {
     TProblem Problem { get; }
+    bool Maximization { get; }
     IRandom Random { get; }
     int Iterations { get; set; }
@@ -73,11 +75,16 @@
   }
 
+  public interface IEvaluationServiceContext<TSolution> : IExecutionContext {
+    double Evaluate(TSolution solution, CancellationToken token);
+    void Evaluate(ISingleObjectiveSolutionScope<TSolution> scope, CancellationToken token);
+  }
+
   public interface IPopulationBasedHeuristicAlgorithmContext<TProblem, TSolution> : IHeuristicAlgorithmContext<TProblem, TSolution>
-      where TProblem : class, ISingleObjectiveProblemDefinition {
+      where TProblem : class, ISingleObjectiveHeuristicOptimizationProblem {
     IEnumerable<ISingleObjectiveSolutionScope<TSolution>> Population { get; }
   }
 
   public interface ISingleSolutionHeuristicAlgorithmContext<TProblem, TSolution> : IHeuristicAlgorithmContext<TProblem, TSolution>
-      where TProblem : class, ISingleObjectiveProblemDefinition {
+      where TProblem : class, ISingleObjectiveHeuristicOptimizationProblem {
     ISingleObjectiveSolutionScope<TSolution> Solution { get; }
   }
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LinearLinkageMemPR.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LinearLinkageMemPR.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LinearLinkageMemPR.cs	(revision 14552)
@@ -37,5 +37,5 @@
   [StorableClass]
   [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 999)]
-  public class LinearLinkageMemPR : MemPRAlgorithm<SingleObjectiveBasicProblem<LinearLinkageEncoding>, LinearLinkage, LinearLinkageMemPRPopulationContext, LinearLinkageMemPRSolutionContext> {
+  public class LinearLinkageMemPR : MemPRAlgorithm<ISingleObjectiveHeuristicOptimizationProblem, LinearLinkage, LinearLinkageMemPRPopulationContext, LinearLinkageMemPRSolutionContext> {
     [StorableConstructor]
     protected LinearLinkageMemPR(bool deserializing) : base(deserializing) { }
@@ -69,12 +69,4 @@
     }
 
-    protected override ISingleObjectiveSolutionScope<LinearLinkage> ToScope(LinearLinkage code, double fitness = double.NaN) {
-      var creator = Problem.SolutionCreator as ILinearLinkageCreator;
-      if (creator == null) throw new InvalidOperationException("Can only solve linear linkage encoded problems with MemPR (linear linkage)");
-      return new SingleObjectiveSolutionScope<LinearLinkage>(code, creator.LLEParameter.ActualName, fitness, Problem.Evaluator.QualityParameter.ActualName) {
-        Parent = Context.Scope
-      };
-    }
-
     protected override ISolutionSubspace<LinearLinkage> CalculateSubspace(IEnumerable<LinearLinkage> solutions, bool inverse = false) {
       var pop = solutions.ToList();
@@ -95,10 +87,10 @@
         int maxEvals, CancellationToken token,
         ISolutionSubspace<LinearLinkage> sub_space = null) {
-      var maximization = Context.Problem.Maximization;
+      var maximization = Context.Maximization;
       var subspace = sub_space is LinearLinkageSolutionSubspace ? ((LinearLinkageSolutionSubspace)sub_space).Subspace : null;
       var evaluations = 0;
       var quality = scope.Fitness;
       if (double.IsNaN(quality)) {
-        Evaluate(scope, token);
+        Context.Evaluate(scope, token);
         quality = scope.Fitness;
         evaluations++;
@@ -168,5 +160,5 @@
               move.Apply(current);
               var qualityToRestore = tabu[i, current[i]]; // current[i] is new next
-              Evaluate(currentScope, token);
+              Context.Evaluate(currentScope, token);
               evaluations++;
               var moveF = currentScope.Fitness;
@@ -255,5 +247,5 @@
       var cachehits = 0;
       var evaluations = 0;
-      var probe = ToScope((LinearLinkage)p1.Solution.Clone());
+      var probe = Context.ToScope((LinearLinkage)p1.Solution.Clone());
       ISingleObjectiveSolutionScope<LinearLinkage> offspring = null;
       while (evaluations < p1.Solution.Length) {
@@ -268,5 +260,5 @@
           continue;
         }
-        Evaluate(probe, token);
+        Context.Evaluate(probe, token);
         evaluations++;
         cache.Add(c);
@@ -283,13 +275,4 @@
     protected override ISingleObjectiveSolutionScope<LinearLinkage> Link(ISingleObjectiveSolutionScope<LinearLinkage> a, ISingleObjectiveSolutionScope<LinearLinkage> b, CancellationToken token, bool delink = false) {
       var evaluations = 0;
-      if (double.IsNaN(a.Fitness)) {
-        Evaluate(a, token);
-        evaluations++;
-      }
-      if (double.IsNaN(b.Fitness)) {
-        Evaluate(b, token);
-        evaluations++;
-      }
-
       var probe = (ISingleObjectiveSolutionScope<LinearLinkage>)a.Clone();
       ISingleObjectiveSolutionScope<LinearLinkage> best = null;
@@ -306,5 +289,5 @@
           if (delink && distAfter > distBefore || !delink && distAfter < distBefore) {
             var beforeQ = probe.Fitness;
-            Evaluate(probe, token);
+            Context.Evaluate(probe, token);
             evaluations++;
             var q = probe.Fitness;
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LinearLinkageMemPRContext.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LinearLinkageMemPRContext.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LinearLinkageMemPRContext.cs	(revision 14552)
@@ -20,4 +20,6 @@
 #endregion
 
+using System;
+using System.Runtime.Remoting.Contexts;
 using HeuristicLab.Algorithms.MemPR.Interfaces;
 using HeuristicLab.Common;
@@ -31,5 +33,5 @@
   [Item("MemPR Population Context (linear linkage)", "MemPR population context for linear linkage encoded problems.")]
   [StorableClass]
-  public sealed class LinearLinkageMemPRPopulationContext : MemPRPopulationContext<SingleObjectiveBasicProblem<LinearLinkageEncoding>, LinearLinkage, LinearLinkageMemPRPopulationContext, LinearLinkageMemPRSolutionContext> {
+  public sealed class LinearLinkageMemPRPopulationContext : MemPRPopulationContext<ISingleObjectiveHeuristicOptimizationProblem, LinearLinkage, LinearLinkageMemPRPopulationContext, LinearLinkageMemPRSolutionContext> {
 
     [StorableConstructor]
@@ -47,9 +49,17 @@
       return new LinearLinkageMemPRSolutionContext(this, solution);
     }
+
+    public override ISingleObjectiveSolutionScope<LinearLinkage> ToScope(LinearLinkage code, double fitness = double.NaN) {
+      var creator = Problem.SolutionCreator as ILinearLinkageCreator;
+      if (creator == null) throw new InvalidOperationException("Can only solve linear linkage encoded problems with MemPR (linear linkage)");
+      return new SingleObjectiveSolutionScope<LinearLinkage>(code, creator.LLEParameter.ActualName, fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+    }
   }
 
   [Item("MemPR Solution Context (linear linkage)", "MemPR solution context for linear linkage encoded problems.")]
   [StorableClass]
-  public sealed class LinearLinkageMemPRSolutionContext : MemPRSolutionContext<SingleObjectiveBasicProblem<LinearLinkageEncoding>, LinearLinkage, LinearLinkageMemPRPopulationContext, LinearLinkageMemPRSolutionContext>, ILinearLinkageSubspaceContext {
+  public sealed class LinearLinkageMemPRSolutionContext : MemPRSolutionContext<ISingleObjectiveHeuristicOptimizationProblem, LinearLinkage, LinearLinkageMemPRPopulationContext, LinearLinkageMemPRSolutionContext>, ILinearLinkageSubspaceContext {
 
     [Storable]
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LocalSearch/ExhaustiveSubspace.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LocalSearch/ExhaustiveSubspace.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LocalSearch/ExhaustiveSubspace.cs	(revision 14552)
@@ -22,5 +22,4 @@
 using System.Threading;
 using HeuristicLab.Algorithms.MemPR.Interfaces;
-using HeuristicLab.Algorithms.MemPR.Util;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -33,5 +32,6 @@
   [StorableClass]
   public class ExhaustiveSubspace<TContext> : NamedItem, ILocalSearch<TContext>
-      where TContext : ISingleSolutionHeuristicAlgorithmContext<SingleObjectiveBasicProblem<LinearLinkageEncoding>, LinearLinkage>, ILinearLinkageSubspaceContext {
+      where TContext : ISingleSolutionHeuristicAlgorithmContext<ISingleObjectiveHeuristicOptimizationProblem, LinearLinkage>,
+                       ILinearLinkageSubspaceContext, IEvaluationServiceContext<LinearLinkage> {
 
     [StorableConstructor]
@@ -48,9 +48,8 @@
 
     public void Optimize(TContext context) {
-      var evalWrapper = new EvaluationWrapper<LinearLinkage>(context.Problem, context.Solution);
       var quality = context.Solution.Fitness;
       try {
         var result = ExhaustiveLocalSearch.Optimize(context.Random, context.Solution.Solution, ref quality,
-          context.Problem.Maximization, evalWrapper.Evaluate, CancellationToken.None, context.Subspace.Subspace);
+          context.Maximization, context.Evaluate, CancellationToken.None, context.Subspace.Subspace);
         context.IncrementEvaluatedSolutions(result.Item1);
         context.Iterations = result.Item2;
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LocalSearch/StaticAPI/ExhaustiveLocalSearch.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LocalSearch/StaticAPI/ExhaustiveLocalSearch.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LocalSearch/StaticAPI/ExhaustiveLocalSearch.cs	(revision 14552)
@@ -21,8 +21,8 @@
 
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Threading;
 using HeuristicLab.Algorithms.MemPR.Util;
-using HeuristicLab.Collections;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.LinearLinkageEncoding;
@@ -30,120 +30,34 @@
 namespace HeuristicLab.Algorithms.MemPR.Grouping.LocalSearch {
   public static class ExhaustiveLocalSearch {
-    public static Tuple<int, int> Optimize(IRandom random, LinearLinkage solution, ref double quality, bool maximization, Func<LinearLinkage, IRandom, double> eval, CancellationToken token, bool[] subspace = null) {
+    public static Tuple<int, int> Optimize(IRandom random, LinearLinkage solution, ref double quality, bool maximization, Func<LinearLinkage, CancellationToken, double> eval, CancellationToken token, bool[] subspace = null) {
       var evaluations = 0;
-      var current = solution;
       if (double.IsNaN(quality)) {
-        quality = eval(current, random);
+        quality = eval(solution, token);
         evaluations++;
       }
       var steps = 0;
-      // this dictionary holds the last relevant links
-      var links = new BidirectionalDictionary<int, int>();
+      var lleb = solution.ToBackLinks();
       for (var iter = 0; iter < int.MaxValue; iter++) {
         var change = false;
-        // clear the dictionary before a new pass through the array is made
-        links.Clear();
-        for (var i = 0; i < current.Length; i++) {
-          if (subspace != null && !subspace[i]) {
-            links.RemoveBySecond(i);
-            links.Add(i, current[i]);
-            continue;
-          }
-          var pred = -1;
-          var isFirst = !links.TryGetBySecond(i, out pred);
-          var keepLink = false;
-          if (!isFirst) {
-            keepLink = subspace != null && !subspace[pred];
-          }
-          var next = current[i];
-          var isLast = next == i;
-
-          if (!keepLink) {
-            // try to insert current into each previous group
-            // first remove i from its group
-            var linksList = links.Where(x => x.Value != i).ToList();
-            if (linksList.Count > 0 && !isFirst) current[pred] = isLast ? pred : next;
-            for (var k = 0; k < linksList.Count; k++) {
-              var l = linksList[k];
-              current[l.Key] = i;
-              current[i] = Math.Max(i, l.Value);
-              var moveF = eval(current, random);
-              evaluations++;
-              if (FitnessComparer.IsBetter(maximization, moveF, quality)) {
-                steps++;
-                quality = moveF;
-                change = true;
-                links.RemoveBySecond(i);
-                links.SetByFirst(l.Key, i); // otherwise the link won't be removed
-                if (!isFirst) links.SetByFirst(pred, isLast ? pred : next);
-                next = current[i];
-                if (next == i) { isLast = true; }
-                pred = l.Key;
-                isFirst = false;
-                break;
-              } else { // undo
-                current[l.Key] = l.Value;
-                if (k == linksList.Count - 1) {
-                  // all attempts unsuccessful
-                  if (!isFirst) current[pred] = i; // undo - readd i to its group
-                  current[i] = next;
-                }
-              }
-            }
-          }
-
-          if (!isLast) {
-            // try to split group at this point
-            // this is safe even if keepLink was true
-            current[i] = i;
-            var moveF = eval(current, random);
+        var groupItems = new List<int>();
+        for (var i = 0; i < solution.Length; i++) {
+          foreach (var move in MoveGenerator.GenerateForItem(i, groupItems, solution, lleb).ToList()) {
+            move.Apply(solution);
+            var moveF = eval(solution, token);
             evaluations++;
             if (FitnessComparer.IsBetter(maximization, moveF, quality)) {
+              move.ApplyToLLEb(lleb);
               steps++;
               quality = moveF;
               change = true;
-              isLast = true;
-              next = i;
-              links.SetBySecond(i, i);
-              continue;
-            } else current[i] = next; // undo
+              break;
+            } else {
+              move.Undo(solution);
+            }
+            if (token.IsCancellationRequested) break;
           }
-
-          if (isFirst && !isLast) {
-            // try merge with all terminated groups
-            foreach (var l in links.Where(x => x.Key == x.Value && (subspace == null || subspace[x.Key]))) {
-              current[l.Key] = i;
-              var moveF = eval(current, random);
-              evaluations++;
-              if (FitnessComparer.IsBetter(maximization, moveF, quality)) {
-                steps++;
-                quality = moveF;
-                change = true;
-                isFirst = false;
-                pred = l.Key;
-                links.SetByFirst(l.Key, i);
-                break;
-              } else {
-                current[l.Key] = l.Value;
-              }
-            }
-          } else if (!isFirst && !keepLink) {
-            // try to extract current into own group
-            current[pred] = isLast ? pred : next;
-            current[i] = i;
-            var moveF = eval(current, random);
-            evaluations++;
-            if (FitnessComparer.IsBetter(maximization, moveF, quality)) {
-              steps++;
-              links.SetByFirst(pred, current[pred]);
-              quality = moveF;
-              change = true;
-            } else { // undo
-              current[pred] = i;
-              current[i] = next;
-            }
-          }
-          links.RemoveBySecond(i);
-          links.Add(i, current[i]);
+          if (lleb[i] != i)
+            groupItems.Remove(lleb[i]);
+          groupItems.Add(i);
           if (token.IsCancellationRequested) break;
         }
@@ -154,5 +68,5 @@
     }
 
-    public static Tuple<int, int> OptimizeSwapOnly(IRandom random, LinearLinkage solution, ref double quality, bool maximization, Func<LinearLinkage, IRandom, double> eval, CancellationToken token) {
+    public static Tuple<int, int> OptimizeSwap(IRandom random, LinearLinkage solution, ref double quality, bool maximization, Func<LinearLinkage, IRandom, double> eval, CancellationToken token) {
       var evaluations = 0;
       var current = solution;
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/SolutionModel/Univariate/UnbiasedModelTrainer.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/SolutionModel/Univariate/UnbiasedModelTrainer.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/SolutionModel/Univariate/UnbiasedModelTrainer.cs	(revision 14552)
@@ -32,5 +32,5 @@
   [StorableClass]
   public class UniasedModelTrainer<TContext> : NamedItem, ISolutionModelTrainer<TContext>
-    where TContext : IPopulationBasedHeuristicAlgorithmContext<SingleObjectiveBasicProblem<LinearLinkageEncoding>, LinearLinkage>, ISolutionModelContext<LinearLinkage> {
+    where TContext : IPopulationBasedHeuristicAlgorithmContext<ISingleObjectiveHeuristicOptimizationProblem, LinearLinkage>, ISolutionModelContext<LinearLinkage> {
     
     [StorableConstructor]
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/MemPRAlgorithm.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/MemPRAlgorithm.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/MemPRAlgorithm.cs	(revision 14552)
@@ -39,5 +39,5 @@
   [StorableClass]
   public abstract class MemPRAlgorithm<TProblem, TSolution, TPopulationContext, TSolutionContext> : BasicAlgorithm, INotifyPropertyChanged
-      where TProblem : class, IItem, ISingleObjectiveHeuristicOptimizationProblem, ISingleObjectiveProblemDefinition
+      where TProblem : class, IItem, ISingleObjectiveHeuristicOptimizationProblem
       where TSolution : class, IItem
       where TPopulationContext : MemPRPopulationContext<TProblem, TSolution, TPopulationContext, TSolutionContext>, new()
@@ -425,10 +425,10 @@
       }
 
-      RunOperator(Analyzer, Context.Scope, token);
+      Context.RunOperator(Analyzer, Context.Scope, token);
     }
 
     protected bool Replace(ISingleObjectiveSolutionScope<TSolution> child, CancellationToken token) {
       if (double.IsNaN(child.Fitness)) {
-        Evaluate(child, token);
+        Context.Evaluate(child, token);
         Context.IncrementEvaluatedSolutions(1);
       }
@@ -524,18 +524,10 @@
     protected abstract bool Eq(TSolution a, TSolution b);
     protected abstract double Dist(ISingleObjectiveSolutionScope<TSolution> a, ISingleObjectiveSolutionScope<TSolution> b);
-    protected abstract ISingleObjectiveSolutionScope<TSolution> ToScope(TSolution code, double fitness = double.NaN);
     protected abstract ISolutionSubspace<TSolution> CalculateSubspace(IEnumerable<TSolution> solutions, bool inverse = false);
-    protected virtual void Evaluate(ISingleObjectiveSolutionScope<TSolution> scope, CancellationToken token) {
-      var prob = Problem as ISingleObjectiveProblemDefinition;
-      if (prob != null) {
-        var ind = new SingleEncodingIndividual(prob.Encoding, scope);
-        scope.Fitness = prob.Evaluate(ind, Context.Random);
-      } else RunOperator(Problem.Evaluator, scope, token);
-    }
 
     #region Create
     protected virtual ISingleObjectiveSolutionScope<TSolution> Create(CancellationToken token) {
-      var child = ToScope(null);
-      RunOperator(Problem.SolutionCreator, child, token);
+      var child = Context.ToScope(null);
+      Context.RunOperator(Problem.SolutionCreator, child, token);
       return child;
     }
@@ -545,5 +537,5 @@
     protected virtual int HillClimb(ISingleObjectiveSolutionScope<TSolution> scope, CancellationToken token, ISolutionSubspace<TSolution> subspace = null) {
       if (double.IsNaN(scope.Fitness)) {
-        Evaluate(scope, token);
+        Context.Evaluate(scope, token);
         Context.IncrementEvaluatedSolutions(1);
       }
@@ -560,5 +552,5 @@
     protected virtual void AdaptiveClimb(ISingleObjectiveSolutionScope<TSolution> scope, int maxEvals, CancellationToken token, ISolutionSubspace<TSolution> subspace = null) {
       if (double.IsNaN(scope.Fitness)) {
-        Evaluate(scope, token);
+        Context.Evaluate(scope, token);
         Context.IncrementEvaluatedSolutions(1);
       }
@@ -585,9 +577,9 @@
 
       if (double.IsNaN(p1.Fitness)) {
-        Evaluate(p1, token);
+        Context.Evaluate(p1, token);
         Context.IncrementEvaluatedSolutions(1);
       }
       if (double.IsNaN(p2.Fitness)) {
-        Evaluate(p2, token);
+        Context.Evaluate(p2, token);
         Context.IncrementEvaluatedSolutions(1);
       }
@@ -597,5 +589,5 @@
 
         if (double.IsNaN(offspring.Fitness)) {
-          Evaluate(offspring, token);
+          Context.Evaluate(offspring, token);
           Context.IncrementEvaluatedSolutions(1);
         }
@@ -630,5 +622,5 @@
       var link = PerformRelinking(p1, p2, token, delink: false);
       if (double.IsNaN(link.Fitness)) {
-        Evaluate(link, token);
+        Context.Evaluate(link, token);
         Context.IncrementEvaluatedSolutions(1);
       }
@@ -654,5 +646,5 @@
       var link = PerformRelinking(p1, p2, token, delink: true);
       if (double.IsNaN(link.Fitness)) {
-        Evaluate(link, token);
+        Context.Evaluate(link, token);
         Context.IncrementEvaluatedSolutions(1);
       }
@@ -668,5 +660,5 @@
 
       if (double.IsNaN(relink.Fitness)) {
-        Evaluate(relink, token);
+        Context.Evaluate(relink, token);
         Context.IncrementEvaluatedSolutions(1);
       }
@@ -696,6 +688,6 @@
         var tries = 1;
         for (; tries < 100; tries++) {
-          var sample = ToScope(Context.Model.Sample());
-          Evaluate(sample, token);
+          var sample = Context.ToScope(Context.Model.Sample());
+          Context.Evaluate(sample, token);
           if (bestSample == null || Context.IsBetter(sample, bestSample)) {
             bestSample = sample;
@@ -714,8 +706,9 @@
 
     protected virtual bool Terminate() {
+      var maximization = ((IValueParameter<BoolValue>)Problem.MaximizationParameter).Value.Value;
       return MaximumEvaluations.HasValue && Context.EvaluatedSolutions >= MaximumEvaluations.Value
         || MaximumExecutionTime.HasValue && ExecutionTime >= MaximumExecutionTime.Value
-        || TargetQuality.HasValue && (Problem.Maximization && Context.BestQuality >= TargetQuality.Value
-                                  || !Problem.Maximization && Context.BestQuality <= TargetQuality.Value);
+        || TargetQuality.HasValue && (maximization && Context.BestQuality >= TargetQuality.Value
+                                  || !maximization && Context.BestQuality <= TargetQuality.Value);
     }
 
@@ -725,32 +718,4 @@
       if (handler != null) handler(this, new PropertyChangedEventArgs(property));
     }
-
-    #region Engine Helper
-    protected void RunOperator(IOperator op, IScope scope, CancellationToken cancellationToken) {
-      var stack = new Stack<IOperation>();
-      stack.Push(Context.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
   }
 }
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/MemPRContext.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/MemPRContext.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/MemPRContext.cs	(revision 14552)
@@ -41,6 +41,6 @@
   [StorableClass]
   public abstract class MemPRPopulationContext<TProblem, TSolution, TPopulationContext, TSolutionContext> : ParameterizedNamedItem,
-    IPopulationBasedHeuristicAlgorithmContext<TProblem, TSolution>, ISolutionModelContext<TSolution>
-      where TProblem : class, IItem, ISingleObjectiveProblemDefinition
+    IPopulationBasedHeuristicAlgorithmContext<TProblem, TSolution>, ISolutionModelContext<TSolution>, IEvaluationServiceContext<TSolution>
+      where TProblem : class, IItem, ISingleObjectiveHeuristicOptimizationProblem
       where TSolution : class, IItem
       where TPopulationContext : MemPRPopulationContext<TProblem, TSolution, TPopulationContext, TSolutionContext>
@@ -70,4 +70,7 @@
       set { problem.Value = value; }
     }
+    public bool Maximization {
+      get { return ((IValueParameter<BoolValue>)Problem.MaximizationParameter).Value.Value; }
+    }
 
     [Storable]
@@ -182,5 +185,5 @@
     }
     public void SortPopulation() {
-      scope.SubScopes.Replace(scope.SubScopes.OfType<ISingleObjectiveSolutionScope<TSolution>>().OrderBy(x => Problem.Maximization ? -x.Fitness : x.Fitness).ToList());
+      scope.SubScopes.Replace(scope.SubScopes.OfType<ISingleObjectiveSolutionScope<TSolution>>().OrderBy(x => Maximization ? -x.Fitness : x.Fitness).ToList());
     }
     public int PopulationCount {
@@ -296,5 +299,5 @@
       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<TSolution>("BestSolution"));
+      Parameters.Add(bestSolution = new ValueParameter<TSolution>("BestFoundSolution"));
       Parameters.Add(localSearchEvaluations = new ValueParameter<IntValue>("LocalSearchEvaluations", new IntValue(0)));
       Parameters.Add(localOptimaLevel = new ValueParameter<DoubleValue>("LocalOptimaLevel", new DoubleValue(0)));
@@ -313,4 +316,22 @@
       hillclimbingStat = new List<Tuple<double, double>>();
       adaptivewalkingStat = new List<Tuple<double, double>>();
+    }
+
+    public abstract ISingleObjectiveSolutionScope<TSolution> ToScope(TSolution code, double fitness = double.NaN);
+
+    public virtual double Evaluate(TSolution solution, CancellationToken token) {
+      var solScope = ToScope(solution);
+      Evaluate(solScope, token);
+      return solScope.Fitness;
+    }
+
+    public virtual void Evaluate(ISingleObjectiveSolutionScope<TSolution> 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);
+      }
     }
 
@@ -509,7 +530,7 @@
       var sdev = Math.Sqrt(model.GetEstimatedVariances(ds, new[] { 0 }).Single());
 
-      var goal = Problem.Maximization ? Population.Min(x => x.Fitness) : Population.Max(x => x.Fitness);
+      var goal = Maximization ? Population.Min(x => x.Fitness) : Population.Max(x => x.Fitness);
       var z = (goal - mean) / sdev;
-      return Problem.Maximization ? 1.0 - Phi(z) /* P(X >= z) */ : Phi(z); // P(X <= z)
+      return Maximization ? 1.0 - Phi(z) /* P(X >= z) */ : Phi(z); // P(X <= z)
     }
 
@@ -519,7 +540,7 @@
       var sdev = Math.Sqrt(model.GetEstimatedVariances(ds, new[] { 0 }).Single());
 
-      var goal = Problem.Maximization ? Population.Min(x => x.Fitness) : Population.Max(x => x.Fitness);
+      var goal = Maximization ? Population.Min(x => x.Fitness) : Population.Max(x => x.Fitness);
       var z = (goal - mean) / sdev;
-      return Problem.Maximization ? 1.0 - Phi(z) /* P(X >= z) */ : Phi(z); // P(X <= z)
+      return Maximization ? 1.0 - Phi(z) /* P(X >= z) */ : Phi(z); // P(X <= z)
     }
 
@@ -531,6 +552,6 @@
     public bool IsBetter(double a, double b) {
       return double.IsNaN(b) && !double.IsNaN(a)
-        || Problem.Maximization && a > b
-        || !Problem.Maximization && a < b;
+        || Maximization && a > b
+        || !Maximization && a < b;
     }
 
@@ -610,4 +631,32 @@
     }
     #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
   }
 
@@ -615,6 +664,6 @@
   [StorableClass]
   public abstract class MemPRSolutionContext<TProblem, TSolution, TContext, TSolutionContext> : ParameterizedNamedItem,
-    ISingleSolutionHeuristicAlgorithmContext<TProblem, TSolution>
-      where TProblem : class, IItem, ISingleObjectiveProblemDefinition
+    ISingleSolutionHeuristicAlgorithmContext<TProblem, TSolution>, IEvaluationServiceContext<TSolution>
+      where TProblem : class, IItem, ISingleObjectiveHeuristicOptimizationProblem
       where TSolution : class, IItem
       where TContext : MemPRPopulationContext<TProblem, TSolution, TContext, TSolutionContext>
@@ -639,4 +688,7 @@
     public TProblem Problem {
       get { return parent.Problem; }
+    }
+    public bool Maximization {
+      get { return parent.Maximization; }
     }
 
@@ -693,4 +745,11 @@
       EvaluatedSolutions += byEvaluations;
     }
+    public virtual double Evaluate(TSolution solution, CancellationToken token) {
+      return parent.Evaluate(solution, token);
+    }
+
+    public virtual void Evaluate(ISingleObjectiveSolutionScope<TSolution> solScope, CancellationToken token) {
+      parent.Evaluate(solScope, token);
+    }
 
     #region IExecutionContext members
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/ExhaustiveHillClimb.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/ExhaustiveHillClimb.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/ExhaustiveHillClimb.cs	(revision 14552)
@@ -33,5 +33,6 @@
   [StorableClass]
   public class ExhaustiveHillClimb<TContext> : NamedItem, ILocalSearch<TContext>
-      where TContext : ISingleSolutionHeuristicAlgorithmContext<SingleObjectiveBasicProblem<PermutationEncoding>, Encodings.PermutationEncoding.Permutation> {
+      where TContext : ISingleSolutionHeuristicAlgorithmContext<ISingleObjectiveHeuristicOptimizationProblem, Encodings.PermutationEncoding.Permutation>,
+                       IEvaluationServiceContext<Encodings.PermutationEncoding.Permutation> {
 
     [StorableConstructor]
@@ -48,9 +49,8 @@
 
     public void Optimize(TContext context) {
-      var evalWrapper = new EvaluationWrapper<Encodings.PermutationEncoding.Permutation>(context.Problem, context.Solution);
       var quality = context.Solution.Fitness;
       try {
         var result = Exhaustive.HillClimb(context.Random, context.Solution.Solution, ref quality,
-          context.Problem.Maximization, evalWrapper.Evaluate, CancellationToken.None);
+          context.Maximization, context.Evaluate, CancellationToken.None);
         context.IncrementEvaluatedSolutions(result.Item1);
         context.Iterations = result.Item2;
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/ExhaustiveHillClimbSubspace.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/ExhaustiveHillClimbSubspace.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/ExhaustiveHillClimbSubspace.cs	(revision 14552)
@@ -34,5 +34,5 @@
   public class ExhaustiveHillClimbSubspace<TContext> : NamedItem, ILocalSearch<TContext>
       where TContext : ISingleSolutionHeuristicAlgorithmContext<SingleObjectiveBasicProblem<PermutationEncoding>, Encodings.PermutationEncoding.Permutation>,
-                       IPermutationSubspaceContext {
+                       IPermutationSubspaceContext, IEvaluationServiceContext<Encodings.PermutationEncoding.Permutation> {
 
     [StorableConstructor]
@@ -49,9 +49,8 @@
 
     public void Optimize(TContext context) {
-      var evalWrapper = new EvaluationWrapper<Encodings.PermutationEncoding.Permutation>(context.Problem, context.Solution);
       var quality = context.Solution.Fitness;
       try {
         var result = Exhaustive.HillClimb(context.Random, context.Solution.Solution, ref quality,
-          context.Problem.Maximization, evalWrapper.Evaluate, CancellationToken.None, context.Subspace.Subspace);
+          context.Problem.Maximization, context.Evaluate, CancellationToken.None, context.Subspace.Subspace);
         context.IncrementEvaluatedSolutions(result.Item1);
         context.Iterations = result.Item2;
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/Exhaustive.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/Exhaustive.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/Exhaustive.cs	(revision 14552)
@@ -34,7 +34,7 @@
 
     public static Tuple<int, int> HillClimb(IRandom random, Encodings.PermutationEncoding.Permutation perm,
-      ref double quality, bool maximization, Func<Encodings.PermutationEncoding.Permutation, double> eval,
+      ref double quality, bool maximization, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval,
       CancellationToken token, bool[,] subspace = null) {
-      if (double.IsNaN(quality)) quality = eval(perm);
+      if (double.IsNaN(quality)) quality = eval(perm, token);
       Tuple<int, int> changes;
       switch (perm.PermutationType) {
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/Exhaustive1Shift.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/Exhaustive1Shift.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/Exhaustive1Shift.cs	(revision 14552)
@@ -31,10 +31,10 @@
   public static class Exhaustive1Shift {
     public static Tuple<int, int> HillClimb(IRandom random, Encodings.PermutationEncoding.Permutation perm,
-      ref double quality, bool maximization, Func<Encodings.PermutationEncoding.Permutation, double> eval,
+      ref double quality, bool maximization, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval,
       CancellationToken token, bool[,] subspace = null) {
       var evaluations = 0;
       var current = perm;
       if (double.IsNaN(quality)) {
-        quality = eval(current);
+        quality = eval(current, token);
         evaluations++;
       }
@@ -59,5 +59,5 @@
             continue;
           TranslocationManipulator.Apply(current, shift.Index1, shift.Index2, shift.Index3);
-          var q = eval(current);
+          var q = eval(current, token);
           evaluations++;
           if (FitnessComparer.IsBetter(maximization, q, quality)) {
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/Exhaustive2Opt.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/Exhaustive2Opt.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/Exhaustive2Opt.cs	(revision 14552)
@@ -31,10 +31,10 @@
   public static class Exhaustive2Opt {
     public static Tuple<int, int> HillClimb(IRandom random, Encodings.PermutationEncoding.Permutation perm,
-      ref double quality, bool maximization, Func<Encodings.PermutationEncoding.Permutation, double> eval,
+      ref double quality, bool maximization, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval,
       CancellationToken token, bool[,] subspace = null) {
       var evaluations = 0;
       var current = perm;
       if (double.IsNaN(quality)) {
-        quality = eval(current);
+        quality = eval(current, token);
         evaluations++;
       }
@@ -56,5 +56,5 @@
 
           InversionManipulator.Apply(current, opt.Index1, opt.Index2);
-          var q = eval(current);
+          var q = eval(current, token);
           evaluations++;
           if (FitnessComparer.IsBetter(maximization, q, quality)) {
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/ExhaustiveSwap2.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/ExhaustiveSwap2.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/StaticAPI/ExhaustiveSwap2.cs	(revision 14552)
@@ -31,10 +31,10 @@
   public static class ExhaustiveSwap2 {
     public static Tuple<int, int> HillClimb(IRandom random, Encodings.PermutationEncoding.Permutation perm,
-      ref double quality, bool maximization, Func<Encodings.PermutationEncoding.Permutation, double> eval,
+      ref double quality, bool maximization, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval,
       CancellationToken token, bool[,] subspace = null) {
       var evaluations = 0;
       var current = perm;
       if (double.IsNaN(quality)) {
-        quality = eval(current);
+        quality = eval(current, token);
         evaluations++;
       }
@@ -55,5 +55,5 @@
           current[swap.Index1] = current[swap.Index2];
           current[swap.Index2] = h;
-          var q = eval(current);
+          var q = eval(current, token);
           evaluations++;
           if (FitnessComparer.IsBetter(maximization, q, quality)) {
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/PermutationMemPR.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/PermutationMemPR.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/PermutationMemPR.cs	(revision 14552)
@@ -38,5 +38,5 @@
   [StorableClass]
   [Creatable(CreatableAttribute.Categories.PopulationBasedAlgorithms, Priority = 999)]
-  public class PermutationMemPR : MemPRAlgorithm<SingleObjectiveBasicProblem<PermutationEncoding>, Encodings.PermutationEncoding.Permutation, PermutationMemPRPopulationContext, PermutationMemPRSolutionContext> {
+  public class PermutationMemPR : MemPRAlgorithm<ISingleObjectiveHeuristicOptimizationProblem, Encodings.PermutationEncoding.Permutation, PermutationMemPRPopulationContext, PermutationMemPRSolutionContext> {
 #if DEBUG
     private const bool VALIDATE = true;
@@ -73,16 +73,13 @@
     }
 
-    protected override ISingleObjectiveSolutionScope<Encodings.PermutationEncoding.Permutation> ToScope(Encodings.PermutationEncoding.Permutation code, double fitness = double.NaN) {
-      var creator = Problem.SolutionCreator as IPermutationCreator;
-      if (creator == null) throw new InvalidOperationException("Can only solve binary encoded problems with MemPR (binary)");
-      return new SingleObjectiveSolutionScope<Encodings.PermutationEncoding.Permutation>(code, creator.PermutationParameter.ActualName, fitness, Problem.Evaluator.QualityParameter.ActualName) {
-        Parent = Context.Scope
-      };
-    }
-
     protected override ISolutionSubspace<Encodings.PermutationEncoding.Permutation> CalculateSubspace(IEnumerable<Encodings.PermutationEncoding.Permutation> solutions, bool inverse = false) {
-      var subspace = new bool[Problem.Encoding.Length, Problem.Encoding.PermutationTypeParameter.Value.Value == PermutationTypes.Absolute ? 1 : Problem.Encoding.Length];
-
-      switch (Problem.Encoding.PermutationTypeParameter.Value.Value) {
+      var solutionsIter = solutions.GetEnumerator();
+      if (!solutionsIter.MoveNext()) throw new ArgumentException("Cannot calculate sub-space when no solutions are given.");
+      var first = solutionsIter.Current;
+
+      var N = solutionsIter.Current.Length;
+      var type = solutionsIter.Current.PermutationType;
+      var subspace = new bool[N, type == PermutationTypes.Absolute ? 1 : N];
+      switch (type) {
         case PermutationTypes.Absolute: {
             if (inverse) {
@@ -90,6 +87,6 @@
                 subspace[i, 0] = true;
             }
-            var first = solutions.First();
-            foreach (var s in solutions.Skip(1)) {
+            while (solutionsIter.MoveNext()) {
+              var s = solutionsIter.Current;
               for (var i = 0; i < s.Length; i++) {
                 if (first[i] != s[i]) subspace[i, 0] = !inverse;
@@ -104,10 +101,10 @@
                   subspace[i, j] = true;
             }
-            var first = solutions.First();
             var placedFirst = new int[first.Length];
             for (var i = 0; i < first.Length; i++) {
               placedFirst[first[i]] = i;
             }
-            foreach (var s in solutions.Skip(1)) {
+            while (solutionsIter.MoveNext()) {
+              var s = solutionsIter.Current;
               for (var i = 0; i < s.Length; i++) {
                 if (placedFirst[s[i]] - placedFirst[s.GetCircular(i + 1)] != -1)
@@ -123,10 +120,10 @@
                   subspace[i, j] = true;
             }
-            var first = solutions.First();
             var placedFirst = new int[first.Length];
             for (var i = 0; i < first.Length; i++) {
               placedFirst[first[i]] = i;
             }
-            foreach (var s in solutions.Skip(1)) {
+            while (solutionsIter.MoveNext()) {
+              var s = solutionsIter.Current;
               for (var i = 0; i < s.Length; i++) {
                 if (Math.Abs(placedFirst[s[i]] - placedFirst[s.GetCircular(i + 1)]) != 1)
@@ -137,5 +134,5 @@
           break;
         default:
-          throw new ArgumentException(string.Format("Unknown permutation type {0}", Problem.Encoding.PermutationTypeParameter.Value.Value));
+          throw new ArgumentException(string.Format("Unknown permutation type {0}", type));
       }
       return new PermutationSolutionSubspace(subspace);
@@ -143,8 +140,7 @@
 
     protected override void AdaptiveWalk(ISingleObjectiveSolutionScope<Encodings.PermutationEncoding.Permutation> scope, int maxEvals, CancellationToken token, ISolutionSubspace<Encodings.PermutationEncoding.Permutation> subspace = null) {
-      var wrapper = new EvaluationWrapper<Encodings.PermutationEncoding.Permutation>(Context.Problem, scope);
       var quality = scope.Fitness;
       try {
-        TabuWalk(Context.Random, scope.Solution, wrapper.Evaluate, ref quality, maxEvals, subspace != null ? ((PermutationSolutionSubspace)subspace).Subspace : null);
+        TabuWalk(Context.Random, scope.Solution, Context.Evaluate, token, ref quality, maxEvals, subspace != null ? ((PermutationSolutionSubspace)subspace).Subspace : null);
       } finally {
         scope.Fitness = quality;
@@ -152,14 +148,14 @@
     }
 
-    public void TabuWalk(IRandom random, Encodings.PermutationEncoding.Permutation perm, Func<Encodings.PermutationEncoding.Permutation, IRandom, double> eval, ref double quality, int maxEvals = int.MaxValue, bool[,] subspace = null) {
+    public void TabuWalk(IRandom random, Encodings.PermutationEncoding.Permutation perm, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval, CancellationToken token, ref double quality, int maxEvals = int.MaxValue, bool[,] subspace = null) {
       switch (perm.PermutationType) {
         case PermutationTypes.Absolute:
-          TabuWalkSwap(random, perm, eval, ref quality, maxEvals, subspace);
+          TabuWalkSwap(random, perm, eval, token, ref quality, maxEvals, subspace);
           break;
         case PermutationTypes.RelativeDirected:
-          TabuWalkShift(random, perm, eval, ref quality, maxEvals, subspace);
+          TabuWalkShift(random, perm, eval, token, ref quality, maxEvals, subspace);
           break;
         case PermutationTypes.RelativeUndirected:
-          TabuWalkOpt(random, perm, eval, ref quality, maxEvals, subspace);
+          TabuWalkOpt(random, perm, eval, token, ref quality, maxEvals, subspace);
           break;
         default: throw new ArgumentException(string.Format("Permutation type {0} is not known", perm.PermutationType));
@@ -168,9 +164,9 @@
     }
 
-    public int TabuWalkSwap(IRandom random, Encodings.PermutationEncoding.Permutation perm, Func<Encodings.PermutationEncoding.Permutation, IRandom, double> eval, ref double quality, int maxEvals = int.MaxValue, bool[,] subspace = null) {
+    public int TabuWalkSwap(IRandom random, Encodings.PermutationEncoding.Permutation perm, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval, CancellationToken token, ref double quality, int maxEvals = int.MaxValue, bool[,] subspace = null) {
       var evaluations = 0;
-      var maximization = Context.Problem.Maximization;
+      var maximization = Context.Maximization;
       if (double.IsNaN(quality)) {
-        quality = eval(perm, random);
+        quality = eval(perm, token);
         evaluations++;
       }
@@ -202,5 +198,5 @@
           current[swap.Index1] = current[swap.Index2];
           current[swap.Index2] = h;
-          var q = eval(current, random);
+          var q = eval(current, token);
           evaluations++;
           if (FitnessComparer.IsBetter(maximization, q, quality)) {
@@ -261,13 +257,13 @@
     }
 
-    public int TabuWalkShift(IRandom random, Encodings.PermutationEncoding.Permutation perm, Func<Encodings.PermutationEncoding.Permutation, IRandom, double> eval, ref double quality, int maxEvals = int.MaxValue, bool[,] subspace = null) {
+    public int TabuWalkShift(IRandom random, Encodings.PermutationEncoding.Permutation perm, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval, CancellationToken token, ref double quality, int maxEvals = int.MaxValue, bool[,] subspace = null) {
       return 0;
     }
 
-    public int TabuWalkOpt(IRandom random, Encodings.PermutationEncoding.Permutation perm, Func<Encodings.PermutationEncoding.Permutation, IRandom, double> eval, ref double quality, int maxEvals = int.MaxValue, bool[,] subspace = null) {
-      var maximization = Context.Problem.Maximization;
+    public int TabuWalkOpt(IRandom random, Encodings.PermutationEncoding.Permutation perm, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval, CancellationToken token, ref double quality, int maxEvals = int.MaxValue, bool[,] subspace = null) {
+      var maximization = Context.Maximization;
       var evaluations = 0;
       if (double.IsNaN(quality)) {
-        quality = eval(perm, random);
+        quality = eval(perm, token);
         evaluations++;
       }
@@ -303,5 +299,5 @@
           InversionManipulator.Apply(current, opt.Index1, opt.Index2);
 
-          var q = eval(current, random);
+          var q = eval(current, token);
           evaluations++;
           if (FitnessComparer.IsBetter(maximization, q, quality)) {
@@ -414,6 +410,6 @@
           continue;
         }
-        var probe = ToScope(c);
-        Evaluate(probe, token);
+        var probe = Context.ToScope(c);
+        Context.Evaluate(probe, token);
         evaluations++;
         cache.Add(c);
@@ -425,5 +421,5 @@
       }
       Context.IncrementEvaluatedSolutions(evaluations);
-      return offspring;
+      return offspring ?? p1;
     }
 
@@ -449,6 +445,6 @@
           continue;
         }
-        var probe = ToScope(c);
-        Evaluate(probe, token);
+        var probe = Context.ToScope(c);
+        Context.Evaluate(probe, token);
         evaluations++;
         cache.Add(c);
@@ -460,5 +456,5 @@
       }
       Context.IncrementEvaluatedSolutions(evaluations);
-      return offspring;
+      return offspring ?? p1;
     }
 
@@ -484,6 +480,6 @@
           continue;
         }
-        var probe = ToScope(c);
-        Evaluate(probe, token);
+        var probe = Context.ToScope(c);
+        Context.Evaluate(probe, token);
         evaluations++;
         cache.Add(c);
@@ -495,28 +491,27 @@
       }
       Context.IncrementEvaluatedSolutions(evaluations);
-      return offspring;
+      return offspring ?? p1;
     }
 
     protected override ISingleObjectiveSolutionScope<Encodings.PermutationEncoding.Permutation> Link(ISingleObjectiveSolutionScope<Encodings.PermutationEncoding.Permutation> a, ISingleObjectiveSolutionScope<Encodings.PermutationEncoding.Permutation> b, CancellationToken token, bool delink = false) {
-      var wrapper = new EvaluationWrapper<Encodings.PermutationEncoding.Permutation>(Problem, ToScope(null));
       double quality;
-      return ToScope(Relink(Context.Random, a.Solution, b.Solution, wrapper.Evaluate, delink, out quality));
-    }
-
-    public Encodings.PermutationEncoding.Permutation Relink(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, IRandom, double> eval, bool delink, out double best) {
+      return Context.ToScope(Relink(Context.Random, a.Solution, b.Solution, Context.Evaluate, token, delink, out quality));
+    }
+
+    public Encodings.PermutationEncoding.Permutation Relink(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval, CancellationToken token, bool delink, out double best) {
       if (p1.PermutationType != p2.PermutationType) throw new ArgumentException(string.Format("Unequal permutation types {0} and {1}", p1.PermutationType, p2.PermutationType));
       switch (p1.PermutationType) {
         case PermutationTypes.Absolute:
-          return delink ? DelinkSwap(random, p1, p2, eval, out best) : RelinkSwap(random, p1, p2, eval, out best);
+          return delink ? DelinkSwap(random, p1, p2, eval, token, out best) : RelinkSwap(random, p1, p2, eval, token, out best);
         case PermutationTypes.RelativeDirected:
-          return RelinkShift(random, p1, p2, eval, delink, out best);
+          return RelinkShift(random, p1, p2, eval, token, delink, out best);
         case PermutationTypes.RelativeUndirected:
-          return RelinkOpt(random, p1, p2, eval, delink, out best);
+          return RelinkOpt(random, p1, p2, eval, token, delink, out best);
         default: throw new ArgumentException(string.Format("Unknown permutation type {0}", p1.PermutationType));
       }
     }
 
-    public Encodings.PermutationEncoding.Permutation RelinkSwap(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, IRandom, double> eval, out double best) {
-      var maximization = Context.Problem.Maximization;
+    public Encodings.PermutationEncoding.Permutation RelinkSwap(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval, CancellationToken token, out double best) {
+      var maximization = Context.Maximization;
       var evaluations = 0;
       var child = (Encodings.PermutationEncoding.Permutation)p1.Clone();
@@ -540,5 +535,5 @@
           }
           Swap(child, invChild[p2[idx]], idx);
-          var moveF = eval(child, random);
+          var moveF = eval(child, token);
           evaluations++;
           if (FitnessComparer.IsBetter(maximization, moveF, bestChange)) {
@@ -565,5 +560,5 @@
       }
       if (bestChild == null) {
-        best = eval(child, random);
+        best = eval(child, token);
         evaluations++;
       }
@@ -576,6 +571,6 @@
     }
 
-    public Encodings.PermutationEncoding.Permutation DelinkSwap(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, IRandom, double> eval, out double best) {
-      var maximization = Context.Problem.Maximization;
+    public Encodings.PermutationEncoding.Permutation DelinkSwap(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval, CancellationToken token, out double best) {
+      var maximization = Context.Maximization;
       var evaluations = 0;
       var child = (Encodings.PermutationEncoding.Permutation)p1.Clone();
@@ -600,5 +595,5 @@
             if (k == idx) continue;
             Swap(child, k, idx);
-            var moveF = eval(child, random);
+            var moveF = eval(child, token);
             evaluations++;
             if (FitnessComparer.IsBetter(maximization, moveF, bestChange)) {
@@ -624,5 +619,5 @@
       }
       if (bestChild == null) {
-        best = eval(child, random);
+        best = eval(child, token);
         evaluations++;
       }
@@ -634,6 +629,6 @@
     }
 
-    public Encodings.PermutationEncoding.Permutation RelinkShift(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, IRandom, double> eval, bool delink, out double best) {
-      var maximization = Context.Problem.Maximization;
+    public Encodings.PermutationEncoding.Permutation RelinkShift(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval, CancellationToken token, bool delink, out double best) {
+      var maximization = Context.Maximization;
       var evaluations = 0;
       var child = (Encodings.PermutationEncoding.Permutation)p1.Clone();
@@ -656,5 +651,5 @@
           if (c < n) Shift(child, from: n, to: c + 1);
           else Shift(child, from: c, to: n);
-          var moveF = eval(child, random);
+          var moveF = eval(child, token);
           evaluations++;
           if (FitnessComparer.IsBetter(maximization, moveF, bestChange)) {
@@ -678,5 +673,5 @@
 
       if (bestChild == null) {
-        best = eval(child, random);
+        best = eval(child, token);
         evaluations++;
       }
@@ -689,6 +684,6 @@
     }
 
-    public Encodings.PermutationEncoding.Permutation RelinkOpt(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, IRandom, double> eval, bool delink, out double best) {
-      var maximization = Context.Problem.Maximization;
+    public Encodings.PermutationEncoding.Permutation RelinkOpt(IRandom random, Encodings.PermutationEncoding.Permutation p1, Encodings.PermutationEncoding.Permutation p2, Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval, CancellationToken token, bool delink, out double best) {
+      var maximization = Context.Maximization;
       var evaluations = 0;
       var child = (Encodings.PermutationEncoding.Permutation)p1.Clone();
@@ -766,5 +761,5 @@
             undoStack.Push(m);
           }
-          var moveF = eval(child, random);
+          var moveF = eval(child, token);
           evaluations++;
           if (FitnessComparer.IsBetter(maximization, moveF, bestChange)) {
@@ -792,5 +787,5 @@
 
       if (bestChild == null) {
-        best = eval(child, random);
+        best = eval(child, token);
         evaluations++;
       }
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/PermutationMemPRContext.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/PermutationMemPRContext.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/PermutationMemPRContext.cs	(revision 14552)
@@ -20,4 +20,6 @@
 #endregion
 
+using System;
+using System.Runtime.Remoting.Contexts;
 using HeuristicLab.Algorithms.MemPR.Interfaces;
 using HeuristicLab.Common;
@@ -31,5 +33,5 @@
   [Item("MemPR Population Context (permutation)", "MemPR population context for permutation encoded problems.")]
   [StorableClass]
-  public sealed class PermutationMemPRPopulationContext : MemPRPopulationContext<SingleObjectiveBasicProblem<PermutationEncoding>, Encodings.PermutationEncoding.Permutation, PermutationMemPRPopulationContext, PermutationMemPRSolutionContext> {
+  public sealed class PermutationMemPRPopulationContext : MemPRPopulationContext<ISingleObjectiveHeuristicOptimizationProblem, Encodings.PermutationEncoding.Permutation, PermutationMemPRPopulationContext, PermutationMemPRSolutionContext> {
 
     [StorableConstructor]
@@ -47,9 +49,17 @@
       return new PermutationMemPRSolutionContext(this, solution);
     }
+
+    public override ISingleObjectiveSolutionScope<Encodings.PermutationEncoding.Permutation> ToScope(Encodings.PermutationEncoding.Permutation code, double fitness = double.NaN) {
+      var creator = Problem.SolutionCreator as IPermutationCreator;
+      if (creator == null) throw new InvalidOperationException("Can only solve binary encoded problems with MemPR (binary)");
+      return new SingleObjectiveSolutionScope<Encodings.PermutationEncoding.Permutation>(code, creator.PermutationParameter.ActualName, fitness, Problem.Evaluator.QualityParameter.ActualName) {
+        Parent = Scope
+      };
+    }
   }
 
   [Item("MemPR Solution Context (permutation)", "MemPR solution context for permutation encoded problems.")]
   [StorableClass]
-  public sealed class PermutationMemPRSolutionContext : MemPRSolutionContext<SingleObjectiveBasicProblem<PermutationEncoding>, Encodings.PermutationEncoding.Permutation, PermutationMemPRPopulationContext, PermutationMemPRSolutionContext>, IPermutationSubspaceContext {
+  public sealed class PermutationMemPRSolutionContext : MemPRSolutionContext<ISingleObjectiveHeuristicOptimizationProblem, Encodings.PermutationEncoding.Permutation, PermutationMemPRPopulationContext, PermutationMemPRSolutionContext>, IPermutationSubspaceContext {
 
     [Storable]
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/SolutionModel/Univariate/BiasedModelTrainer.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/SolutionModel/Univariate/BiasedModelTrainer.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/SolutionModel/Univariate/BiasedModelTrainer.cs	(revision 14552)
@@ -34,6 +34,6 @@
   [StorableClass]
   public class BiasedModelTrainer<TContext> : ParameterizedNamedItem, ISolutionModelTrainer<TContext>
-    where TContext : IPopulationBasedHeuristicAlgorithmContext<SingleObjectiveBasicProblem<PermutationEncoding>, Encodings.PermutationEncoding.Permutation>,
-    ISolutionModelContext<Encodings.PermutationEncoding.Permutation> {
+    where TContext : IPopulationBasedHeuristicAlgorithmContext<ISingleObjectiveHeuristicOptimizationProblem, Encodings.PermutationEncoding.Permutation>,
+    ISolutionModelContext<Encodings.PermutationEncoding.Permutation>, IEvaluationServiceContext<Encodings.PermutationEncoding.Permutation> {
 
     [Storable]
@@ -59,5 +59,5 @@
 
     public void TrainModel(TContext context) {
-      context.Model = Trainer.TrainBiased(ModelBias, context.Random, context.Problem.Maximization, context.Population.Select(x => x.Solution).ToList(), context.Population.Select(x => x.Fitness).ToList(), context.Problem.Encoding.Length);
+      context.Model = Trainer.TrainBiased(ModelBias, context.Random, context.Maximization, context.Population.Select(x => x.Solution).ToList(), context.Population.Select(x => x.Fitness).ToList(), context.Population.First().Solution.Length);
     }
   }
Index: /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/SolutionModel/Univariate/UnbiasedModelTrainer.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/SolutionModel/Univariate/UnbiasedModelTrainer.cs	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Permutation/SolutionModel/Univariate/UnbiasedModelTrainer.cs	(revision 14552)
@@ -33,5 +33,5 @@
   [StorableClass]
   public class UnbiasedModelTrainer<TContext> : NamedItem, ISolutionModelTrainer<TContext>
-    where TContext : IPopulationBasedHeuristicAlgorithmContext<SingleObjectiveBasicProblem<PermutationEncoding>, Encodings.PermutationEncoding.Permutation>,
+    where TContext : IPopulationBasedHeuristicAlgorithmContext<ISingleObjectiveHeuristicOptimizationProblem, Encodings.PermutationEncoding.Permutation>,
     ISolutionModelContext<Encodings.PermutationEncoding.Permutation> {
     
@@ -49,5 +49,5 @@
 
     public void TrainModel(TContext context) {
-      context.Model = Trainer.TrainUnbiased(context.Random, context.Population.Select(x => x.Solution).ToList(), context.Problem.Encoding.Length);
+      context.Model = Trainer.TrainUnbiased(context.Random, context.Population.Select(x => x.Solution).ToList(), context.Population.First().Solution.Length);
     }
   }
Index: anches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Util/EvaluationWrapper.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/Util/EvaluationWrapper.cs	(revision 14551)
+++ 	(revision )
@@ -1,50 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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.Algorithms.MemPR.Interfaces;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Optimization;
-
-namespace HeuristicLab.Algorithms.MemPR.Util {
-  public sealed class EvaluationWrapper<TSolution>
-      where TSolution : class, IItem {
-    private readonly ISingleObjectiveProblemDefinition problem;
-    private readonly ISingleObjectiveSolutionScope<TSolution> scope;
-    private readonly SingleEncodingIndividual individual;
-
-    public EvaluationWrapper(ISingleObjectiveProblemDefinition problem, ISingleObjectiveSolutionScope<TSolution> solution) {
-      this.problem = problem;
-      this.scope = (ISingleObjectiveSolutionScope<TSolution>)solution.Clone();
-      this.individual = new SingleEncodingIndividual(problem.Encoding, this.scope);
-    }
-
-    public double Evaluate(TSolution b) {
-      scope.Solution = b;
-      return problem.Evaluate(individual, null);
-    }
-
-    public double Evaluate(TSolution b, IRandom random) {
-      scope.Solution = b;
-      return problem.Evaluate(individual, random);
-    }
-  }
-}
Index: /branches/MemPRAlgorithm/HeuristicLab.Problems.Binary/3.3/AlternatingBitsProblem.cs
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Problems.Binary/3.3/AlternatingBitsProblem.cs	(revision 14552)
+++ /branches/MemPRAlgorithm/HeuristicLab.Problems.Binary/3.3/AlternatingBitsProblem.cs	(revision 14552)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.BinaryVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Binary {
+  [Item("Alternating Bits Problem", "Represents a problem whose objective is to achieve an alternating sequence of bits, long sequences of consecutive bits receive a penalty.")]
+  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 220)]
+  [StorableClass]
+  public class AlternatingBitsProblem : BinaryProblem {
+    public override bool Maximization {
+      get { return false; }
+    }
+
+    public AlternatingBitsProblem()
+      : base() {
+      Encoding.Length = 256;
+      BestKnownQuality = 0;
+    }
+
+    [StorableConstructor]
+    protected AlternatingBitsProblem(bool deserializing) : base(deserializing) { }
+    protected AlternatingBitsProblem(AlternatingBitsProblem original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AlternatingBitsProblem(this, cloner);
+    }
+
+    public override double Evaluate(BinaryVector vector, IRandom random) {
+      var quality = 0.0;
+      var curr = vector[0];
+      var lastOk = 0;
+      for (var i = 1; i < vector.Length; i++) {
+        if (curr && !vector[i] || !curr && vector[i]) {
+          lastOk = i;
+        } else quality += (i - lastOk);
+        curr = vector[i];
+      }
+      return quality;
+    }
+  }
+}
Index: /branches/MemPRAlgorithm/HeuristicLab.Problems.Binary/3.3/HeuristicLab.Problems.Binary-3.3.csproj
===================================================================
--- /branches/MemPRAlgorithm/HeuristicLab.Problems.Binary/3.3/HeuristicLab.Problems.Binary-3.3.csproj	(revision 14551)
+++ /branches/MemPRAlgorithm/HeuristicLab.Problems.Binary/3.3/HeuristicLab.Problems.Binary-3.3.csproj	(revision 14552)
@@ -87,4 +87,5 @@
     <Compile Include="HIFFProblem.cs" />
     <Compile Include="BinaryKnapsackProblem.cs" />
+    <Compile Include="AlternatingBitsProblem.cs" />
     <Compile Include="OneMaxProblem.cs" />
     <Compile Include="Plugin.cs" />
