Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/Individual.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/Individual.cs	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/Individual.cs	(revision 15256)
@@ -21,4 +21,6 @@
 
 using System;
+using System.Collections.Generic;
+using System.Linq;
 using HeuristicLab.Core;
 
@@ -27,5 +29,4 @@
     protected IEncoding Encoding { get; private set; }
     protected IScope Scope { get; private set; }
-
     public string Name { get { return Encoding.Name; } }
 
@@ -35,14 +36,22 @@
     }
 
-    public abstract IItem this[string name] { get; set; }
+    public IItem this[string name] {
+      get { return ExtractScopeValue(name, Scope); }
+      set { SetScopeValue(name, Scope, value); }
+    }
+
+    public IEnumerable<KeyValuePair<string, IItem>> Values {
+      get { return Scope.Variables.Select(v => new KeyValuePair<string, IItem>(v.Name, v.Value)); }
+    }
     public abstract TEncoding GetEncoding<TEncoding>() where TEncoding : class, IEncoding;
 
-    public Individual Copy() {
-      return CopyToScope(new Scope());
+    public abstract Individual Copy();
+    internal void CopyToScope(IScope scope) {
+      foreach (var val in Values)
+        SetScopeValue(val.Key, scope, val.Value);
     }
 
-    public abstract Individual CopyToScope(IScope scope);
-
-    protected static IItem ExtractScopeValue(string name, IScope scope) {
+    private static IItem ExtractScopeValue(string name, IScope scope) {
+      if (scope == null) throw new ArgumentNullException("scope");
       if (!scope.Variables.ContainsKey(name)) throw new ArgumentException(string.Format(" {0} cannot be found in the provided scope.", name));
       var value = scope.Variables[name].Value;
@@ -51,6 +60,8 @@
     }
 
-    protected static void SetScopeValue(string name, IScope scope, IItem value) {
+    private static void SetScopeValue(string name, IScope scope, IItem value) {
+      if (scope == null) throw new ArgumentNullException("scope");
       if (value == null) throw new ArgumentNullException("value");
+
       if (!scope.Variables.ContainsKey(name)) scope.Variables.Add(new Variable(name, value));
       else scope.Variables[name].Value = value;
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/MultiEncodingIndividual.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/MultiEncodingIndividual.cs	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/MultiEncodingIndividual.cs	(revision 15256)
@@ -32,28 +32,12 @@
     }
 
-    private readonly IEnumerable<Individual> individuals;
+    public MultiEncodingIndividual(MultiEncoding encoding, IScope scope)
+      : base(encoding, scope) { }
 
-    public MultiEncodingIndividual(MultiEncoding encoding, IScope scope)
-      : base(encoding, scope) {
-      individuals = encoding.Encodings.Select(e => e.GetIndividual(scope)).ToArray();
+    private MultiEncodingIndividual(MultiEncodingIndividual copy) : base(copy.Encoding, new Scope()) {
+      copy.CopyToScope(Scope);
     }
-
-    private MultiEncodingIndividual(MultiEncoding encoding, IScope scope, IEnumerable<Individual> individuals)
-      : base(encoding, scope) {
-      this.individuals = individuals;
-    }
-
-
-    public override IItem this[string name] {
-      get {
-        var individual = individuals.SingleOrDefault(i => i.Name == name);
-        if (individual == null) throw new ArgumentException(string.Format("{0} is not part of the specified encoding.", name));
-        return individual[name];
-      }
-      set {
-        var individual = individuals.SingleOrDefault(i => i.Name == name);
-        if (individual == null) throw new ArgumentException(string.Format("{0} is not part of the specified encoding.", name));
-        individual[name] = value;
-      }
+    public override Individual Copy() {
+      return new MultiEncodingIndividual(this);
     }
 
@@ -62,5 +46,6 @@
       try {
         encoding = (TEncoding)Encoding.Encodings.SingleOrDefault(e => e is TEncoding);
-      } catch (InvalidOperationException) {
+      }
+      catch (InvalidOperationException) {
         throw new InvalidOperationException(string.Format("The individual uses multiple {0} .", typeof(TEncoding).GetPrettyName()));
       }
@@ -68,9 +53,4 @@
       return encoding;
     }
-
-    public override Individual CopyToScope(IScope scope) {
-      var copies = individuals.Select(i => i.CopyToScope(scope)).ToArray();
-      return new MultiEncodingIndividual(Encoding, scope, copies);
-    }
   }
 }
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/SingleEncodingIndividual.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/SingleEncodingIndividual.cs	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/SingleEncodingIndividual.cs	(revision 15256)
@@ -32,13 +32,9 @@
     }
 
-    public override IItem this[string name] {
-      get {
-        if (Name != name) throw new ArgumentException(string.Format("{0} is not part of the individual.", name));
-        return ExtractScopeValue(Name, Scope);
-      }
-      set {
-        if (Name != name) throw new ArgumentException(string.Format("{0} is not part of the individual.", name));
-        SetScopeValue(Name, Scope, value);
-      }
+    private SingleEncodingIndividual(SingleEncodingIndividual copy) : base(copy.Encoding, new Scope()) {
+      copy.CopyToScope(Scope);
+    }
+    public override Individual Copy() {
+      return new SingleEncodingIndividual(this);
     }
 
@@ -48,9 +44,4 @@
       return encoding;
     }
-
-    public override Individual CopyToScope(IScope scope) {
-      SetScopeValue(Name, scope, (IItem)this[Name].Clone());
-      return new SingleEncodingIndividual(Encoding, scope);
-    }
   }
 
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/MultiObjectiveBasicProblem.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/MultiObjectiveBasicProblem.cs	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/MultiObjectiveBasicProblem.cs	(revision 15256)
@@ -20,4 +20,6 @@
 #endregion
 
