Index: branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/EvaluationTracker.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/EvaluationTracker.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/EvaluationTracker.cs	(revision 17363)
@@ -23,4 +23,5 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading;
 using HEAL.Attic;
@@ -110,4 +111,12 @@
     }
 
+    public void Evaluate(ISingleObjectiveSolutionContext<BinaryVector> solutionContext, IRandom random) {
+      Evaluate(solutionContext, random, CancellationToken.None);
+    }
+    public void Evaluate(ISingleObjectiveSolutionContext<BinaryVector> solutionContext, IRandom random, CancellationToken cancellationToken) {
+      double quality = Evaluate(solutionContext.EncodedSolution, random, cancellationToken);
+      solutionContext.EvaluationResult = new SingleObjectiveEvaluationResult(quality);
+    }
+
     public bool Maximization {
       get {
@@ -125,7 +134,16 @@
     }
 
+    public void Analyze(ISingleObjectiveSolutionContext<BinaryVector>[] solutionContexts, ResultCollection results, IRandom random) {
+      var solutions = solutionContexts.Select(c => c.EncodedSolution).ToArray();
+      var qualities = solutionContexts.Select(c => c.EvaluationResult.Quality).ToArray();
+      Analyze(solutions, qualities, results, random);
+    }
+
     public IEnumerable<BinaryVector> GetNeighbors(BinaryVector individual, IRandom random) {
       return problem.GetNeighbors(individual, random);
     }
+    public IEnumerable<ISingleObjectiveSolutionContext<BinaryVector>> GetNeighbors(ISingleObjectiveSolutionContext<BinaryVector> solutionContext, IRandom random) {
+      return GetNeighbors(solutionContext.EncodedSolution, random).Select(n => new SingleObjectiveSolutionContext<BinaryVector>(n));
+    }
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISingleObjectiveProblemDefinition.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISingleObjectiveProblemDefinition.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISingleObjectiveProblemDefinition.cs	(revision 17363)
@@ -39,7 +39,12 @@
     double Evaluate(TEncodedSolution solution, IRandom random);
     double Evaluate(TEncodedSolution solution, IRandom random, CancellationToken cancellationToken);
+    void Evaluate(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random);
+    void Evaluate(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random, CancellationToken cancellationToken);
 
     void Analyze(TEncodedSolution[] solutions, double[] qualities, ResultCollection results, IRandom random);
+    void Analyze(ISingleObjectiveSolutionContext<TEncodedSolution>[] solutionContexts, ResultCollection results, IRandom random);
+
     IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution solution, IRandom random);
