Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/Algorithm.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/Algorithm.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/Algorithm.cs	(revision 12526)
@@ -0,0 +1,330 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// A base class for algorithms.
+  /// </summary>
+  [Item("Algorithm", "A base class for algorithms.")]
+  [StorableClass]
+  public abstract class Algorithm : ParameterizedNamedItem, IAlgorithm {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Event; }
+    }
+    public override Image ItemImage {
+      get {
+        if (ExecutionState == ExecutionState.Prepared) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePrepared;
+        else if (ExecutionState == ExecutionState.Started) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
+        else if (ExecutionState == ExecutionState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePaused;
+        else if (ExecutionState == ExecutionState.Stopped) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
+        else return base.ItemImage;
+      }
+    }
+
+    [Storable]
+    private ExecutionState executionState;
+    public ExecutionState ExecutionState {
+      get { return executionState; }
+      private set {
+        if (executionState != value) {
+          executionState = value;
+          OnExecutionStateChanged();
+          OnItemImageChanged();
+        }
+      }
+    }
+
+    [Storable]
+    private TimeSpan executionTime;
+    public TimeSpan ExecutionTime {
+      get { return executionTime; }
+      protected set {
+        executionTime = value;
+        OnExecutionTimeChanged();
+      }
+    }
+
+    public virtual Type ProblemType {
+      get { return typeof(IProblem); }
+    }
+
+    [Storable]
+    private IProblem problem;
+    public IProblem Problem {
+      get { return problem; }
+      set {
+        if (problem != value) {
+          if ((value != null) && !ProblemType.IsInstanceOfType(value)) throw new ArgumentException("Invalid problem type.");
+          if (problem != null) DeregisterProblemEvents();
+          problem = value;
+          if (problem != null) RegisterProblemEvents();
+          OnProblemChanged();
+          Prepare();
+        }
+      }
+    }
+
+    public abstract ResultCollection Results { get; }
+
+    [Storable]
+    private bool storeAlgorithmInEachRun;
+    public bool StoreAlgorithmInEachRun {
+      get { return storeAlgorithmInEachRun; }
+      set {
+        if (storeAlgorithmInEachRun != value) {
+          storeAlgorithmInEachRun = value;
+          OnStoreAlgorithmInEachRunChanged();
+        }
+      }
+    }
+
+    [Storable]
+    protected int runsCounter;
+
+    [Storable]
+    private RunCollection runs;
+    public RunCollection Runs {
+      get { return runs; }
+      protected set {
+        if (value == null) throw new ArgumentNullException();
+        if (runs != value) {
+          if (runs != null) DeregisterRunsEvents();
+          runs = value;
+          if (runs != null) RegisterRunsEvents();
+        }
+      }
+    }
+
+    public virtual IEnumerable<IOptimizer> NestedOptimizers {
+      get { return Enumerable.Empty<IOptimizer>(); }
+    }
+
+    protected Algorithm()
+      : base() {
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      storeAlgorithmInEachRun = false;
+      runsCounter = 0;
+      Runs = new RunCollection { OptimizerName = Name };
+    }
+    protected Algorithm(string name)
+      : base(name) {
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      storeAlgorithmInEachRun = false;
+      runsCounter = 0;
+      Runs = new RunCollection { OptimizerName = Name };
+    }
+    protected Algorithm(string name, ParameterCollection parameters)
+      : base(name, parameters) {
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      storeAlgorithmInEachRun = false;
+      runsCounter = 0;
+      Runs = new RunCollection { OptimizerName = Name };
+    }
+    protected Algorithm(string name, string description)
+      : base(name, description) {
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      storeAlgorithmInEachRun = false;
+      runsCounter = 0;
+      Runs = new RunCollection { OptimizerName = Name };
+    }
+    protected Algorithm(string name, string description, ParameterCollection parameters)
+      : base(name, description, parameters) {
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      storeAlgorithmInEachRun = false;
+      runsCounter = 0;
+      Runs = new RunCollection { OptimizerName = Name };
+    }
+    [StorableConstructor]
+    protected Algorithm(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      Initialize();
+    }
+
+    protected Algorithm(Algorithm original, Cloner cloner)
+      : base(original, cloner) {
+      if (ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
+      executionState = original.executionState;
+      executionTime = original.executionTime;
+      problem = cloner.Clone(original.problem);
+      storeAlgorithmInEachRun = original.storeAlgorithmInEachRun;
+      runsCounter = original.runsCounter;
+      runs = cloner.Clone(original.runs);
+      Initialize();
+    }
+
+    private void Initialize() {
+      if (problem != null) RegisterProblemEvents();
+      if (runs != null) RegisterRunsEvents();
+    }
+
+    public virtual void Prepare() {
+      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
+        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
+    }
+    public void Prepare(bool clearRuns) {
+      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
+        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
+      if (clearRuns) runs.Clear();
+      Prepare();
+    }
+    public virtual void Start() {
+      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
+        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
+    }
+    public virtual void Pause() {
+      if (ExecutionState != ExecutionState.Started)
+        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
+    }
+    public virtual void Stop() {
+      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
+        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
+    }
+
+    public override void CollectParameterValues(IDictionary<string, IItem> values) {
+      base.CollectParameterValues(values);
+      values.Add("Algorithm Name", new StringValue(Name));
+      values.Add("Algorithm Type", new StringValue(this.GetType().GetPrettyName()));
+      if (Problem != null) {
+        Problem.CollectParameterValues(values);
+        values.Add("Problem Name", new StringValue(Problem.Name));
+        values.Add("Problem Type", new StringValue(Problem.GetType().GetPrettyName()));
+      }
+    }
+    public virtual void CollectResultValues(IDictionary<string, IItem> values) {
+      values.Add("Execution Time", new TimeSpanValue(ExecutionTime));
+      Results.CollectResultValues(values);
+    }
+
+    protected override IEnumerable<KeyValuePair<string, IItem>> GetCollectedValues(IValueParameter param) {
+      var children = base.GetCollectedValues(param);
+      foreach (var child in children) {
+        if (child.Value is IOperator)
+          yield return new KeyValuePair<string, IItem>(child.Key, new StringValue(((IOperator)child.Value).Name));
+        else yield return child;
+      }
+    }
+
+    #region Events
+    protected override void OnNameChanged() {
+      base.OnNameChanged();
+      Runs.OptimizerName = Name;
+    }
+
+    public event EventHandler ExecutionStateChanged;
+    protected virtual void OnExecutionStateChanged() {
+      EventHandler handler = ExecutionStateChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ExecutionTimeChanged;
+    protected virtual void OnExecutionTimeChanged() {
+      EventHandler handler = ExecutionTimeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ProblemChanged;
+    protected virtual void OnProblemChanged() {
+      EventHandler handler = ProblemChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler StoreAlgorithmInEachRunChanged;
+    protected virtual void OnStoreAlgorithmInEachRunChanged() {
+      EventHandler handler = StoreAlgorithmInEachRunChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Prepared;
+    protected virtual void OnPrepared() {
+      ExecutionTime = TimeSpan.Zero;
+      foreach (IStatefulItem statefulObject in this.GetObjectGraphObjects(new HashSet<object>() { Runs }).OfType<IStatefulItem>()) {
+        statefulObject.InitializeState();
+      }
+      ExecutionState = ExecutionState.Prepared;
+      EventHandler handler = Prepared;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Started;
+    protected virtual void OnStarted() {
+      ExecutionState = ExecutionState.Started;
+      EventHandler handler = Started;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Paused;
+    protected virtual void OnPaused() {
+      ExecutionState = ExecutionState.Paused;
+      EventHandler handler = Paused;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Stopped;
+    protected virtual void OnStopped() {
+      foreach (IStatefulItem statefulObject in this.GetObjectGraphObjects(new HashSet<object>() { Runs }).OfType<IStatefulItem>()) {
+        statefulObject.ClearState();
+      }
+      runsCounter++;
+      runs.Add(new Run(string.Format("{0} Run {1}", Name, runsCounter), this));
+      ExecutionState = ExecutionState.Stopped;
+      EventHandler handler = Stopped;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
+    protected virtual void OnExceptionOccurred(Exception exception) {
+      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
+      if (handler != null) handler(this, new EventArgs<Exception>(exception));
+    }
+
+    protected virtual void DeregisterProblemEvents() {
+      problem.OperatorsChanged -= new EventHandler(Problem_OperatorsChanged);
+      problem.Reset -= new EventHandler(Problem_Reset);
+    }
+    protected virtual void RegisterProblemEvents() {
+      problem.OperatorsChanged += new EventHandler(Problem_OperatorsChanged);
+      problem.Reset += new EventHandler(Problem_Reset);
+    }
+    protected virtual void Problem_OperatorsChanged(object sender, EventArgs e) { }
+    protected virtual void Problem_Reset(object sender, EventArgs e) {
+      Prepare();
+    }
+
+    protected virtual void DeregisterRunsEvents() {
+      runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
+    }
+    protected virtual void RegisterRunsEvents() {
+      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
+    }
+    protected virtual void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      runsCounter = runs.Count;
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/BasicAlgorithm.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/BasicAlgorithm.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/BasicAlgorithm.cs	(revision 12526)
@@ -0,0 +1,129 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  public abstract class BasicAlgorithm : Algorithm, IStorableContent {
+    public string Filename { get; set; }
+
+    [Storable]
+    private ResultCollection results;
+    public override ResultCollection Results {
+      get { return results; }
+    }
+
+    private CancellationTokenSource cancellationTokenSource;
+    protected CancellationTokenSource CancellationTokenSource {
+      get { return cancellationTokenSource; }
+      private set { cancellationTokenSource = value; }
+    }
+
+    [StorableConstructor]
+    protected BasicAlgorithm(bool deserializing) : base(deserializing) { }
+    protected BasicAlgorithm(BasicAlgorithm original, Cloner cloner)
+      : base(original, cloner) {
+      results = cloner.Clone(original.Results);
+    }
+    protected BasicAlgorithm()
+      : base() {
+      results = new ResultCollection();
+    }
+
+    public override void Prepare() {
+      if (Problem == null) return;
+      base.Prepare();
+      results.Clear();
+      OnPrepared();
+    }
+
+    public override void Start() {
+      base.Start();
+      CancellationTokenSource = new CancellationTokenSource();
+
+      OnStarted();
+      Task task = Task.Factory.StartNew(Run, cancellationTokenSource.Token, cancellationTokenSource.Token);
+      task.ContinueWith(t => {
+        try {
+          t.Wait();
+        } catch (AggregateException ex) {
+          try {
+            ex.Flatten().Handle(x => x is OperationCanceledException);
+          } catch (AggregateException remaining) {
+            if (remaining.InnerExceptions.Count == 1) OnExceptionOccurred(remaining.InnerExceptions[0]);
+            else OnExceptionOccurred(remaining);
+          }
+        }
+        CancellationTokenSource.Dispose();
+        CancellationTokenSource = null;
+        OnStopped();
+      });
+    }
+
+    public override void Pause() {
+      throw new NotSupportedException("Pause is not supported in basic algorithms.");
+    }
+
+    public override void Stop() {
+      // CancellationToken.ThrowIfCancellationRequested() must be called from within the Run method, otherwise stop does nothing
+      // alternatively check the IsCancellationRequested property of the cancellation token
+      base.Stop();
+      CancellationTokenSource.Cancel();
+    }
+
+
+    private DateTime lastUpdateTime;
+    private void Run(object state) {
+      CancellationToken cancellationToken = (CancellationToken)state;
+      lastUpdateTime = DateTime.UtcNow;
+      System.Timers.Timer timer = new System.Timers.Timer(250);
+      timer.AutoReset = true;
+      timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
+      timer.Start();
+      try {
+        Run(cancellationToken);
+      } finally {
+        timer.Elapsed -= new System.Timers.ElapsedEventHandler(timer_Elapsed);
+        timer.Stop();
+        ExecutionTime += DateTime.UtcNow - lastUpdateTime;
+      }
+    }
+
+    protected abstract void Run(CancellationToken cancellationToken);
+
+    #region Events
+    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
+      System.Timers.Timer timer = (System.Timers.Timer)sender;
+      timer.Enabled = false;
+      DateTime now = DateTime.UtcNow;
+      ExecutionTime += now - lastUpdateTime;
+      lastUpdateTime = now;
+      timer.Enabled = true;
+    }
+    #endregion
+
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/EngineAlgorithm.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/EngineAlgorithm.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/EngineAlgorithm.cs	(revision 12526)
@@ -0,0 +1,238 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// A base class for algorithms which use an engine for execution.
+  /// </summary>
+  [Item("EngineAlgorithm", "A base class for algorithms which use an engine for execution.")]
+  [StorableClass]
+  public abstract class EngineAlgorithm : Algorithm {
+    [Storable]
+    private OperatorGraph operatorGraph;
+    public OperatorGraph OperatorGraph {
+      get { return operatorGraph; }
+      protected set {
+        if (value == null) throw new ArgumentNullException();
+        if (value != operatorGraph) {
+          operatorGraph.InitialOperatorChanged -= new EventHandler(OperatorGraph_InitialOperatorChanged);
+          operatorGraph = value;
+          operatorGraph.InitialOperatorChanged += new EventHandler(OperatorGraph_InitialOperatorChanged);
+          OnOperatorGraphChanged();
+          Prepare();
+        }
+      }
+    }
+
+    [Storable]
+    private IScope globalScope;
+    protected IScope GlobalScope {
+      get { return globalScope; }
+    }
+
+    [Storable]
+    private IEngine engine;
+    public IEngine Engine {
+      get { return engine; }
+      set {
+        if (engine != value) {
+          if (engine != null) DeregisterEngineEvents();
+          engine = value;
+          if (engine != null) RegisterEngineEvents();
+          OnEngineChanged();
+          Prepare();
+        }
+      }
+    }
+
+    public override ResultCollection Results {
+      get {
+        return (ResultCollection)globalScope.Variables["Results"].Value;
+      }
+    }
+
+    protected EngineAlgorithm()
+      : base() {
+      globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Variable("Results", new ResultCollection()));
+      operatorGraph = new OperatorGraph();
+      Initialize();
+    }
+    protected EngineAlgorithm(string name)
+      : base(name) {
+      globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Variable("Results", new ResultCollection()));
+      operatorGraph = new OperatorGraph();
+      Initialize();
+    }
+    protected EngineAlgorithm(string name, ParameterCollection parameters)
+      : base(name, parameters) {
+      globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Variable("Results", new ResultCollection()));
+      operatorGraph = new OperatorGraph();
+      Initialize();
+    }
+    protected EngineAlgorithm(string name, string description)
+      : base(name, description) {
+      globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Variable("Results", new ResultCollection()));
+      operatorGraph = new OperatorGraph();
+      Initialize();
+    }
+    protected EngineAlgorithm(string name, string description, ParameterCollection parameters)
+      : base(name, description, parameters) {
+      globalScope = new Scope("Global Scope");
+      globalScope.Variables.Add(new Variable("Results", new ResultCollection()));
+      operatorGraph = new OperatorGraph();
+      Initialize();
+    }
+    [StorableConstructor]
+    protected EngineAlgorithm(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      Initialize();
+
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code (remove with 3.4)
+      // clear global scope if it contains any sub-scopes or additional variables
+      if ((ExecutionState == Core.ExecutionState.Stopped) && ((globalScope.SubScopes.Count > 0) || (globalScope.Variables.Count > 1))) {
+        ResultCollection results = Results;
+        globalScope.Clear();
+        globalScope.Variables.Add(new Variable("Results", results));
+      }
+      #endregion
+    }
+
+    protected EngineAlgorithm(EngineAlgorithm original, Cloner cloner)
+      : base(original, cloner) {
+      globalScope = cloner.Clone(original.globalScope);
+      engine = cloner.Clone(original.engine);
+      operatorGraph = cloner.Clone(original.operatorGraph);
+      Initialize();
+    }
+
+    private void Initialize() {
+      operatorGraph.InitialOperatorChanged += new EventHandler(OperatorGraph_InitialOperatorChanged);
+      if (engine == null) {
+        var types = ApplicationManager.Manager.GetTypes(typeof(IEngine));
+        Type t = types.FirstOrDefault(x => x.Name.Equals("SequentialEngine"));
+        if (t == null) t = types.FirstOrDefault();
+        if (t != null) engine = (IEngine)Activator.CreateInstance(t);
+      }
+      if (engine != null) RegisterEngineEvents();
+    }
+
+    public virtual IAlgorithm CreateUserDefinedAlgorithm() {
+      return new UserDefinedAlgorithm(this, new Cloner());
+    }
+
+    public override void Prepare() {
+      base.Prepare();
+      globalScope.Clear();
+      globalScope.Variables.Add(new Variable("Results", new ResultCollection()));
+
+      if ((engine != null) && (operatorGraph.InitialOperator != null)) {
+        ExecutionContext context = null;
+        if (Problem != null) {
+          foreach (var item in Problem.ExecutionContextItems)
+            context = new ExecutionContext(context, item, globalScope);
+        }
+        context = new ExecutionContext(context, this, globalScope);
+        context = new ExecutionContext(context, operatorGraph.InitialOperator, globalScope);
+        engine.Prepare(context);
+      }
+    }
+    public override void Start() {
+      base.Start();
+      if (engine != null) engine.Start();
+    }
+    public override void Pause() {
+      base.Pause();
+      if (engine != null) engine.Pause();
+    }
+    public override void Stop() {
+      base.Stop();
+      if (engine != null) engine.Stop();
+    }
+
+    #region Events
+    public event EventHandler EngineChanged;
+    protected virtual void OnEngineChanged() {
+      EventHandler handler = EngineChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler OperatorGraphChanged;
+    protected virtual void OnOperatorGraphChanged() {
+      EventHandler handler = OperatorGraphChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    private void RegisterEngineEvents() {
+      Engine.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(Engine_ExceptionOccurred);
+      Engine.ExecutionTimeChanged += new EventHandler(Engine_ExecutionTimeChanged);
+      Engine.Paused += new EventHandler(Engine_Paused);
+      Engine.Prepared += new EventHandler(Engine_Prepared);
+      Engine.Started += new EventHandler(Engine_Started);
+      Engine.Stopped += new EventHandler(Engine_Stopped);
+    }
+    private void DeregisterEngineEvents() {
+      Engine.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(Engine_ExceptionOccurred);
+      Engine.ExecutionTimeChanged -= new EventHandler(Engine_ExecutionTimeChanged);
+      Engine.Paused -= new EventHandler(Engine_Paused);
+      Engine.Prepared -= new EventHandler(Engine_Prepared);
+      Engine.Started -= new EventHandler(Engine_Started);
+      Engine.Stopped -= new EventHandler(Engine_Stopped);
+    }
+    private void Engine_ExceptionOccurred(object sender, EventArgs<Exception> e) {
+      OnExceptionOccurred(e.Value);
+    }
+    private void Engine_ExecutionTimeChanged(object sender, EventArgs e) {
+      ExecutionTime = Engine.ExecutionTime;
+    }
+    private void Engine_Paused(object sender, EventArgs e) {
+      OnPaused();
+    }
+    private void Engine_Prepared(object sender, EventArgs e) {
+      OnPrepared();
+    }
+    private void Engine_Started(object sender, EventArgs e) {
+      OnStarted();
+    }
+    private void Engine_Stopped(object sender, EventArgs e) {
+      ResultCollection results = Results;
+      globalScope.Clear();
+      globalScope.Variables.Add(new Variable("Results", results));
+      OnStopped();
+    }
+
+    private void OperatorGraph_InitialOperatorChanged(object sender, EventArgs e) {
+      Prepare();
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/HeuristicOptimizationAlgorithm.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/HeuristicOptimizationAlgorithm.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/HeuristicOptimizationAlgorithm.cs	(revision 12526)
@@ -0,0 +1,65 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// A base class for heuristic optimization algorithms.
+  /// </summary>
+  [Item("Heuristic Optimization Algorithm", "A base class for heuristic optimization algorithms.")]
+  [StorableClass]
+  public abstract class HeuristicOptimizationAlgorithm : Algorithm {
+    public new IHeuristicOptimizationProblem Problem {
+      get { return (IHeuristicOptimizationProblem)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    protected HeuristicOptimizationAlgorithm() : base() { }
+    protected HeuristicOptimizationAlgorithm(string name) : base(name) { }
+    protected HeuristicOptimizationAlgorithm(string name, ParameterCollection parameters) : base(name, parameters) { }
+    protected HeuristicOptimizationAlgorithm(string name, string description) : base(name, description) { }
+    protected HeuristicOptimizationAlgorithm(string name, string description, ParameterCollection parameters) : base(name, description, parameters) { }
+
+    [StorableConstructor]
+    protected HeuristicOptimizationAlgorithm(bool deserializing) : base(deserializing) { }
+    protected HeuristicOptimizationAlgorithm(HeuristicOptimizationAlgorithm original, Cloner cloner) : base(original, cloner) { }
+
+    #region Events
+    protected override void DeregisterProblemEvents() {
+      Problem.SolutionCreatorChanged -= new EventHandler(Problem_SolutionCreatorChanged);
+      Problem.EvaluatorChanged -= new EventHandler(Problem_EvaluatorChanged);
+      base.DeregisterProblemEvents();
+    }
+    protected override void RegisterProblemEvents() {
+      base.RegisterProblemEvents();
+      Problem.SolutionCreatorChanged += new EventHandler(Problem_SolutionCreatorChanged);
+      Problem.EvaluatorChanged += new EventHandler(Problem_EvaluatorChanged);
+    }
+
+    protected virtual void Problem_SolutionCreatorChanged(object sender, EventArgs e) { }
+    protected virtual void Problem_EvaluatorChanged(object sender, EventArgs e) { }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/HeuristicOptimizationEngineAlgorithm.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/HeuristicOptimizationEngineAlgorithm.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/HeuristicOptimizationEngineAlgorithm.cs	(revision 12526)
@@ -0,0 +1,65 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// A base class for heuristic optimization algorithms using an execution engine.
+  /// </summary>
+  [Item("Heuristic Optimization Enigne Algorithm", "A base class for heuristic optimization algorithms using an execution engine.")]
+  [StorableClass]
+  public abstract class HeuristicOptimizationEngineAlgorithm : EngineAlgorithm {
+    public new IHeuristicOptimizationProblem Problem {
+      get { return (IHeuristicOptimizationProblem)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    protected HeuristicOptimizationEngineAlgorithm() : base() { }
+    protected HeuristicOptimizationEngineAlgorithm(string name) : base(name) { }
+    protected HeuristicOptimizationEngineAlgorithm(string name, ParameterCollection parameters) : base(name, parameters) { }
+    protected HeuristicOptimizationEngineAlgorithm(string name, string description) : base(name, description) { }
+    protected HeuristicOptimizationEngineAlgorithm(string name, string description, ParameterCollection parameters) : base(name, description, parameters) { }
+
+    [StorableConstructor]
+    protected HeuristicOptimizationEngineAlgorithm(bool deserializing) : base(deserializing) { }
+    protected HeuristicOptimizationEngineAlgorithm(HeuristicOptimizationEngineAlgorithm original, Cloner cloner) : base(original, cloner) { }
+
+    #region Events
+    protected override void DeregisterProblemEvents() {
+      Problem.SolutionCreatorChanged -= new EventHandler(Problem_SolutionCreatorChanged);
+      Problem.EvaluatorChanged -= new EventHandler(Problem_EvaluatorChanged);
+      base.DeregisterProblemEvents();
+    }
+    protected override void RegisterProblemEvents() {
+      base.RegisterProblemEvents();
+      Problem.SolutionCreatorChanged += new EventHandler(Problem_SolutionCreatorChanged);
+      Problem.EvaluatorChanged += new EventHandler(Problem_EvaluatorChanged);
+    }
+
+    protected virtual void Problem_SolutionCreatorChanged(object sender, EventArgs e) { }
+    protected virtual void Problem_EvaluatorChanged(object sender, EventArgs e) { }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/UserDefinedAlgorithm.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/UserDefinedAlgorithm.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Algorithms/UserDefinedAlgorithm.cs	(revision 12526)
@@ -0,0 +1,115 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An algorithm which can be defined by the user.
+  /// </summary>
+  [Item("User-Defined Algorithm", "An algorithm which can be defined by the user.")]
+  [Creatable(CreatableAttribute.Categories.Algorithms, Priority = 100)]
+  [StorableClass]
+  public sealed class UserDefinedAlgorithm : EngineAlgorithm, IParameterizedItem, IStorableContent {
+    public string Filename { get; set; }
+
+    public new ParameterCollection Parameters {
+      get { return base.Parameters; }
+    }
+    IKeyedItemCollection<string, IParameter> IParameterizedItem.Parameters {
+      get { return Parameters; }
+    }
+
+    public new OperatorGraph OperatorGraph {
+      get { return base.OperatorGraph; }
+      set { base.OperatorGraph = value; }
+    }
+
+    public new IScope GlobalScope {
+      get { return base.GlobalScope; }
+    }
+
+    private IValueParameter AnalyzerParameter {
+      get {
+        IParameter param;
+        if (Parameters.TryGetValue("Analyzer", out param))
+          return param as IValueParameter;
+        return null;
+      }
+    }
+    private IMultiAnalyzer Analyzer {
+      get {
+        if (AnalyzerParameter != null)
+          return AnalyzerParameter.Value as IMultiAnalyzer;
+        return null;
+      }
+    }
+
+    public UserDefinedAlgorithm() : base() { }
+    public UserDefinedAlgorithm(string name) : base(name) { }
+    public UserDefinedAlgorithm(string name, string description) : base(name, description) { }
+    [StorableConstructor]
+    private UserDefinedAlgorithm(bool deserializing) : base(deserializing) { }
+    private UserDefinedAlgorithm(UserDefinedAlgorithm original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    internal UserDefinedAlgorithm(EngineAlgorithm original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new UserDefinedAlgorithm(this, cloner);
+    }
+
+    #region update of problem specific analyzers
+    protected override void OnProblemChanged() {
+      AddProblemAnalyzer();
+      base.OnProblemChanged();
+    }
+    protected override void Problem_OperatorsChanged(object sender, System.EventArgs e) {
+      RemoveProblemAnalyzers();
+      AddProblemAnalyzer();
+      base.Problem_OperatorsChanged(sender, e);
+    }
+
+    protected override void DeregisterProblemEvents() {
+      RemoveProblemAnalyzers();
+      base.DeregisterProblemEvents();
+    }
+
+    private void RemoveProblemAnalyzers() {
+      if (Analyzer != null) {
+        foreach (var analyzer in Problem.Operators.OfType<IAnalyzer>())
+          Analyzer.Operators.Remove(analyzer);
+      }
+    }
+    private void AddProblemAnalyzer() {
+      if (Analyzer != null && Problem != null) {
+        foreach (IAnalyzer analyzer in Problem.Operators.OfType<IAnalyzer>()) {
+          Analyzer.Operators.Add(analyzer, analyzer.EnabledByDefault);
+        }
+      }
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/BasicProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/BasicProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/BasicProblem.cs	(revision 12526)
@@ -0,0 +1,160 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  public abstract class BasicProblem<TEncoding, TEvaluator> : HeuristicOptimizationProblem<TEvaluator, ISolutionCreator>, IProblemDefinition, IStorableContent
+    where TEncoding : class, IEncoding
+    where TEvaluator : class, IEvaluator {
+
+    public string Filename { get; set; }
+
+    protected IValueParameter<TEncoding> EncodingParameter {
+      get { return (IValueParameter<TEncoding>)Parameters["Encoding"]; }
+    }
+
+    //mkommend necessary for reuse of operators if the encoding changes
+    private TEncoding oldEncoding;
+
+    IEncoding IProblemDefinition.Encoding { get { return Encoding; } }
+    public TEncoding Encoding {
+      get { return EncodingParameter.Value; }
+      protected set {
+        if (value == null) throw new ArgumentNullException("Encoding must not be null.");
+        EncodingParameter.Value = value;
+      }
+    }
+
+    protected override IEnumerable<IItem> GetOperators() {
+      if (Encoding == null) return base.GetOperators();
+      return base.GetOperators().Concat(Encoding.Operators);
+    }
+    public override IEnumerable<IParameterizedItem> ExecutionContextItems {
+      get {
+        if (Encoding == null) return base.ExecutionContextItems;
+        return base.ExecutionContextItems.Concat(new[] { Encoding });
+      }
+    }
+
+    protected BasicProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<TEncoding>("Encoding", "Describes the configuration of the encoding, what the variables are called, what type they are and their bounds if any."));
+      oldEncoding = Encoding;
+      if(Encoding != null) Parameterize();
+      RegisterEvents();
+    }
+
+    protected BasicProblem(BasicProblem<TEncoding, TEvaluator> original, Cloner cloner)
+      : base(original, cloner) {
+      oldEncoding = cloner.Clone(original.oldEncoding);
+      RegisterEvents();
+    }
+
+    [StorableConstructor]
+    protected BasicProblem(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      oldEncoding = Encoding;
+      RegisterEvents();
+    }
+
+    private void RegisterEvents() {
+      EncodingParameter.ValueChanged += (o, e) => OnEncodingChanged();
+      var multiEncoding = Encoding as MultiEncoding;
+      if (multiEncoding != null) multiEncoding.EncodingsChanged += MultiEncodingOnEncodingsChanged;
+    }
+
+    protected virtual void OnEncodingChanged() {
+      Parameterize();
+
+      OnOperatorsChanged();
+      OnReset();
+    }
+
+    private void Parameterize() {
+      if (oldEncoding != null) {
+        AdaptEncodingOperators(oldEncoding, Encoding);
+        var oldMultiEncoding = oldEncoding as MultiEncoding;
+        if (oldMultiEncoding != null)
+          oldMultiEncoding.EncodingsChanged -= MultiEncodingOnEncodingsChanged;
+      }
+      oldEncoding = Encoding;
+
+      foreach (var op in Operators.OfType<IEncodingOperator>())
+        op.EncodingParameter.ActualName = EncodingParameter.Name;
+
+      var solutionCreatorType = Encoding.GetType().BaseType.GetGenericArguments();
+      var paramType = typeof(ValueParameter<>).MakeGenericType(solutionCreatorType);
+      var solutionCreatorParam = (IParameter)Activator.CreateInstance(paramType, SolutionCreatorParameter.Name, SolutionCreatorParameter.Description,
+        Encoding.SolutionCreator);
+      Parameters.Remove(SolutionCreatorParameter);
+      Parameters.Add(solutionCreatorParam);
+      ((IValueParameter)solutionCreatorParam).ValueChanged += SolutionCreatorParameter_ValueChanged;
+
+      var multiEncoding = Encoding as MultiEncoding;
+      if (multiEncoding != null) multiEncoding.EncodingsChanged += MultiEncodingOnEncodingsChanged;
+    }
+
+    protected override void OnSolutionCreatorChanged() {
+      base.OnSolutionCreatorChanged();
+      Encoding.SolutionCreator = SolutionCreator;
+    }
+
+    private static void AdaptEncodingOperators(IEncoding oldEncoding, IEncoding newEncoding) {
+      if (oldEncoding.GetType() != newEncoding.GetType()) return;
+
+      if (oldEncoding.GetType() == typeof(MultiEncoding)) {
+        var oldMultiEncoding = (MultiEncoding)oldEncoding;
+        var newMultiEncoding = (MultiEncoding)newEncoding;
+        if (!oldMultiEncoding.Encodings.SequenceEqual(newMultiEncoding.Encodings, new TypeEqualityComparer<IEncoding>())) return;
+
+        var nestedEncodings = oldMultiEncoding.Encodings.Zip(newMultiEncoding.Encodings, (o, n) => new { oldEnc = o, newEnc = n });
+        foreach (var multi in nestedEncodings)
+          AdaptEncodingOperators(multi.oldEnc, multi.newEnc);
+      }
+
+      var comparer = new TypeEqualityComparer<IOperator>();
+      var cloner = new Cloner();
+      var oldOperators = oldEncoding.Operators;
+      var newOperators = newEncoding.Operators;
+
+      cloner.RegisterClonedObject(oldEncoding, newEncoding);
+      var operators = oldOperators.Intersect(newOperators, comparer)
+                                  .Select(cloner.Clone)
+                                  .Union(newOperators, comparer).ToList();
+
+      newEncoding.ConfigureOperators(operators);
+      newEncoding.Operators = operators;
+    }
+
+    protected virtual void MultiEncodingOnEncodingsChanged(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Encoding.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Encoding.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Encoding.cs	(revision 12526)
@@ -0,0 +1,125 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Encoding", "Base class for describing different encodings.")]
+  [StorableClass]
+  public abstract class Encoding<T> : ParameterizedNamedItem, IEncoding
+    where T : class,ISolutionCreator {
+    public override sealed bool CanChangeName {
+      get { return false; }
+    }
+
+    private ItemSet<IOperator> encodingOperators = new ItemSet<IOperator>(new TypeEqualityComparer<IOperator>());
+
+    [Storable(Name = "Operators")]
+    private IEnumerable<IOperator> StorableOperators {
+      get { return encodingOperators; }
+      set { encodingOperators = new ItemSet<IOperator>(value, new TypeEqualityComparer<IOperator>()); ; }
+    }
+
+    public IEnumerable<IOperator> Operators {
+      get { return encodingOperators; }
+      set {
+        if (!value.OfType<T>().Any())
+          throw new ArgumentException("The provided operators contain no suitable solution creator");
+        encodingOperators.Clear();
+        foreach (var op in value) encodingOperators.Add(op);
+
+        T newSolutionCreator = (T)encodingOperators.FirstOrDefault(o => o.GetType() == solutionCreator.GetType()) ??
+                               encodingOperators.OfType<T>().First();
+        SolutionCreator = newSolutionCreator;
+        OnOperatorsChanged();
+      }
+    }
+
+    ISolutionCreator IEncoding.SolutionCreator {
+      get { return SolutionCreator; }
+      set {
+        if (!(value is T)) throw new ArgumentException(string.Format("Cannot assign the solution creator {0} to the encoding {1}.", value.GetType().GetPrettyName(), GetType().GetPrettyName()));
+        SolutionCreator = (T)value;
+      }
+    }
+    private T solutionCreator;
+    public T SolutionCreator {
+      get {
+        return solutionCreator;
+      }
+      set {
+        if (value == null) throw new ArgumentNullException("SolutionCreator must not be null.");
+        if (solutionCreator == value) return;
+        encodingOperators.Remove(solutionCreator);
+        encodingOperators.Add(value);
+        solutionCreator = value;
+        OnSolutionCreatorChanged();
+      }
+    }
+
+    [StorableConstructor]
+    protected Encoding(bool deserializing) : base(deserializing) { }
+    protected Encoding(Encoding<T> original, Cloner cloner)
+      : base(original, cloner) {
+      encodingOperators = cloner.Clone(original.encodingOperators);
+      solutionCreator = cloner.Clone(original.solutionCreator);
+    }
+    protected Encoding(string name)
+      : base(name) {
+      Parameters.Add(new FixedValueParameter<ReadOnlyItemSet<IOperator>>(name + ".Operators", "The operators that the encoding specifies.", encodingOperators.AsReadOnly()));
+    }
+
+    public virtual Individual GetIndividual(IScope scope) {
+      return new SingleEncodingIndividual(this, scope);
+    }
+
+    protected bool AddOperator(IOperator @operator) {
+      return encodingOperators.Add(@operator);
+    }
+
+    protected bool RemoveOperator(IOperator @operator) {
+      return encodingOperators.Remove(@operator);
+    }
+
+    public void ConfigureOperator(IOperator @operator) { ConfigureOperators(new[] { @operator }); }
+    public abstract void ConfigureOperators(IEnumerable<IOperator> operators);
+
+    public event EventHandler SolutionCreatorChanged;
+    protected virtual void OnSolutionCreatorChanged() {
+      ConfigureOperator(SolutionCreator);
+      var handler = SolutionCreatorChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler OperatorsChanged;
+    protected virtual void OnOperatorsChanged() {
+      ConfigureOperators(Operators);
+      var handler = OperatorsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/Individual.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/Individual.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/Individual.cs	(revision 12526)
@@ -0,0 +1,59 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Core;
+
+namespace HeuristicLab.Optimization {
+  public abstract class Individual {
+    protected IEncoding Encoding { get; private set; }
+    protected IScope Scope { get; private set; }
+
+    public string Name { get { return Encoding.Name; } }
+
+    protected Individual(IEncoding encoding, IScope scope) {
+      Encoding = encoding;
+      Scope = scope;
+    }
+
+    public abstract IItem this[string name] { get; set; }
+    public abstract TEncoding GetEncoding<TEncoding>() where TEncoding : class, IEncoding;
+
+    public Individual Copy() {
+      return CopyToScope(new Scope());
+    }
+
+    public abstract Individual CopyToScope(IScope scope);
+
+    protected static IItem ExtractScopeValue(string name, IScope 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;
+      if (value == null) throw new InvalidOperationException(string.Format("Value of {0} is null.", name));
+      return value;
+    }
+
+    protected static void SetScopeValue(string name, IScope scope, IItem value) {
+      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/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/MultiEncodingIndividual.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/MultiEncodingIndividual.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/MultiEncodingIndividual.cs	(revision 12526)
@@ -0,0 +1,76 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public sealed class MultiEncodingIndividual : Individual {
+    private new MultiEncoding Encoding {
+      get { return (MultiEncoding)base.Encoding; }
+    }
+
+    private readonly IEnumerable<Individual> individuals;
+
+    public MultiEncodingIndividual(MultiEncoding encoding, IScope scope)
+      : base(encoding, scope) {
+      individuals = encoding.Encodings.Select(e => e.GetIndividual(scope)).ToArray();
+    }
+
+    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 TEncoding GetEncoding<TEncoding>() {
+      TEncoding encoding;
+      try {
+        encoding = (TEncoding)Encoding.Encodings.SingleOrDefault(e => e is TEncoding);
+      } catch (InvalidOperationException) {
+        throw new InvalidOperationException(string.Format("The individual uses multiple {0} .", typeof(TEncoding).GetPrettyName()));
+      }
+      if (encoding == null) throw new InvalidOperationException(string.Format("The individual does not use a {0}.", typeof(TEncoding).GetPrettyName()));
+      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/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/SingleEncodingIndividual.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/SingleEncodingIndividual.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Individuals/SingleEncodingIndividual.cs	(revision 12526)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+
+namespace HeuristicLab.Optimization {
+  public sealed class SingleEncodingIndividual : Individual {
+    public SingleEncodingIndividual(IEncoding encoding, IScope scope)
+      : base(encoding, scope) {
+      if (encoding is MultiEncoding) throw new ArgumentException("A MultiEncoding must not be used for the creation of a SingleEncodingIndividual");
+      if (!scope.Variables.ContainsKey(encoding.Name)) throw new ArgumentException("The provided scope does not contain an individual.");
+    }
+
+    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);
+      }
+    }
+
+    public override TEncoding GetEncoding<TEncoding>() {
+      TEncoding encoding = Encoding as TEncoding;
+      if (encoding == null) throw new InvalidOperationException(string.Format("The individual does not use a {0}.", typeof(TEncoding).GetPrettyName()));
+      return encoding;
+    }
+
+    public override Individual CopyToScope(IScope scope) {
+      SetScopeValue(Name, scope, (IItem)this[Name].Clone());
+      return new SingleEncodingIndividual(Encoding, scope);
+    }
+  }
+
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IEncoding.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IEncoding.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IEncoding.cs	(revision 12526)
@@ -0,0 +1,38 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IEncoding : IParameterizedNamedItem {
+    ISolutionCreator SolutionCreator { get; set; }
+    IEnumerable<IOperator> Operators { get; set; }
+
+    Individual GetIndividual(IScope scope);
+    void ConfigureOperator(IOperator @operator);
+    void ConfigureOperators(IEnumerable<IOperator> operators);
+
+    event EventHandler SolutionCreatorChanged;
+    event EventHandler OperatorsChanged;
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IEncodingOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IEncodingOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IEncodingOperator.cs	(revision 12526)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IEncodingOperator : IOperator {
+    ILookupParameter<IEncoding> EncodingParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IMultiEncodingOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IMultiEncodingOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IMultiEncodingOperator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IMultiEncodingOperator : IOperator {
+    void AddEncoding(IEncoding encoding);
+    bool RemoveEncoding(IEncoding encoding);
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IMultiObjectiveProblemDefinition.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IMultiObjectiveProblemDefinition.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IMultiObjectiveProblemDefinition.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IMultiObjectiveProblemDefinition : IProblemDefinition {
+    bool[] Maximization { get; }
+    double[] Evaluate(Individual individual, IRandom random);
+    void Analyze(Individual[] individuals, double[][] qualities, ResultCollection results, IRandom random);
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IProblemDefinition.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IProblemDefinition.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/IProblemDefinition.cs	(revision 12526)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 IProblemDefinition {
+    IEncoding Encoding { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISingleObjectiveMoveOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISingleObjectiveMoveOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISingleObjectiveMoveOperator.cs	(revision 12526)
@@ -0,0 +1,25 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 ISingleObjectiveMoveOperator : IMoveOperator, ISingleObjectiveOperator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISingleObjectiveProblemDefinition.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISingleObjectiveProblemDefinition.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/ISingleObjectiveProblemDefinition.cs	(revision 12526)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface ISingleObjectiveProblemDefinition : IProblemDefinition {
+    bool Maximization { get; }
+    double Evaluate(Individual individual, IRandom random);
+    void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random);
+    IEnumerable<Individual> GetNeighbors(Individual individual, IRandom random);
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/IMultiObjectiveAnalysisOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/IMultiObjectiveAnalysisOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/IMultiObjectiveAnalysisOperator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Core;
+
+namespace HeuristicLab.Optimization {
+  internal interface IMultiObjectiveAnalysisOperator : IEncodingOperator, IAnalyzer, IMultiObjectiveOperator {
+    Action<Individual[], double[][], ResultCollection, IRandom> AnalyzeAction { get; set; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/IMultiObjectiveEvaluationOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/IMultiObjectiveEvaluationOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/IMultiObjectiveEvaluationOperator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Core;
+
+namespace HeuristicLab.Optimization {
+  internal interface IMultiObjectiveEvaluationOperator : IMultiObjectiveEvaluator, IEncodingOperator {
+    Func<Individual, IRandom, double[]> EvaluateFunc { get; set; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/INeighborBasedOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/INeighborBasedOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/INeighborBasedOperator.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  internal interface INeighborBasedOperator : IEncodingOperator {
+    Func<Individual, IRandom, IEnumerable<Individual>> GetNeighborsFunc { get; set; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveAnalysisOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveAnalysisOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveAnalysisOperator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Core;
+
+namespace HeuristicLab.Optimization {
+  internal interface ISingleObjectiveAnalysisOperator : IEncodingOperator, ISingleObjectiveOperator {
+    Action<Individual[], double[], ResultCollection, IRandom> AnalyzeAction { get; set; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveEvaluationOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveEvaluationOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Interfaces/internal/ISingleObjectiveEvaluationOperator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Core;
+
+namespace HeuristicLab.Optimization {
+  internal interface ISingleObjectiveEvaluationOperator : ISingleObjectiveEvaluator, IEncodingOperator {
+    Func<Individual, IRandom, double> EvaluateFunc { get; set; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/MultiEncoding.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/MultiEncoding.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/MultiEncoding.cs	(revision 12526)
@@ -0,0 +1,98 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Optimization {
+  [Item("MultiEncoding", "Describes a combined encoding consisting of multiple simpler encodings.")]
+  [StorableClass]
+  public sealed class MultiEncoding : Encoding<MultiEncodingCreator> {
+
+    private readonly List<IEncoding> encodings;
+    [Storable]
+    public IEnumerable<IEncoding> Encodings {
+      get { return encodings; }
+      private set { encodings.AddRange(value); }
+    }
+
+    [StorableConstructor]
+    private MultiEncoding(bool deserializing)
+      : base(deserializing) {
+      encodings = new List<IEncoding>();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new MultiEncoding(this, cloner); }
+    private MultiEncoding(MultiEncoding original, Cloner cloner)
+      : base(original, cloner) {
+      encodings = new List<IEncoding>(original.Encodings.Select(cloner.Clone));
+    }
+    public MultiEncoding()
+      : base("MultiEncoding") {
+      encodings = new List<IEncoding>();
+      SolutionCreator = new MultiEncodingCreator();
+
+      foreach (var @operator in ApplicationManager.Manager.GetInstances<IMultiEncodingOperator>())
+        AddOperator(@operator);
+    }
+
+    public override Individual GetIndividual(IScope scope) {
+      return new MultiEncodingIndividual(this, scope);
+    }
+
+    public MultiEncoding Add(IEncoding encoding) {
+      if (encoding is MultiEncoding) throw new InvalidOperationException("Nesting of MultiEncodings is not supported.");
+      if (Encodings.Any(e => e.Name == encoding.Name)) throw new ArgumentException("Encoding name must be unique", "encoding.Name");
+      encodings.Add(encoding);
+
+      Parameters.AddRange(encoding.Parameters);
+
+      foreach (var @operator in Operators.OfType<IMultiEncodingOperator>()) {
+        @operator.AddEncoding(encoding);
+      }
+      OnEncodingsChanged();
+      return this;
+    }
+
+    public bool Remove(IEncoding encoding) {
+      var success = encodings.Remove(encoding);
+      Parameters.RemoveRange(encoding.Parameters);
+      foreach (var @operator in Operators.OfType<IMultiEncodingOperator>()) {
+        @operator.RemoveEncoding(encoding);
+      }
+      OnEncodingsChanged();
+      return success;
+    }
+
+    public override void ConfigureOperators(IEnumerable<IOperator> operators) {
+    }
+
+    public event EventHandler EncodingsChanged;
+    private void OnEncodingsChanged() {
+      var handler = EncodingsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/MultiObjectiveBasicProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/MultiObjectiveBasicProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/MultiObjectiveBasicProblem.cs	(revision 12526)
@@ -0,0 +1,100 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  public abstract class MultiObjectiveBasicProblem<TEncoding> : BasicProblem<TEncoding, MultiObjectiveEvaluator>, IMultiObjectiveHeuristicOptimizationProblem, IMultiObjectiveProblemDefinition
+  where TEncoding : class, IEncoding {
+    [StorableConstructor]
+    protected MultiObjectiveBasicProblem(bool deserializing) : base(deserializing) { }
+
+    protected MultiObjectiveBasicProblem(MultiObjectiveBasicProblem<TEncoding> original, Cloner cloner)
+      : base(original, cloner) {
+      ParameterizeOperators();
+    }
+
+    protected MultiObjectiveBasicProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<BoolArray>("Maximization", "Set to false if the problem should be minimized.", (BoolArray)new BoolArray(Maximization).AsReadOnly()));
+
+      Operators.Add(Evaluator);
+      Operators.Add(new MultiObjectiveAnalyzer());
+
+      ParameterizeOperators();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      ParameterizeOperators();
+    }
+
+    public abstract bool[] Maximization { get; }
+    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();
+      if (Encoding != null) {
+        PruneSingleObjectiveOperators(Encoding);
+        var multiEncoding = Encoding as MultiEncoding;
+        if (multiEncoding != null) {
+          foreach (var encoding in multiEncoding.Encodings.ToList()) {
+            PruneSingleObjectiveOperators(encoding);
+          }
+        }
+      }
+    }
+
+    private void PruneSingleObjectiveOperators(IEncoding encoding) {
+      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();
+    }
+
+    protected override void OnEvaluatorChanged() {
+      base.OnEvaluatorChanged();
+      ParameterizeOperators();
+    }
+
+    private void ParameterizeOperators() {
+      foreach (var op in Operators.OfType<IMultiObjectiveEvaluationOperator>())
+        op.EvaluateFunc = Evaluate;
+      foreach (var op in Operators.OfType<IMultiObjectiveAnalysisOperator>())
+        op.AnalyzeAction = Analyze;
+    }
+
+
+    #region IMultiObjectiveHeuristicOptimizationProblem Members
+    IParameter IMultiObjectiveHeuristicOptimizationProblem.MaximizationParameter {
+      get { return Parameters["Maximization"]; }
+    }
+    IMultiObjectiveEvaluator IMultiObjectiveHeuristicOptimizationProblem.Evaluator {
+      get { return Evaluator; }
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCreator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCreator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCreator.cs	(revision 12526)
@@ -0,0 +1,65 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("MultiEncodingCreator", "Contains solution creators that together create a multi-encoding.")]
+  [StorableClass]
+  public sealed class MultiEncodingCreator : MultiEncodingOperator<ISolutionCreator>, ISolutionCreator {
+    [StorableConstructor]
+    private MultiEncodingCreator(bool deserializing) : base(deserializing) { }
+
+    private MultiEncodingCreator(MultiEncodingCreator original, Cloner cloner) : base(original, cloner) { }
+    public MultiEncodingCreator() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiEncodingCreator(this, cloner);
+    }
+
+    public override void AddEncoding(IEncoding encoding) {
+      base.AddEncoding(encoding);
+      var parameter = GetParameter(encoding);
+      parameter.Value = encoding.SolutionCreator;
+      encoding.SolutionCreatorChanged += Encoding_SolutionCreatorChanged;
+    }
+
+    public override bool RemoveEncoding(IEncoding encoding) {
+      var success = base.RemoveEncoding(encoding);
+      encoding.SolutionCreatorChanged -= Encoding_SolutionCreatorChanged;
+      return success;
+    }
+
+    private void Encoding_SolutionCreatorChanged(object sender, EventArgs e) {
+      var encoding = (IEncoding)sender;
+      var parameter = GetParameter(encoding);
+
+      var oldCreator = parameter.ValidValues.Single(creator => creator.GetType() == encoding.SolutionCreator.GetType());
+      parameter.ValidValues.Remove(oldCreator);
+      parameter.ValidValues.Add(encoding.SolutionCreator);
+      parameter.Value = encoding.SolutionCreator;
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCrossover.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCrossover.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCrossover.cs	(revision 12526)
@@ -0,0 +1,37 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("MultiEncoding Crossover", "Applies different crossovers to cross a multi-encoding.")]
+  [StorableClass]
+  public sealed class MultiEncodingCrossover : MultiEncodingOperator<ICrossover>, ICrossover {
+    [StorableConstructor]
+    private MultiEncodingCrossover(bool deserializing) : base(deserializing) { }
+    private MultiEncodingCrossover(MultiEncodingCrossover original, Cloner cloner) : base(original, cloner) { }
+    public MultiEncodingCrossover() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) { return new MultiEncodingCrossover(this, cloner); }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingManipulator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingManipulator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingManipulator.cs	(revision 12526)
@@ -0,0 +1,39 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("MultiEncoding Manipulator", "Applies different manipulators to change a multi-encoding.")]
+  [StorableClass]
+  public sealed class MultiEncodingManipulator : MultiEncodingOperator<IManipulator>, IManipulator {
+    [StorableConstructor]
+    private MultiEncodingManipulator(bool deserializing) : base(deserializing) { }
+    private MultiEncodingManipulator(MultiEncodingManipulator original, Cloner cloner)
+      : base(original, cloner) { }
+    public MultiEncodingManipulator() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) { return new MultiEncodingManipulator(this, cloner); }
+
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingOperator.cs	(revision 12526)
@@ -0,0 +1,104 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  public abstract class MultiEncodingOperator<T> : Operator, IMultiEncodingOperator where T : class,IOperator {
+    private List<IEncoding> encodings = new List<IEncoding>();
+    [Storable(Name = "Encodings")]
+    private IEnumerable<IEncoding> StorableEncodings {
+      get { return encodings; }
+      set { encodings = new List<IEncoding>(value); }
+    }
+
+    [StorableConstructor]
+    protected MultiEncodingOperator(bool deserializing)
+      : base(deserializing) {
+    }
+
+    protected MultiEncodingOperator(MultiEncodingOperator<T> original, Cloner cloner)
+      : base(original, cloner) {
+      encodings = new List<IEncoding>(original.encodings.Select(cloner.Clone));
+      foreach (var encoding in encodings)
+        encoding.OperatorsChanged += Encoding_OperatorsChanged;
+    }
+
+    protected MultiEncodingOperator() : base() { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      foreach (var encoding in encodings)
+        encoding.OperatorsChanged += Encoding_OperatorsChanged;
+    }
+
+
+    public override IOperation Apply() {
+      var operations = Parameters.Select(p => p.ActualValue).OfType<IOperator>().Select(op => ExecutionContext.CreateOperation(op));
+      return new OperationCollection(operations);
+    }
+
+    public virtual void AddEncoding(IEncoding encoding) {
+      if (Parameters.ContainsKey(encoding.Name)) throw new ArgumentException(string.Format("Encoding {0} was already added.", encoding.Name));
+
+      encodings.Add(encoding);
+      encoding.OperatorsChanged += Encoding_OperatorsChanged;
+
+      var param = new ConstrainedValueParameter<T>(encoding.Name, new ItemSet<T>(encoding.Operators.OfType<T>()));
+      param.Value = param.ValidValues.First();
+      Parameters.Add(param);
+    }
+
+    public virtual bool RemoveEncoding(IEncoding encoding) {
+      if (!encodings.Remove(encoding)) throw new ArgumentException(string.Format("Encoding {0} was not added to the MultiEncoding.", encoding.Name));
+      encoding.OperatorsChanged -= Encoding_OperatorsChanged;
+      return Parameters.Remove(encoding.Name);
+    }
+
+    protected IConstrainedValueParameter<T> GetParameter(IEncoding encoding) {
+      if (!Parameters.ContainsKey(encoding.Name)) throw new ArgumentException(string.Format("Encoding {0} was not added to the MultiEncoding.", encoding.Name));
+
+      return (IConstrainedValueParameter<T>)Parameters[encoding.Name];
+    }
+
+    private void Encoding_OperatorsChanged(object sender, EventArgs e) {
+      var encoding = (IEncoding)sender;
+      var param = GetParameter(encoding);
+
+      var oldParameterValue = param.Value;
+      param.ValidValues.Clear();
+      foreach (var op in encoding.Operators.OfType<T>())
+        param.ValidValues.Add(op);
+
+      var newValue = param.ValidValues.FirstOrDefault(op => op.GetType() == oldParameterValue.GetType());
+      if (newValue == null) newValue = param.ValidValues.First();
+      param.Value = newValue;
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiObjectiveAnalyzer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiObjectiveAnalyzer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiObjectiveAnalyzer.cs	(revision 12526)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Multi-objective Analyzer", "Calls the Analyze method of the problem definition.")]
+  [StorableClass]
+  public class MultiObjectiveAnalyzer : SingleSuccessorOperator, IMultiObjectiveAnalysisOperator, IStochasticOperator {
+    public bool EnabledByDefault { get { return true; } }
+
+    public ILookupParameter<IEncoding> EncodingParameter {
+      get { return (ILookupParameter<IEncoding>)Parameters["Encoding"]; }
+    }
+
+    public IScopeTreeLookupParameter<DoubleArray> QualitiesParameter {
+      get { return (IScopeTreeLookupParameter<DoubleArray>)Parameters["Qualities"]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public Action<Individual[], double[][], ResultCollection, IRandom> AnalyzeAction { get; set; }
+
+    [StorableConstructor]
+    protected MultiObjectiveAnalyzer(bool deserializing) : base(deserializing) { }
+    protected MultiObjectiveAnalyzer(MultiObjectiveAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public MultiObjectiveAnalyzer() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<IEncoding>("Encoding", "An item that holds the problem's encoding."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>("Qualities", "The qualities of the parameter vector."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The results collection to write to."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiObjectiveAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var encoding = EncodingParameter.ActualValue;
+      var results = ResultsParameter.ActualValue;
+      var random = RandomParameter.ActualValue;
+
+      IEnumerable<IScope> scopes = new[] { ExecutionContext.Scope };
+      for (var i = 0; i < QualitiesParameter.Depth; i++)
+        scopes = scopes.Select(x => (IEnumerable<IScope>)x.SubScopes).Aggregate((a, b) => a.Concat(b));
+
+      var individuals = scopes.Select(encoding.GetIndividual).ToArray();
+      AnalyzeAction(individuals, QualitiesParameter.ActualValue.Select(x => x.ToArray()).ToArray(), results, random);
+      return base.Apply();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiObjectiveEvaluator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiObjectiveEvaluator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiObjectiveEvaluator.cs	(revision 12526)
@@ -0,0 +1,70 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Multi-objective Evaluator", "Calls the Evaluate method of the problem definition and writes the return value into the scope.")]
+  [StorableClass]
+  public class MultiObjectiveEvaluator : SingleSuccessorOperator, IMultiObjectiveEvaluationOperator, IStochasticOperator {
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<IEncoding> EncodingParameter {
+      get { return (ILookupParameter<IEncoding>)Parameters["Encoding"]; }
+    }
+
+    public ILookupParameter<DoubleArray> QualitiesParameter {
+      get { return (ILookupParameter<DoubleArray>)Parameters["Qualities"]; }
+    }
+
+    public Func<Individual, IRandom, double[]> EvaluateFunc { get; set; }
+
+    [StorableConstructor]
+    protected MultiObjectiveEvaluator(bool deserializing) : base(deserializing) { }
+    protected MultiObjectiveEvaluator(MultiObjectiveEvaluator original, Cloner cloner) : base(original, cloner) { }
+    public MultiObjectiveEvaluator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<IEncoding>("Encoding", "An item that holds the problem's encoding."));
+      Parameters.Add(new LookupParameter<DoubleArray>("Qualities", "The qualities of the parameter vector."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiObjectiveEvaluator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var encoding = EncodingParameter.ActualValue;
+      var individual = encoding.GetIndividual(ExecutionContext.Scope);
+      QualitiesParameter.ActualValue = new DoubleArray(EvaluateFunc(individual, random));
+      return base.Apply();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveAnalyzer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveAnalyzer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveAnalyzer.cs	(revision 12526)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Single-objective Analyzer", "Calls the script's Analyze method to be able to write into the results collection.")]
+  [StorableClass]
+  public sealed class SingleObjectiveAnalyzer : SingleSuccessorOperator, ISingleObjectiveAnalysisOperator, IAnalyzer, IStochasticOperator {
+    public bool EnabledByDefault { get { return true; } }
+
+    public ILookupParameter<IEncoding> EncodingParameter {
+      get { return (ILookupParameter<IEncoding>)Parameters["Encoding"]; }
+    }
+
+    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public Action<Individual[], double[], ResultCollection, IRandom> AnalyzeAction { get; set; }
+
+    [StorableConstructor]
+    private SingleObjectiveAnalyzer(bool deserializing) : base(deserializing) { }
+    private SingleObjectiveAnalyzer(SingleObjectiveAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public SingleObjectiveAnalyzer() {
+      Parameters.Add(new LookupParameter<IEncoding>("Encoding", "An item that holds the problem's encoding."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The quality of the parameter vector."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The results collection to write to."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectiveAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var encoding = EncodingParameter.ActualValue;
+      var results = ResultsParameter.ActualValue;
+      var random = RandomParameter.ActualValue;
+
+      IEnumerable<IScope> scopes = new[] { ExecutionContext.Scope };
+      for (var i = 0; i < QualityParameter.Depth; i++)
+        scopes = scopes.Select(x => (IEnumerable<IScope>)x.SubScopes).Aggregate((a, b) => a.Concat(b));
+
+      var individuals = scopes.Select(encoding.GetIndividual).ToArray();
+      AnalyzeAction(individuals, QualityParameter.ActualValue.Select(x => x.Value).ToArray(), results, random);
+      return base.Apply();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveEvaluator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveEvaluator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveEvaluator.cs	(revision 12526)
@@ -0,0 +1,68 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Single-objective Evaluator", "Calls the script's Evaluate method to get the quality value of the parameter vector.")]
+  [StorableClass]
+  public sealed class SingleObjectiveEvaluator : SingleSuccessorOperator, ISingleObjectiveEvaluationOperator, IStochasticOperator {
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<IEncoding> EncodingParameter {
+      get { return (ILookupParameter<IEncoding>)Parameters["Encoding"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public Func<Individual, IRandom, double> EvaluateFunc { get; set; }
+
+    [StorableConstructor]
+    private SingleObjectiveEvaluator(bool deserializing) : base(deserializing) { }
+    private SingleObjectiveEvaluator(SingleObjectiveEvaluator original, Cloner cloner) : base(original, cloner) { }
+    public SingleObjectiveEvaluator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<IEncoding>("Encoding", "An item that holds the problem's encoding."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the parameter vector."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) { return new SingleObjectiveEvaluator(this, cloner); }
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var encoding = EncodingParameter.ActualValue;
+      var individual = encoding.GetIndividual(ExecutionContext.Scope);
+      QualityParameter.ActualValue = new DoubleValue(EvaluateFunc(individual, random));
+      return base.Apply();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveImprover.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveImprover.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveImprover.cs	(revision 12526)
@@ -0,0 +1,115 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Single-objective Improver", "Improves a solution by calling GetNeighbors and Evaluate of the corresponding problem definition.")]
+  [StorableClass]
+  public sealed class SingleObjectiveImprover : SingleSuccessorOperator, INeighborBasedOperator, IImprovementOperator, ISingleObjectiveEvaluationOperator, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<IEncoding> EncodingParameter {
+      get { return (ILookupParameter<IEncoding>)Parameters["Encoding"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+
+    public IValueLookupParameter<IntValue> ImprovementAttemptsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["ImprovementAttempts"]; }
+    }
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    public ILookupParameter<IntValue> LocalEvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["LocalEvaluatedSolutions"]; }
+    }
+
+    public Func<Individual, IRandom, double> EvaluateFunc { get; set; }
+    public Func<Individual, IRandom, IEnumerable<Individual>> GetNeighborsFunc { get; set; }
+
+    [StorableConstructor]
+    private SingleObjectiveImprover(bool deserializing) : base(deserializing) { }
+    private SingleObjectiveImprover(SingleObjectiveImprover original, Cloner cloner) : base(original, cloner) { }
+    public SingleObjectiveImprover() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<IEncoding>("Encoding", "An item that holds the problem's encoding."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the parameter vector."));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "Whether the problem should be minimized or maximized."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("ImprovementAttempts", "The number of improvement attempts the operator should perform.", new IntValue(100)));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of samples to draw from the neighborhood function at maximum.", new IntValue(300)));
+      Parameters.Add(new LookupParameter<IntValue>("LocalEvaluatedSolutions", "The number of solution evaluations that have been performed."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectiveImprover(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var encoding = EncodingParameter.ActualValue;
+      var maximize = MaximizationParameter.ActualValue.Value;
+      var maxAttempts = ImprovementAttemptsParameter.ActualValue.Value;
+      var sampleSize = SampleSizeParameter.ActualValue.Value;
+      var individual = encoding.GetIndividual(ExecutionContext.Scope);
+      var quality = QualityParameter.ActualValue == null ? EvaluateFunc(individual, random) : QualityParameter.ActualValue.Value;
+
+      var count = 0;
+      for (var i = 0; i < maxAttempts; i++) {
+        Individual best = null;
+        var bestQuality = quality;
+        foreach (var neighbor in GetNeighborsFunc(individual, random).Take(sampleSize)) {
+          var q = EvaluateFunc(neighbor, random);
+          count++;
+          if (maximize && bestQuality > q || !maximize && bestQuality < q) continue;
+          best = neighbor;
+          bestQuality = q;
+        }
+        if (best == null) break;
+        individual = best;
+        quality = bestQuality;
+      }
+
+      LocalEvaluatedSolutionsParameter.ActualValue = new IntValue(count);
+      QualityParameter.ActualValue = new DoubleValue(quality);
+      individual.CopyToScope(ExecutionContext.Scope);
+      return base.Apply();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveEvaluator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveEvaluator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveEvaluator.cs	(revision 12526)
@@ -0,0 +1,75 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Single-objective MoveEvaluator", "Evaluates a parameter vector that results from a move.")]
+  [StorableClass]
+  public class SingleObjectiveMoveEvaluator : SingleSuccessorOperator, ISingleObjectiveEvaluationOperator, ISingleObjectiveMoveEvaluator, IStochasticOperator, ISingleObjectiveMoveOperator {
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<IEncoding> EncodingParameter {
+      get { return (ILookupParameter<IEncoding>)Parameters["Encoding"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+
+    public Func<Individual, IRandom, double> EvaluateFunc { get; set; }
+
+    [StorableConstructor]
+    protected SingleObjectiveMoveEvaluator(bool deserializing) : base(deserializing) { }
+    protected SingleObjectiveMoveEvaluator(SingleObjectiveMoveEvaluator original, Cloner cloner) : base(original, cloner) { }
+    public SingleObjectiveMoveEvaluator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<IEncoding>("Encoding", "An item that holds the problem's encoding."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the parameter vector."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the move."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectiveMoveEvaluator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var encoding = EncodingParameter.ActualValue;
+      var individual = encoding.GetIndividual(ExecutionContext.Scope);
+      MoveQualityParameter.ActualValue = new DoubleValue(EvaluateFunc(individual, random));
+      return base.Apply();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveGenerator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveGenerator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveGenerator.cs	(revision 12526)
@@ -0,0 +1,82 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Single-objective MoveGenerator", "Calls the GetNeighbors method of the problem definition to obtain the moves.")]
+  [StorableClass]
+  public class SingleObjectiveMoveGenerator : SingleSuccessorOperator, INeighborBasedOperator, IMultiMoveGenerator, IStochasticOperator, ISingleObjectiveMoveOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    public ILookupParameter<IEncoding> EncodingParameter {
+      get { return (ILookupParameter<IEncoding>)Parameters["Encoding"]; }
+    }
+
+    public Func<Individual, IRandom, IEnumerable<Individual>> GetNeighborsFunc { get; set; }
+
+    [StorableConstructor]
+    protected SingleObjectiveMoveGenerator(bool deserializing) : base(deserializing) { }
+    protected SingleObjectiveMoveGenerator(SingleObjectiveMoveGenerator original, Cloner cloner)
+      : base(original, cloner) { }
+    public SingleObjectiveMoveGenerator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to sample."));
+      Parameters.Add(new LookupParameter<IEncoding>("Encoding", "An item that holds the problem's encoding."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectiveMoveGenerator(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var sampleSize = SampleSizeParameter.ActualValue.Value;
+      var encoding = EncodingParameter.ActualValue;
+      var individual = encoding.GetIndividual(ExecutionContext.Scope);
+      var nbhood = GetNeighborsFunc(individual, 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));
+        nbhood[i].CopyToScope(moveScopes[i]);
+      }
+      ExecutionContext.Scope.SubScopes.AddRange(moveScopes);
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveMaker.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveMaker.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/Operators/SingleObjectiveMoveMaker.cs	(revision 12526)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Single-objective MoveMaker", "Applies a move.")]
+  [StorableClass]
+  public class SingleObjectiveMoveMaker : InstrumentedOperator, IMoveMaker, ISingleObjectiveMoveOperator {
+    public ILookupParameter<IEncoding> EncodingParameter {
+      get { return (ILookupParameter<IEncoding>)Parameters["Encoding"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+
+    [StorableConstructor]
+    protected SingleObjectiveMoveMaker(bool deserializing) : base(deserializing) { }
+    protected SingleObjectiveMoveMaker(SingleObjectiveMoveMaker original, Cloner cloner) : base(original, cloner) { }
+    public SingleObjectiveMoveMaker() {
+      Parameters.Add(new LookupParameter<IEncoding>("Encoding", "An item that holds the problem's encoding."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the parameter vector."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the move."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectiveMoveMaker(this, cloner);
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (MoveQualityParameter.ActualValue == null) throw new InvalidOperationException("Move has not been evaluated!");
+
+      var encoding = EncodingParameter.ActualValue;
+      var individual = encoding.GetIndividual(ExecutionContext.Scope);
+      individual.CopyToScope(ExecutionContext.Scope.Parent.Parent);
+
+      if (QualityParameter.ActualValue == null) QualityParameter.ActualValue = new DoubleValue(MoveQualityParameter.ActualValue.Value);
+      else QualityParameter.ActualValue.Value = MoveQualityParameter.ActualValue.Value;
+
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveBasicProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveBasicProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveBasicProblem.cs	(revision 12526)
@@ -0,0 +1,130 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  public abstract class SingleObjectiveBasicProblem<TEncoding> : BasicProblem<TEncoding, SingleObjectiveEvaluator>,
+    ISingleObjectiveProblemDefinition, ISingleObjectiveHeuristicOptimizationProblem
+  where TEncoding : class, IEncoding {
+
+    protected IValueParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+
+    public double BestKnownQuality {
+      get {
+        if (BestKnownQualityParameter.Value == null) return double.NaN;
+        return BestKnownQualityParameter.Value.Value;
+      }
+      set {
+        if (BestKnownQualityParameter.Value == null) BestKnownQualityParameter.Value = new DoubleValue(value);
+        else BestKnownQualityParameter.Value.Value = value;
+      }
+    }
+
+    [StorableConstructor]
+    protected SingleObjectiveBasicProblem(bool deserializing) : base(deserializing) { }
+
+    protected SingleObjectiveBasicProblem(SingleObjectiveBasicProblem<TEncoding> original, Cloner cloner)
+      : base(original, cloner) {
+      ParameterizeOperators();
+    }
+
+    protected SingleObjectiveBasicProblem()
+      : base() {
+      Parameters.Add(new FixedValueParameter<BoolValue>("Maximization", "Set to false if the problem should be minimized.", (BoolValue)new BoolValue(Maximization).AsReadOnly()) { Hidden = true });
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this problem."));
+
+      Operators.Add(Evaluator);
+      Operators.Add(new SingleObjectiveAnalyzer());
+      Operators.Add(new SingleObjectiveImprover());
+      Operators.Add(new SingleObjectiveMoveEvaluator());
+      Operators.Add(new SingleObjectiveMoveGenerator());
+      Operators.Add(new SingleObjectiveMoveMaker());
+
+      ParameterizeOperators();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      ParameterizeOperators();
+    }
+
+    public abstract bool Maximization { get; }
+    public abstract double Evaluate(Individual individual, IRandom random);
+    public virtual void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) { }
+    public virtual IEnumerable<Individual> GetNeighbors(Individual individual, IRandom random) {
+      return Enumerable.Empty<Individual>();
+    }
+
+    protected override void OnOperatorsChanged() {
+      base.OnOperatorsChanged();
+      if (Encoding != null) {
+        PruneMultiObjectiveOperators(Encoding);
+        var multiEncoding = Encoding as MultiEncoding;
+        if (multiEncoding != null) {
+          foreach (var encoding in multiEncoding.Encodings.ToList()) {
+            PruneMultiObjectiveOperators(encoding);
+          }
+        }
+      }
+    }
+
+    private void PruneMultiObjectiveOperators(IEncoding encoding) {
+      if (encoding.Operators.Any(x => x is IMultiObjectiveOperator && !(x is ISingleObjectiveOperator)))
+        encoding.Operators = encoding.Operators.Where(x => !(x is IMultiObjectiveOperator) || x is ISingleObjectiveOperator).ToList();
+    }
+
+    protected override void OnEvaluatorChanged() {
+      base.OnEvaluatorChanged();
+      ParameterizeOperators();
+    }
+
+    private void ParameterizeOperators() {
+      foreach (var op in Operators.OfType<ISingleObjectiveEvaluationOperator>())
+        op.EvaluateFunc = Evaluate;
+      foreach (var op in Operators.OfType<ISingleObjectiveAnalysisOperator>())
+        op.AnalyzeAction = Analyze;
+      foreach (var op in Operators.OfType<INeighborBasedOperator>())
+        op.GetNeighborsFunc = GetNeighbors;
+    }
+
+    #region ISingleObjectiveHeuristicOptimizationProblem Members
+    IParameter ISingleObjectiveHeuristicOptimizationProblem.MaximizationParameter {
+      get { return Parameters["Maximization"]; }
+    }
+    IParameter ISingleObjectiveHeuristicOptimizationProblem.BestKnownQualityParameter {
+      get { return Parameters["BestKnownQuality"]; }
+    }
+    ISingleObjectiveEvaluator ISingleObjectiveHeuristicOptimizationProblem.Evaluator {
+      get { return Evaluator; }
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/HeuristicLab.Optimization-3.3.csproj	(revision 12526)
@@ -0,0 +1,344 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{14AB8D24-25BC-400C-A846-4627AA945192}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Optimization</RootNamespace>
+    <AssemblyName>HeuristicLab.Optimization-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>
+    </DocumentationFile>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Algorithms\BasicAlgorithm.cs" />
+    <Compile Include="BasicProblems\BasicProblem.cs" />
+    <Compile Include="BasicProblems\Encoding.cs" />
+    <Compile Include="BasicProblems\Individuals\Individual.cs" />
+    <Compile Include="BasicProblems\Individuals\MultiEncodingIndividual.cs" />
+    <Compile Include="BasicProblems\Individuals\SingleEncodingIndividual.cs" />
+    <Compile Include="BasicProblems\Interfaces\IEncoding.cs" />
+    <Compile Include="BasicProblems\Interfaces\IEncodingOperator.cs" />
+    <Compile Include="BasicProblems\Interfaces\IMultiEncodingOperator.cs" />
+    <Compile Include="BasicProblems\Interfaces\IMultiObjectiveProblemDefinition.cs" />
+    <Compile Include="BasicProblems\Interfaces\internal\IMultiObjectiveAnalysisOperator.cs" />
+    <Compile Include="BasicProblems\Interfaces\internal\IMultiObjectiveEvaluationOperator.cs" />
+    <Compile Include="BasicProblems\Interfaces\internal\INeighborBasedOperator.cs" />
+    <Compile Include="BasicProblems\Interfaces\internal\ISingleObjectiveAnalysisOperator.cs" />
+    <Compile Include="BasicProblems\Interfaces\internal\ISingleObjectiveEvaluationOperator.cs" />
+    <Compile Include="BasicProblems\Interfaces\IProblemDefinition.cs" />
+    <Compile Include="BasicProblems\Interfaces\ISingleObjectiveMoveOperator.cs" />
+    <Compile Include="BasicProblems\Interfaces\ISingleObjectiveProblemDefinition.cs" />
+    <Compile Include="BasicProblems\MultiEncoding.cs" />
+    <Compile Include="BasicProblems\MultiObjectiveBasicProblem.cs" />
+    <Compile Include="BasicProblems\Operators\MultiEncodingCreator.cs" />
+    <Compile Include="BasicProblems\Operators\MultiEncodingCrossover.cs" />
+    <Compile Include="BasicProblems\Operators\MultiEncodingManipulator.cs" />
+    <Compile Include="BasicProblems\Operators\MultiEncodingOperator.cs" />
+    <Compile Include="BasicProblems\Operators\MultiObjectiveAnalyzer.cs" />
+    <Compile Include="BasicProblems\Operators\MultiObjectiveEvaluator.cs" />
+    <Compile Include="BasicProblems\Operators\SingleObjectiveAnalyzer.cs" />
+    <Compile Include="BasicProblems\Operators\SingleObjectiveEvaluator.cs" />
+    <Compile Include="BasicProblems\Operators\SingleObjectiveImprover.cs" />
+    <Compile Include="BasicProblems\Operators\SingleObjectiveMoveEvaluator.cs" />
+    <Compile Include="BasicProblems\Operators\SingleObjectiveMoveGenerator.cs" />
+    <Compile Include="BasicProblems\Operators\SingleObjectiveMoveMaker.cs" />
+    <Compile Include="BasicProblems\SingleObjectiveBasicProblem.cs" />
+    <Compile Include="Interfaces\ILocalImprovementAlgorithmOperator.cs" />
+    <Compile Include="Interfaces\IMultiObjectiveOperator.cs" />
+    <Compile Include="Interfaces\ISingleObjectiveOperator.cs" />
+    <Compile Include="Interfaces\ISingleObjectivePathRelinker.cs" />
+    <Compile Include="Interfaces\ISingleObjectiveImprovementOperator.cs" />
+    <Compile Include="Interfaces\ISingleObjectiveSolutionSimilarityCalculator.cs" />
+    <Compile Include="Interfaces\IImprovementOperator.cs" />
+    <Compile Include="Interfaces\IPathRelinker.cs" />
+    <Compile Include="Interfaces\ISimilarityBasedOperator.cs" />
+    <Compile Include="Interfaces\ISolutionSimilarityCalculator.cs" />
+    <Compile Include="MetaOptimizers\BatchRun.cs" />
+    <Compile Include="MetaOptimizers\Experiment.cs" />
+    <Compile Include="RunCollectionModification\RunCollectionRunRemover.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="RunCollectionModification\RunCollectionDiscretizer.cs" />
+    <Compile Include="RunCollectionModification\RunCollectionGroupCreater.cs" />
+    <Compile Include="RunCollectionModification\RunCollectionSorter.cs" />
+    <Compile Include="RunCollectionModification\RunCollectionValueRemover.cs" />
+    <Compile Include="Interfaces\IRunCollectionModifier.cs" />
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="Algorithms\Algorithm.cs" />
+    <Compile Include="RunCollectionModification\Calculator.cs" />
+    <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" />
+    <Compile Include="MoveHelper.cs" />
+    <Compile Include="Problems\MultiObjectiveHeuristicOptimizationProblem.cs" />
+    <Compile Include="Problems\HeuristicOptimizationProblem.cs" />
+    <Compile Include="Problems\SingleObjectiveHeuristicOptimizationProblem.cs" />
+    <Compile Include="Interfaces\IHeuristicOptimizationProblem.cs" />
+    <Compile Include="Interfaces\IMultiAnalyzer.cs" />
+    <Compile Include="Interfaces\IIterationBasedOperator.cs" />
+    <Compile Include="Interfaces\IParticleCreator.cs" />
+    <Compile Include="Interfaces\IParticleUpdater.cs" />
+    <Compile Include="Interfaces\ISwarmUpdater.cs" />
+    <Compile Include="Interfaces\ITopologyInitializer.cs" />
+    <Compile Include="Interfaces\ITopologyUpdater.cs" />
+    <Compile Include="Interfaces\IMultiObjectiveHeuristicOptimizationProblem.cs" />
+    <Compile Include="Interfaces\ISingleObjectiveHeuristicOptimizationProblem.cs" />
+    <Compile Include="Problems\Problem.cs" />
+    <Compile Include="RunCollectionModification\RunCollectionFormulaModifer.cs" />
+    <Compile Include="RunCollectionConstraints\RunCollectionComparisonConstraint.cs" />
+    <Compile Include="RunCollectionConstraints\RunCollectionConstraintCollection.cs" />
+    <Compile Include="RunCollectionConstraints\RunCollectionContentConstraint.cs" />
+    <Compile Include="RunCollectionConstraints\RunCollectionTypeCompatiblityConstraint.cs" />
+    <Compile Include="RunCollectionConstraints\RunCollectionEqualityConstraint.cs" />
+    <Compile Include="Interfaces\IAnalyzer.cs" />
+    <Compile Include="Interfaces\ISingleObjectiveReplacer.cs" />
+    <Compile Include="Interfaces\IMigrator.cs" />
+    <Compile Include="Interfaces\IReplacer.cs" />
+    <Compile Include="Interfaces\ISubScopesQualityComparator.cs" />
+    <Compile Include="Interfaces\IQualityComparator.cs" />
+    <Compile Include="Interfaces\ISelfAdaptiveManipulator.cs" />
+    <Compile Include="Interfaces\IStrategyParameterCrossover.cs" />
+    <Compile Include="Interfaces\IStrategyParameterManipulator.cs" />
+    <Compile Include="Interfaces\IStrategyParameterCreator.cs" />
+    <Compile Include="Interfaces\IRun.cs" />
+    <Compile Include="RunCollectionConstraints\IRunCollectionConstraint.cs" />
+    <Compile Include="OptimizerList.cs" />
+    <Compile Include="Interfaces\IOptimizer.cs" />
+    <Compile Include="RunCollection.cs" />
+    <Compile Include="Run.cs" />
+    <Compile Include="Interfaces\IResult.cs" />
+    <Compile Include="Interfaces\IDiscreteDoubleValueModifier.cs" />
+    <Compile Include="Interfaces\IExhaustiveMoveGenerator.cs" />
+    <Compile Include="Interfaces\IMoveOperator.cs" />
+    <Compile Include="Interfaces\IMultiMoveGenerator.cs" />
+    <Compile Include="Interfaces\ISingleMoveGenerator.cs" />
+    <Compile Include="Interfaces\ISingleObjectiveMoveEvaluator.cs" />
+    <Compile Include="Interfaces\IMoveGenerator.cs" />
+    <Compile Include="Interfaces\IMoveMaker.cs" />
+    <Compile Include="Interfaces\IMultiObjectiveSelector.cs" />
+    <Compile Include="Interfaces\ISingleObjectiveSelector.cs" />
+    <Compile Include="Interfaces\IReducer.cs" />
+    <Compile Include="Interfaces\ISelector.cs" />
+    <Compile Include="Interfaces\IMultiObjectiveEvaluator.cs" />
+    <Compile Include="Interfaces\IAlgorithm.cs" />
+    <Compile Include="Interfaces\ICrossover.cs" />
+    <Compile Include="Interfaces\IEvaluator.cs" />
+    <Compile Include="Interfaces\IManipulator.cs" />
+    <Compile Include="Interfaces\IProblem.cs" />
+    <Compile Include="Interfaces\ISingleObjectiveEvaluator.cs" />
+    <Compile Include="Interfaces\ISolutionCreator.cs" />
+    <Compile Include="Interfaces\IStochasticOperator.cs" />
+    <Compile Include="Interfaces\ITabuChecker.cs" />
+    <Compile Include="Interfaces\ITabuMaker.cs" />
+    <Compile Include="Result.cs" />
+    <Compile Include="Algorithms\UserDefinedAlgorithm.cs" />
+    <Compile Include="Algorithms\EngineAlgorithm.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ResultCollection.cs" />
+    <Compile Include="Problems\UserDefinedProblem.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
+      <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
+      <Name>HeuristicLab.Collections-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
+      <Project>{0E27A536-1C4A-4624-A65E-DC4F4F23E3E1}</Project>
+      <Name>HeuristicLab.Common.Resources-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
+      <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
+      <Name>HeuristicLab.Common-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Core\3.3\HeuristicLab.Core-3.3.csproj">
+      <Project>{C36BD924-A541-4A00-AFA8-41701378DDC5}</Project>
+      <Name>HeuristicLab.Core-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
+      <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
+      <Name>HeuristicLab.Data-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
+      <Project>{23da7ff4-d5b8-41b6-aa96-f0561d24f3ee}</Project>
+      <Name>HeuristicLab.Operators-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Parameters\3.3\HeuristicLab.Parameters-3.3.csproj">
+      <Project>{56F9106A-079F-4C61-92F6-86A84C2D84B7}</Project>
+      <Name>HeuristicLab.Parameters-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Persistence\3.3\HeuristicLab.Persistence-3.3.csproj">
+      <Project>{102BC7D3-0EF9-439C-8F6D-96FF0FDB8E1B}</Project>
+      <Name>HeuristicLab.Persistence-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
+      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+</PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IAlgorithm.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IAlgorithm.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IAlgorithm.cs	(revision 12526)
@@ -0,0 +1,41 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Interface to represent an algorithm.
+  /// </summary>
+  public interface IAlgorithm : IParameterizedNamedItem, IOptimizer {
+    Type ProblemType { get; }
+    IProblem Problem { get; set; }
+    ResultCollection Results { get; }
+    bool StoreAlgorithmInEachRun { get; set; }
+
+    void CollectResultValues(IDictionary<string, IItem> values);
+
+    event EventHandler ProblemChanged;
+    event EventHandler StoreAlgorithmInEachRunChanged;
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IAnalyzer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IAnalyzer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IAnalyzer.cs	(revision 12526)
@@ -0,0 +1,31 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an analysis operator.
+  /// </summary>
+  public interface IAnalyzer : IOperator {
+    bool EnabledByDefault { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ICrossover.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ICrossover.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ICrossover.cs	(revision 12526)
@@ -0,0 +1,29 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for crossing solutions.
+  /// </summary>
+  public interface ICrossover : IOperator { }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IDiscreteDoubleMatrixModifier.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IDiscreteDoubleMatrixModifier.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IDiscreteDoubleMatrixModifier.cs	(revision 12526)
@@ -0,0 +1,37 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Optimization {
+  public interface IDiscreteDoubleMatrixModifier : IOperator {
+    ILookupParameter<DoubleMatrix> ValueParameter { get; }
+    ILookupParameter<DoubleValue> ScaleParameter { get; }
+    ConstrainedValueParameter<IDiscreteDoubleValueModifier> ScalingOperatorParameter { get; }
+    IValueLookupParameter<DoubleValue> StartValueParameter { get; }
+    IValueLookupParameter<DoubleValue> EndValueParameter { get; }
+    ILookupParameter<IntValue> IndexParameter { get; }
+    IValueLookupParameter<IntValue> StartIndexParameter { get; }
+    IValueLookupParameter<IntValue> EndIndexParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IDiscreteDoubleValueModifier.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IDiscreteDoubleValueModifier.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IDiscreteDoubleValueModifier.cs	(revision 12526)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface IDiscreteDoubleValueModifier : IOperator {
+    ILookupParameter<DoubleValue> ValueParameter { get; }
+    /// <summary>
+    /// The start value of the parameter, will be assigned to <see cref="ValueParameter"/> as soon as <see cref="IndexParamter"/> equals <see cref="StartIndexParameter"/>.
+    /// </summary>
+    IValueLookupParameter<DoubleValue> StartValueParameter { get; }
+    /// <summary>
+    /// The end value of the parameter, will be assigned to <see cref="ValueParameter"/> as soon as <see cref="IndexParamter"/> equals <see cref="EndIndexParameter"/>.
+    /// </summary>
+    IValueLookupParameter<DoubleValue> EndValueParameter { get; }
+    /// <summary>
+    /// The index that denotes from which point in the function (relative to <see cref="StartIndexParameter"/> and <see cref="EndIndexParameter"/> the value should be assigned.
+    /// </summary>
+    ILookupParameter<IntValue> IndexParameter { get; }
+    /// <summary>
+    /// As soon as <see cref="IndexParameter"/> is &gt;= this parameter the value will start to be modified.
+    /// </summary>
+    IValueLookupParameter<IntValue> StartIndexParameter { get; }
+    /// <summary>
+    /// As long as <see cref="IndexParameter"/> is &lt;= this parameter the value will start to be modified.
+    /// </summary>
+    IValueLookupParameter<IntValue> EndIndexParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IEvaluator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IEvaluator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IEvaluator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an evaluation operator for optimization problems.
+  /// </summary>
+  public interface IEvaluator : IOperator { }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IExhaustiveMoveGenerator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IExhaustiveMoveGenerator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IExhaustiveMoveGenerator.cs	(revision 12526)
@@ -0,0 +1,25 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 IExhaustiveMoveGenerator : IMoveGenerator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IGlobalParticleUpdater.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IGlobalParticleUpdater.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IGlobalParticleUpdater.cs	(revision 12526)
@@ -0,0 +1,25 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IHeuristicOptimizationProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IHeuristicOptimizationProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IHeuristicOptimizationProblem.cs	(revision 12526)
@@ -0,0 +1,38 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Interface to represent a heuristic optimization problem.
+  /// </summary>
+  public interface IHeuristicOptimizationProblem : IProblem {
+    IParameter SolutionCreatorParameter { get; }
+    ISolutionCreator SolutionCreator { get; }
+    IParameter EvaluatorParameter { get; }
+    IEvaluator Evaluator { get; }
+
+    event EventHandler SolutionCreatorChanged;
+    event EventHandler EvaluatorChanged;
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IImprovementOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IImprovementOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IImprovementOperator.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for improvement.
+  /// </summary>
+  public interface IImprovementOperator : IOperator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IIterationBasedOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IIterationBasedOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IIterationBasedOperator.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface IIterationBasedOperator : IOperator {
+    ILookupParameter<IntValue> IterationsParameter { get; }
+    IValueLookupParameter<IntValue> MaximumIterationsParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ILocalImprovementAlgorithmOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ILocalImprovementAlgorithmOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ILocalImprovementAlgorithmOperator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+
+namespace HeuristicLab.Optimization {
+  public interface ILocalImprovementAlgorithmOperator : ILocalImprovementOperator {
+    Type ProblemType { get; }
+    IProblem Problem { get; set; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ILocalImprovementOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ILocalImprovementOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ILocalImprovementOperator.cs	(revision 12526)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface ILocalImprovementOperator : IOperator {
+    IValueLookupParameter<IntValue> MaximumIterationsParameter { get; }
+    ILookupParameter<IntValue> EvaluatedSolutionsParameter { get; }
+    ILookupParameter<ResultCollection> ResultsParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ILocalParticleUpdater.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ILocalParticleUpdater.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ILocalParticleUpdater.cs	(revision 12526)
@@ -0,0 +1,25 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IManipulator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IManipulator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IManipulator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for manipulating solutions.
+  /// </summary>
+  public interface IManipulator : IOperator { }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMigrator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMigrator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMigrator.cs	(revision 12526)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IMigrator : IOperator { }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMoveGenerator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMoveGenerator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMoveGenerator.cs	(revision 12526)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for generating moves.
+  /// </summary>
+  /// <remarks>
+  /// Please read the remarks on <see cref="IMoveOperator"/> on how to implement moves.
+  /// </remarks>
+  public interface IMoveGenerator : IOperator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMoveMaker.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMoveMaker.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMoveMaker.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface IMoveMaker : IOperator {
+    ILookupParameter<DoubleValue> QualityParameter { get; }
+    ILookupParameter<DoubleValue> MoveQualityParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMoveOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMoveOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMoveOperator.cs	(revision 12526)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// The basic interface that marks all move operators. Derived interfaces
+  /// are used to group move operators together.
+  /// </summary>
+  /// <remarks>
+  /// A group of move operators that belong together should derive a new
+  /// interface from IMoveOperator and implement the new interface in each
+  /// operator.<br />
+  /// 
+  /// E.g. a new move is to be implemented and INewMove is created as a derived
+  /// type of IMoveOperator. Then you create the additional following types<br />
+  /// <list type="bullet">
+  /// <item>
+  ///   <term>NewMoveGenerator</term>
+  ///   <description>
+  ///   implements INewMove as well as either IExhaustiveMoveGenerator,
+  ///   IMultiMoveGenerator or ISingleMoveGenerator
+  ///   </description>
+  /// </item>
+  /// <item>
+  ///   <term>NewMoveMaker</term>
+  ///   <description>
+  ///   implements INewMove as well as IMoveMaker
+  ///   </description>
+  /// </item>
+  /// <item>
+  ///   <term>NewMoveEvaluator</term>
+  ///   <description>
+  ///   (problem plugin) implements INewMove as well as ISingleObjectiveMoveEvaluator
+  ///   </description>
+  /// </item>
+  /// <item>
+  ///   <term>NewMoveTabuMaker</term>
+  ///   <description>
+  ///   (only for Tabu Search) implements INewMove as well as TabuMaker
+  ///   </description>
+  /// </item>
+  /// <item>
+  ///   <term>NewMoveTabuChecker</term>
+  ///   <description>
+  ///   (only for Tabu Search) implements INewMove as well as ITabuChecker
+  ///   </description>
+  /// </item>
+  /// </list>
+  /// 
+  /// These operators should not implement further move types. For further moves
+  /// a new interface derived from IMoveOperator should be created.
+  public interface IMoveOperator : IOperator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiAnalyzer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiAnalyzer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiAnalyzer.cs	(revision 12526)
@@ -0,0 +1,29 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+
+using HeuristicLab.Core;
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents a multi analysis operator.
+  /// </summary>
+  public interface IMultiAnalyzer : ICheckedMultiOperator<IAnalyzer>, IAnalyzer { }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiMoveGenerator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiMoveGenerator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiMoveGenerator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface IMultiMoveGenerator : IMoveGenerator {
+    IValueLookupParameter<IntValue> SampleSizeParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiNeighborhoodShakingOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiNeighborhoodShakingOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiNeighborhoodShakingOperator.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface IMultiNeighborhoodShakingOperator : IOperator {
+    IValueLookupParameter<IntValue> CurrentNeighborhoodIndexParameter { get; }
+    ILookupParameter<IntValue> NeighborhoodCountParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveEvaluator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveEvaluator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveEvaluator.cs	(revision 12526)
@@ -0,0 +1,32 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an evaluation operator for multi-objective optimization problems.
+  /// </summary>
+  public interface IMultiObjectiveEvaluator : IEvaluator, IMultiObjectiveOperator {
+    ILookupParameter<DoubleArray> QualitiesParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveHeuristicOptimizationProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveHeuristicOptimizationProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveHeuristicOptimizationProblem.cs	(revision 12526)
@@ -0,0 +1,32 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface to represent a multi-objective optimization problem.
+  /// </summary>
+  public interface IMultiObjectiveHeuristicOptimizationProblem : IHeuristicOptimizationProblem {
+    IParameter MaximizationParameter { get; }
+    new IMultiObjectiveEvaluator Evaluator { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveOperator.cs	(revision 12526)
@@ -0,0 +1,52 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 {
+  /// <summary>
+  /// This is only a marker interface to prevent operators that expect to work with multiple quality values
+  /// and/or multiple maximization flags to appear in single-objective algorithms.
+  /// </summary>
+  /// <remarks>
+  /// Marker interfaces are typically not a good design, however specifying a reasonable non-empty common
+  /// interface for all multi-objective operators is difficult. There are many different variants of
+  /// multi-ojective operators with specific needs that can currently only be abstracted by an empty interface.
+  /// In the following, please find a list of different kinds of multi-objective operators.
+  /// <list type="bullet">
+  ///   <item>
+  ///     <term>Evaluators</term>
+  ///     <description>These only need a qualities parameter, but not a maximization parameter.</description>
+  ///   </item>
+  ///   <item>
+  ///     <term>Population-based operators</term>
+  ///     <description>These require the qualities parameter to be a scope-tree lookup, e.g. analyzers, crossovers, multi-objective selectors.</description>
+  ///   </item>
+  ///   <item>
+  ///     <term>Problem-specific operators</term>
+  ///     <description>They may perform multiple operations on a solution, evaluate and select without taking into account maximization or the evaluator</description>
+  ///   </item>
+  ///   <item>
+  ///     <term>Other multi-objective operators</term>
+  ///     <description>They would need both a qualities, and a maximization parameter, and may be population-based or not.</description>
+  ///   </item>
+  /// </list>
+  /// </remarks>
+  public interface IMultiObjectiveOperator { }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveSelector.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveSelector.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IMultiObjectiveSelector.cs	(revision 12526)
@@ -0,0 +1,33 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents a selection operator for selecting solutions of multi-objective optimization problems.
+  /// </summary>
+  public interface IMultiObjectiveSelector : ISelector, IMultiObjectiveOperator {
+    ILookupParameter<BoolArray> MaximizationParameter { get; }
+    ILookupParameter<ItemArray<DoubleArray>> QualitiesParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IOptimizer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IOptimizer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IOptimizer.cs	(revision 12526)
@@ -0,0 +1,36 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Interface to represent optimizers such as algorithms, batch runs, or experiments.
+  /// </summary>
+  public interface IOptimizer : INamedItem, IExecutable {
+    RunCollection Runs { get; }
+
+    void Prepare(bool clearRuns);
+
+    IEnumerable<IOptimizer> NestedOptimizers { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IParticleCreator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IParticleCreator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IParticleCreator.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Interface to represent an operator that generates a particle. 
+  /// </summary>
+  public interface IParticleCreator : ISolutionCreator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IParticleUpdater.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IParticleUpdater.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IParticleUpdater.cs	(revision 12526)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Interface to represent an operator that updates a particle 
+  /// </summary>
+  public interface IParticleUpdater : IOperator {
+    ILookupParameter<DoubleValue> InertiaParameter { get; }
+    ILookupParameter<DoubleValue> NeighborBestAttractionParameter { get; }
+    ILookupParameter<DoubleValue> PersonalBestAttractionParameter { get; }
+    ILookupParameter<IRandom> RandomParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IPathRelinker.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IPathRelinker.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IPathRelinker.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for path relinking.
+  /// </summary>
+  public interface IPathRelinker : IOperator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IProblem.cs	(revision 12526)
@@ -0,0 +1,38 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Interface to represent an optimization problem.
+  /// </summary>
+  public interface IProblem : IParameterizedNamedItem {
+    IEnumerable<IItem> Operators { get; }
+
+
+    IEnumerable<IParameterizedItem> ExecutionContextItems { get; }
+    event EventHandler OperatorsChanged;
+    event EventHandler Reset;
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IQualityComparator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IQualityComparator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IQualityComparator.cs	(revision 12526)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface IQualityComparator {
+    ILookupParameter<DoubleValue> LeftSideParameter { get; }
+    IValueLookupParameter<DoubleValue> RightSideParameter { get; }
+    ILookupParameter<BoolValue> ResultParameter { get; }
+    IValueLookupParameter<BoolValue> MaximizationParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IReducer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IReducer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IReducer.cs	(revision 12526)
@@ -0,0 +1,29 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents a reduction opertor.
+  /// </summary>
+  public interface IReducer : IOperator { }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IReplacer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IReplacer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IReplacer.cs	(revision 12526)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Interface to mark operators that can be used as replacers.
+  /// Replacers are merging a remaining and a selected branch in several special ways.
+  /// </summary>
+  public interface IReplacer : IOperator {
+    IValueLookupParameter<ISelector> ReplacedSelectorParameter { get; }
+    IValueLookupParameter<ISelector> SelectedSelectorParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IResult.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IResult.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IResult.cs	(revision 12526)
@@ -0,0 +1,36 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Represents a result which has a name and a data type and holds an IItem.
+  /// </summary>
+  public interface IResult : INamedItem {
+    Type DataType { get; }
+    IItem Value { get; set; }
+
+    /// <inheritdoc/>
+    event EventHandler ValueChanged;
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IRun.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IRun.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IRun.cs	(revision 12526)
@@ -0,0 +1,39 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.ComponentModel;
+using System.Drawing;
+using HeuristicLab.Collections;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Represents the parameters and results of an algorithm run.
+  /// </summary>
+  public interface IRun : INamedItem, INotifyPropertyChanged {
+    IAlgorithm Algorithm { get; }
+    IObservableDictionary<string, IItem> Parameters { get; }
+    IObservableDictionary<string, IItem> Results { get; }
+
+    Color Color { get; set; }
+    bool Visible { get; set; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IRunCollectionModifier.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IRunCollectionModifier.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IRunCollectionModifier.cs	(revision 12526)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IRunCollectionModifier : IItem {    
+    void Modify(List<IRun> runs);
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISelector.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISelector.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISelector.cs	(revision 12526)
@@ -0,0 +1,33 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents a selection operator.
+  /// </summary>
+  public interface ISelector : IOperator {
+    BoolValue CopySelected { get; set; }
+    IValueLookupParameter<IntValue> NumberOfSelectedSubScopesParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISelfAdaptiveManipulator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISelfAdaptiveManipulator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISelfAdaptiveManipulator.cs	(revision 12526)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for manipulating solutions, given a strategy parameter.
+  /// </summary>
+  public interface ISelfAdaptiveManipulator : IManipulator {
+    Type StrategyParameterType { get; }
+    IParameter StrategyParameterParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISimilarityBasedOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISimilarityBasedOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISimilarityBasedOperator.cs	(revision 12526)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface ISimilarityBasedOperator : IOperator {
+    IConstrainedValueParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleMoveGenerator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleMoveGenerator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleMoveGenerator.cs	(revision 12526)
@@ -0,0 +1,25 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 ISingleMoveGenerator : IMoveGenerator, ISingleObjectiveOperator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveEvaluator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveEvaluator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveEvaluator.cs	(revision 12526)
@@ -0,0 +1,32 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an evaluation operator for single-objective optimization problems.
+  /// </summary>
+  public interface ISingleObjectiveEvaluator : IEvaluator, ISingleObjectiveOperator {
+    ILookupParameter<DoubleValue> QualityParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveHeuristicOptimizationProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveHeuristicOptimizationProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveHeuristicOptimizationProblem.cs	(revision 12526)
@@ -0,0 +1,33 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface to represent a single-objective optimization problem.
+  /// </summary>
+  public interface ISingleObjectiveHeuristicOptimizationProblem : IHeuristicOptimizationProblem {
+    IParameter MaximizationParameter { get; }
+    IParameter BestKnownQualityParameter { get; }
+    new ISingleObjectiveEvaluator Evaluator { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveImprovementOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveImprovementOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveImprovementOperator.cs	(revision 12526)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for improvement of a single objective solution.
+  /// </summary>
+  public interface ISingleObjectiveImprovementOperator : IImprovementOperator, ISingleObjectiveOperator {
+    IValueLookupParameter<IItem> SolutionParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveMoveEvaluator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveMoveEvaluator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveMoveEvaluator.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface ISingleObjectiveMoveEvaluator : IOperator, ISingleObjectiveOperator {
+    ILookupParameter<DoubleValue> QualityParameter { get; }
+    ILookupParameter<DoubleValue> MoveQualityParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveOperator.cs	(revision 12526)
@@ -0,0 +1,52 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 {
+  /// <summary>
+  /// This is only a marker interface to prevent operators that expect to work with a single quality value
+  /// and/or a single maximization flag to appear in multi-objective algorithms.
+  /// </summary>
+  /// <remarks>
+  /// Marker interfaces are typically not a good design, however specifying a reasonable non-empty common
+  /// interface for all single-objective operators is difficult. There are many different variants of
+  /// single-ojective operators with specific needs that can currently only be abstracted by an empty interface.
+  /// In the following, please find a list of different kinds of single-objective operators.
+  /// <list type="bullet">
+  ///   <item>
+  ///     <term>Evaluators</term>
+  ///     <description>These only need a quality parameter, but not a maximization parameter.</description>
+  ///   </item>
+  ///   <item>
+  ///     <term>Population-based operators</term>
+  ///     <description>These require the quality parameter to be a scope-tree lookup, e.g. analyzers, crossovers, single-objective replacers and selectors.</description>
+  ///   </item>
+  ///   <item>
+  ///     <term>Problem-specific operators</term>
+  ///     <description>They may perform multiple operations on a solution, evaluate and select without taking into account maximization or the evaluator, e.g. many improvement operators.</description>
+  ///   </item>
+  ///   <item>
+  ///     <term>Other single-objective operators</term>
+  ///     <description>They would need both a quality, and a maximization parameter, and may be population-based or not.</description>
+  ///   </item>
+  /// </list>
+  /// </remarks>
+  public interface ISingleObjectiveOperator { }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectivePathRelinker.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectivePathRelinker.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectivePathRelinker.cs	(revision 12526)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for path relinking between single objective solutions.
+  /// </summary>
+  public interface ISingleObjectivePathRelinker : IPathRelinker, ISingleObjectiveOperator {
+    ILookupParameter<ItemArray<IItem>> ParentsParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveReplacer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveReplacer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveReplacer.cs	(revision 12526)
@@ -0,0 +1,33 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents a replacement operator for replacing solutions of single-objective optimization problems.
+  /// </summary>
+  public interface ISingleObjectiveReplacer : IReplacer, ISingleObjectiveOperator {
+    IValueLookupParameter<BoolValue> MaximizationParameter { get; }
+    ILookupParameter<ItemArray<DoubleValue>> QualityParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveSelector.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveSelector.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveSelector.cs	(revision 12526)
@@ -0,0 +1,33 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents a selection operator for selecting solutions of single-objective optimization problems.
+  /// </summary>
+  public interface ISingleObjectiveSelector : ISelector, ISingleObjectiveOperator {
+    IValueLookupParameter<BoolValue> MaximizationParameter { get; }
+    ILookupParameter<ItemArray<DoubleValue>> QualityParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveSolutionSimilarityCalculator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveSolutionSimilarityCalculator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISingleObjectiveSolutionSimilarityCalculator.cs	(revision 12526)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+
+namespace HeuristicLab.Optimization {
+  // use HeuristicLab.Optimization.ISolutionSimilarityCalculator instead
+  // BackwardsCompatibility3.3
+  #region Backwards compatible code, remove with 3.4
+  /// <summary>
+  /// An interface which represents an operator for similarity calculation between single objective solutions.
+  /// </summary>
+  [Obsolete("use HeuristicLab.Optimization.ISolutionSimilarityCalculator instead")]
+  public interface ISingleObjectiveSolutionSimilarityCalculator : ISolutionSimilarityCalculator, ISingleObjectiveOperator {
+
+  }
+  #endregion
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISolutionCreator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISolutionCreator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISolutionCreator.cs	(revision 12526)
@@ -0,0 +1,29 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for creating new solutions.
+  /// </summary>
+  public interface ISolutionCreator : IOperator { }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISolutionSimilarityCalculator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISolutionSimilarityCalculator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISolutionSimilarityCalculator.cs	(revision 12526)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents an operator for similarity calculation.
+  /// </summary>
+  public interface ISolutionSimilarityCalculator : IItem, IEqualityComparer<IScope> {
+    string SolutionVariableName { get; set; }
+    string QualityVariableName { get; set; }
+
+    /// <summary>
+    /// Calculates the similarity of two solutions.
+    /// </summary>
+    /// <param name="leftSolution">The first scope that contains a solution.</param>
+    /// <param name="rightSolution">The second scope that contains a solution.</param>
+    /// <returns>A double between zero and one. Zero means the two solutions differ in every aspect, one indicates that the two solutions are the same.</returns>
+    double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution);
+
+    /// <summary>
+    /// Calculates the similarity of solutions in one scope.
+    /// </summary>
+    /// <param name="solutionCrowd">The scope that contains solutions.</param>
+    /// <returns>A similarity matrix. Zero means the two solutions differ in every aspect, one indicates that the two solutions are the same.</returns>
+    double[][] CalculateSolutionCrowdSimilarity(IScope solutionCrowd);
+
+    /// <summary>
+    /// Calculates the similarity of solutions in two scopes.
+    /// </summary>
+    /// <param name="leftSolutionCrowd">The first scope that contains solutions.</param>
+    /// <param name="rightSolutionCrowd">The second scope that contains solutions.</param>
+    /// <returns>A similarity matrix. Zero means the two solutions differ in every aspect, one indicates that the two solutions are the same.</returns>
+    double[][] CalculateSolutionCrowdSimilarity(IScope leftSolutionCrowd, IScope rightSolutionCrowd);
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStochasticOperator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStochasticOperator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStochasticOperator.cs	(revision 12526)
@@ -0,0 +1,31 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An interface which represents a stochastic operator.
+  /// </summary>
+  public interface IStochasticOperator : IOperator {
+    ILookupParameter<IRandom> RandomParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStrategyParameterCreator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStrategyParameterCreator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStrategyParameterCreator.cs	(revision 12526)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IStrategyParameterCreator : IOperator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStrategyParameterCrossover.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStrategyParameterCrossover.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStrategyParameterCrossover.cs	(revision 12526)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IStrategyParameterCrossover : IOperator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStrategyParameterManipulator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStrategyParameterManipulator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/IStrategyParameterManipulator.cs	(revision 12526)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IStrategyParameterManipulator : IOperator {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISubScopesQualityComparator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISubScopesQualityComparator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISubScopesQualityComparator.cs	(revision 12526)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface ISubScopesQualityComparator {
+    ILookupParameter<DoubleValue> LeftSideParameter { get; }
+    ILookupParameter<ItemArray<DoubleValue>> RightSideParameter { get; }
+    ILookupParameter<BoolValue> ResultParameter { get; }
+    IValueLookupParameter<BoolValue> MaximizationParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISwarmUpdater.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISwarmUpdater.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ISwarmUpdater.cs	(revision 12526)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface ISwarmUpdater : IOperator {
+    IScopeTreeLookupParameter<DoubleValue> QualityParameter { get; }
+    IScopeTreeLookupParameter<DoubleValue> NeighborBestQualityParameter { get; }
+    IScopeTreeLookupParameter<DoubleValue> PersonalBestQualityParameter { get; }
+    ILookupParameter<BoolValue> MaximizationParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITabuChecker.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITabuChecker.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITabuChecker.cs	(revision 12526)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface ITabuChecker : IOperator {
+    ILookupParameter<BoolValue> MoveTabuParameter { get; }
+    ILookupParameter<DoubleValue> MoveQualityParameter { get; }
+    IValueLookupParameter<BoolValue> MaximizationParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITabuMaker.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITabuMaker.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITabuMaker.cs	(revision 12526)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface ITabuMaker : IOperator {
+    ILookupParameter<DoubleValue> MoveQualityParameter { get; }
+    ILookupParameter<DoubleValue> QualityParameter { get; }
+    IValueLookupParameter<BoolValue> MaximizationParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITopologyInitializer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITopologyInitializer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITopologyInitializer.cs	(revision 12526)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface ITopologyInitializer : IOperator {
+    IScopeTreeLookupParameter<IntArray> NeighborsParameter { get; }
+    ILookupParameter<IntValue> SwarmSizeParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITopologyUpdater.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITopologyUpdater.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Interfaces/ITopologyUpdater.cs	(revision 12526)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Data;
+
+namespace HeuristicLab.Optimization {
+  public interface ITopologyUpdater : IOperator {
+    IScopeTreeLookupParameter<IntArray> NeighborsParameter { get; }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs	(revision 12526)
@@ -0,0 +1,454 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  internal enum BatchRunAction { None, Prepare, Start, Pause, Stop };
+
+  /// <summary>
+  /// A run in which an optimizer is executed a given number of times.
+  /// </summary>
+  [Item("Batch Run", "A run in which an optimizer is executed a given number of times.")]
+  [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 110)]
+  [StorableClass]
+  public sealed class BatchRun : NamedItem, IOptimizer, IStorableContent {
+    public string Filename { get; set; }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Event; }
+    }
+    public override Image ItemImage {
+      get {
+        if (ExecutionState == ExecutionState.Prepared) return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunPrepared;
+        else if (ExecutionState == ExecutionState.Started) return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunStarted;
+        else if (ExecutionState == ExecutionState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunPaused;
+        else if (ExecutionState == ExecutionState.Stopped) return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunStopped;
+        else return base.ItemImage;
+      }
+    }
+
+    [Storable]
+    private ExecutionState executionState;
+    public ExecutionState ExecutionState {
+      get { return executionState; }
+      private set {
+        if (executionState != value) {
+          executionState = value;
+          OnExecutionStateChanged();
+          OnItemImageChanged();
+        }
+      }
+    }
+
+    [Storable]
+    private TimeSpan executionTime;
+    public TimeSpan ExecutionTime {
+      get {
+        if ((Optimizer != null) && (Optimizer.ExecutionState != ExecutionState.Stopped))
+          return executionTime + Optimizer.ExecutionTime;
+        else
+          return executionTime;
+      }
+      private set {
+        executionTime = value;
+        OnExecutionTimeChanged();
+      }
+    }
+
+    [Storable]
+    private TimeSpan runsExecutionTime;
+
+    [Storable]
+    private IOptimizer optimizer;
+    public IOptimizer Optimizer {
+      get { return optimizer; }
+      set {
+        if (optimizer != value) {
+          if (optimizer != null) {
+            DeregisterOptimizerEvents();
+            IEnumerable<IRun> runs = optimizer.Runs;
+            optimizer = null; //necessary to avoid removing the runs from the old optimizer
+            Runs.RemoveRange(runs);
+          }
+          optimizer = value;
+          if (optimizer != null) {
+            RegisterOptimizerEvents();
+            Runs.AddRange(optimizer.Runs);
+          }
+          OnOptimizerChanged();
+          Prepare();
+        }
+      }
+    }
+    // BackwardsCompatibility3.3
+    #region Backwards compatible code (remove with 3.4)
+    [Storable(AllowOneWay = true)]
+    private IAlgorithm algorithm {
+      set { optimizer = value; }
+    }
+    #endregion
+
+    [Storable]
+    private int repetitions;
+    public int Repetitions {
+      get { return repetitions; }
+      set {
+        if (repetitions != value) {
+          repetitions = value;
+          OnRepetitionsChanged();
+          if ((Optimizer != null) && (Optimizer.ExecutionState == ExecutionState.Stopped))
+            Prepare();
+        }
+      }
+    }
+    [Storable]
+    private int repetitionsCounter;
+    public int RepetitionsCounter {
+      get { return repetitionsCounter; }
+      private set {
+        if (value != repetitionsCounter) {
+          repetitionsCounter = value;
+          OnRepetitionsCounterChanged();
+        }
+      }
+    }
+
+    [Storable]
+    private RunCollection runs;
+    public RunCollection Runs {
+      get { return runs; }
+      private set {
+        if (value == null) throw new ArgumentNullException();
+        if (runs != value) {
+          if (runs != null) DeregisterRunsEvents();
+          runs = value;
+          if (runs != null) RegisterRunsEvents();
+        }
+      }
+    }
+
+    public IEnumerable<IOptimizer> NestedOptimizers {
+      get {
+        if (Optimizer == null) yield break;
+
+        yield return Optimizer;
+        foreach (IOptimizer opt in Optimizer.NestedOptimizers)
+          yield return opt;
+      }
+    }
+
+    private BatchRunAction batchRunAction = BatchRunAction.None;
+
+    public BatchRun()
+      : base() {
+      name = ItemName;
+      description = ItemDescription;
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      runsExecutionTime = TimeSpan.Zero;
+      repetitions = 10;
+      repetitionsCounter = 0;
+      Runs = new RunCollection { OptimizerName = Name };
+    }
+    public BatchRun(string name)
+      : base(name) {
+      description = ItemDescription;
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      runsExecutionTime = TimeSpan.Zero;
+      repetitions = 10;
+      repetitionsCounter = 0;
+      Runs = new RunCollection { OptimizerName = Name };
+    }
+    public BatchRun(string name, string description)
+      : base(name, description) {
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      runsExecutionTime = TimeSpan.Zero;
+      repetitions = 10;
+      repetitionsCounter = 0;
+      Runs = new RunCollection { OptimizerName = Name };
+    }
+    [StorableConstructor]
+    private BatchRun(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      Initialize();
+    }
+
+    private BatchRun(BatchRun original, Cloner cloner)
+      : base(original, cloner) {
+      executionState = original.executionState;
+      executionTime = original.executionTime;
+      runsExecutionTime = original.runsExecutionTime;
+      optimizer = cloner.Clone(original.optimizer);
+      repetitions = original.repetitions;
+      repetitionsCounter = original.repetitionsCounter;
+      runs = cloner.Clone(original.runs);
+      batchRunAction = original.batchRunAction;
+      Initialize();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      if (ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
+      return new BatchRun(this, cloner);
+    }
+
+    private void Initialize() {
+      if (optimizer != null) RegisterOptimizerEvents();
+      if (runs != null) RegisterRunsEvents();
+    }
+
+    public void Prepare() {
+      Prepare(false);
+    }
+    public void Prepare(bool clearRuns) {
+      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
+        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
+      if (Optimizer != null) {
+        ExecutionTime = TimeSpan.Zero;
+        RepetitionsCounter = 0;
+        if (clearRuns) runs.Clear();
+        batchRunAction = BatchRunAction.Prepare;
+        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+        try { Optimizer.Prepare(clearRuns); }
+        catch (InvalidOperationException) { }
+      } else {
+        ExecutionState = ExecutionState.Stopped;
+      }
+    }
+    public void Start() {
+      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
+        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
+      if (Optimizer == null) return;
+      batchRunAction = BatchRunAction.Start;
+      if (Optimizer.ExecutionState == ExecutionState.Stopped) Optimizer.Prepare();
+      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+      try { Optimizer.Start(); }
+      catch (InvalidOperationException) { }
+    }
+    public void Pause() {
+      if (ExecutionState != ExecutionState.Started)
+        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
+      if (Optimizer == null) return;
+      batchRunAction = BatchRunAction.Pause;
+      if (Optimizer.ExecutionState != ExecutionState.Started) return;
+      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+      try { Optimizer.Pause(); }
+      catch (InvalidOperationException) { }
+    }
+    public void Stop() {
+      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
+        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
+      if (Optimizer == null) return;
+      batchRunAction = BatchRunAction.Stop;
+      if (Optimizer.ExecutionState != ExecutionState.Started && Optimizer.ExecutionState != ExecutionState.Paused) {
+        OnStopped();
+        return;
+      }
+      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+      try { Optimizer.Stop(); }
+      catch (InvalidOperationException) { }
+    }
+
+    #region Events
+    protected override void OnNameChanged() {
+      base.OnNameChanged();
+      runs.OptimizerName = Name;
+    }
+
+    public event EventHandler ExecutionStateChanged;
+    private void OnExecutionStateChanged() {
+      EventHandler handler = ExecutionStateChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ExecutionTimeChanged;
+    private void OnExecutionTimeChanged() {
+      EventHandler handler = ExecutionTimeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler OptimizerChanged;
+    private void OnOptimizerChanged() {
+      EventHandler handler = OptimizerChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RepetitionsChanged;
+    private void OnRepetitionsChanged() {
+      EventHandler handler = RepetitionsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RepetetionsCounterChanged;
+    private void OnRepetitionsCounterChanged() {
+      EventHandler handler = RepetetionsCounterChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Prepared;
+    private void OnPrepared() {
+      batchRunAction = BatchRunAction.None;
+      ExecutionState = ExecutionState.Prepared;
+      EventHandler handler = Prepared;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Started;
+    private void OnStarted() {
+      // no reset of BatchRunAction.Started, because we need to differ which of the two was started by the user
+      ExecutionState = ExecutionState.Started;
+      EventHandler handler = Started;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Paused;
+    private void OnPaused() {
+      batchRunAction = BatchRunAction.None;
+      ExecutionState = ExecutionState.Paused;
+      EventHandler handler = Paused;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Stopped;
+    private void OnStopped() {
+      batchRunAction = BatchRunAction.None;
+      ExecutionState = ExecutionState.Stopped;
+      EventHandler handler = Stopped;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
+    private void OnExceptionOccurred(Exception exception) {
+      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
+      if (handler != null) handler(this, new EventArgs<Exception>(exception));
+    }
+
+    private void RegisterOptimizerEvents() {
+      optimizer.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(Optimizer_ExceptionOccurred);
+      optimizer.ExecutionTimeChanged += new EventHandler(Optimizer_ExecutionTimeChanged);
+      optimizer.Paused += new EventHandler(Optimizer_Paused);
+      optimizer.Prepared += new EventHandler(Optimizer_Prepared);
+      optimizer.Started += new EventHandler(Optimizer_Started);
+      optimizer.Stopped += new EventHandler(Optimizer_Stopped);
+      optimizer.Runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_CollectionReset);
+      optimizer.Runs.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsAdded);
+      optimizer.Runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsRemoved);
+    }
+    private void DeregisterOptimizerEvents() {
+      optimizer.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(Optimizer_ExceptionOccurred);
+      optimizer.ExecutionTimeChanged -= new EventHandler(Optimizer_ExecutionTimeChanged);
+      optimizer.Paused -= new EventHandler(Optimizer_Paused);
+      optimizer.Prepared -= new EventHandler(Optimizer_Prepared);
+      optimizer.Started -= new EventHandler(Optimizer_Started);
+      optimizer.Stopped -= new EventHandler(Optimizer_Stopped);
+      optimizer.Runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_CollectionReset);
+      optimizer.Runs.ItemsAdded -= new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsAdded);
+      optimizer.Runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsRemoved);
+    }
+    private void Optimizer_ExceptionOccurred(object sender, EventArgs<Exception> e) {
+      OnExceptionOccurred(e.Value);
+    }
+    private void Optimizer_ExecutionTimeChanged(object sender, EventArgs e) {
+      OnExecutionTimeChanged();
+    }
+    private void Optimizer_Paused(object sender, EventArgs e) {
+      if (ExecutionState == ExecutionState.Started) {
+        OnPaused();
+      }
+    }
+    private void Optimizer_Prepared(object sender, EventArgs e) {
+      if (batchRunAction == BatchRunAction.Prepare || ExecutionState == ExecutionState.Stopped) {
+        ExecutionTime = TimeSpan.Zero;
+        runsExecutionTime = TimeSpan.Zero;
+        RepetitionsCounter = 0;
+        OnPrepared();
+      }
+    }
+    private void Optimizer_Started(object sender, EventArgs e) {
+      if (ExecutionState != ExecutionState.Started)
+        OnStarted();
+    }
+    private void Optimizer_Stopped(object sender, EventArgs e) {
+      RepetitionsCounter++;
+      ExecutionTime += runsExecutionTime;
+      runsExecutionTime = TimeSpan.Zero;
+
+      if (batchRunAction == BatchRunAction.Stop) OnStopped();
+      else if (repetitionsCounter >= repetitions) OnStopped();
+      else if (batchRunAction == BatchRunAction.Pause) OnPaused();
+      else if (batchRunAction == BatchRunAction.Start) {
+        Optimizer.Prepare();
+        Optimizer.Start();
+      } else if (executionState == ExecutionState.Started) {
+        // if the batch run hasn't been started but the inner optimizer was run then pause
+        OnPaused();
+      } else OnStopped();
+    }
+    private void Optimizer_Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      Runs.RemoveRange(e.OldItems);
+      Runs.AddRange(e.Items);
+    }
+    private void Optimizer_Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      Runs.AddRange(e.Items);
+    }
+    private void Optimizer_Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      Runs.RemoveRange(e.Items);
+    }
+
+    private void RegisterRunsEvents() {
+      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
+      runs.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsAdded);
+      runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
+    }
+
+    private void DeregisterRunsEvents() {
+      runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
+      runs.ItemsAdded -= new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsAdded);
+      runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
+    }
+    private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      if (Optimizer != null) Optimizer.Runs.RemoveRange(e.OldItems);
+      foreach (IRun run in e.Items) {
+        IItem item;
+        run.Results.TryGetValue("Execution Time", out item);
+        TimeSpanValue executionTime = item as TimeSpanValue;
+        if (executionTime != null) ExecutionTime += executionTime.Value;
+      }
+    }
+    private void Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      foreach (IRun run in e.Items) {
+        IItem item;
+        run.Results.TryGetValue("Execution Time", out item);
+        TimeSpanValue executionTime = item as TimeSpanValue;
+        if (executionTime != null) {
+          if (Optimizer.ExecutionState == ExecutionState.Started)
+            runsExecutionTime += executionTime.Value;
+          else
+            ExecutionTime += executionTime.Value;
+        }
+      }
+    }
+    private void Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      if (Optimizer != null) Optimizer.Runs.RemoveRange(e.Items);
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs	(revision 12526)
@@ -0,0 +1,412 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// An experiment which contains multiple algorithms, batch runs or other experiments.
+  /// </summary>
+  [Item("Experiment", "An experiment which contains multiple algorithms, batch runs or other experiments.")]
+  [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 100)]
+  [StorableClass]
+  public sealed class Experiment : NamedItem, IOptimizer, IStorableContent {
+    public string Filename { get; set; }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Event; }
+    }
+    public override Image ItemImage {
+      get {
+        if (ExecutionState == ExecutionState.Prepared) return HeuristicLab.Common.Resources.VSImageLibrary.ExperimentPrepared;
+        else if (ExecutionState == ExecutionState.Started) return HeuristicLab.Common.Resources.VSImageLibrary.ExperimentStarted;
+        else if (ExecutionState == ExecutionState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExperimentPaused;
+        else if (ExecutionState == ExecutionState.Stopped) return HeuristicLab.Common.Resources.VSImageLibrary.ExperimentStopped;
+        else return base.ItemImage;
+      }
+    }
+
+    [Storable]
+    private ExecutionState executionState;
+    public ExecutionState ExecutionState {
+      get { return executionState; }
+      private set {
+        if (executionState != value) {
+          executionState = value;
+          OnExecutionStateChanged();
+          OnItemImageChanged();
+        }
+      }
+    }
+
+    [Storable]
+    private TimeSpan executionTime;
+    public TimeSpan ExecutionTime {
+      get { return executionTime; }
+      private set {
+        executionTime = value;
+        OnExecutionTimeChanged();
+      }
+    }
+
+    [Storable]
+    private OptimizerList optimizers;
+    public OptimizerList Optimizers {
+      get { return optimizers; }
+    }
+
+    [Storable]
+    private RunCollection runs;
+    public RunCollection Runs {
+      get { return runs; }
+      private set {
+        if (value == null) throw new ArgumentNullException();
+        if (runs != value) {
+          if (runs != null) DeregisterRunsEvents();
+          runs = value;
+          if (runs != null) RegisterRunsEvents();
+        }
+      }
+    }
+
+    public IEnumerable<IOptimizer> NestedOptimizers {
+      get {
+        if (Optimizers == null) yield break;
+
+        foreach (IOptimizer opt in Optimizers) {
+          yield return opt;
+          foreach (IOptimizer nestedOpt in opt.NestedOptimizers)
+            yield return nestedOpt;
+        }
+      }
+    }
+
+    private bool experimentStarted = false;
+    private bool experimentStopped = false;
+
+    public Experiment()
+      : base() {
+      name = ItemName;
+      description = ItemDescription;
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      optimizers = new OptimizerList();
+      Runs = new RunCollection { OptimizerName = Name };
+      Initialize();
+    }
+    public Experiment(string name)
+      : base(name) {
+      description = ItemDescription;
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      optimizers = new OptimizerList();
+      Runs = new RunCollection { OptimizerName = Name };
+      Initialize();
+    }
+    public Experiment(string name, string description)
+      : base(name, description) {
+      executionState = ExecutionState.Stopped;
+      executionTime = TimeSpan.Zero;
+      optimizers = new OptimizerList();
+      Runs = new RunCollection { OptimizerName = Name };
+      Initialize();
+    }
+    [StorableConstructor]
+    private Experiment(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      Initialize();
+    }
+    private Experiment(Experiment original, Cloner cloner)
+      : base(original, cloner) {
+      executionState = original.executionState;
+      executionTime = original.executionTime;
+      optimizers = cloner.Clone(original.optimizers);
+      runs = cloner.Clone(original.runs);
+
+      experimentStarted = original.experimentStarted;
+      experimentStopped = original.experimentStopped;
+      Initialize();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      if (ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
+      return new Experiment(this, cloner);
+    }
+
+    private void Initialize() {
+      RegisterOptimizersEvents();
+      foreach (IOptimizer optimizer in optimizers)
+        RegisterOptimizerEvents(optimizer);
+      if (runs != null) RegisterRunsEvents();
+    }
+
+    public void Prepare() {
+      Prepare(false);
+    }
+    public void Prepare(bool clearRuns) {
+      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
+        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
+      if (Optimizers.Count == 0) return;
+
+      if (clearRuns) runs.Clear();
+
+      experimentStarted = false;
+      experimentStopped = false;
+      foreach (IOptimizer optimizer in Optimizers.Where(x => x.ExecutionState != ExecutionState.Started)) {
+        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+        try { optimizer.Prepare(clearRuns); }
+        catch (InvalidOperationException) { }
+      }
+    }
+    public void Start() {
+      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
+        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
+      if (Optimizers.Count == 0) return;
+
+      experimentStarted = true;
+      experimentStopped = false;
+      IOptimizer optimizer = Optimizers.FirstOrDefault(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused));
+      if (optimizer != null) {
+        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+        try { optimizer.Start(); }
+        catch (InvalidOperationException) { }
+      }
+    }
+    public void Pause() {
+      if (ExecutionState != ExecutionState.Started)
+        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
+      if (Optimizers.Count == 0) return;
+
+      experimentStarted = false;
+      experimentStopped = false;
+      foreach (IOptimizer optimizer in Optimizers.Where(x => x.ExecutionState == ExecutionState.Started)) {
+        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+        try { optimizer.Pause(); }
+        catch (InvalidOperationException) { }
+      }
+    }
+    public void Stop() {
+      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
+        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
+      if (Optimizers.Count == 0) return;
+
+      experimentStarted = false;
+      experimentStopped = true;
+      if (Optimizers.Any(x => (x.ExecutionState == ExecutionState.Started) || (x.ExecutionState == ExecutionState.Paused))) {
+        foreach (var optimizer in Optimizers.Where(x => (x.ExecutionState == ExecutionState.Started) || (x.ExecutionState == ExecutionState.Paused))) {
+          // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+          try { optimizer.Stop(); }
+          catch (InvalidOperationException) { }
+        }
+      } else {
+        OnStopped();
+      }
+    }
+
+    #region Events
+    protected override void OnNameChanged() {
+      base.OnNameChanged();
+      Runs.OptimizerName = Name;
+    }
+
+    public event EventHandler ExecutionStateChanged;
+    private void OnExecutionStateChanged() {
+      EventHandler handler = ExecutionStateChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ExecutionTimeChanged;
+    private void OnExecutionTimeChanged() {
+      EventHandler handler = ExecutionTimeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Prepared;
+    private void OnPrepared() {
+      ExecutionState = ExecutionState.Prepared;
+      EventHandler handler = Prepared;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Started;
+    private void OnStarted() {
+      ExecutionState = ExecutionState.Started;
+      EventHandler handler = Started;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Paused;
+    private void OnPaused() {
+      ExecutionState = ExecutionState.Paused;
+      EventHandler handler = Paused;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Stopped;
+    private void OnStopped() {
+      ExecutionState = ExecutionState.Stopped;
+      EventHandler handler = Stopped;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
+    private void OnExceptionOccurred(Exception exception) {
+      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
+      if (handler != null) handler(this, new EventArgs<Exception>(exception));
+    }
+
+    private void RegisterOptimizersEvents() {
+      Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
+      Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
+      Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
+      Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
+    }
+    private void DeregisterOptimizersEvents() {
+      Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
+      Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
+      Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
+      Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
+    }
+    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
+      foreach (IndexedItem<IOptimizer> item in e.OldItems)
+        RemoveOptimizer(item.Value);
+      foreach (IndexedItem<IOptimizer> item in e.Items)
+        AddOptimizer(item.Value);
+    }
+    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
+      foreach (IndexedItem<IOptimizer> item in e.Items)
+        AddOptimizer(item.Value);
+    }
+    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
+      foreach (IndexedItem<IOptimizer> item in e.Items)
+        RemoveOptimizer(item.Value);
+    }
+    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
+      foreach (IndexedItem<IOptimizer> item in e.OldItems)
+        RemoveOptimizer(item.Value);
+      foreach (IndexedItem<IOptimizer> item in e.Items)
+        AddOptimizer(item.Value);
+    }
+    private void AddOptimizer(IOptimizer optimizer) {
+      RegisterOptimizerEvents(optimizer);
+      Runs.AddRange(optimizer.Runs);
+      optimizer.Prepare();
+      if (ExecutionState == ExecutionState.Stopped && optimizer.ExecutionState == ExecutionState.Prepared)
+        OnPrepared();
+    }
+    private void RemoveOptimizer(IOptimizer optimizer) {
+      DeregisterOptimizerEvents(optimizer);
+      Runs.RemoveRange(optimizer.Runs);
+      if (ExecutionState == ExecutionState.Prepared && !optimizers.Any(opt => opt.ExecutionState == ExecutionState.Prepared))
+        OnStopped();
+    }
+
+    private void RegisterOptimizerEvents(IOptimizer optimizer) {
+      optimizer.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(optimizer_ExceptionOccurred);
+      optimizer.ExecutionTimeChanged += new EventHandler(optimizer_ExecutionTimeChanged);
+      optimizer.Paused += new EventHandler(optimizer_Paused);
+      optimizer.Prepared += new EventHandler(optimizer_Prepared);
+      optimizer.Started += new EventHandler(optimizer_Started);
+      optimizer.Stopped += new EventHandler(optimizer_Stopped);
+      optimizer.Runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_CollectionReset);
+      optimizer.Runs.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsAdded);
+      optimizer.Runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsRemoved);
+    }
+    private void DeregisterOptimizerEvents(IOptimizer optimizer) {
+      optimizer.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(optimizer_ExceptionOccurred);
+      optimizer.ExecutionTimeChanged -= new EventHandler(optimizer_ExecutionTimeChanged);
+      optimizer.Paused -= new EventHandler(optimizer_Paused);
+      optimizer.Prepared -= new EventHandler(optimizer_Prepared);
+      optimizer.Started -= new EventHandler(optimizer_Started);
+      optimizer.Stopped -= new EventHandler(optimizer_Stopped);
+      optimizer.Runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_CollectionReset);
+      optimizer.Runs.ItemsAdded -= new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsAdded);
+      optimizer.Runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsRemoved);
+    }
+
+    private readonly object locker = new object();
+    private void optimizer_ExceptionOccurred(object sender, EventArgs<Exception> e) {
+      lock (locker)
+        OnExceptionOccurred(e.Value);
+    }
+    private void optimizer_ExecutionTimeChanged(object sender, EventArgs e) {
+      lock (locker)
+        ExecutionTime = Optimizers.Aggregate(TimeSpan.Zero, (t, o) => t + o.ExecutionTime);
+    }
+    private void optimizer_Paused(object sender, EventArgs e) {
+      lock (locker)
+        if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started)) OnPaused();
+    }
+    private void optimizer_Prepared(object sender, EventArgs e) {
+      lock (locker)
+        if (Optimizers.All(x => x.ExecutionState == ExecutionState.Prepared)) OnPrepared();
+    }
+    private void optimizer_Started(object sender, EventArgs e) {
+      lock (locker)
+        if (ExecutionState != ExecutionState.Started) OnStarted();
+    }
+    private void optimizer_Stopped(object sender, EventArgs e) {
+      lock (locker) {
+        if (experimentStopped) {
+          if (Optimizers.All(x => (x.ExecutionState == ExecutionState.Stopped) || (x.ExecutionState == ExecutionState.Prepared))) OnStopped();
+        } else {
+          if (experimentStarted && Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused))) {
+            Optimizers.First(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused)).Start();
+          } else if (Optimizers.All(x => x.ExecutionState == ExecutionState.Stopped)) OnStopped();
+          else if (Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused)) && Optimizers.All(o => o.ExecutionState != ExecutionState.Started)) OnPaused();
+        }
+      }
+    }
+    private void optimizer_Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      lock (locker) {
+        Runs.RemoveRange(e.OldItems);
+        Runs.AddRange(e.Items);
+      }
+    }
+    private void optimizer_Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      lock (locker)
+        Runs.AddRange(e.Items);
+    }
+    private void optimizer_Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      lock (locker)
+        Runs.RemoveRange(e.Items);
+    }
+
+    private void RegisterRunsEvents() {
+      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
+      runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
+    }
+    private void DeregisterRunsEvents() {
+      runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
+      runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
+    }
+    private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      foreach (IOptimizer optimizer in Optimizers)
+        optimizer.Runs.RemoveRange(e.OldItems);
+    }
+    private void Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      foreach (IOptimizer optimizer in Optimizers)
+        optimizer.Runs.RemoveRange(e.Items);
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/MoveHelper.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/MoveHelper.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/MoveHelper.cs	(revision 12526)
@@ -0,0 +1,66 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// This class provides some methods useful when dealing with moves, such as getting compatible move makers to a move generator.
+  /// Compatibility is generally ensured in that both the generator and the move maker implement the same specific interface which is derived from IMoveOperator
+  /// </summary>
+  public static class MoveHelper {
+
+    public static IEnumerable<IMoveMaker> GetCompatibleMoveMakers(IMoveGenerator generator, IEnumerable<IOperator> operators) {
+      return GetCompatibleOperators<IMoveMaker>(generator, operators);
+    }
+
+    public static IEnumerable<ISingleObjectiveMoveEvaluator> GetCompatibleSingleObjectiveMoveEvaluators(IMoveGenerator generator, IEnumerable<IOperator> operators) {
+      return GetCompatibleOperators<ISingleObjectiveMoveEvaluator>(generator, operators);
+    }
+
+    public static IEnumerable<ITabuChecker> GetCompatibleTabuChekers(IMoveGenerator generator, IEnumerable<IOperator> operators) {
+      return GetCompatibleOperators<ITabuChecker>(generator, operators);
+    }
+
+    public static IEnumerable<ITabuMaker> GetCompatibleTabuMakers(IMoveGenerator generator, IEnumerable<IOperator> operators) {
+      return GetCompatibleOperators<ITabuMaker>(generator, operators);
+    }
+
+    private static IEnumerable<T> GetCompatibleOperators<T>(IMoveGenerator generator, IEnumerable<IOperator> operators) where T : IOperator {
+      foreach (Type type in GetMostSpecificMoveOperatorTypes(generator)) {
+        foreach (T op in operators.Where(x => type.IsAssignableFrom(x.GetType())).OfType<T>())
+          yield return op;
+      }
+    }
+
+    private static List<Type> GetMostSpecificMoveOperatorTypes(IMoveGenerator generator) {
+      List<Type> moveTypes = generator.GetType().GetInterfaces().Where(x => typeof(IMoveOperator).IsAssignableFrom(x)).ToList();
+      foreach (Type type in moveTypes.ToList()) {
+        if (moveTypes.Any(t => t != type && type.IsAssignableFrom(t)))
+          moveTypes.Remove(type);
+      }
+      return moveTypes;
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/OptimizerList.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/OptimizerList.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/OptimizerList.cs	(revision 12526)
@@ -0,0 +1,43 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Optimizer List", "Represents a list of optimizers.")]
+  [StorableClass]
+  public class OptimizerList : ItemList<IOptimizer> {
+    public OptimizerList() : base() { }
+    public OptimizerList(int capacity) : base(capacity) { }
+    public OptimizerList(IEnumerable<IOptimizer> collection) : base(collection) { }
+    [StorableConstructor]
+    protected OptimizerList(bool deserializing) : base(deserializing) { }
+    protected OptimizerList(OptimizerList original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OptimizerList(this, cloner);
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Plugin.cs.frame
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Plugin.cs.frame	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Plugin.cs.frame	(revision 12526)
@@ -0,0 +1,40 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Plugin class for HeuristicLab.Optimization plugin.
+  /// </summary>
+  [Plugin("HeuristicLab.Optimization", "3.3.11.$WCREV$")]
+  [PluginFile("HeuristicLab.Optimization-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  public class HeuristicLabOptimizationPlugin : PluginBase {
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/HeuristicOptimizationProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/HeuristicOptimizationProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/HeuristicOptimizationProblem.cs	(revision 12526)
@@ -0,0 +1,112 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Heuristic Optimization Problem", "Represents the base class for a heuristic optimization problem.")]
+  [StorableClass]
+  public abstract class HeuristicOptimizationProblem<T, U> : Problem, IHeuristicOptimizationProblem
+    where T : class,IEvaluator
+    where U : class,ISolutionCreator {
+    private const string EvaluatorParameterName = "Evaluator";
+    private const string SolutionCreateParameterName = "SolutionCreator";
+
+    [StorableConstructor]
+    protected HeuristicOptimizationProblem(bool deserializing) : base(deserializing) { }
+    protected HeuristicOptimizationProblem(HeuristicOptimizationProblem<T, U> original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+
+    protected HeuristicOptimizationProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<T>(EvaluatorParameterName, "The operator used to evaluate a solution."));
+      Parameters.Add(new ValueParameter<U>(SolutionCreateParameterName, "The operator to create a solution."));
+      RegisterEventHandlers();
+    }
+
+    protected HeuristicOptimizationProblem(T evaluator, U solutionCreator)
+      : base() {
+      Parameters.Add(new ValueParameter<T>(EvaluatorParameterName, "The operator used to evaluate a solution.", evaluator));
+      Parameters.Add(new ValueParameter<U>(SolutionCreateParameterName, "The operator to create a solution.", solutionCreator));
+      RegisterEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      EvaluatorParameter.ValueChanged += new EventHandler(EvaluatorParameter_ValueChanged);
+      SolutionCreatorParameter.ValueChanged += new EventHandler(SolutionCreatorParameter_ValueChanged);
+    }
+
+    #region properties
+    public T Evaluator {
+      get { return EvaluatorParameter.Value; }
+      protected set { EvaluatorParameter.Value = value; }
+    }
+    public ValueParameter<T> EvaluatorParameter {
+      get { return (ValueParameter<T>)Parameters[EvaluatorParameterName]; }
+    }
+    IEvaluator IHeuristicOptimizationProblem.Evaluator { get { return Evaluator; } }
+    IParameter IHeuristicOptimizationProblem.EvaluatorParameter { get { return EvaluatorParameter; } }
+
+    public U SolutionCreator {
+      get { return (U)SolutionCreatorParameter.Value; }
+      protected set { SolutionCreatorParameter.Value = value; }
+    }
+    public IValueParameter SolutionCreatorParameter {
+      get { return (IValueParameter)Parameters[SolutionCreateParameterName]; }
+    }
+    ISolutionCreator IHeuristicOptimizationProblem.SolutionCreator { get { return SolutionCreator; } }
+    IParameter IHeuristicOptimizationProblem.SolutionCreatorParameter { get { return SolutionCreatorParameter; } }
+    #endregion
+
+    #region events
+    private void EvaluatorParameter_ValueChanged(object sender, EventArgs e) {
+      OnEvaluatorChanged();
+    }
+    public event EventHandler EvaluatorChanged;
+    protected virtual void OnEvaluatorChanged() {
+      EventHandler handler = EvaluatorChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    protected virtual void SolutionCreatorParameter_ValueChanged(object sender, EventArgs e) {
+      OnSolutionCreatorChanged();
+    }
+    public event EventHandler SolutionCreatorChanged;
+    protected virtual void OnSolutionCreatorChanged() {
+      EventHandler handler = SolutionCreatorChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/MultiObjectiveHeuristicOptimizationProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/MultiObjectiveHeuristicOptimizationProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/MultiObjectiveHeuristicOptimizationProblem.cs	(revision 12526)
@@ -0,0 +1,64 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Multi-Objective Heuristic Optimization Problem", "A base class for multi-objective heuristic optimization problems.")]
+  [StorableClass]
+  public abstract class MultiObjectiveHeuristicOptimizationProblem<T, U> : HeuristicOptimizationProblem<T, U>, IMultiObjectiveHeuristicOptimizationProblem
+    where T : class, IMultiObjectiveEvaluator
+    where U : class, ISolutionCreator {
+    private const string MaximizationParameterName = "Maximization";
+
+    [StorableConstructor]
+    protected MultiObjectiveHeuristicOptimizationProblem(bool deserializing) : base(deserializing) { }
+    protected MultiObjectiveHeuristicOptimizationProblem(MultiObjectiveHeuristicOptimizationProblem<T, U> original, Cloner cloner) : base(original, cloner) { }
+    protected MultiObjectiveHeuristicOptimizationProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<BoolArray>(MaximizationParameterName, "Determines for each objective whether it should be maximized or minimized."));
+    }
+
+    protected MultiObjectiveHeuristicOptimizationProblem(T evaluator, U solutionCreator)
+      : base(evaluator, solutionCreator) {
+      Parameters.Add(new ValueParameter<BoolArray>(MaximizationParameterName, "Determines for each objective whether it should be maximized or minimized."));
+    }
+
+    public ValueParameter<BoolArray> MaximizationParameter {
+      get { return (ValueParameter<BoolArray>)Parameters[MaximizationParameterName]; }
+    }
+    IParameter IMultiObjectiveHeuristicOptimizationProblem.MaximizationParameter {
+      get { return MaximizationParameter; }
+    }
+    public BoolArray Maximization {
+      get { return MaximizationParameter.Value; }
+      protected set { MaximizationParameter.Value = value; }
+    }
+
+    IMultiObjectiveEvaluator IMultiObjectiveHeuristicOptimizationProblem.Evaluator {
+      get { return Evaluator; }
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/Problem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/Problem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/Problem.cs	(revision 12526)
@@ -0,0 +1,155 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Problem", "Represents the base class for a problem.")]
+  [StorableClass]
+  public abstract class Problem : ParameterizedNamedItem, IProblem {
+    private const string OperatorsParameterName = "Operators";
+    public IFixedValueParameter<ItemCollection<IItem>> OperatorsParameter {
+      get { return (IFixedValueParameter<ItemCollection<IItem>>)Parameters[OperatorsParameterName]; }
+    }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
+    }
+
+    [StorableConstructor]
+    protected Problem(bool deserializing) : base(deserializing) { }
+    protected Problem(Problem original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+
+    protected Problem()
+      : base() {
+      Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>(), false));
+      OperatorsParameter.Hidden = true;
+      RegisterEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      IParameter operatorsParam;
+      if (Parameters.TryGetValue(OperatorsParameterName, out operatorsParam)) {
+        var operators = operatorsParam.ActualValue as OperatorCollection;
+        if (operators != null) {
+          Parameters.Remove(OperatorsParameterName);
+          Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>(operators), false));
+          OperatorsParameter.Hidden = true;
+        }
+      }
+      #endregion
+
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      Operators.ItemsAdded += new CollectionItemsChangedEventHandler<IItem>(Operators_Changed);
+      Operators.ItemsRemoved += new CollectionItemsChangedEventHandler<IItem>(Operators_Changed);
+      Operators.CollectionReset += new CollectionItemsChangedEventHandler<IItem>(Operators_Changed);
+    }
+
+    #region properties
+    // BackwardsCompatibility3.3
+    #region Backwards compatible code, remove with 3.4
+    [Storable(Name = "Operators", AllowOneWay = true)]
+    private IEnumerable<IOperator> StorableOperators {
+      set {
+        IParameter operatorsParam;
+        if (Parameters.TryGetValue(OperatorsParameterName, out operatorsParam)) {
+          var items = operatorsParam.ActualValue as ItemCollection<IItem>;
+          if (items == null) Parameters.Remove(operatorsParam);
+        }
+
+        //necessary to convert old experiments files where no parameter was used for saving the operators
+        if (!Parameters.ContainsKey(OperatorsParameterName)) {
+          Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>(), false));
+          OperatorsParameter.Hidden = true;
+        }
+        if (value != null) Operators.AddRange(value);
+      }
+    }
+    #endregion
+    protected ItemCollection<IItem> Operators {
+      get {
+        // BackwardsCompatibility3.3
+        #region Backwards compatible code, remove with 3.4
+        if (!Parameters.ContainsKey(OperatorsParameterName)) {
+          Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>(), false));
+          OperatorsParameter.Hidden = true;
+        }
+        #endregion
+        return OperatorsParameter.Value;
+      }
+    }
+    IEnumerable<IItem> IProblem.Operators { get { return GetOperators(); } }
+
+    protected virtual IEnumerable<IItem> GetOperators() {
+      return Operators;
+    }
+
+    public virtual IEnumerable<IParameterizedItem> ExecutionContextItems {
+      get { yield return this; }
+    }
+    #endregion
+
+    protected override IEnumerable<KeyValuePair<string, IItem>> GetCollectedValues(IValueParameter param) {
+      var children = base.GetCollectedValues(param);
+      foreach (var child in children) {
+        if (child.Value is IOperator)
+          yield return new KeyValuePair<string, IItem>(child.Key, new StringValue(((IOperator)child.Value).Name));
+        else yield return child;
+      }
+    }
+
+    #region events
+    private void Operators_Changed(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+    public event EventHandler OperatorsChanged;
+    protected virtual void OnOperatorsChanged() {
+      EventHandler handler = OperatorsChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Reset;
+    protected virtual void OnReset() {
+      EventHandler handler = Reset;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/SingleObjectiveHeuristicOptimizationProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/SingleObjectiveHeuristicOptimizationProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/SingleObjectiveHeuristicOptimizationProblem.cs	(revision 12526)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Single-Objective Heuristic OptimizationProblem", "A base class for single-objective heuristic optimization problems.")]
+  [StorableClass]
+  public abstract class SingleObjectiveHeuristicOptimizationProblem<T, U> : HeuristicOptimizationProblem<T, U>, ISingleObjectiveHeuristicOptimizationProblem
+    where T : class, ISingleObjectiveEvaluator
+    where U : class, ISolutionCreator {
+    private const string MaximizationParameterName = "Maximization";
+    private const string BestKnownQualityParameterName = "BestKnownQuality";
+
+    [StorableConstructor]
+    protected SingleObjectiveHeuristicOptimizationProblem(bool deserializing) : base(deserializing) { }
+    protected SingleObjectiveHeuristicOptimizationProblem(SingleObjectiveHeuristicOptimizationProblem<T, U> original, Cloner cloner) : base(original, cloner) { }
+    protected SingleObjectiveHeuristicOptimizationProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<BoolValue>(MaximizationParameterName, "Set to false if the problem should be minimized.", new BoolValue()));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>(BestKnownQualityParameterName, "The quality of the best known solution of this problem."));
+    }
+
+    protected SingleObjectiveHeuristicOptimizationProblem(T evaluator, U solutionCreator)
+      : base(evaluator, solutionCreator) {
+      Parameters.Add(new ValueParameter<BoolValue>(MaximizationParameterName, "Set to false if the problem should be minimized.", new BoolValue()));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>(BestKnownQualityParameterName, "The quality of the best known solution of this problem."));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code (remove with 3.4)
+      if (BestKnownQualityParameter is ValueParameter<DoubleValue>) {
+        Parameters.Remove(BestKnownQualityParameterName);
+        Parameters.Add(new OptionalValueParameter<DoubleValue>(BestKnownQualityParameterName, "The quality of the best known solution of this problem."));
+      }
+      #endregion
+    }
+    public ValueParameter<BoolValue> MaximizationParameter {
+      get { return (ValueParameter<BoolValue>)Parameters[MaximizationParameterName]; }
+    }
+    IParameter ISingleObjectiveHeuristicOptimizationProblem.MaximizationParameter {
+      get { return MaximizationParameter; }
+    }
+    public BoolValue Maximization {
+      get { return MaximizationParameter.Value; }
+      set { MaximizationParameter.Value = value; }
+    }
+
+    public IValueParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters[BestKnownQualityParameterName]; }
+    }
+    IParameter ISingleObjectiveHeuristicOptimizationProblem.BestKnownQualityParameter {
+      get { return BestKnownQualityParameter; }
+    }
+    public DoubleValue BestKnownQuality {
+      get { return BestKnownQualityParameter.Value; }
+      set { BestKnownQualityParameter.Value = value; }
+    }
+
+    ISingleObjectiveEvaluator ISingleObjectiveHeuristicOptimizationProblem.Evaluator {
+      get { return Evaluator; }
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/UserDefinedProblem.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/UserDefinedProblem.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Problems/UserDefinedProblem.cs	(revision 12526)
@@ -0,0 +1,283 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// A problem which can be defined by the user.
+  /// </summary>
+  [Item("User-Defined Problem", "A problem which can be defined by the user.")]
+  [Creatable(CreatableAttribute.Categories.Problems, Priority = 120)]
+  [StorableClass]
+  public sealed class UserDefinedProblem : ParameterizedNamedItem, ISingleObjectiveHeuristicOptimizationProblem, IStorableContent {
+    public string Filename { get; set; }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
+    }
+    public new ParameterCollection Parameters {
+      get { return base.Parameters; }
+    }
+    IKeyedItemCollection<string, IParameter> IParameterizedItem.Parameters {
+      get { return Parameters; }
+    }
+
+    #region Parameters
+    public IValueParameter<ISingleObjectiveEvaluator> EvaluatorParameter {
+      get { return (IValueParameter<ISingleObjectiveEvaluator>)Parameters["Evaluator"]; }
+    }
+    public ValueParameter<BoolValue> MaximizationParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    IParameter ISingleObjectiveHeuristicOptimizationProblem.MaximizationParameter {
+      get { return MaximizationParameter; }
+    }
+    public ValueParameter<ISolutionCreator> SolutionCreatorParameter {
+      get { return (ValueParameter<ISolutionCreator>)Parameters["SolutionCreator"]; }
+    }
+    IParameter IHeuristicOptimizationProblem.SolutionCreatorParameter {
+      get { return SolutionCreatorParameter; }
+    }
+    IParameter IHeuristicOptimizationProblem.EvaluatorParameter {
+      get { return EvaluatorParameter; }
+    }
+    public OptionalValueParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (OptionalValueParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    IParameter ISingleObjectiveHeuristicOptimizationProblem.BestKnownQualityParameter {
+      get { return BestKnownQualityParameter; }
+    }
+    public OptionalValueParameter<IScope> BestKnownSolutionParameter {
+      get { return (OptionalValueParameter<IScope>)Parameters["BestKnownSolution"]; }
+    }
+    public ValueParameter<ItemList<IItem>> OperatorsParameter {
+      get { return (ValueParameter<ItemList<IItem>>)Parameters["Operators"]; }
+    }
+    #endregion
+
+    #region Properties
+    public BoolValue Maximization {
+      get { return MaximizationParameter.Value; }
+      set { MaximizationParameter.Value = value; }
+    }
+    public ISolutionCreator SolutionCreator {
+      get { return SolutionCreatorParameter.Value; }
+      set { SolutionCreatorParameter.Value = value; }
+    }
+    ISolutionCreator IHeuristicOptimizationProblem.SolutionCreator {
+      get { return SolutionCreatorParameter.Value; }
+    }
+    public ISingleObjectiveEvaluator Evaluator {
+      get { return EvaluatorParameter.Value; }
+      set { EvaluatorParameter.Value = value; }
+    }
+    ISingleObjectiveEvaluator ISingleObjectiveHeuristicOptimizationProblem.Evaluator {
+      get { return EvaluatorParameter.Value; }
+    }
+    IEvaluator IHeuristicOptimizationProblem.Evaluator {
+      get { return EvaluatorParameter.Value; }
+    }
+    public DoubleValue BestKnownQuality {
+      get { return BestKnownQualityParameter.Value; }
+      set { BestKnownQualityParameter.Value = value; }
+    }
+    public IEnumerable<IItem> Operators {
+      get { return OperatorsParameter.Value; }
+    }
+
+    public IEnumerable<IParameterizedItem> ExecutionContextItems {
+      get { yield return this; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private UserDefinedProblem(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (Parameters.ContainsKey("Operators") && Parameters["Operators"] is ValueParameter<ItemList<IOperator>>) {
+        ItemList<IOperator> tmp = ((ValueParameter<ItemList<IOperator>>)Parameters["Operators"]).Value;
+        Parameters.Remove("Operators");
+        Parameters.Add(new ValueParameter<ItemList<IItem>>("Operators", "The operators and items that the problem provides to the algorithms.", new ItemList<IItem>(tmp), false));
+      }
+      #endregion
+
+      RegisterEventHandlers();
+    }
+    public UserDefinedProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<ISingleObjectiveEvaluator>("Evaluator", "The evaluator that collects the values to exchange.", new EmptyUserDefinedProblemEvaluator()));
+      Parameters.Add(new ValueParameter<ISolutionCreator>("SolutionCreator", "An operator to create the solution components."));
+      Parameters.Add(new ValueParameter<BoolValue>("Maximization", "Set to false as most test functions are minimization problems.", new BoolValue(false)));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this problem."));
+      Parameters.Add(new OptionalValueParameter<IScope>("BestKnownSolution", "The best known solution for this external evaluation problem."));
+      Parameters.Add(new ValueParameter<ItemList<IItem>>("Operators", "The operators and items that the problem provides to the algorithms.", new ItemList<IItem>()));
+
+      RegisterEventHandlers();
+    }
+
+    private UserDefinedProblem(UserDefinedProblem original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new UserDefinedProblem(this, cloner);
+    }
+
+    #region Events
+    public event EventHandler SolutionCreatorChanged;
+    private void OnSolutionCreatorChanged() {
+      EventHandler handler = SolutionCreatorChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler EvaluatorChanged;
+    private void OnEvaluatorChanged() {
+      EventHandler handler = EvaluatorChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler OperatorsChanged;
+    private void OnOperatorsChanged() {
+      EventHandler handler = OperatorsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Reset;
+    private void OnReset() {
+      EventHandler handler = Reset;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    #region Event handlers
+    private void SolutionCreatorParameter_ValueChanged(object sender, EventArgs e) {
+      OnSolutionCreatorChanged();
+    }
+    private void EvaluatorParameter_ValueChanged(object sender, EventArgs e) {
+      if (Evaluator != null)
+        Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+      ParameterizeOperators();
+      OnEvaluatorChanged();
+    }
+    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
+      ParameterizeOperators();
+    }
+    private void OperatorsParameter_ValueChanged(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+    private void OperatorsParameter_Value_ItemsAdded(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+    private void OperatorsParameter_Value_ItemsRemoved(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+    private void OperatorsParameter_Value_CollectionReset(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+    #endregion
+
+    #region Helpers
+    private void RegisterEventHandlers() {
+      SolutionCreatorParameter.ValueChanged += new EventHandler(SolutionCreatorParameter_ValueChanged);
+      EvaluatorParameter.ValueChanged += new EventHandler(EvaluatorParameter_ValueChanged);
+      if (Evaluator != null)
+        Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+      OperatorsParameter.ValueChanged += new EventHandler(OperatorsParameter_ValueChanged);
+      OperatorsParameter.Value.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IItem>>(OperatorsParameter_Value_ItemsAdded);
+      OperatorsParameter.Value.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IItem>>(OperatorsParameter_Value_ItemsRemoved);
+      OperatorsParameter.Value.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IItem>>(OperatorsParameter_Value_CollectionReset);
+    }
+
+    private void ParameterizeOperators() {
+      // A best effort approach to wiring
+      if (Evaluator != null) {
+        string qualityName = Evaluator.QualityParameter.ActualName;
+        foreach (IOperator op in OperatorsParameter.Value.OfType<IOperator>()) {
+          foreach (ILookupParameter<DoubleValue> param in op.Parameters.OfType<ILookupParameter<DoubleValue>>()) {
+            if (param.Name.Equals("Quality")) param.ActualName = qualityName;
+          }
+          foreach (IScopeTreeLookupParameter<DoubleValue> param in op.Parameters.OfType<IScopeTreeLookupParameter<DoubleValue>>()) {
+            if (param.Name.Equals("Quality")) param.ActualName = qualityName;
+          }
+        }
+      }
+    }
+    #endregion
+
+    [Item("EmptyUserDefinedProblemEvaluator", "A dummy evaluator that will throw an exception when executed.")]
+    [StorableClass]
+    [NonDiscoverableType]
+    private sealed class EmptyUserDefinedProblemEvaluator : ParameterizedNamedItem, ISingleObjectiveEvaluator {
+
+      [StorableConstructor]
+      private EmptyUserDefinedProblemEvaluator(bool deserializing) : base(deserializing) { }
+      private EmptyUserDefinedProblemEvaluator(EmptyUserDefinedProblemEvaluator original, Cloner cloner)
+        : base(original, cloner) {
+      }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new EmptyUserDefinedProblemEvaluator(this, cloner);
+      }
+
+      #region ISingleObjectiveEvaluator Members
+
+      public ILookupParameter<DoubleValue> QualityParameter {
+        get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+      }
+
+      #endregion
+
+      public EmptyUserDefinedProblemEvaluator() {
+        Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The solution quality."));
+      }
+
+      #region IOperator Members
+
+      public bool Breakpoint { get; set; }
+
+      public IOperation Execute(IExecutionContext context, CancellationToken cancellationToken) {
+        throw new InvalidOperationException("Please choose an appropriate evaluation operator.");
+      }
+
+#pragma warning disable 67
+      public event EventHandler BreakpointChanged;
+
+      public event EventHandler Executed;
+#pragma warning restore 67
+
+      #endregion
+
+      public static new Image StaticItemImage {
+        get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; }
+      }
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Properties/AssemblyInfo.cs.frame	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Properties/AssemblyInfo.cs.frame	(revision 12526)
@@ -0,0 +1,56 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Optimization")]
+[assembly: AssemblyDescription("HeuristicLab optimization classes")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2015 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("4b3c29b7-1df7-41d2-aebf-b20fab8de1ee")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.11.$WCREV$")]
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Result.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Result.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Result.cs	(revision 12526)
@@ -0,0 +1,157 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Represents a result which has a name and a data type and holds an IItem.
+  /// </summary>
+  [Item("Result", "A result which has a name and a data type and holds an IItem.")]
+  [StorableClass]
+  public sealed class Result : NamedItem, IResult, IStorableContent {
+    public string Filename { get; set; }
+
+    public override Image ItemImage {
+      get {
+        if (value != null) return value.ItemImage;
+        else return base.ItemImage;
+      }
+    }
+
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public override bool CanChangeDescription {
+      get { return false; }
+    }
+
+    [Storable]
+    private Type dataType;
+    public Type DataType {
+      get { return dataType; }
+    }
+
+    [Storable]
+    private IItem value;
+    public IItem Value {
+      get { return value; }
+      set {
+        if (this.value != value) {
+          if ((value != null) && (!dataType.IsInstanceOfType(value)))
+            throw new ArgumentException(
+              string.Format("Type mismatch. Value is not a \"{0}\".",
+                            dataType.GetPrettyName())
+            );
+
+          DeregisterValueEvents();
+          this.value = value;
+          RegisterValueEvents();
+          OnValueChanged();
+        }
+      }
+    }
+
+    [StorableConstructor]
+    private Result(bool deserializing) : base(deserializing) { }
+    private Result(Result original, Cloner cloner)
+      : base(original, cloner) {
+      dataType = original.dataType;
+      value = cloner.Clone(original.value);
+      Initialize();
+    }
+    public Result()
+      : base("Anonymous") {
+      this.dataType = typeof(IItem);
+      this.value = null;
+    }
+    public Result(string name, Type dataType)
+      : base(name) {
+      this.dataType = dataType;
+      this.value = null;
+    }
+    public Result(string name, string description, Type dataType)
+      : base(name, description) {
+      this.dataType = dataType;
+      this.value = null;
+    }
+    public Result(string name, IItem value)
+      : base(name) {
+      this.dataType = value == null ? typeof(IItem) : value.GetType();
+      this.value = value;
+      Initialize();
+    }
+    public Result(string name, string description, IItem value)
+      : base(name, description) {
+      this.dataType = value == null ? typeof(IItem) : value.GetType();
+      this.value = value;
+      Initialize();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      Initialize();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Result(this, cloner);
+    }
+
+    private void Initialize() {
+      RegisterValueEvents();
+    }
+
+    public override string ToString() {
+      return string.Format("{0}: {1}", Name, Value == null ? "null" : Value.ToString());
+    }
+
+    public event EventHandler ValueChanged;
+    private void OnValueChanged() {
+      var handler = ValueChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+      OnItemImageChanged();
+      OnToStringChanged();
+    }
+
+    private void RegisterValueEvents() {
+      if (value != null) {
+        value.ItemImageChanged += new EventHandler(Value_ItemImageChanged);
+        value.ToStringChanged += new EventHandler(Value_ToStringChanged);
+      }
+    }
+    private void DeregisterValueEvents() {
+      if (value != null) {
+        value.ItemImageChanged -= new EventHandler(Value_ItemImageChanged);
+        value.ToStringChanged -= new EventHandler(Value_ToStringChanged);
+      }
+    }
+    private void Value_ItemImageChanged(object sender, EventArgs e) {
+      OnItemImageChanged();
+    }
+    private void Value_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/ResultCollection.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/ResultCollection.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/ResultCollection.cs	(revision 12526)
@@ -0,0 +1,78 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  [Item("ResultCollection", "Represents a collection of results.")]
+  public class ResultCollection : NamedItemCollection<IResult> {
+    public ResultCollection() : base() { }
+    public ResultCollection(int capacity) : base(capacity) { }
+    public ResultCollection(IEnumerable<IResult> collection) : base(collection) { }
+    [StorableConstructor]
+    protected ResultCollection(bool deserializing) : base(deserializing) { }
+    protected ResultCollection(ResultCollection original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ResultCollection(this, cloner);
+    }
+
+    public static new System.Drawing.Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Object; }
+    }
+
+    public virtual void CollectResultValues(IDictionary<string, IItem> values) {
+      CollectResultValues(values, string.Empty);
+    }
+
+    public virtual void CollectResultValues(IDictionary<string, IItem> values, string rootPath) {
+      foreach (IResult result in this) {
+        var children = GetCollectedResults(result);
+        string path = string.Empty;
+        if (!string.IsNullOrWhiteSpace(rootPath))
+          path = rootPath + ".";
+        foreach (var c in children) {
+          if (string.IsNullOrEmpty(c.Key))
+            values.Add(path + result.Name, c.Value);
+          else values.Add(path + result.Name + "." + c.Key, c.Value);
+        }
+      }
+    }
+
+    protected virtual IEnumerable<KeyValuePair<string, IItem>> GetCollectedResults(IResult result) {
+      if (result.Value == null) yield break;
+      yield return new KeyValuePair<string, IItem>(string.Empty, result.Value);
+
+      var resultCollection = result.Value as ResultCollection;
+      if (resultCollection != null) {
+        var children = new Dictionary<string, IItem>();
+        resultCollection.CollectResultValues(children);
+        foreach (var child in children) yield return child;
+      }
+    }
+
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Run.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Run.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/Run.cs	(revision 12526)
@@ -0,0 +1,190 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  /// <summary>
+  /// Represents the parameters and results of an algorithm run.
+  /// </summary>
+  [Item("Run", "The parameters and results of an algorithm run.")]
+  [StorableClass]
+  public sealed class Run : NamedItem, IRun, IStorableContent {
+    public string Filename { get; set; }
+
+    [StorableConstructor]
+    private Run(bool deserializing) : base(deserializing) { }
+    private Run(Run original, Cloner cloner)
+      : base(original, cloner) {
+      color = original.color;
+      algorithm = cloner.Clone(original.algorithm);
+
+      parameters = new ObservableDictionary<string, IItem>();
+      foreach (string key in original.parameters.Keys)
+        parameters.Add(key, cloner.Clone(original.parameters[key]));
+
+      results = new ObservableDictionary<string, IItem>();
+      foreach (string key in original.results.Keys)
+        results.Add(key, cloner.Clone(original.results[key]));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Run(this, cloner);
+    }
+
+    public Run()
+      : base() {
+      name = ItemName;
+      description = ItemDescription;
+      color = Color.Black;
+      algorithm = null;
+      parameters = new ObservableDictionary<string, IItem>();
+      results = new ObservableDictionary<string, IItem>();
+    }
+    public Run(IAlgorithm algorithm)
+      : base() {
+      if (algorithm == null) throw new ArgumentNullException();
+      name = algorithm.Name + " Run (" + algorithm.ExecutionTime.ToString() + ")";
+      description = ItemDescription;
+      color = Color.Black;
+      Initialize(algorithm);
+    }
+    public Run(string name, IAlgorithm algorithm)
+      : base(name) {
+      if (algorithm == null) throw new ArgumentNullException();
+      color = Color.Black;
+      description = ItemDescription;
+      Initialize(algorithm);
+    }
+    public Run(string name, string description, IAlgorithm algorithm)
+      : base(name, description) {
+      if (algorithm == null) throw new ArgumentNullException();
+      color = Color.Black;
+      Initialize(algorithm);
+    }
+
+    private void Initialize(IAlgorithm algorithm) {
+      parameters = new ObservableDictionary<string, IItem>();
+      results = new ObservableDictionary<string, IItem>();
+
+      if (algorithm.StoreAlgorithmInEachRun) {
+        var clone = (IAlgorithm)algorithm.Clone();
+        clone.CollectParameterValues(parameters);
+        clone.CollectResultValues(results);
+        clone.Runs.Clear();
+        this.algorithm = clone;
+      } else {
+        var par = new Dictionary<string, IItem>();
+        var res = new Dictionary<string, IItem>();
+        algorithm.CollectParameterValues(par);
+        algorithm.CollectResultValues(res);
+        var cloner = new Cloner();
+        foreach (var k in par) parameters.Add(k.Key, cloner.Clone(k.Value));
+        foreach (var k in res) results.Add(k.Key, cloner.Clone(k.Value));
+      }
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (color == Color.Empty) color = Color.Black;
+    }
+
+    [Storable]
+    private IAlgorithm algorithm;
+    public IAlgorithm Algorithm {
+      get { return algorithm; }
+    }
+
+    [Storable(Name = "parameters")]
+    private IDictionary<string, IItem> StorableParameters {
+      get { return parameters; }
+      set {
+        if (!(value is IObservableDictionary<string, IItem>))
+          parameters = new ObservableDictionary<string, IItem>(value);
+        else parameters = (IObservableDictionary<string, IItem>)value;
+      }
+    }
+    private IObservableDictionary<string, IItem> parameters;
+    public IObservableDictionary<string, IItem> Parameters {
+      get { return parameters; }
+      private set {
+        if (parameters != value) {
+          parameters = value;
+          OnPropertyChanged("Parameters");
+        }
+      }
+    }
+
+    [Storable(Name = "results")]
+    private IDictionary<string, IItem> StorableResults {
+      get { return results; }
+      set {
+        if (!(value is IObservableDictionary<string, IItem>))
+          results = new ObservableDictionary<string, IItem>(value);
+        else results = (IObservableDictionary<string, IItem>)value;
+      }
+    }
+    private IObservableDictionary<string, IItem> results;
+    public IObservableDictionary<string, IItem> Results {
+      get { return results; }
+      private set {
+        if (results != value) {
+          results = value;
+          OnPropertyChanged("Results");
+        }
+      }
+    }
+
+    [Storable]
+    private Color color;
+    public Color Color {
+      get { return this.color; }
+      set {
+        if (color != value) {
+          this.color = value;
+          OnPropertyChanged("Color");
+        }
+      }
+    }
+    private bool visible = true;
+    public bool Visible {
+      get { return this.visible; }
+      set {
+        if (visible != value) {
+          this.visible = value;
+          OnPropertyChanged("Visible");
+        }
+      }
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    private void OnPropertyChanged(string property) {
+      var handler = PropertyChanged;
+      if (handler != null) handler(this, new PropertyChangedEventArgs(property));
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollection.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollection.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollection.cs	(revision 12526)
@@ -0,0 +1,591 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("Run Collection", "Represents a collection of runs.")]
+  [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 120)]
+  [StorableClass]
+  public class RunCollection : ItemCollection<IRun>, IStringConvertibleMatrix, IStorableContent {
+    public string Filename { get; set; }
+
+    [StorableConstructor]
+    protected RunCollection(bool deserializing)
+      : base(deserializing) {
+      updateOfRunsInProgress = false;
+    }
+    protected RunCollection(RunCollection original, Cloner cloner)
+      : base(original, cloner) {
+      updateOfRunsInProgress = false;
+      optimizerName = original.optimizerName;
+
+      resultNames = new List<string>(original.resultNames);
+      parameterNames = new List<string>(original.parameterNames);
+      dataTypes = new Dictionary<string, HashSet<Type>>();
+      foreach (string s in original.dataTypes.Keys)
+        dataTypes[s] = new HashSet<Type>(original.dataTypes[s]);
+
+      constraints = new RunCollectionConstraintCollection(original.constraints.Select(x => cloner.Clone(x)));
+      modifiers = new CheckedItemList<IRunCollectionModifier>(original.modifiers.Select(cloner.Clone));
+      foreach (IRunCollectionConstraint constraint in constraints)
+        constraint.ConstrainedValue = this;
+      RegisterConstraintsEvents();
+      RegisterConstraintEvents(constraints);
+
+      foreach (var run in this) {
+        RegisterRunParametersEvents(run);
+        RegisterRunResultsEvents(run);
+      }
+
+      UpdateFiltering(true);
+    }
+    public RunCollection() : base() { Initialize(); }
+    public RunCollection(int capacity) : base(capacity) { Initialize(); }
+    public RunCollection(IEnumerable<IRun> collection) : base(collection) { Initialize(); this.OnItemsAdded(collection); }
+    private void Initialize() {
+      updateOfRunsInProgress = false;
+      parameterNames = new List<string>();
+      resultNames = new List<string>();
+      dataTypes = new Dictionary<string, HashSet<Type>>();
+      constraints = new RunCollectionConstraintCollection();
+      modifiers = new CheckedItemList<IRunCollectionModifier>();
+      RegisterConstraintsEvents();
+    }
+
+    [Storable]
+    private Dictionary<string, HashSet<Type>> dataTypes;
+    public IEnumerable<Type> GetDataType(string columnName) {
+      if (!dataTypes.ContainsKey(columnName))
+        return new Type[0];
+      return dataTypes[columnName];
+    }
+
+    [Storable]
+    private RunCollectionConstraintCollection constraints;
+    public RunCollectionConstraintCollection Constraints {
+      get { return constraints; }
+    }
+
+    [Storable]
+    private CheckedItemList<IRunCollectionModifier> modifiers;
+    public CheckedItemList<IRunCollectionModifier> Modifiers {
+      get { return modifiers; }
+    }
+
+
+    private bool updateOfRunsInProgress;
+    public bool UpdateOfRunsInProgress {
+      get { return updateOfRunsInProgress; }
+      set {
+        if (updateOfRunsInProgress != value) {
+          updateOfRunsInProgress = value;
+          OnUpdateOfRunsInProgressChanged();
+        }
+      }
+    }
+
+    private string optimizerName = string.Empty;
+    [Storable]
+    public string OptimizerName {
+      get { return optimizerName; }
+      set {
+        if (value != optimizerName && !string.IsNullOrEmpty(value)) {
+          optimizerName = value;
+          OnOptimizerNameChanged();
+        }
+      }
+    }
+
+    // BackwardsCompatibility3.3
+    #region Backwards compatible code, remove with 3.4
+    [Storable(AllowOneWay = true)]
+    private string AlgorithmName {
+      set { optimizerName = value; }
+    }
+    #endregion
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (constraints == null) constraints = new RunCollectionConstraintCollection();
+      if (modifiers == null) modifiers = new CheckedItemList<IRunCollectionModifier>();
+      RegisterConstraintsEvents();
+      RegisterConstraintEvents(constraints);
+
+      foreach (var run in this) {
+        RegisterRunParametersEvents(run);
+        RegisterRunResultsEvents(run);
+      }
+      UpdateFiltering(true);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollection(this, cloner);
+    }
+
+    public event EventHandler UpdateOfRunsInProgressChanged;
+    protected virtual void OnUpdateOfRunsInProgressChanged() {
+      var handler = UpdateOfRunsInProgressChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler OptimizerNameChanged;
+    protected virtual void OnOptimizerNameChanged() {
+      var handler = OptimizerNameChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    protected override void OnCollectionReset(IEnumerable<IRun> items, IEnumerable<IRun> oldItems) {
+      parameterNames.Clear();
+      resultNames.Clear();
+      dataTypes.Clear();
+      foreach (IRun run in items) {
+        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
+          AddParameter(parameter.Key, parameter.Value);
+        foreach (KeyValuePair<string, IItem> result in run.Results)
+          AddResult(result.Key, result.Value);
+        run.PropertyChanged += RunOnPropertyChanged;
+        RegisterRunParametersEvents(run);
+        RegisterRunResultsEvents(run);
+      }
+      foreach (IRun run in oldItems) {
+        run.PropertyChanged -= RunOnPropertyChanged;
+        DeregisterRunParametersEvents(run);
+        DeregisterRunResultsEvents(run);
+      }
+      columnNameCache = null;
+      OnColumnsChanged();
+      OnColumnNamesChanged();
+      rowNamesCache = null;
+      base.OnCollectionReset(items, oldItems);
+      OnRowsChanged();
+      OnRowNamesChanged();
+      OnReset();
+      UpdateFiltering(false);
+    }
+    protected override void OnItemsAdded(IEnumerable<IRun> items) {
+      bool columnsChanged = false;
+      foreach (IRun run in items) {
+        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
+          columnsChanged |= AddParameter(parameter.Key, parameter.Value);
+        foreach (KeyValuePair<string, IItem> result in run.Results)
+          columnsChanged |= AddResult(result.Key, result.Value);
+        run.PropertyChanged += RunOnPropertyChanged;
+        RegisterRunParametersEvents(run);
+        RegisterRunResultsEvents(run);
+      }
+      if (columnsChanged) columnNameCache = null;
+      rowNamesCache = null;
+      base.OnItemsAdded(items);
+      OnReset();
+      OnRowsChanged();
+      OnRowNamesChanged();
+      if (columnsChanged) {
+        OnColumnsChanged();
+        OnColumnNamesChanged();
+      }
+      UpdateFiltering(false);
+    }
+    protected override void OnItemsRemoved(IEnumerable<IRun> items) {
+      bool columnsChanged = false;
+      foreach (IRun run in items) {
+        foreach (string parameterName in run.Parameters.Keys)
+          columnsChanged |= RemoveParameterName(parameterName);
+        foreach (string resultName in run.Results.Keys)
+          columnsChanged |= RemoveResultName(resultName);
+        run.PropertyChanged -= RunOnPropertyChanged;
+        DeregisterRunParametersEvents(run);
+        DeregisterRunResultsEvents(run);
+      }
+      if (columnsChanged) columnNameCache = null;
+      rowNamesCache = null;
+      base.OnItemsRemoved(items);
+      OnReset();
+      OnRowsChanged();
+      OnRowNamesChanged();
+      if (columnsChanged) {
+        OnColumnsChanged();
+        OnColumnNamesChanged();
+      }
+    }
+
+    private void RunOnPropertyChanged(object sender, PropertyChangedEventArgs e) {
+      if (e.PropertyName == "Parameters") {
+        RegisterRunParametersEvents((IRun)sender);
+      } else if (e.PropertyName == "Results") {
+        RegisterRunResultsEvents((IRun)sender);
+      }
+    }
+
+    private void RegisterRunParametersEvents(IRun run) {
+      IObservableDictionary<string, IItem> dict = run.Parameters;
+      dict.ItemsAdded += RunOnParameterChanged;
+      dict.ItemsRemoved += RunOnParameterRemoved;
+      dict.ItemsReplaced += RunOnParameterChanged;
+      dict.CollectionReset += RunOnParameterChanged;
+    }
+
+    private void RegisterRunResultsEvents(IRun run) {
+      IObservableDictionary<string, IItem> dict = run.Results;
+      dict.ItemsAdded += RunOnResultChanged;
+      dict.ItemsRemoved += RunOnResultRemoved;
+      dict.ItemsReplaced += RunOnResultChanged;
+      dict.CollectionReset += RunOnResultChanged;
+    }
+
+    private void DeregisterRunParametersEvents(IRun run) {
+      IObservableDictionary<string, IItem> dict = run.Parameters;
+      dict.ItemsAdded -= RunOnParameterChanged;
+      dict.ItemsRemoved -= RunOnParameterRemoved;
+      dict.ItemsReplaced -= RunOnParameterChanged;
+      dict.CollectionReset -= RunOnParameterChanged;
+    }
+
+    private void DeregisterRunResultsEvents(IRun run) {
+      IObservableDictionary<string, IItem> dict = run.Results;
+      dict.ItemsAdded -= RunOnResultChanged;
+      dict.ItemsRemoved -= RunOnResultRemoved;
+      dict.ItemsReplaced -= RunOnResultChanged;
+      dict.CollectionReset -= RunOnResultChanged;
+    }
+
+    private void RunOnParameterChanged(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
+      bool columnsChanged = false;
+      foreach (var param in e.Items)
+        columnsChanged |= AddParameter(param.Key, param.Value);
+      foreach (var param in e.OldItems)
+        columnsChanged |= RemoveParameterName(param.Key);
+      if (columnsChanged) columnNameCache = null;
+      OnReset();
+      if (columnsChanged) {
+        OnColumnsChanged();
+        OnColumnNamesChanged();
+      }
+    }
+
+    private void RunOnParameterRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
+      bool columnsChanged = false;
+      foreach (var param in e.Items)
+        columnsChanged |= RemoveParameterName(param.Key);
+      if (columnsChanged) columnNameCache = null;
+      OnReset();
+      if (columnsChanged) {
+        OnColumnsChanged();
+        OnColumnNamesChanged();
+      }
+    }
+
+    private void RunOnResultChanged(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
+      bool columnsChanged = false;
+      foreach (var result in e.Items)
+        columnsChanged |= AddResult(result.Key, result.Value);
+      foreach (var result in e.OldItems)
+        columnsChanged |= RemoveResultName(result.Key);
+      if (columnsChanged) columnNameCache = null;
+      OnReset();
+      if (columnsChanged) {
+        OnColumnsChanged();
+        OnColumnNamesChanged();
+      }
+    }
+
+    private void RunOnResultRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
+      bool columnsChanged = false;
+      foreach (var result in e.Items)
+        columnsChanged |= RemoveResultName(result.Key);
+      if (columnsChanged) columnNameCache = null;
+      OnReset();
+      if (columnsChanged) {
+        OnColumnsChanged();
+        OnColumnNamesChanged();
+      }
+    }
+
+    private bool AddParameter(string name, IItem value) {
+      if (value == null)
+        return false;
+      if (!parameterNames.Contains(name)) {
+        parameterNames.Add(name);
+        dataTypes[name] = new HashSet<Type>();
+        dataTypes[name].Add(value.GetType());
+        return true;
+      }
+      dataTypes[name].Add(value.GetType());
+      return false;
+    }
+    private bool AddResult(string name, IItem value) {
+      if (value == null)
+        return false;
+      if (!resultNames.Contains(name)) {
+        resultNames.Add(name);
+        dataTypes[name] = new HashSet<Type>();
+        dataTypes[name].Add(value.GetType());
+        return true;
+      }
+      dataTypes[name].Add(value.GetType());
+      return false;
+    }
+    private bool RemoveParameterName(string name) {
+      if (!list.Any(x => x.Parameters.ContainsKey(name))) {
+        parameterNames.Remove(name);
+        return true;
+      }
+      return false;
+    }
+    private bool RemoveResultName(string name) {
+      if (!list.Any(x => x.Results.ContainsKey(name))) {
+        resultNames.Remove(name);
+        return true;
+      }
+      return false;
+    }
+
+    public IItem GetValue(int rowIndex, int columnIndex) {
+      IRun run = this.list[rowIndex];
+      return GetValue(run, columnIndex);
+    }
+
+    public IItem GetValue(IRun run, int columnIndex) {
+      string name = ((IStringConvertibleMatrix)this).ColumnNames.ElementAt(columnIndex);
+      return GetValue(run, name);
+    }
+
+    public IItem GetValue(IRun run, string columnName) {
+      IItem value = null;
+      if (run.Parameters.ContainsKey(columnName))
+        value = run.Parameters[columnName];
+      else if (run.Results.ContainsKey(columnName))
+        value = run.Results[columnName];
+      return value;
+    }
+
+    #region IStringConvertibleMatrix Members
+    [Storable]
+    private List<string> parameterNames;
+    public IEnumerable<string> ParameterNames {
+      get { return this.parameterNames; }
+    }
+    [Storable]
+    private List<string> resultNames;
+    public IEnumerable<string> ResultNames {
+      get { return this.resultNames; }
+    }
+    int IStringConvertibleMatrix.Rows {
+      get { return this.Count; }
+      set { throw new NotSupportedException(); }
+    }
+    int IStringConvertibleMatrix.Columns {
+      get { return parameterNames.Count + resultNames.Count; }
+      set { throw new NotSupportedException(); }
+    }
+    private List<string> columnNameCache;
+    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
+      get {
+        if (columnNameCache == null) {
+          columnNameCache = new List<string>(parameterNames);
+          columnNameCache.AddRange(resultNames);
+          columnNameCache.Sort();
+        }
+        return columnNameCache;
+      }
+      set { throw new NotSupportedException(); }
+    }
+    private List<string> rowNamesCache;
+    IEnumerable<string> IStringConvertibleMatrix.RowNames {
+      get {
+        if (rowNamesCache == null)
+          rowNamesCache = list.Select(x => x.Name).ToList();
+        return rowNamesCache;
+      }
+      set { throw new NotSupportedException(); }
+    }
+    bool IStringConvertibleMatrix.SortableView {
+      get { return true; }
+      set { throw new NotSupportedException(); }
+    }
+    bool IStringConvertibleMatrix.ReadOnly {
+      get { return true; }
+    }
+
+    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
+      IItem value = GetValue(rowIndex, columnIndex);
+      if (value == null)
+        return string.Empty;
+      return value.ToString();
+    }
+
+    public event EventHandler<EventArgs<int, int>> ItemChanged;
+    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
+      EventHandler<EventArgs<int, int>> handler = ItemChanged;
+      if (handler != null) handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
+      OnToStringChanged();
+    }
+    public event EventHandler Reset;
+    protected virtual void OnReset() {
+      EventHandler handler = Reset;
+      if (handler != null) handler(this, EventArgs.Empty);
+      OnToStringChanged();
+    }
+    public event EventHandler ColumnsChanged;
+    protected virtual void OnColumnsChanged() {
+      var handler = ColumnsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowsChanged;
+    protected virtual void OnRowsChanged() {
+      var handler = RowsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ColumnNamesChanged;
+    protected virtual void OnColumnNamesChanged() {
+      EventHandler handler = ColumnNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowNamesChanged;
+    protected virtual void OnRowNamesChanged() {
+      EventHandler handler = RowNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler SortableViewChanged;
+    protected virtual void OnSortableViewChanged() {
+      EventHandler handler = SortableViewChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public bool Validate(string value, out string errorMessage) { throw new NotSupportedException(); }
+    public bool SetValue(string value, int rowIndex, int columnIndex) { throw new NotSupportedException(); }
+    #endregion
+
+    #region Filtering
+    private void UpdateFiltering(bool reset) {
+      UpdateOfRunsInProgress = true;
+      if (reset)
+        list.ForEach(r => r.Visible = true);
+      foreach (IRunCollectionConstraint constraint in this.constraints)
+        constraint.Check();
+      UpdateOfRunsInProgress = false;
+    }
+
+    private void RegisterConstraintsEvents() {
+      constraints.ItemsAdded += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsAdded);
+      constraints.ItemsRemoved += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsRemoved);
+      constraints.CollectionReset += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_CollectionReset);
+    }
+
+    private void RegisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
+      foreach (IRunCollectionConstraint constraint in constraints) {
+        constraint.ActiveChanged += new EventHandler(Constraint_ActiveChanged);
+        constraint.ConstrainedValueChanged += new EventHandler(Constraint_ConstrainedValueChanged);
+        constraint.ConstraintOperationChanged += new EventHandler(Constraint_ConstraintOperationChanged);
+        constraint.ConstraintDataChanged += new EventHandler(Constraint_ConstraintDataChanged);
+      }
+    }
+    private void DeregisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
+      foreach (IRunCollectionConstraint constraint in constraints) {
+        constraint.ActiveChanged -= new EventHandler(Constraint_ActiveChanged);
+        constraint.ConstrainedValueChanged -= new EventHandler(Constraint_ConstrainedValueChanged);
+        constraint.ConstraintOperationChanged -= new EventHandler(Constraint_ConstraintOperationChanged);
+        constraint.ConstraintDataChanged -= new EventHandler(Constraint_ConstraintDataChanged);
+      }
+    }
+
+    protected virtual void Constraints_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
+      DeregisterConstraintEvents(e.OldItems);
+      RegisterConstraintEvents(e.Items);
+      this.UpdateFiltering(true);
+    }
+    protected virtual void Constraints_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
+      RegisterConstraintEvents(e.Items);
+      foreach (IRunCollectionConstraint constraint in e.Items)
+        constraint.ConstrainedValue = this;
+      this.UpdateFiltering(false);
+    }
+    protected virtual void Constraints_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
+      DeregisterConstraintEvents(e.Items);
+      this.UpdateFiltering(true);
+    }
+    protected virtual void Constraint_ActiveChanged(object sender, EventArgs e) {
+      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
+      this.UpdateFiltering(!constraint.Active);
+    }
+    protected virtual void Constraint_ConstrainedValueChanged(object sender, EventArgs e) {
+      //mkommend: this method is intentionally left empty, because the constrainedValue is set in the ItemsAdded method
+    }
+    protected virtual void Constraint_ConstraintOperationChanged(object sender, EventArgs e) {
+      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
+      if (constraint.Active)
+        this.UpdateFiltering(true);
+    }
+    protected virtual void Constraint_ConstraintDataChanged(object sender, EventArgs e) {
+      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
+      if (constraint.Active)
+        this.UpdateFiltering(true);
+    }
+    #endregion
+
+    #region Modification
+    public void Modify() {
+      UpdateOfRunsInProgress = true;
+      var runs = this.ToList();
+      var selectedRuns = runs.Where(r => r.Visible).ToList();
+      int nSelected = selectedRuns.Count;
+      if (nSelected > 0) {
+        foreach (var modifier in Modifiers.CheckedItems)
+          modifier.Value.Modify(selectedRuns);
+        if (nSelected != selectedRuns.Count || HaveDifferentOrder(selectedRuns, runs.Where(r => r.Visible))) {
+          Clear();
+          AddRange(ReplaceVisibleRuns(runs, selectedRuns));
+        } else if (runs.Count > 0) {
+          OnCollectionReset(this, runs);
+        }
+      }
+      UpdateOfRunsInProgress = false;
+    }
+
+    private static IEnumerable<IRun> ReplaceVisibleRuns(IEnumerable<IRun> runs, IEnumerable<IRun> visibleRuns) {
+      var newRuns = new List<IRun>();
+      var runIt = runs.GetEnumerator();
+      var visibleRunIt = visibleRuns.GetEnumerator();
+      while (runIt.MoveNext()) {
+        if (runIt.Current != null && !runIt.Current.Visible)
+          newRuns.Add(runIt.Current);
+        else if (visibleRunIt.MoveNext())
+          newRuns.Add(visibleRunIt.Current);
+      }
+      while (visibleRunIt.MoveNext())
+        newRuns.Add(visibleRunIt.Current);
+      return newRuns;
+    }
+
+    private static bool HaveDifferentOrder(IEnumerable<IRun> l1, IEnumerable<IRun> l2) {
+      return l1.Zip(l2, (r1, r2) => r1 != r2).Any();
+    }
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/IRunCollectionConstraint.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/IRunCollectionConstraint.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/IRunCollectionConstraint.cs	(revision 12526)
@@ -0,0 +1,34 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Core;
+
+namespace HeuristicLab.Optimization {
+  public interface IRunCollectionConstraint : IConstraint {
+    new RunCollection ConstrainedValue { get; set; }
+  }
+
+  public interface IRunCollectionColumnConstraint : IRunCollectionConstraint {
+    string ConstraintColumn { get; set; }
+    event EventHandler ConstraintColumnChanged;
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionComparisonConstraint.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionComparisonConstraint.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionComparisonConstraint.cs	(revision 12526)
@@ -0,0 +1,139 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  [Item("RunCollectionComparisonConstraint", "A constraint which compares the members of the contained runs with the constraint data.")]
+  public class RunCollectionComparisonConstraint : ComparisonConstraint, IRunCollectionColumnConstraint {
+    [StorableConstructor]
+    protected RunCollectionComparisonConstraint(bool deserializing) : base(deserializing) { }
+
+    protected RunCollectionComparisonConstraint(RunCollectionComparisonConstraint original, Cloner cloner)
+      : base(original, cloner) {
+      constraintColumn = original.constraintColumn;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionComparisonConstraint(this, cloner);
+    }
+
+    public RunCollectionComparisonConstraint() : base() { }
+    public RunCollectionComparisonConstraint(RunCollection constrainedValue, ConstraintOperation constraintOperation, object constraintData)
+      : base(constrainedValue, constraintOperation, constraintData) {
+    }
+    public RunCollectionComparisonConstraint(RunCollection constrainedValue, ConstraintOperation constraintOperation, object constraintData, bool active)
+      : base(constrainedValue, constraintOperation, constraintData, active) {
+    }
+
+    public new RunCollection ConstrainedValue {
+      get { return (RunCollection)base.ConstrainedValue; }
+      set { base.ConstrainedValue = value; }
+    }
+
+    public new IStringConvertibleValue ConstraintData {
+      get { return (IStringConvertibleValue)base.ConstraintData; }
+      set {
+        if (!(value is IComparable))
+          throw new ArgumentException("Only IComparables allowed for ConstraintData");
+        base.ConstraintData = value;
+      }
+    }
+
+    [Storable]
+    private string constraintColumn;
+    public string ConstraintColumn {
+      get { return constraintColumn; }
+      set {
+        if (!((IStringConvertibleMatrix)ConstrainedValue).ColumnNames.Contains(value))
+          throw new ArgumentException("Could not set ConstraintData to not existing column index.");
+        if (constraintColumn != value) {
+          constraintColumn = value;
+          this.OnConstraintColumnChanged();
+          this.OnToStringChanged();
+        }
+      }
+    }
+
+    public event EventHandler ConstraintColumnChanged;
+    protected virtual void OnConstraintColumnChanged() {
+      EventHandler handler = ConstraintColumnChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    protected override void OnConstrainedValueChanged() {
+      base.OnConstrainedValueChanged();
+      IStringConvertibleMatrix matrix = (IStringConvertibleMatrix)ConstrainedValue;
+      if (constraintColumn == null && ConstrainedValue != null && matrix.Columns != 0)
+        constraintColumn = matrix.ColumnNames.ElementAt(0);
+    }
+
+    protected override bool Check(object constrainedMember) {
+      if (!Active)
+        return true;
+
+      foreach (IRun run in ConstrainedValue.Where(r => r.Visible)) {
+        IItem item = ConstrainedValue.GetValue(run, constraintColumn);
+        if (!base.Check(item))
+          run.Visible = false;
+      }
+      return true;
+    }
+
+    protected override bool Check(object constrainedMember, out string errorMessage) {
+      errorMessage = string.Empty;
+      if (!Active)
+        return true;
+
+      foreach (IRun run in ConstrainedValue.Where(r => r.Visible)) {
+        IItem item = ConstrainedValue.GetValue(run, constraintColumn);
+        if (!base.Check(item))
+          run.Visible = false;
+      }
+      return true;
+    }
+
+    public override string ToString() {
+      string s = string.Empty;
+      IStringConvertibleMatrix matrix = ConstrainedValue;
+      if (matrix != null && matrix.ColumnNames.Count() != 0)
+        s += constraintColumn + " ";
+      else
+        return "ComparisonConstraint";
+
+      if (ConstraintOperation != null)
+        s += ConstraintOperation.ToString() + " ";
+
+      if (ConstraintData != null)
+        s += ConstraintData.GetValue();
+      else
+        s += "null";
+
+      return s;
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionConstraintCollection.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionConstraintCollection.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionConstraintCollection.cs	(revision 12526)
@@ -0,0 +1,42 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  [Item("RunCollectionConstraintCollection", "Represents a collection of constraints.")]
+  public class RunCollectionConstraintCollection : ItemCollection<IRunCollectionConstraint> {
+    public RunCollectionConstraintCollection() : base() { }
+    public RunCollectionConstraintCollection(int capacity) : base(capacity) { }
+    public RunCollectionConstraintCollection(IEnumerable<IRunCollectionConstraint> collection) : base(collection) { }
+    [StorableConstructor]
+    protected RunCollectionConstraintCollection(bool deserializing) : base(deserializing) { }
+    protected RunCollectionConstraintCollection(RunCollectionConstraintCollection original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionConstraintCollection(this, cloner);
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionContentConstraint.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionContentConstraint.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionContentConstraint.cs	(revision 12526)
@@ -0,0 +1,107 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  public class RunCollectionContentConstraint : Constraint, IRunCollectionConstraint {
+    public new RunCollection ConstrainedValue {
+      get { return (RunCollection)base.ConstrainedValue; }
+      set { base.ConstrainedValue = value; }
+    }
+
+    public new ItemSet<IRun> ConstraintData {
+      get { return (ItemSet<IRun>)base.ConstraintData; }
+      set { base.ConstraintData = value; }
+    }
+
+    public override IEnumerable<ConstraintOperation> AllowedConstraintOperations {
+      get { return new List<ConstraintOperation>() { ConstraintOperation.Equal }; }
+    }
+
+    [StorableConstructor]
+    protected RunCollectionContentConstraint(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterConstraintDataEvents();
+    }
+    protected RunCollectionContentConstraint(RunCollectionContentConstraint original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterConstraintDataEvents();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new RunCollectionContentConstraint(this, cloner); }
+
+    public RunCollectionContentConstraint()
+      : base() {
+      ConstraintData = new ItemSet<IRun>();
+    }
+    public RunCollectionContentConstraint(RunCollection constrainedValue, IObservableSet<IRun> constraintData)
+      : base(constrainedValue, ConstraintOperation.Equal, constraintData) {
+    }
+    public RunCollectionContentConstraint(RunCollection constrainedValue, IObservableSet<IRun> constraintData, bool active)
+      : base(constrainedValue, ConstraintOperation.Equal, constraintData, active) {
+    }
+
+    protected override void OnConstraintDataChanged() {
+      RegisterConstraintDataEvents();
+      base.OnConstraintDataChanged();
+    }
+    private void RegisterConstraintDataEvents() {
+      if (ConstraintData != null) {
+        ConstraintData.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(ConstraintData_ItemsAdded);
+        ConstraintData.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(ConstraintData_ItemsRemoved);
+        ConstraintData.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(ConstraintData_CollectionReset);
+      }
+    }
+    private void ConstraintData_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      base.OnConstraintDataChanged();
+    }
+    private void ConstraintData_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      base.OnConstraintDataChanged();
+    }
+    private void ConstraintData_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      base.OnConstraintDataChanged();
+    }
+
+    protected override bool Check(object constrainedMember) {
+      if (!Active) return true;
+
+      foreach (IRun run in ConstrainedValue.Where(r => r.Visible))
+        run.Visible = !ConstraintData.Contains(run);
+      return true;
+    }
+
+    protected override bool Check(object constrainedMember, out string errorMessage) {
+      errorMessage = string.Empty;
+      if (!Active) return true;
+
+      foreach (IRun run in ConstrainedValue.Where(r => r.Visible))
+        run.Visible = !ConstraintData.Contains(run);
+      return true;
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionEqualityConstraint.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionEqualityConstraint.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionEqualityConstraint.cs	(revision 12526)
@@ -0,0 +1,140 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  [Item("RunCollectionEqualityConstraint", "A constraint which checks the members of the contained runs for equality to the constraint data.")]
+  public class RunCollectionEqualityConstraint : EqualityConstraint, IRunCollectionColumnConstraint {
+    [StorableConstructor]
+    protected RunCollectionEqualityConstraint(bool deserializing) : base(deserializing) { }
+
+    protected RunCollectionEqualityConstraint(RunCollectionEqualityConstraint original, Cloner cloner)
+      : base(original, cloner) {
+      ConstraintData = original.ConstraintData;
+      ConstraintOperation = original.ConstraintOperation;
+      constraintColumn = original.constraintColumn;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionEqualityConstraint(this, cloner);
+    }
+
+    public RunCollectionEqualityConstraint()
+      : base() {
+      this.ConstraintData = string.Empty;
+    }
+    public RunCollectionEqualityConstraint(RunCollection constrainedValue, ConstraintOperation constraintOperation, string constraintData)
+      : base(constrainedValue, constraintOperation, constraintData) {
+    }
+    public RunCollectionEqualityConstraint(RunCollection constrainedValue, ConstraintOperation constraintOperation, string constraintData, bool active)
+      : base(constrainedValue, constraintOperation, constraintData, active) {
+    }
+
+    public new RunCollection ConstrainedValue {
+      get { return (RunCollection)base.ConstrainedValue; }
+      set { base.ConstrainedValue = value; }
+    }
+
+    public new string ConstraintData {
+      get { return (string)base.ConstraintData; }
+      set { base.ConstraintData = value; }
+    }
+
+    [Storable]
+    private string constraintColumn;
+    public string ConstraintColumn {
+      get { return constraintColumn; }
+      set {
+        if (!((IStringConvertibleMatrix)ConstrainedValue).ColumnNames.Contains(value))
+          throw new ArgumentException("Could not set ConstraintData to not existing column index.");
+        if (constraintColumn != value) {
+          constraintColumn = value;
+          this.OnConstraintColumnChanged();
+          this.OnToStringChanged();
+        }
+      }
+    }
+
+    public event EventHandler ConstraintColumnChanged;
+    protected virtual void OnConstraintColumnChanged() {
+      EventHandler handler = ConstraintColumnChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    protected override void OnConstrainedValueChanged() {
+      base.OnConstrainedValueChanged();
+      IStringConvertibleMatrix matrix = (IStringConvertibleMatrix)ConstrainedValue;
+      if (constraintColumn == null && ConstrainedValue != null && matrix.Columns != 0)
+        constraintColumn = matrix.ColumnNames.ElementAt(0);
+    }
+
+    protected override bool Check(object constrainedMember) {
+      if (!Active)
+        return true;
+
+      foreach (IRun run in ConstrainedValue.Where(r => r.Visible)) {
+        IItem item = ConstrainedValue.GetValue(run, constraintColumn);
+        if (item != null && !base.Check(item.ToString()))
+          run.Visible = false;
+      }
+      return true;
+    }
+
+    protected override bool Check(object constrainedMember, out string errorMessage) {
+      errorMessage = string.Empty;
+      if (!Active)
+        return true;
+
+      foreach (IRun run in ConstrainedValue.Where(r => r.Visible)) {
+        IItem item = ConstrainedValue.GetValue(run, constraintColumn);
+        if (!base.Check(item))
+          run.Visible = false;
+      }
+      return true;
+    }
+
+    public override string ToString() {
+      string s = string.Empty;
+      IStringConvertibleMatrix matrix = ConstrainedValue;
+      if (matrix != null && matrix.ColumnNames.Count() != 0)
+        s += constraintColumn + " ";
+      else
+        return "EqualityConstraint";
+
+      if (ConstraintOperation != null)
+        s += ConstraintOperation.ToString() + " ";
+
+      if (!string.IsNullOrEmpty(ConstraintData))
+        s += ConstraintData;
+      else
+        s += "null";
+
+      return s;
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionTypeCompatiblityConstraint.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionTypeCompatiblityConstraint.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionConstraints/RunCollectionTypeCompatiblityConstraint.cs	(revision 12526)
@@ -0,0 +1,133 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [StorableClass]
+  [Item("RunCollectionTypeCompatibilityConstraint", "A constraint which checks the members of the contained runs for type compabitiliby to the constraint data.")]
+  public class RunCollectionTypeCompatibilityConstraint : TypeCompatibilityConstraint, IRunCollectionColumnConstraint {
+    [StorableConstructor]
+    protected RunCollectionTypeCompatibilityConstraint(bool deserializing) {
+    }
+    protected RunCollectionTypeCompatibilityConstraint(RunCollectionTypeCompatibilityConstraint original, Cloner cloner)
+      : base(original, cloner) {
+      ConstraintData = original.ConstraintData;
+      ConstraintOperation = original.ConstraintOperation;
+      constraintColumn = original.constraintColumn;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionTypeCompatibilityConstraint(this, cloner);
+    }
+
+    public RunCollectionTypeCompatibilityConstraint()
+      : base() {
+    }
+    public RunCollectionTypeCompatibilityConstraint(RunCollection constrainedValue, ConstraintOperation constraintOperation, Type constraintData)
+      : base(constrainedValue, constraintOperation, constraintData) {
+    }
+    public RunCollectionTypeCompatibilityConstraint(RunCollection constrainedValue, ConstraintOperation constraintOperation, Type constraintData, bool active)
+      : base(constrainedValue, constraintOperation, constraintData, active) {
+    }
+
+    public new RunCollection ConstrainedValue {
+      get { return (RunCollection)base.ConstrainedValue; }
+      set { base.ConstrainedValue = value; }
+    }
+    [Storable]
+    private string constraintColumn;
+    public string ConstraintColumn {
+      get { return constraintColumn; }
+      set {
+        if (!((IStringConvertibleMatrix)ConstrainedValue).ColumnNames.Contains(value))
+          throw new ArgumentException("Could not set ConstraintData to not existing column index.");
+        if (constraintColumn != value) {
+          constraintColumn = value;
+          this.OnConstraintColumnChanged();
+          this.OnToStringChanged();
+        }
+      }
+    }
+
+    public event EventHandler ConstraintColumnChanged;
+    protected virtual void OnConstraintColumnChanged() {
+      EventHandler handler = ConstraintColumnChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    protected override void OnConstrainedValueChanged() {
+      base.OnConstrainedValueChanged();
+      IStringConvertibleMatrix matrix = (IStringConvertibleMatrix)ConstrainedValue;
+      if (constraintColumn == null && ConstrainedValue != null && matrix.Columns != 0)
+        constraintColumn = matrix.ColumnNames.ElementAt(0);
+    }
+
+    protected override bool Check(object constrainedMember) {
+      if (!Active)
+        return true;
+
+      foreach (IRun run in ConstrainedValue.Where(r => r.Visible)) {
+        IItem item = ConstrainedValue.GetValue(run, constraintColumn);
+        if (item == null || !base.Check(item))
+          run.Visible = false;
+      }
+      return true;
+    }
+
+    protected override bool Check(object constrainedMember, out string errorMessage) {
+      errorMessage = string.Empty;
+      if (!Active)
+        return true;
+
+      foreach (IRun run in ConstrainedValue.Where(r => r.Visible)) {
+        IItem item = ConstrainedValue.GetValue(run, constraintColumn);
+        if (!base.Check(item))
+          run.Visible = false;
+      }
+      return true;
+    }
+
+    public override string ToString() {
+      string s = string.Empty;
+      IStringConvertibleMatrix matrix = ConstrainedValue;
+      if (matrix != null && matrix.ColumnNames.Count() != 0)
+        s += constraintColumn + " ";
+      else
+        return "TypeCompabitilityConstraint";
+
+      if (ConstraintOperation != null)
+        s += ConstraintOperation.ToString() + " ";
+
+      if (ConstraintData != null)
+        s += ConstraintData;
+      else
+        s += "null";
+
+      return s;
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/Calculator.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/Calculator.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/Calculator.cs	(revision 12526)
@@ -0,0 +1,287 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+
+  [StorableClass]
+  public class Calculator : IDeepCloneable {
+
+    #region Fields & Properties
+
+    private List<string> tokens;
+
+    [Storable]
+    public string Formula {
+      get { return tokens == null ? string.Empty : string.Join(" ", tokens); }
+      set { tokens = Tokenize(value).ToList(); }
+    }
+
+    private static readonly Regex TokenRegex =
+      new Regex(@"""(\\""|[^""])*""|'(\\'|[^'])*'|[^\s]+");
+
+    #endregion
+
+    #region Construction & Cloning
+
+    [StorableConstructor]
+    protected Calculator(bool deserializing) { }
+    public Calculator() { }
+    protected Calculator(Calculator original, Cloner cloner) {
+      cloner.RegisterClonedObject(original, this);
+      if (original.tokens != null)
+        tokens = original.tokens.ToList();
+    }
+    public IDeepCloneable Clone(Cloner cloner) {
+      return new Calculator(this, cloner);
+    }
+    public object Clone() {
+      return Clone(new Cloner());
+    }
+    #endregion
+
+    private static IEnumerable<string> Tokenize(string s) {
+      return TokenRegex.Matches(s).Cast<Match>().Select(m => m.Value);
+    }
+
+    public IItem GetValue(IDictionary<string, IItem> variables) {
+      var stack = new Stack<object>();
+      int i = 0;
+      try {
+        for (; i < tokens.Count; i++) {
+          var token = tokens[i];
+          double d;
+          if (TryParse(token, out d)) {
+            stack.Push(d);
+          } else if (token.StartsWith("\"")) {
+            stack.Push(GetVariableValue(variables, token.Substring(1, token.Length - 2).Replace("\\\"", "\"")));
+          } else if (token.StartsWith("'")) {
+            stack.Push(token.Substring(1, token.Length - 2).Replace("\\'", "'"));
+          } else {
+            Apply(token, stack, variables);
+          }
+        }
+      } catch (Exception x) {
+        throw new Exception(string.Format(
+          "Calculation of '{1}'{0}failed at token #{2}: {3} {0}current stack is: {0}{4}", Environment.NewLine,
+          Formula, i, TokenWithContext(tokens, i, 3),
+          string.Join(Environment.NewLine, stack.Select(AsString))),
+          x);
+      }
+      if (stack.Count != 1)
+        throw new Exception(
+          string.Format("Invalid final evaluation stack size {0} (should be 1) in formula '{1}'",
+          stack.Count, Formula));
+      var result = stack.Pop();
+      if (result is string) return new StringValue((string)result);
+      if (result is int) return new IntValue((int)result);
+      if (result is double) return new DoubleValue((double)result);
+      if (result is bool) return new BoolValue((bool)result);
+      return null;
+    }
+
+    private string TokenWithContext(List<string> tokens, int i, int context) {
+      var sb = new StringBuilder();
+      if (i > context + 1)
+        sb.Append("... ");
+      int prefix = Math.Max(0, i - context);
+      sb.Append(string.Join(" ", tokens.GetRange(prefix, i - prefix)));
+      sb.Append("   ---> ").Append(tokens[i]).Append(" <---   ");
+      int postfix = Math.Min(tokens.Count, i + 1 + context);
+      sb.Append(string.Join(" ", tokens.GetRange(i + 1, postfix - (i + 1))));
+      if (postfix < tokens.Count)
+        sb.Append(" ...");
+      return sb.ToString();
+    }
+
+
+    private static void Apply(string token, Stack<object> stack, IDictionary<string, IItem> variables) {
+      switch (token) {
+        case "null": stack.Push(null); break;
+        case "true": stack.Push(true); break;
+        case "false": stack.Push(false); break;
+
+        case "drop": stack.Pop(); break;
+        case "dup": stack.Push(stack.Peek()); break;
+        case "swap":
+          var top = stack.Pop();
+          var next = stack.Pop();
+          stack.Push(top);
+          stack.Push(next);
+          break;
+
+        case "log": Apply(stack, x => Math.Log(Convert.ToDouble(x))); break;
+        case "+": Apply(stack, (x, y) => Convert.ToDouble(x) + Convert.ToDouble(y)); break;
+        case "-": Apply(stack, (x, y) => Convert.ToDouble(x) - Convert.ToDouble(y)); break;
+        case "*": Apply(stack, (x, y) => Convert.ToDouble(x) * Convert.ToDouble(y)); break;
+        case "/": Apply(stack, (x, y) => Convert.ToDouble(x) / Convert.ToDouble(y)); break;
+        case "^": Apply(stack, (x, y) => Math.Pow(Convert.ToDouble(x), Convert.ToDouble(y))); break;
+        case "<": Apply(stack, (x, y) => Convert.ToDouble(x) < Convert.ToDouble(y)); break;
+        case ">": Apply(stack, (x, y) => Convert.ToDouble(x) > Convert.ToDouble(y)); break;
+
+        case "toint": Apply(stack, x => Convert.ToInt32(x)); break;
+        case "todouble": Apply(stack, x => Convert.ToDouble(x)); break;
+
+        case "[]": Apply(stack, (a, i) => GetArrayValueAtIndex(a, Convert.ToInt32(i))); break;
+
+        case "==": Apply(stack, (x, y) => Equal(x, y)); break;
+        case "not": Apply(stack, x => !Convert.ToBoolean(x)); break;
+        case "isnull": Apply(stack, x => x == null); break;
+        case "if": Apply(stack, (then, else_, cond) => Convert.ToBoolean(cond) ? then : else_); break;
+
+        case "ismatch": Apply(stack, (s, p) => new Regex(Convert.ToString(p)).IsMatch(Convert.ToString(s))); break;
+        case "rename": Apply(stack, (s, p, r) => new Regex(Convert.ToString(p)).Replace(Convert.ToString(s), Convert.ToString(r))); break;
+
+        default: stack.Push(GetVariableValue(variables, token)); break;
+      }
+    }
+
+    #region Auxiliary Functions
+
+    #region IItem value conversion
+    private static object GetIntValue(IItem value) {
+      var v = value as IntValue;
+      if (v != null) return (double)v.Value;
+      return null;
+    }
+
+    private static object GetDoubleValue(IItem value) {
+      var v = value as DoubleValue;
+      if (v != null) return v.Value;
+      return null;
+    }
+
+    private static object GetBoolValue(IItem value) {
+      var v = value as BoolValue;
+      if (v != null) return v.Value;
+      return null;
+    }
+
+    private static object GetArrayValue(IItem value) {
+      if (value is IntArray || value is DoubleArray || value is BoolArray || value is StringArray)
+        return value;
+      return null;
+    }
+
+    private static object GetVariableValue(IDictionary<string, IItem> variables, string name) {
+      if (variables.ContainsKey(name)) {
+        var item = variables[name];
+        return
+          GetIntValue(item) ??
+          GetDoubleValue(item) ??
+          GetBoolValue(item) ??
+          GetArrayValue(item) ??
+          item.ToString();
+      }
+      return null;
+    }
+
+    private static object GetArrayValueAtIndex(object array, int index) {
+      if (array is IntArray)
+        return ((IntArray)array)[index];
+      if (array is DoubleArray)
+        return ((DoubleArray)array)[index];
+      if (array is BoolArray)
+        return ((BoolArray)array)[index];
+      if (array is StringArray)
+        return ((StringArray)array)[index];
+      throw new NotSupportedException(string.Format("Type {0} is not a supported array type", array.GetType().Name));
+    }
+    #endregion
+
+    #region variadic equality
+    private static bool Equal(object a, object b) { return EqualIntegerNumber(a, b) || EqualFloatingNumber(a, b) || EqualBool(a, b) || EqualString(a, b) || a == b; }
+    private static bool EqualIntegerNumber(object a, object b) { return a is int && b is int && (int)a == (int)b; }
+    private static bool EqualFloatingNumber(object a, object b) { return a is double && b is double && (double)a == (double)b; }
+    private static bool EqualBool(object a, object b) { return a is bool && b is bool && (bool)a == (bool)b; }
+    private static bool EqualString(object a, object b) { return a is string && b is string && ((string)a).Equals((string)b); }
+    #endregion
+
+    #region stack calculation
+    private static void Apply(Stack<object> stack, Func<object, object> func) {
+      if (stack.Count < 1)
+        throw new InvalidOperationException("Stack is empty");
+      var a = stack.Pop();
+      try {
+        stack.Push(func(a));
+      } catch (Exception) {
+        stack.Push(a);
+        throw;
+      }
+    }
+
+    private static void Apply(Stack<object> stack, Func<object, object, object> func) {
+      if (stack.Count < 2)
+        throw new InvalidOperationException("Stack contains less than two elements");
+      var b = stack.Pop();
+      var a = stack.Pop();
+      try {
+        stack.Push(func(a, b));
+      } catch (Exception) {
+        stack.Push(b);
+        stack.Push(a);
+        throw;
+      }
+    }
+
+    private static void Apply(Stack<object> stack, Func<object, object, object, object> func) {
+      if (stack.Count < 3)
+        throw new InvalidOperationException("Stack contains less than three elements");
+      var c = stack.Pop();
+      var b = stack.Pop();
+      var a = stack.Pop();
+      try {
+        stack.Push(func(a, b, c));
+      } catch (Exception) {
+        stack.Push(a);
+        stack.Push(b);
+        stack.Push(c);
+        throw;
+      }
+    }
+    #endregion
+
+    private static bool TryParse(string token, out double d) {
+      return double.TryParse(token,
+                             NumberStyles.AllowDecimalPoint |
+                             NumberStyles.AllowExponent |
+                             NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out d);
+    }
+
+    private static string AsString(object o) {
+      if (o == null) return "null";
+      if (o is string) return string.Format("'{0}'", o);
+      return o.ToString();
+    }
+
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionDiscretizer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionDiscretizer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionDiscretizer.cs	(revision 12526)
@@ -0,0 +1,203 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("RunCollection Discretizer",
+    "Creates several levels from the distribution of a certain result accross a run collection and " +
+    "assigns a discretized value. Non-existing numbers as well as NaN and infinities are excluded from the caluclation.")]
+  [StorableClass]
+  public class RunCollectionDiscretizer : ParameterizedNamedItem, IRunCollectionModifier {
+
+    public override bool CanChangeName { get { return false; } }
+    public override bool CanChangeDescription { get { return false; } }
+
+    #region Parameters
+    public ValueParameter<StringValue> SourceParameter {
+      get { return (ValueParameter<StringValue>)Parameters["Source"]; }
+    }
+    public ValueParameter<StringValue> TargetParameter {
+      get { return (ValueParameter<StringValue>)Parameters["Target"]; }
+    }
+    public ValueParameter<DoubleValue> SpreadParameter {
+      get { return (ValueParameter<DoubleValue>)Parameters["Spread"]; }
+    }
+    public ValueParameter<StringValue> GroupByParameter {
+      get { return (ValueParameter<StringValue>)Parameters["GroupBy"]; }
+    }    
+    public ValueParameter<ItemList<StringValue>> LevelsParameter {
+      get { return (ValueParameter<ItemList<StringValue>>)Parameters["Levels"]; }
+    }    
+    #endregion
+
+    private string Source { get { return SourceParameter.Value.Value; } }
+    private string Target {
+      get { return TargetParameter.Value.Value; }
+      set { TargetParameter.Value.Value = value; }
+    }    
+    private double Spread { get { return SpreadParameter.Value.Value; } }
+    private string GroupBy { get { return GroupByParameter.Value.Value; } }
+    private List<string> Levels { get { return LevelsParameter.Value.Select(v => v.Value).ToList(); } }
+
+      #region Construction & Cloning
+    [StorableConstructor]
+    protected RunCollectionDiscretizer(bool deserializing) : base(deserializing) { }
+    protected RunCollectionDiscretizer(RunCollectionDiscretizer original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEvents();
+    }
+    public RunCollectionDiscretizer() {
+      Parameters.Add(new ValueParameter<StringValue>("Source", "Source value name to be fuzzified.", new StringValue("Value")));
+      Parameters.Add(new ValueParameter<StringValue>("Target", "Target value name. The new, fuzzified variable to be created.", new StringValue("Calc.Value")));
+      Parameters.Add(new ValueParameter<DoubleValue>("Spread", "The number of standard deviations considered one additional level. Set to zero to use empirical distribution instead.", new DoubleValue(1)));
+      Parameters.Add(new ValueParameter<StringValue>("GroupBy", "Create separate analyzes for different values of this variable.", new StringValue("")));
+      Parameters.Add(new ValueParameter<ItemList<StringValue>>("Levels", "The list of levels to be assigned.",
+        new ItemList<StringValue> {
+          new StringValue("Very Low"),
+          new StringValue("Low"),
+          new StringValue("Average"),
+          new StringValue("High"),
+          new StringValue("Very High"),
+        }));     
+      RegisterEvents();
+      UpdateName();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionDiscretizer(this, cloner);
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEvents();
+    }
+    #endregion
+
+    private void RegisterEvents() {
+      SourceParameter.ToStringChanged += SourceParameter_NameChanged;
+      TargetParameter.ToStringChanged += Parameter_NameChanged;
+      GroupByParameter.ToStringChanged += Parameter_NameChanged;
+    }
+
+    private void SourceParameter_NameChanged(object sender, EventArgs e) {
+      Target = string.Format("{0}/Level", Source);
+    }
+
+    private void Parameter_NameChanged(object sender, EventArgs e) {
+      UpdateName();
+    }
+
+    private void UpdateName() {
+      name = string.Format("{0} := Discrete({1}{2})",
+        Target,
+        Source,
+        string.IsNullOrWhiteSpace(GroupBy) ? "" : string.Format("/{0}", GroupBy));        
+      OnNameChanged();
+    }
+
+    #region IRunCollectionModifier Members
+
+    public void Modify(List<IRun> runs) {
+      foreach (var group in runs
+        .Select(r => new {Run=r, Value=GetSourceValue(r)})
+        .Where(r => r.Value.HasValue && !double.IsNaN(r.Value.Value) && !double.IsInfinity(r.Value.Value))
+        .Select(r => new {r.Run, r.Value.Value, Bin=GetGroupByValue(r.Run)})
+        .GroupBy(r => r.Bin).ToList()) {
+        var values = group.Select(r => r.Value).ToList();
+        if (values.Count > 0) {
+          if (Spread > 0) {
+            var avg = values.Average();
+            var stdDev = values.StandardDeviation();
+            foreach (var r in group) {
+              r.Run.Results[Target] = new StringValue(Discretize(r.Value, avg, stdDev));
+            }
+          } else {
+            values.Sort();
+            var a = values.ToArray();
+            foreach (var r in group) {
+              r.Run.Results[Target] = new StringValue(Discretize(r.Value, a));
+            }
+          }
+        }
+      }      
+    }
+
+    private double? GetSourceValue(IRun run) {
+      return CastSourceValue(run.Results) ?? CastSourceValue(run.Parameters);
+    }
+
+    private string GetGroupByValue(IRun run) {
+      if (string.IsNullOrWhiteSpace(GroupBy))
+        return String.Empty;
+      IItem value;
+      run.Results.TryGetValue(GroupBy, out value);
+      if (value == null)
+        run.Parameters.TryGetValue(GroupBy, out value);
+      if (value != null)
+        return value.ToString();
+      else
+        return String.Empty;
+    }
+
+    private double? CastSourceValue(IDictionary<string, IItem> variables) {
+      IItem value;
+      variables.TryGetValue(Source, out value);
+      var intValue = value as IntValue;
+      if (intValue != null) 
+        return intValue.Value;
+      var doubleValue = value as DoubleValue;
+      if (doubleValue != null)
+        return doubleValue.Value;
+      return null;
+    }
+
+    private string Discretize(double value, double avg, double stdDev) {
+      double dev = (value - avg)/(stdDev*Spread);
+      int index;
+      if (Levels.Count % 2 == 1) {
+        index = (int) Math.Floor(Math.Abs(dev));
+        index = (Levels.Count - 1)/2 + Math.Sign(dev) * index;
+      } else {
+        index = (int) Math.Ceiling(Math.Abs(dev));
+        if (dev > 0)
+          index = Levels.Count/2 + index;
+        else
+          index = Levels.Count/2 + 1 - index;
+      }
+      return Levels[Math.Min(Levels.Count - 1, Math.Max(0, index))];
+    }
+
+    private string Discretize(double value, double[] values) {
+      var index = Array.BinarySearch(values, value);
+      var pos = 1.0*(index < 0 ? ~index : index)/(values.Length-1);
+      return Levels[Math.Min(Levels.Count - 1, Math.Max(0, (int) Math.Round(pos*(Levels.Count-1))))];
+    }
+
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionFormulaModifer.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionFormulaModifer.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionFormulaModifer.cs	(revision 12526)
@@ -0,0 +1,136 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+
+  [Item("RunCollection Formula Modifier", "Modifies a RunCollection by adding results using the given formula.")]
+  [StorableClass]
+  public class RunCollectionFormulaModifer : ParameterizedNamedItem, IRunCollectionModifier {
+
+    public override bool CanChangeName { get { return false; } }
+    public override bool CanChangeDescription { get { return false; } }
+
+    public ValueParameter<StringValue> ResultNameParameter {
+      get { return (ValueParameter<StringValue>)Parameters["ResultName"]; }
+    }
+
+    public ValueParameter<StringValue> FormulaParameter {
+      get { return (ValueParameter<StringValue>)Parameters["Formula"]; }
+    }
+
+    private string ResultName { get { return ResultNameParameter.Value.Value; } }
+    private string Formula { get { return FormulaParameter.Value.Value; } }
+
+    #region Construction & Cloning
+    [StorableConstructor]
+    protected RunCollectionFormulaModifer(bool deserializing) : base(deserializing) { }
+    protected RunCollectionFormulaModifer(RunCollectionFormulaModifer original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEvents();
+    }
+    public RunCollectionFormulaModifer() {
+      Parameters.Add(new ValueParameter<StringValue>("ResultName", "The name of the result to be generated by this formula.", new StringValue("Calc.Value")));
+      Parameters.Add(new ValueParameter<StringValue>("Formula",
+@"RPN formula for new value in postfix notation.
+
+This can contain the following elements:
+
+literals:
+  numbers, true, false, null and strings in single quotes
+variables (run parameters or results):
+  unquoted or in double quotes if they contain special characters or whitespace
+mathematical functions (resulting in double values):
+  +, -, *, /, ^ (power), log
+predicates:
+  ==, <, >, isnull, not
+conversions:
+  toint, todouble
+array indexing:
+  []
+stack manipulation:
+  drop swap dup
+string matching:
+  <string> <pattern> ismatch
+string replacing:
+  <string> <pattern> <replacement> rename
+conditionals:
+  <then> <else> <condition> if
+
+If the final value is null, the result variable is removed if it exists.",
+        new StringValue("1 1 +")));
+      UpdateName();
+      RegisterEvents();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionFormulaModifer(this, cloner);
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEvents();
+    }
+    #endregion
+
+    private void RegisterEvents() {
+      ResultNameParameter.ToStringChanged += Parameter_NameChanged;
+      FormulaParameter.ToStringChanged += Parameter_NameChanged;
+    }
+
+    void Parameter_NameChanged(object sender, EventArgs e) {
+      UpdateName();
+    }
+
+    private void UpdateName() {
+      name = string.Format("{0} := {1}", ResultName, Formula);
+      OnNameChanged();
+    }
+
+    public void Modify(List<IRun> runs) {
+      var calc = new Calculator { Formula = Formula };
+      foreach (var run in runs) {
+        var variables = new Dictionary<string, IItem>();
+        foreach (var param in run.Parameters)
+          variables[param.Key] = param.Value;
+        foreach (var result in run.Results)
+          variables[result.Key] = result.Value;
+        try {
+          var value = calc.GetValue(variables);
+          if (value != null)
+            run.Results[ResultName] = value;
+          else
+            run.Results.Remove(ResultName);
+        } catch (Exception x) {
+          throw new Exception(string.Format("Calculation failed at Run {0}", run.Name), x);
+        }
+      }
+    }
+
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionGroupCreater.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionGroupCreater.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionGroupCreater.cs	(revision 12526)
@@ -0,0 +1,105 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+
+  [Item("RunCollection Group Creater", "Regroups existing runs according to equal values in GroupBy and prefixes them according to their value in Prefix.")]
+  [StorableClass]
+  public class RunCollectionGroupCreater : ParameterizedNamedItem, IRunCollectionModifier {
+    
+    public ValueParameter<ItemCollection<StringValue>> GroupByParameter {
+      get { return (ValueParameter<ItemCollection<StringValue>>)Parameters["GroupBy"]; }
+    }
+
+    public ValueParameter<StringValue> PrefixParameter {
+      get { return (ValueParameter<StringValue>)Parameters["Prefix"]; }
+    }
+
+    private IEnumerable<string> GroupBy { get { return GroupByParameter.Value.Select(v => v.Value); } }
+    private string Prefix { get { return PrefixParameter.Value.Value; } }
+
+    #region Construction & Cloning
+    [StorableConstructor]
+    protected RunCollectionGroupCreater(bool deserializing) : base(deserializing) { }
+    protected RunCollectionGroupCreater(RunCollectionGroupCreater original, Cloner cloner) : base(original, cloner) { }
+    public RunCollectionGroupCreater() {
+      Parameters.Add(new ValueParameter<ItemCollection<StringValue>>("GroupBy", "The variable that has to be the same for all members of a group.",
+        new ItemCollection<StringValue>(new[] { new StringValue("Problem Name") })));
+      Parameters.Add(new ValueParameter<StringValue>("Prefix", "The distinguishing prefix values for the individual runs.",
+        new StringValue("Algorithm Name")));      
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionGroupCreater(this, cloner);
+    }
+    #endregion    
+
+    private static string GetStringValue(string name, IRun r) {
+      IItem item;
+      r.Results.TryGetValue(name, out item);
+      if (item != null)
+        return item.ToString();
+      r.Parameters.TryGetValue(name, out item);
+      return item != null ? item.ToString() : "<none>";
+    }
+
+    private static string GetValues(IEnumerable<string> names, IRun r) {
+      return string.Join("/", names.Select(n => GetStringValue(n, r)));
+    }
+
+    public void Modify(List<IRun> runs) {
+      var groups = runs.GroupBy(r => GetValues(GroupBy, r).ToString()).ToList();
+      runs.Clear();
+      foreach (var group in groups) {
+        var run = new Run { Name = string.Format(group.Key) };
+        foreach (var r in group) {
+          var prefix = GetStringValue(Prefix, r);
+          foreach (var result in r.Results) {
+            InsertNew(run.Results, prefix, result.Key, result.Value);
+          }
+          foreach (var parameter in r.Parameters) {
+            InsertNew(run.Parameters, prefix, parameter.Key, parameter.Value);
+          }
+        }
+        runs.Add(run);
+      }
+    }
+
+    private static void InsertNew(IDictionary<string, IItem> dict, string prefix, string key, IItem value) {
+      if (prefix == null)
+        prefix = "<null>";
+      var n = 0;
+      var name = string.Format("{0}.{1}", prefix, key);
+      while (dict.ContainsKey(name)) {
+        name = string.Format("{0}_{1}.{2}", prefix, ++n, key);
+      }
+      dict.Add(name, value);      
+    }
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionRunRemover.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionRunRemover.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionRunRemover.cs	(revision 12526)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("RunCollection Run Remover", "Removes all currently visible runs. Use the filtering tab to selectively remove runs.")]
+  [StorableClass]
+  public class RunCollectionRunRemover : ParameterizedNamedItem, IRunCollectionModifier {
+
+    #region Construction & Cloning
+    [StorableConstructor]
+    protected RunCollectionRunRemover(bool deserializing) : base(deserializing) { }
+    protected RunCollectionRunRemover(RunCollectionRunRemover original, Cloner cloner) : base(original, cloner) {}
+    public RunCollectionRunRemover() {}
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionRunRemover(this, cloner);
+    }
+    #endregion
+
+    #region IRunCollectionModifier Members
+    public void Modify(List<IRun> runs) {
+      runs.Clear();
+    }
+    #endregion
+
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionSorter.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionSorter.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionSorter.cs	(revision 12526)
@@ -0,0 +1,129 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+  [Item("RunCollection Sorter", "Sorts a run collection according the specified key variable.")]
+  [StorableClass]
+  public class RunCollectionSorter : ParameterizedNamedItem, IRunCollectionModifier {
+
+    public override bool CanChangeName { get { return false; } }
+    public override bool CanChangeDescription { get { return false; } }
+
+    #region Parameters
+    public ValueParameter<StringValue> ValueParameter {
+      get { return (ValueParameter<StringValue>)Parameters["Value"]; }
+    }
+    #endregion
+
+    private string Value { get { return ValueParameter.Value.Value; } }
+
+    #region Construction & Cloning
+    [StorableConstructor]
+    protected RunCollectionSorter(bool deserializing) : base(deserializing) { }
+    protected RunCollectionSorter(RunCollectionSorter original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEvents();
+    }
+    public RunCollectionSorter() {
+      Parameters.Add(new ValueParameter<StringValue>("Value", "The variable name used as sorting key.", new StringValue("Value")));
+      RegisterEvents();
+      UpdateName();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionSorter(this, cloner);
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEvents();
+    }
+    #endregion
+
+    private void RegisterEvents() {
+      ValueParameter.ToStringChanged += Parameter_NameChanged;
+    }
+
+    private void Parameter_NameChanged(object sender, EventArgs e) {
+      UpdateName();
+    }
+
+    private void UpdateName() {
+      name = string.Format("Sort by {0}", Value);
+      OnNameChanged();
+    }
+
+    private class ValueComparer : IComparer<IComparable> {
+
+      #region IComparer<IComparable> Members
+
+      public int Compare(IComparable x, IComparable y) {
+        if (x == null && y == null) return 0;
+        if (x == null) return -1;
+        if (y == null) return 1;
+        return x.CompareTo(y);
+      }
+
+      #endregion
+    }
+
+    private static readonly ValueComparer Comparer = new ValueComparer();
+
+    #region IRunCollectionModifier Members
+
+    public void Modify(List<IRun> runs) {
+      var sortedRuns = runs
+        .Select(r => new {Run = r, Key = GetValue(r)})
+        .OrderBy(r => r.Key, Comparer)
+        .Select(r => r.Run).ToList();
+      runs.Clear();
+      runs.AddRange(sortedRuns);
+    }
+
+    private IComparable GetValue(IRun run) {
+      return GetValue(run.Results) ?? GetValue(run.Parameters);
+    }
+
+    private IComparable GetValue(IDictionary<string, IItem> variables) {
+      IItem value;
+      variables.TryGetValue(Value, out value);
+      var intValue = value as IntValue;
+      if (intValue != null)
+        return intValue;
+      var doubleValue = value as DoubleValue;
+      if (doubleValue != null)
+        return doubleValue;
+      if (value != null)
+        return value.ToString();
+      return null;
+    }
+
+    #endregion
+  }
+}
Index: branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionValueRemover.cs
===================================================================
--- branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionValueRemover.cs	(revision 12526)
+++ branches/TerminationCriteria/HeuristicLab.Optimization/3.3/RunCollectionModification/RunCollectionValueRemover.cs	(revision 12526)
@@ -0,0 +1,70 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization {
+
+  [Item("RunCollection Value Remover", "Modifies a RunCollection by removing results or parameters.")]
+  [StorableClass]
+  public class RunCollectionValueRemover : ParameterizedNamedItem, IRunCollectionModifier {
+    
+    public ValueParameter<CheckedItemCollection<StringValue>> ValuesParameter {
+      get { return (ValueParameter<CheckedItemCollection<StringValue>>)Parameters["Values"]; }
+    }
+
+    public IEnumerable<string> Values {
+      get { return ValuesParameter.Value.CheckedItems.Select(v => v.Value); }
+    }
+
+    #region Construction & Cloning    
+    [StorableConstructor]
+    protected RunCollectionValueRemover(bool deserializing) : base(deserializing) { }
+    protected RunCollectionValueRemover(RunCollectionValueRemover original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public RunCollectionValueRemover() {
+      Parameters.Add(new ValueParameter<CheckedItemCollection<StringValue>>("Values", "The result or parameter values to be removed from each run."));      
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RunCollectionValueRemover(this, cloner);
+    }    
+    #endregion    
+
+    public void Modify(List<IRun> runs) {      
+      foreach (var run in runs) {
+        foreach (var value in Values) {
+          run.Parameters.Remove(value);
+          run.Results.Remove(value);
+        }        
+      }      
+    }
+    
+  }
+}