+using System;
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
@@ -57,5 +59,5 @@
     public abstract double[] Evaluate(Individual individual, IRandom random);
     public virtual void Analyze(Individual[] individuals, double[][] qualities, ResultCollection results, IRandom random) { }
-
+    
     protected override void OnOperatorsChanged() {
       base.OnOperatorsChanged();
@@ -74,4 +76,10 @@
       if (encoding != null && encoding.Operators.Any(x => x is ISingleObjectiveOperator && !(x is IMultiObjectiveOperator)))
         encoding.Operators = encoding.Operators.Where(x => !(x is ISingleObjectiveOperator) || x is IMultiObjectiveOperator).ToList();
+
+      foreach (var multiOp in Encoding.Operators.OfType<IMultiOperator>()) {
+        foreach (var soOp in multiOp.Operators.Where(x => x is ISingleObjectiveOperator).ToList()) {
+          multiOp.RemoveOperator(soOp);
+        }
+      }
     }
 
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveBasicProblem.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveBasicProblem.cs	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveBasicProblem.cs	(revision 15256)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -84,4 +85,13 @@
     }
 
+    protected Tuple<Individual, double> GetBestIndividual(Individual[] individuals, double[] qualities) {
+      return GetBestIndividual(individuals, qualities, Maximization);
+    }
+    public static Tuple<Individual, double> GetBestIndividual(Individual[] individuals, double[] qualities, bool maximization) {
+      var zipped = individuals.Zip(qualities, (i, q) => new { Individual = i, Quality = q });
+      var best = (maximization ? zipped.OrderByDescending(z => z.Quality) : zipped.OrderBy(z => z.Quality)).First();
+      return Tuple.Create(best.Individual, best.Quality);
+    }
+
     protected override void OnOperatorsChanged() {
       base.OnOperatorsChanged();
@@ -100,4 +110,10 @@
       if (encoding.Operators.Any(x => x is IMultiObjectiveOperator && !(x is ISingleObjectiveOperator)))
         encoding.Operators = encoding.Operators.Where(x => !(x is IMultiObjectiveOperator) || x is ISingleObjectiveOperator).ToList();
+
+      foreach (var multiOp in Encoding.Operators.OfType<IMultiOperator>()) {
+        foreach (var moOp in multiOp.Operators.Where(x => x is IMultiObjectiveOperator).ToList()) {
+          multiOp.RemoveOperator(moOp);
+        }
+      }
     }
 
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 15256)
@@ -201,4 +201,5 @@
     <Compile Include="Interfaces\ILocalImprovementAlgorithmOperator.cs" />
     <Compile Include="Interfaces\IMultiObjectiveOperator.cs" />