+    IEnumerable<ISingleObjectiveSolutionContext<TEncodedSolution>> GetNeighbors(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random);
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISolutionContext.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISolutionContext.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISolutionContext.cs	(revision 17363)
@@ -24,4 +24,5 @@
 
 namespace HeuristicLab.Optimization {
+  //TODO discuss renaming to solution scope?
   [StorableType("383A35EB-03C9-473D-A20B-EE34E00BC174")]
   public interface ISolutionContext : IItem {
@@ -36,11 +37,19 @@
   }
 
-  public interface ISingleObjectiveSolutionContext : ISolutionContext {
-    //TODO discuss with abeham hiding of base property
-    new ISingleObjectiveEvaluationResult EvaluationResult { get; }
+  public interface ISolutionContext<TEncodedSolution> : ISolutionContext
+    where TEncodedSolution : class, IEncodedSolution {
+    new TEncodedSolution EncodedSolution { get; }
   }
 
-  public interface IMultiObjectiveSolutionContext : ISolutionContext {
-    new IMultiObjectiveEvaluationResult EvaluationResult { get; }
+
+  public interface ISingleObjectiveSolutionContext<TEncodedSolution> : ISolutionContext<TEncodedSolution>
+    where TEncodedSolution : class, IEncodedSolution {
+    //TODO discuss with abeham hiding of base property
+    new ISingleObjectiveEvaluationResult EvaluationResult { get; set; }
+  }
+
+  public interface IMultiObjectiveSolutionContext<TEncodedSolution> : ISolutionContext<TEncodedSolution>
+    where TEncodedSolution : class, IEncodedSolution {
+    new IMultiObjectiveEvaluationResult EvaluationResult { get; set; }
   }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/INeighborBasedOperator.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/INeighborBasedOperator.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/INeighborBasedOperator.cs	(revision 17363)
@@ -29,5 +29,5 @@
   internal interface INeighborBasedOperator<TEncodedSolution> : IEncodingOperator<TEncodedSolution>
   where TEncodedSolution : class, IEncodedSolution {
-    Func<TEncodedSolution, IRandom, IEnumerable<TEncodedSolution>> GetNeighborsFunc { get; set; }
+    Func<ISingleObjectiveSolutionContext<TEncodedSolution>, IRandom, IEnumerable<ISingleObjectiveSolutionContext<TEncodedSolution>>> GetNeighbors { get; set; }
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveAnalysisOperator.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveAnalysisOperator.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveAnalysisOperator.cs	(revision 17363)
@@ -21,6 +21,6 @@
 
 using System;
+using HEAL.Attic;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Optimization {
@@ -28,5 +28,5 @@
   internal interface ISingleObjectiveAnalysisOperator<TEncodedSolution> : IEncodingOperator<TEncodedSolution>, ISingleObjectiveOperator
   where TEncodedSolution : class, IEncodedSolution {
-    Action<TEncodedSolution[], double[], ResultCollection, IRandom> AnalyzeAction { get; set; }
+    Action<ISingleObjectiveSolutionContext<TEncodedSolution>[], ResultCollection, IRandom> Analyze { get; set; }
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveEvaluationOperator.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveEvaluationOperator.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveEvaluationOperator.cs	(revision 17363)
@@ -21,6 +21,6 @@
 
 using System;
+using HEAL.Attic;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Optimization {
@@ -28,5 +28,5 @@
   internal interface ISingleObjectiveEvaluationOperator<TEncodedSolution> : ISingleObjectiveEvaluator, IEncodingOperator<TEncodedSolution>
   where TEncodedSolution : class, IEncodedSolution {
-    Func<TEncodedSolution, IRandom, double> EvaluateFunc { get; set; }
+    Action<ISingleObjectiveSolutionContext<TEncodedSolution>, IRandom> Evaluate { get; set; }
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISolutionScope.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISolutionScope.cs	(revision 17363)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISolutionScope.cs	(revision 17363)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Optimization {
+  [StorableType("E019F914-0D0C-4668-970F-0EAE4A270038")]
+  interface ISolutionScope : IScope, ISolutionContext { }
+
+  [StorableType("E8A9C9B5-19E4-424B-8125-9732C76AA17C")]
+  interface ISingleObjectiveSolutionScope<TEncodedSolution> : ISolutionScope, ISingleObjectiveSolutionContext<TEncodedSolution>
+      where TEncodedSolution : class, IEncodedSolution { }
+
+  [StorableType("14F7D2BD-83CE-40FC-B389-68D23A8E544B")]
+  interface IMultiObjectiveSolutionScope<TEncodedSolution> : ISolutionScope, IMultiObjectiveSolutionContext<TEncodedSolution>
+      where TEncodedSolution : class, IEncodedSolution { }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveAnalyzer.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveAnalyzer.cs	(revision 17363)
@@ -53,5 +53,5 @@
     }
 
-    public Action<TEncodedSolution[], double[], ResultCollection, IRandom> AnalyzeAction { get; set; }
+    public Action<ISingleObjectiveSolutionContext<TEncodedSolution>[], ResultCollection, IRandom> Analyze { get; set; }
 
     [StorableConstructor]
@@ -78,6 +78,13 @@
         scopes = scopes.Select(x => (IEnumerable<IScope>)x.SubScopes).Aggregate((a, b) => a.Concat(b));
 
-      var individuals = scopes.Select(s => ScopeUtil.GetEncodedSolution(s, encoding)).ToArray();
-      AnalyzeAction(individuals, QualityParameter.ActualValue.Select(x => x.Value).ToArray(), results, random);
+      var solutionContexts = scopes.Select(scope => {
+        var solution = ScopeUtil.GetEncodedSolution(scope, encoding);
+        var quality = ((DoubleValue)scope.Variables[QualityParameter.ActualName].Value).Value;
+        var solutionContext = new SingleObjectiveSolutionContextScope<TEncodedSolution>(scope, solution);
+        solutionContext.EvaluationResult = new SingleObjectiveEvaluationResult(quality);
+        return solutionContext;
+      }).ToArray();
+
+      Analyze(solutionContexts, results, random);
       return base.Apply();
     }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveEvaluator.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveEvaluator.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveEvaluator.cs	(revision 17363)
@@ -46,5 +46,5 @@
     }
 
-    public Func<TEncodedSolution, IRandom, double> EvaluateFunc { get; set; }
+    public Action<ISingleObjectiveSolutionContext<TEncodedSolution>, IRandom> Evaluate { get; set; }
 
     [StorableConstructor]
@@ -63,5 +63,10 @@
       var encoding = EncodingParameter.ActualValue;
       var solution = ScopeUtil.GetEncodedSolution(ExecutionContext.Scope, encoding);
-      QualityParameter.ActualValue = new DoubleValue(EvaluateFunc(solution, random));
+      var solutionContext = new SingleObjectiveSolutionContextScope<TEncodedSolution>(ExecutionContext.Scope, solution);
+
+      Evaluate(solutionContext, random);
+      var qualityValue = solutionContext.EvaluationResult.Quality;
+
+      QualityParameter.ActualValue = new DoubleValue(qualityValue);
       return base.InstrumentedApply();
     }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveImprover.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveImprover.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveImprover.cs	(revision 17363)
@@ -63,6 +63,6 @@
     }
 
-    public Func<TEncodedSolution, IRandom, double> EvaluateFunc { get; set; }
-    public Func<TEncodedSolution, IRandom, IEnumerable<TEncodedSolution>> GetNeighborsFunc { get; set; }
+    public Action<ISingleObjectiveSolutionContext<TEncodedSolution>, IRandom> Evaluate { get; set; }
+    public Func<ISingleObjectiveSolutionContext<TEncodedSolution>, IRandom, IEnumerable<ISingleObjectiveSolutionContext<TEncodedSolution>>> GetNeighbors { get; set; }
 
     [StorableConstructor]
@@ -90,5 +90,12 @@
       var sampleSize = SampleSizeParameter.ActualValue.Value;
       var solution = ScopeUtil.GetEncodedSolution(ExecutionContext.Scope, encoding);
-      var quality = QualityParameter.ActualValue == null ? EvaluateFunc(solution, random) : QualityParameter.ActualValue.Value;
+      var solutionContext = new SingleObjectiveSolutionContextScope<TEncodedSolution>(ExecutionContext.Scope, solution);
+
+      double quality;
+      if (QualityParameter.ActualValue == null) {
+        if (!solutionContext.IsEvaluated) Evaluate(solutionContext, random);
+
+        quality = solutionContext.EvaluationResult.Quality;
+      } else quality = QualityParameter.ActualValue.Value;
 
       var count = 0;
@@ -96,9 +103,10 @@
         TEncodedSolution best = default(TEncodedSolution);
         var bestQuality = quality;
-        foreach (var neighbor in GetNeighborsFunc(solution, random).Take(sampleSize)) {
-          var q = EvaluateFunc(neighbor, random);
+        foreach (var neighbor in GetNeighbors(solutionContext, random).Take(sampleSize)) {
+          Evaluate(neighbor, random);
+          var q = neighbor.EvaluationResult.Quality;
           count++;
           if (maximize && bestQuality > q || !maximize && bestQuality < q) continue;
-          best = neighbor;
+          best = neighbor.EncodedSolution;
           bestQuality = q;
         }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveEvaluator.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveEvaluator.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveEvaluator.cs	(revision 17363)
@@ -50,5 +50,5 @@
     }
 
-    public Func<TEncodedSolution, IRandom, double> EvaluateFunc { get; set; }
+    public Action<ISingleObjectiveSolutionContext<TEncodedSolution>, IRandom> Evaluate { get; set; }
 
     [StorableConstructor]
@@ -69,6 +69,11 @@
       var random = RandomParameter.ActualValue;
       var encoding = EncodingParameter.ActualValue;
-      var individual = ScopeUtil.GetEncodedSolution(ExecutionContext.Scope, encoding);
-      MoveQualityParameter.ActualValue = new DoubleValue(EvaluateFunc(individual, random));
+      var solution = ScopeUtil.GetEncodedSolution(ExecutionContext.Scope, encoding);
+      var solutionContext = new SingleObjectiveSolutionContextScope<TEncodedSolution>(ExecutionContext.Scope, solution);
+
+      Evaluate(solutionContext, random);
+      var qualityValue = solutionContext.EvaluationResult.Quality;
+
+      MoveQualityParameter.ActualValue = new DoubleValue(qualityValue);
       return base.Apply();
     }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveGenerator.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveGenerator.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveGenerator.cs	(revision 17363)
@@ -48,5 +48,5 @@
     }
 
-    public Func<TEncodedSolution, IRandom, IEnumerable<TEncodedSolution>> GetNeighborsFunc { get; set; }
+    public Func<ISingleObjectiveSolutionContext<TEncodedSolution>, IRandom, IEnumerable<ISingleObjectiveSolutionContext<TEncodedSolution>>> GetNeighbors { get; set; }
 
     [StorableConstructor]
@@ -69,10 +69,11 @@
       var encoding = EncodingParameter.ActualValue;
       var solution = ScopeUtil.GetEncodedSolution(ExecutionContext.Scope, encoding);
-      var nbhood = GetNeighborsFunc(solution, random).Take(sampleSize).ToList();
+      var solutionContext = new SingleObjectiveSolutionContextScope<TEncodedSolution>(ExecutionContext.Scope, solution);
 
+      var nbhood = GetNeighbors(solutionContext, random).Take(sampleSize).ToList();
       var moveScopes = new Scope[nbhood.Count];
       for (int i = 0; i < moveScopes.Length; i++) {
         moveScopes[i] = new Scope(i.ToString(CultureInfo.InvariantCulture.NumberFormat));
-        ScopeUtil.CopyEncodedSolutionToScope(moveScopes[i], encoding, nbhood[i]);
+        ScopeUtil.CopyEncodedSolutionToScope(moveScopes[i], encoding, nbhood[i].EncodedSolution);
       }
       ExecutionContext.Scope.SubScopes.AddRange(moveScopes);
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SolutionContextScope.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SolutionContextScope.cs	(revision 17363)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SolutionContextScope.cs	(revision 17363)
@@ -0,0 +1,92 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+
+using System;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+//TODO: don't derive from NamedItem, this has been done to have a fast working prototype
+namespace HeuristicLab.Optimization {
+  internal class SolutionContextScope<TEncodedSolution> : SolutionContext<TEncodedSolution>, ISolutionScope
+   where TEncodedSolution : class, IEncodedSolution {
+    private readonly IScope scope;
+
+    public SolutionContextScope(IScope scope, TEncodedSolution solution) : base(solution) {
+      this.scope = scope;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      throw new NotSupportedException();
+    }
+
+    IScope IScope.Parent {
+      get { return scope.Parent; }
+      set { throw new NotSupportedException(); }
+    }
+
+    VariableCollection IScope.Variables => scope.Variables;
+    ScopeList IScope.SubScopes => scope.SubScopes;
+
+    void IScope.Clear() { throw new NotImplementedException(); }
+
+
+
+    #region INamedItem members
+    string INamedItem.Name { get { return scope.Name; } set => throw new NotImplementedException(); }
+    bool INamedItem.CanChangeName => false;
+
+    string INamedItem.Description { get { return scope.Description; } set => throw new NotImplementedException(); }
+    bool INamedItem.CanChangeDescription => false;
+
+    event EventHandler<CancelEventArgs<string>> INamedItem.NameChanging {
+      add { throw new NotImplementedException(); }
+      remove { throw new NotImplementedException(); }
+    }
+
+    event EventHandler INamedItem.NameChanged {
+      add { throw new NotImplementedException(); }
+      remove { throw new NotImplementedException(); }
+    }
+
+    event EventHandler INamedItem.DescriptionChanged {
+      add { throw new NotImplementedException(); }
+      remove { throw new NotImplementedException(); }
+    }
+    #endregion
+  }
+
+  internal class SingleObjectiveSolutionContextScope<TEncodedSolution> : SolutionContextScope<TEncodedSolution>, ISingleObjectiveSolutionScope<TEncodedSolution>
+    where TEncodedSolution : class, IEncodedSolution {
+
+    public new ISingleObjectiveEvaluationResult EvaluationResult { get; set; }
+    public SingleObjectiveSolutionContextScope(IScope scope, TEncodedSolution solution) : base(scope, solution) {
+    }
+  }
+
+  internal class MultiObjectiveSolutionContextScope<TEncodedSolution> : SolutionContextScope<TEncodedSolution>, IMultiObjectiveSolutionScope<TEncodedSolution>
+  where TEncodedSolution : class, IEncodedSolution {
+
+    public new IMultiObjectiveEvaluationResult EvaluationResult { get; set; }
+    public MultiObjectiveSolutionContextScope(IScope scope, TEncodedSolution solution) : base(scope, solution) {
+    }
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveProblem.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveProblem.cs	(revision 17363)
@@ -117,8 +117,28 @@
     }
     public abstract double Evaluate(TEncodedSolution solution, IRandom random, CancellationToken cancellationToken);
+
+    public virtual void Evaluate(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random) {
+      Evaluate(solutionContext, random, CancellationToken.None);
+    }
+    public virtual void Evaluate(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random, CancellationToken cancellationToken) {
+      double quality = Evaluate(solutionContext.EncodedSolution, random, cancellationToken);
+      solutionContext.EvaluationResult = new SingleObjectiveEvaluationResult(quality);
+    }
+
     public virtual void Analyze(TEncodedSolution[] solutions, double[] qualities, ResultCollection results, IRandom random) { }
-    public virtual IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution solution, IRandom random) {
+    public virtual void Analyze(ISingleObjectiveSolutionContext<TEncodedSolution>[] solutionContexts, ResultCollection results, IRandom random) {
+      var solutions = solutionContexts.Select(c => c.EncodedSolution).ToArray();
+      var qualities = solutionContexts.Select(c => c.EvaluationResult.Quality).ToArray();
+      Analyze(solutions, qualities, results, random);
+    }
+
+    public virtual IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution solutions, IRandom random) {
       return Enumerable.Empty<TEncodedSolution>();
     }
+    public virtual IEnumerable<ISingleObjectiveSolutionContext<TEncodedSolution>> GetNeighbors(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random) {
+      return GetNeighbors(solutionContext.EncodedSolution, random).Select(n => new SingleObjectiveSolutionContext<TEncodedSolution>(n));
+    }
+
+
 
     public static bool IsBetter(bool maximization, double quality, double bestQuality) {
@@ -130,4 +150,5 @@
     }
 
+    //TODO refactor to solution contexts
     protected Tuple<TEncodedSolution, double> GetBestSolution(TEncodedSolution[] solutions, double[] qualities) {
       return GetBestSolution(solutions, qualities, Maximization);
@@ -170,9 +191,9 @@
     private void ParameterizeOperators() {
       foreach (var op in Operators.OfType<ISingleObjectiveEvaluationOperator<TEncodedSolution>>())
-        op.EvaluateFunc = Evaluate;
+        op.Evaluate = Evaluate;
       foreach (var op in Operators.OfType<ISingleObjectiveAnalysisOperator<TEncodedSolution>>())
-        op.AnalyzeAction = Analyze;
+        op.Analyze = Analyze;
       foreach (var op in Operators.OfType<INeighborBasedOperator<TEncodedSolution>>())
-        op.GetNeighborsFunc = GetNeighbors;
+        op.GetNeighbors = GetNeighbors;
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/SolutionContext.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/SolutionContext.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/BasicProblems/SolutionContext.cs	(revision 17363)
@@ -30,11 +30,14 @@
 namespace HeuristicLab.Optimization {
   [StorableType("72638F28-11DD-440D-B7A2-79E16E0EFB83")]
-  public abstract class SolutionContext : Item {
+  public abstract class SolutionContext<TEncodedSolution> : Item, ISolutionContext
+    where TEncodedSolution : class, IEncodedSolution {
 
     [Storable]
     private readonly Dictionary<string, object> data = new Dictionary<string, object>();
 
+    IEncodedSolution ISolutionContext.EncodedSolution { get { return EncodedSolution; } }
+
     [Storable]
-    public IEncodedSolution EncodedSolution { get; private set; }
+    public TEncodedSolution EncodedSolution { get; private set; }
 
     [Storable]
@@ -43,9 +46,9 @@
     public bool IsEvaluated => EvaluationResult != null;
 
-    protected SolutionContext(IEncodedSolution encodedSolution) : base() {
+    protected SolutionContext(TEncodedSolution encodedSolution) : base() {
       EncodedSolution = encodedSolution ?? throw new ArgumentNullException("encodedSolution");
     }
 
-    protected SolutionContext(IEncodedSolution encodedSolution, IEvaluationResult evaluationResult) : this(encodedSolution) {
+    protected SolutionContext(TEncodedSolution encodedSolution, IEvaluationResult evaluationResult) : this(encodedSolution) {
       EvaluationResult = evaluationResult ?? throw new ArgumentNullException("evaluationResult");
     }
@@ -54,5 +57,5 @@
     protected SolutionContext(StorableConstructorFlag _) : base(_) { }
 
-    public SolutionContext(SolutionContext original, Cloner cloner) : base(original, cloner) {
+    public SolutionContext(SolutionContext<TEncodedSolution> original, Cloner cloner) : base(original, cloner) {
       //TODO clone data dictionary
       EncodedSolution = cloner.Clone(original.EncodedSolution);
@@ -69,40 +72,42 @@
 
   [StorableType("DF6DA9C9-7EF4-4DC3-9855-6C43BDEDD735")]
-  public class SingleObjectiveSolutionContext : SolutionContext, ISingleObjectiveSolutionContext {
+  public class SingleObjectiveSolutionContext<TEncodedSolution> : SolutionContext<TEncodedSolution>, ISingleObjectiveSolutionContext<TEncodedSolution>
+   where TEncodedSolution : class, IEncodedSolution {
     public new ISingleObjectiveEvaluationResult EvaluationResult { get; set; }
 
-    public SingleObjectiveSolutionContext(IEncodedSolution encodedSolution) : base(encodedSolution) { }
+    public SingleObjectiveSolutionContext(TEncodedSolution encodedSolution) : base(encodedSolution) { }
 
 
-    public SingleObjectiveSolutionContext(IEncodedSolution encodedSolution, IEvaluationResult evaluationResult) : base(encodedSolution, evaluationResult) { }
+    public SingleObjectiveSolutionContext(TEncodedSolution encodedSolution, IEvaluationResult evaluationResult) : base(encodedSolution, evaluationResult) { }
 
     [StorableConstructor]
-    public SingleObjectiveSolutionContext(StorableConstructorFlag _) : base(_) {    }
+    public SingleObjectiveSolutionContext(StorableConstructorFlag _) : base(_) { }
 
-    public SingleObjectiveSolutionContext(SingleObjectiveSolutionContext original, Cloner cloner) : base(original, cloner) { }
+    public SingleObjectiveSolutionContext(SingleObjectiveSolutionContext<TEncodedSolution> original, Cloner cloner) : base(original, cloner) { }
 
 
     public override IDeepCloneable Clone(Cloner cloner) {
-      return new SingleObjectiveSolutionContext(this, cloner);
+      return new SingleObjectiveSolutionContext<TEncodedSolution>(this, cloner);
     }
   }
 
   [StorableType("929868B3-8994-4D75-B363-CCF9C51410F9")]
-  public class MultiObjectiveSolutionContext : SolutionContext, IMultiObjectiveSolutionContext {
+  public class MultiObjectiveSolutionContext<TEncodedSolution> : SolutionContext<TEncodedSolution>, IMultiObjectiveSolutionContext<TEncodedSolution>
+   where TEncodedSolution : class, IEncodedSolution {
     public new IMultiObjectiveEvaluationResult EvaluationResult { get; set; }
 
-    public MultiObjectiveSolutionContext(IEncodedSolution encodedSolution) : base(encodedSolution) { }
+    public MultiObjectiveSolutionContext(TEncodedSolution encodedSolution) : base(encodedSolution) { }
 
 
-    public MultiObjectiveSolutionContext(IEncodedSolution encodedSolution, IEvaluationResult evaluationResult) : base(encodedSolution, evaluationResult) { }
+    public MultiObjectiveSolutionContext(TEncodedSolution encodedSolution, IEvaluationResult evaluationResult) : base(encodedSolution, evaluationResult) { }
 
     [StorableConstructor]
     public MultiObjectiveSolutionContext(StorableConstructorFlag _) : base(_) { }
 
-    public MultiObjectiveSolutionContext(MultiObjectiveSolutionContext original, Cloner cloner) : base(original, cloner) { }
+    public MultiObjectiveSolutionContext(MultiObjectiveSolutionContext<TEncodedSolution> original, Cloner cloner) : base(original, cloner) { }
 
 
     public override IDeepCloneable Clone(Cloner cloner) {
-      return new MultiObjectiveSolutionContext(this, cloner);
+      return new MultiObjectiveSolutionContext<TEncodedSolution>(this, cloner);
     }
   }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 17363)
@@ -126,4 +126,5 @@
     <Compile Include="BasicProblems\Interfaces\IMultiEncodingOperator.cs" />
     <Compile Include="BasicProblems\Interfaces\IMultiObjectiveProblem.cs" />
+    <Compile Include="BasicProblems\Interfaces\internal\ISolutionScope.cs" />
     <Compile Include="BasicProblems\Interfaces\ISingleObjectiveProblem.cs" />
     <Compile Include="BasicProblems\CombinedEncoding.cs" />
@@ -133,4 +134,5 @@
     <Compile Include="BasicProblems\Operators\MultiEncodingManipulator.cs" />
     <Compile Include="BasicProblems\Operators\MultiEncodingOperator.cs" />
+    <Compile Include="BasicProblems\Operators\SolutionContextScope.cs" />
     <Compile Include="BasicProblems\Problem.cs" />
     <Compile Include="BasicProblems\Encoding.cs" />
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/SingleObjectiveExternalEvaluationProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/SingleObjectiveExternalEvaluationProblem.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.ExternalEvaluation/3.4/SingleObjectiveExternalEvaluationProblem.cs	(revision 17363)
@@ -113,5 +113,5 @@
     public virtual QualityMessage Evaluate(SolutionMessage solutionMessage, CancellationToken cancellationToken) {
       return Cache == null
-        ? EvaluateOnNextAvailableClient(solutionMessage,cancellationToken)
+        ? EvaluateOnNextAvailableClient(solutionMessage, cancellationToken)
         : Cache.GetValue(solutionMessage, EvaluateOnNextAvailableClient, GetQualityMessageExtensions(), cancellationToken);
     }
@@ -120,5 +120,4 @@
       OptimizationSupport.Analyze(solutions, qualities, results, random);
     }
-
     public override IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution solutions, IRandom random) {
       return OptimizationSupport.GetNeighbors(solutions, random);
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/ProbabilisticTSP.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/ProbabilisticTSP.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/ProbabilisticTSP.cs	(revision 17363)
@@ -124,5 +124,5 @@
         try {
           var tour = new Permutation(PermutationTypes.RelativeUndirected, data.BestKnownTour);
-          var tourLength = Evaluate(tour, new MersenneTwister(1));          
+          var tourLength = Evaluate(tour, new MersenneTwister(1));
           BestKnownSolution = ProbabilisticTSPData.GetSolution(tour, tourLength);
           BestKnownQuality = tourLength;
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.Programmable/3.3/CompiledProblemDefinition.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.Programmable/3.3/CompiledProblemDefinition.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.Programmable/3.3/CompiledProblemDefinition.cs	(revision 17363)
@@ -22,4 +22,5 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading;
 using HeuristicLab.Core;
@@ -64,6 +65,26 @@
     }
     public abstract double Evaluate(TEncodedSolution solution, IRandom random, CancellationToken cancellationToken);
-    public abstract void Analyze(TEncodedSolution[] individuals, double[] qualities, ResultCollection results, IRandom random);
-    public abstract IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution individual, IRandom random);
+
+    public virtual void Evaluate(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random) {
+      Evaluate(solutionContext, random, CancellationToken.None);
+    }
+    public virtual void Evaluate(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random, CancellationToken cancellationToken) {
+      double quality = Evaluate(solutionContext.EncodedSolution, random, cancellationToken);
+      solutionContext.EvaluationResult = new SingleObjectiveEvaluationResult(quality);
+    }
+
+    public virtual void Analyze(TEncodedSolution[] solutions, double[] qualities, ResultCollection results, IRandom random) { }
+    public virtual void Analyze(ISingleObjectiveSolutionContext<TEncodedSolution>[] solutionContexts, ResultCollection results, IRandom random) {
+      var solutions = solutionContexts.Select(c => c.EncodedSolution).ToArray();
+      var qualities = solutionContexts.Select(c => c.EvaluationResult.Quality).ToArray();
+      Analyze(solutions, qualities, results, random);
+    }
+
+    public virtual IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution solutions, IRandom random) {
+      return Enumerable.Empty<TEncodedSolution>();
+    }
+    public virtual IEnumerable<ISingleObjectiveSolutionContext<TEncodedSolution>> GetNeighbors(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random) {
+      return GetNeighbors(solutionContext.EncodedSolution, random).Select(n => new SingleObjectiveSolutionContext<TEncodedSolution>(n));
+    }
 
     public bool IsBetter(double quality, double bestQuality) {
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.Programmable/3.3/SingleObjectiveProblemDefinitionScript.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.Programmable/3.3/SingleObjectiveProblemDefinitionScript.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.Programmable/3.3/SingleObjectiveProblemDefinitionScript.cs	(revision 17363)
@@ -59,9 +59,25 @@
     }
 
+    void ISingleObjectiveProblemDefinition<TEncoding, TEncodedSolution>.Evaluate(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random) {
+      CompiledProblemDefinition.Evaluate(solutionContext, random, CancellationToken.None);
+    }
+    void ISingleObjectiveProblemDefinition<TEncoding, TEncodedSolution>.Evaluate(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random, CancellationToken cancellationToken) {
+      double quality = CompiledProblemDefinition.Evaluate(solutionContext.EncodedSolution, random, cancellationToken);
+      solutionContext.EvaluationResult = new SingleObjectiveEvaluationResult(quality);
+    }
+
     void ISingleObjectiveProblemDefinition<TEncoding, TEncodedSolution>.Analyze(TEncodedSolution[] individuals, double[] qualities, ResultCollection results, IRandom random) {
       CompiledProblemDefinition.Analyze(individuals, qualities, results, random);
     }
+    void ISingleObjectiveProblemDefinition<TEncoding, TEncodedSolution>.Analyze(ISingleObjectiveSolutionContext<TEncodedSolution>[] solutionContexts, ResultCollection results, IRandom random) {
+      CompiledProblemDefinition.Analyze(solutionContexts, results, random);
+    }
+
+
     IEnumerable<TEncodedSolution> ISingleObjectiveProblemDefinition<TEncoding, TEncodedSolution>.GetNeighbors(TEncodedSolution individual, IRandom random) {
       return CompiledProblemDefinition.GetNeighbors(individual, random);
+    }
+    IEnumerable<ISingleObjectiveSolutionContext<TEncodedSolution>> ISingleObjectiveProblemDefinition<TEncoding, TEncodedSolution>.GetNeighbors(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random) {
+      return CompiledProblemDefinition.GetNeighbors(solutionContext, random);
     }
 
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.Programmable/3.3/SingleObjectiveProgrammableProblem.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.Programmable/3.3/SingleObjectiveProgrammableProblem.cs	(revision 17361)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.Programmable/3.3/SingleObjectiveProgrammableProblem.cs	(revision 17363)
@@ -108,10 +108,20 @@
     }
 
+    public override void Evaluate(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random, CancellationToken cancellationToken) {
+      ProblemDefinition.Evaluate(solutionContext, random, cancellationToken);
+    }
     public override double Evaluate(TEncodedSolution individual, IRandom random, CancellationToken cancellationToken) {
       return ProblemDefinition.Evaluate(individual, random, cancellationToken);
     }
 
+    public override void Analyze(ISingleObjectiveSolutionContext<TEncodedSolution>[] solutionContexts, ResultCollection results, IRandom random) {
+      ProblemDefinition.Analyze(solutionContexts, results, random);
+    }
     public override void Analyze(TEncodedSolution[] individuals, double[] qualities, ResultCollection results, IRandom random) {
       ProblemDefinition.Analyze(individuals, qualities, results, random);
+    }
+
+    public override IEnumerable<ISingleObjectiveSolutionContext<TEncodedSolution>> GetNeighbors(ISingleObjectiveSolutionContext<TEncodedSolution> solutionContext, IRandom random) {
+      return ProblemDefinition.GetNeighbors(solutionContext, random);
     }
     public override IEnumerable<TEncodedSolution> GetNeighbors(TEncodedSolution individual, IRandom random) {