+    <Compile Include="MultiObjective\DominationCalculator.cs" />
     <Compile Include="Interfaces\IPreexistingSolutionCreator.cs" />
     <Compile Include="Interfaces\ISolutionModel.cs" />
@@ -240,7 +241,5 @@
     <Compile Include="Interfaces\IDiscreteDoubleMatrixModifier.cs" />
     <Compile Include="Algorithms\HeuristicOptimizationEngineAlgorithm.cs" />
-    <Compile Include="Interfaces\IGlobalParticleUpdater.cs" />
     <Compile Include="Interfaces\ILocalImprovementOperator.cs" />
-    <Compile Include="Interfaces\ILocalParticleUpdater.cs" />
     <Compile Include="Algorithms\HeuristicOptimizationAlgorithm.cs" />
     <Compile Include="Interfaces\IMultiNeighborhoodShakingOperator.cs" />
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Interfaces/IGlobalParticleUpdater.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Interfaces/IGlobalParticleUpdater.cs	(revision 14776)
+++ 	(revision )
@@ -1,25 +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
-
-namespace HeuristicLab.Optimization {
-  public interface IGlobalParticleUpdater : IParticleUpdater {
-  }
-}
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Interfaces/ILocalParticleUpdater.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Interfaces/ILocalParticleUpdater.cs	(revision 14776)
+++ 	(revision )
@@ -1,25 +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
-
-namespace HeuristicLab.Optimization {
-  public interface ILocalParticleUpdater : IParticleUpdater {
-  }
-}
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Interfaces/IParticleCreator.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Interfaces/IParticleCreator.cs	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Interfaces/IParticleCreator.cs	(revision 15256)
@@ -27,4 +27,5 @@
   /// </summary>
   public interface IParticleCreator : ISolutionCreator {
+    ILookupParameter<ISolutionCreator> SolutionCreatorParameter { get; }
   }
 }
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/MultiObjective/DominationCalculator.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/MultiObjective/DominationCalculator.cs	(revision 15256)
+++ branches/PerformanceComparison/HeuristicLab.Optimization/3.3/MultiObjective/DominationCalculator.cs	(revision 15256)
@@ -0,0 +1,183 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace HeuristicLab.Optimization {
+  public enum DominationResult { Dominates, IsDominated, IsNonDominated };
+
+  public static class DominationCalculator<T> {
+    /// <summary>
+    /// Calculates the best pareto front only. The fast non-dominated sorting algorithm is used
+    /// as described in Deb, K., Pratap, A., Agarwal, S., and Meyarivan, T. (2002).
+    /// A Fast and Elitist Multiobjective Genetic Algorithm: NSGA-II.
+    /// IEEE Transactions on Evolutionary Computation, 6(2), 182-197.
+    /// </summary>
+    /// <remarks>
+    /// When there are plateaus in the fitness landscape several solutions might have exactly
+    /// the same fitness vector. In this case parameter <paramref name="dominateOnEqualQualities"/>
+    /// can be set to true to avoid plateaus becoming too attractive for the search process.
+    /// </remarks>
+    /// <param name="solutions">The solutions of the population.</param>
+    /// <param name="qualities">The qualities resp. fitness for each solution.</param>
+    /// <param name="maximization">The objective in each dimension.</param>
+    /// <param name="dominateOnEqualQualities">Whether solutions of exactly equal quality should dominate one another.</param>
+    /// <returns>The pareto front containing the best solutions and their associated quality resp. fitness.</returns>
+    public static List<Tuple<T, double[]>> CalculateBestParetoFront(T[] solutions, double[][] qualities, bool[] maximization, bool dominateOnEqualQualities = true) {
+      int populationSize = solutions.Length;
+
+      Dictionary<T, List<int>> dominatedIndividuals;
+      int[] dominationCounter, rank;
+      return CalculateBestFront(solutions, qualities, maximization, dominateOnEqualQualities, populationSize, out dominatedIndividuals, out dominationCounter, out rank);
+    }
+
+    /// <summary>
+    /// Calculates all pareto fronts. The first in the list is the best front.
+    /// The fast non-dominated sorting algorithm is used as described in
+    /// Deb, K., Pratap, A., Agarwal, S., and Meyarivan, T. (2002).
+    /// A Fast and Elitist Multiobjective Genetic Algorithm: NSGA-II.
+    /// IEEE Transactions on Evolutionary Computation, 6(2), 182-197.
+    /// </summary>
+    /// <remarks>
+    /// When there are plateaus in the fitness landscape several solutions might have exactly
+    /// the same fitness vector. In this case parameter <paramref name="dominateOnEqualQualities"/>
+    /// can be set to true to avoid plateaus becoming too attractive for the search process.
+    /// </remarks>
+    /// <param name="solutions">The solutions of the population.</param>
+    /// <param name="qualities">The qualities resp. fitness for each solution.</param>
+    /// <param name="maximization">The objective in each dimension.</param>
+    /// <param name="rank">The rank of each of the solutions, corresponds to the front it is put in.</param>
+    /// <param name="dominateOnEqualQualities">Whether solutions of exactly equal quality should dominate one another.</param>
+    /// <returns>A sorted list of the pareto fronts from best to worst.</returns>
+    public static List<List<Tuple<T, double[]>>> CalculateAllParetoFronts(T[] solutions, double[][] qualities, bool[] maximization, out int[] rank, bool dominateOnEqualQualities = true) {
+      int populationSize = solutions.Length;
+
+      Dictionary<T, List<int>> dominatedIndividuals;
+      int[] dominationCounter;
+      var fronts = new List<List<Tuple<T, double[]>>>();
+      fronts.Add(CalculateBestFront(solutions, qualities, maximization, dominateOnEqualQualities, populationSize, out dominatedIndividuals, out dominationCounter, out rank));
+      int i = 0;
+      while (i < fronts.Count && fronts[i].Count > 0) {
+        var nextFront = new List<Tuple<T, double[]>>();
+        foreach (var p in fronts[i]) {
+          List<int> dominatedIndividualsByp;
+          if (dominatedIndividuals.TryGetValue(p.Item1, out dominatedIndividualsByp)) {
+            for (int k = 0; k < dominatedIndividualsByp.Count; k++) {
+              int dominatedIndividual = dominatedIndividualsByp[k];
+              dominationCounter[dominatedIndividual] -= 1;
+              if (dominationCounter[dominatedIndividual] == 0) {
+                rank[dominatedIndividual] = i + 1;
+                nextFront.Add(Tuple.Create(solutions[dominatedIndividual], qualities[dominatedIndividual]));
+              }
+            }
+          }
+        }
+        i += 1;
+        fronts.Add(nextFront);
+      }
+      return fronts;
+    }
+
+    private static List<Tuple<T, double[]>> CalculateBestFront(T[] solutions, double[][] qualities, bool[] maximization, bool dominateOnEqualQualities, int populationSize, out Dictionary<T, List<int>> dominatedIndividuals, out int[] dominationCounter, out int[] rank) {
+      var front = new List<Tuple<T, double[]>>();
+      dominatedIndividuals = new Dictionary<T, List<int>>();
+      dominationCounter = new int[populationSize];
+      rank = new int[populationSize];
+      for (int pI = 0; pI < populationSize - 1; pI++) {
+        var p = solutions[pI];
+        List<int> dominatedIndividualsByp;
+        if (!dominatedIndividuals.TryGetValue(p, out dominatedIndividualsByp))
+          dominatedIndividuals[p] = dominatedIndividualsByp = new List<int>();
+        for (int qI = pI + 1; qI < populationSize; qI++) {
+          var test = Dominates(qualities[pI], qualities[qI], maximization, dominateOnEqualQualities);
+          if (test == DominationResult.Dominates) {
+            dominatedIndividualsByp.Add(qI);
+            dominationCounter[qI] += 1;
+          } else if (test == DominationResult.IsDominated) {
+            dominationCounter[pI] += 1;
+            if (!dominatedIndividuals.ContainsKey(solutions[qI]))
+              dominatedIndividuals.Add(solutions[qI], new List<int>());
+            dominatedIndividuals[solutions[qI]].Add(pI);
+          }
+          if (pI == populationSize - 2
+            && qI == populationSize - 1
+            && dominationCounter[qI] == 0) {
+            rank[qI] = 0;
+            front.Add(Tuple.Create(solutions[qI], qualities[qI]));
+          }
+        }
+        if (dominationCounter[pI] == 0) {
+          rank[pI] = 0;
+          front.Add(Tuple.Create(p, qualities[pI]));
+        }
+      }
+      return front;
+    }
+
+    /// <summary>
+    /// Calculates the domination result of two solutions which are given in form
+    /// of their quality resp. fitness vector.
+    /// </summary>
+    /// <param name="left">The fitness of the solution that is to be compared.</param>
+    /// <param name="right">The fitness of the solution which is compared against.</param>
+    /// <param name="maximizations">The objective in each dimension.</param>
+    /// <param name="dominateOnEqualQualities">Whether the result should be Dominates in case both fitness vectors are exactly equal</param>
+    /// <returns>Dominates if left dominates right, IsDominated if right dominates left and IsNonDominated otherwise.</returns>
+    public static DominationResult Dominates(double[] left, double[] right, bool[] maximizations, bool dominateOnEqualQualities) {
+      //mkommend Caution: do not use LINQ.SequenceEqual for comparing the two quality arrays (left and right) due to performance reasons
+      if (dominateOnEqualQualities) {
+        var equal = true;
+        for (int i = 0; i < left.Length; i++) {
+          if (left[i] != right[i]) {
+            equal = false;
+            break;
+          }
+        }
+        if (equal) return DominationResult.Dominates;
+      }
+
+      bool leftIsBetter = false, rightIsBetter = false;
+      for (int i = 0; i < left.Length; i++) {
+        if (IsDominated(left[i], right[i], maximizations[i])) rightIsBetter = true;
+        else if (IsDominated(right[i], left[i], maximizations[i])) leftIsBetter = true;
+        if (leftIsBetter && rightIsBetter) break;
+      }
+
+      if (leftIsBetter && !rightIsBetter) return DominationResult.Dominates;
+      if (!leftIsBetter && rightIsBetter) return DominationResult.IsDominated;
+      return DominationResult.IsNonDominated;
+    }
+
+    /// <summary>
+    /// A simple check if the quality resp. fitness in <paramref name="left"/> is better than
+    /// that given in <paramref name="right"/>.
+    /// </summary>
+    /// <param name="left">The first fitness value</param>
+    /// <param name="right">The second fitness value</param>
+    /// <param name="maximization">The objective direction</param>
+    /// <returns>True if left is better than right, false if it is not.</returns>
+    public static bool IsDominated(double left, double right, bool maximization) {
+      return maximization && left < right
+        || !maximization && left > right;
+    }
+  }
+}
Index: branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Results/ResultCollection.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Results/ResultCollection.cs	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Optimization/3.3/Results/ResultCollection.cs	(revision 15256)
@@ -75,4 +75,11 @@
     }
 
+    public void AddOrUpdateResult(string name, IItem value) {
+      IResult res;
+      if (!TryGetValue(name, out res)) {
+        res = new Result(name, value);
+        Add(res);
+      } else res.Value = value;
+    }
   }
 }
