Index: branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/AlgorithmContext.cs
===================================================================
--- branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/AlgorithmContext.cs	(revision 14429)
+++ branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/AlgorithmContext.cs	(revision 14429)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization.Algorithms {
+  [Item("AlgorithmContext", "")]
+  [StorableClass]
+  public abstract class AlgorithmContext : ParameterizedNamedItem, IExecutionContext {
+
+    private IExecutionContext parent;
+    public IExecutionContext Parent {
+      get { return parent; }
+      set { parent = value; }
+    }
+
+    IKeyedItemCollection<string, IParameter> IExecutionContext.Parameters {
+      get { return Parameters; }
+    }
+
+    [Storable]
+    private IScope scope;
+    public IScope Scope {
+      get { return scope; }
+    }
+
+    [StorableConstructor]
+    protected AlgorithmContext(bool deserializing) : base(deserializing) { }
+    protected AlgorithmContext(AlgorithmContext original, Cloner cloner)
+      : base(original, cloner) { }
+    protected AlgorithmContext() : this(new Scope("Scope")) { }
+    protected AlgorithmContext(IScope s) {
+      scope = s;
+    }
+
+
+    public IAtomicOperation CreateOperation(IOperator op) {
+      return new ExecutionContext(parent, op, scope);
+    }
+
+    public IAtomicOperation CreateOperation(IOperator op, IScope s) {
+      return new ExecutionContext(parent, op, s);
+    }
+
+    public IAtomicOperation CreateChildOperation(IOperator op) {
+      return new ExecutionContext(this, op, scope);
+    }
+
+    public IAtomicOperation CreateChildOperation(IOperator op, IScope s) {
+      return new ExecutionContext(this, op, s);
+    }
+  }
+}
Index: branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/SingleObjective/HeuristicAlgorithm.cs
===================================================================
--- branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/SingleObjective/HeuristicAlgorithm.cs	(revision 14429)
+++ branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/SingleObjective/HeuristicAlgorithm.cs	(revision 14429)
@@ -0,0 +1,339 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization.Algorithms.SingleObjective {
+  public abstract class HeuristicAlgorithm<TContext, TProblem, TEncoding, TSolution> : Algorithm
+      where TContext : HeuristicAlgorithmContext<TProblem, TEncoding, TSolution>,
+                       IStochasticContext, IEvaluatedSolutionsContext, IBestQualityContext,
+                       IBestSolutionContext<TSolution>, new()
+      where TProblem : class, ISingleObjectiveProblem<TEncoding, TSolution>, ISingleObjectiveProblemDefinition<TEncoding, TSolution>
+      where TEncoding : class, IEncoding<TSolution>
+      where TSolution : class, ISolution {
+    private Type problemType;
+
+    public override Type ProblemType {
+      get { return typeof(SingleObjectiveProblem<TEncoding, TSolution>); }
+    }
+
+    public new TProblem Problem {
+      get { return (TProblem)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    private CancellationTokenSource cancellationTokenSource;
+    protected CancellationTokenSource CancellationTokenSource {
+      get { return cancellationTokenSource; }
+      private set { cancellationTokenSource = value; }
+    }
+
+
+    public int? MaximumEvaluations {
+      get {
+        var val = ((OptionalValueParameter<IntValue>)Parameters["MaximumEvaluations"]).Value;
+        return val != null ? val.Value : (int?)null;
+      }
+      set {
+        var param = (OptionalValueParameter<IntValue>)Parameters["MaximumEvaluations"];
+        param.Value = value.HasValue ? new IntValue(value.Value) : null;
+      }
+    }
+
+    public TimeSpan? MaximumExecutionTime {
+      get {
+        var val = ((OptionalValueParameter<TimeSpanValue>)Parameters["MaximumExecutionTime"]).Value;
+        return val != null ? val.Value : (TimeSpan?)null;
+      }
+      set {
+        var param = (OptionalValueParameter<TimeSpanValue>)Parameters["MaximumExecutionTime"];
+        param.Value = value.HasValue ? new TimeSpanValue(value.Value) : null;
+      }
+    }
+
+    public double? TargetQuality {
+      get {
+        var val = ((OptionalValueParameter<DoubleValue>)Parameters["TargetQuality"]).Value;
+        return val != null ? val.Value : (double?)null;
+      }
+      set {
+        var param = (OptionalValueParameter<DoubleValue>)Parameters["TargetQuality"];
+        param.Value = value.HasValue ? new DoubleValue(value.Value) : null;
+      }
+    }
+
+    public bool SetSeedRandomly {
+      get { return ((FixedValueParameter<BoolValue>)Parameters["SetSeedRandomly"]).Value.Value; }
+      set { ((FixedValueParameter<BoolValue>)Parameters["SetSeedRandomly"]).Value.Value = value; }
+    }
+
+    public int Seed {
+      get { return ((FixedValueParameter<IntValue>)Parameters["Seed"]).Value.Value; }
+      set { ((FixedValueParameter<IntValue>)Parameters["Seed"]).Value.Value = value; }
+    }
+
+    public IMultiAnalyzer AlgorithmAnalyzer {
+      get { return ((ValueParameter<IMultiAnalyzer>)Parameters["Analyzer.Algorithm"]).Value; }
+      set { ((ValueParameter<IMultiAnalyzer>)Parameters["Analyzer.Algorithm"]).Value = value; }
+    }
+
+    public IMultiAnalyzer ProblemAnalyzer {
+      get { return ((ValueParameter<IMultiAnalyzer>)Parameters["Analyzer.Problem"]).Value; }
+      set { ((ValueParameter<IMultiAnalyzer>)Parameters["Analyzer.Problem"]).Value = value; }
+    }
+
+    [Storable]
+    private ResultCollection results;
+    public override ResultCollection Results {
+      get { return results; }
+    }
+
+    [Storable]
+    private TContext context;
+    public TContext Context {
+      get { return context; }
+      protected set {
+        if (context == value) return;
+        context = value;
+      }
+    }
+
+    [StorableConstructor]
+    protected HeuristicAlgorithm(bool deserializing) : base(deserializing) { }
+    protected HeuristicAlgorithm(HeuristicAlgorithm<TContext, TProblem, TEncoding, TSolution> original, Cloner cloner)
+      : base(original, cloner) { }
+    protected HeuristicAlgorithm() {
+      results = new ResultCollection();
+
+      Parameters.Add(new ValueParameter<IMultiAnalyzer>("Analyzer.Algorithm", "The algorithm's analyzers to apply to the solution(s) (independent of the problem)."));
+      Parameters.Add(new ValueParameter<IMultiAnalyzer>("Analyzer.Problem", "The problem's analyzer to apply to the solution(s)."));
+      Parameters.Add(new OptionalValueParameter<IntValue>("MaximumEvaluations", "The maximum number of solution evaluations."));
+      Parameters.Add(new OptionalValueParameter<TimeSpanValue>("MaximumExecutionTime", "The maximum runtime.", new TimeSpanValue(TimeSpan.FromMinutes(1))));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("TargetQuality", "The target quality at which the algorithm terminates."));
+      Parameters.Add(new FixedValueParameter<BoolValue>("SetSeedRandomly", "Whether each run of the algorithm should be conducted with a new random seed.", new BoolValue(true)));
+      Parameters.Add(new FixedValueParameter<IntValue>("Seed", "The random number seed that is used in case SetSeedRandomly is false.", new IntValue(0)));
+
+    }
+
+    protected override void OnProblemChanged() {
+      base.OnProblemChanged();
+      if (ProblemAnalyzer != null) {
+        ProblemAnalyzer.Operators.Clear();
+        if (Problem != null) {
+          foreach (var analyzer in Problem.Operators.OfType<IAnalyzer>()) {
+            foreach (var param in analyzer.Parameters.OfType<IScopeTreeLookupParameter>())
+              param.Depth = 1;
+            ProblemAnalyzer.Operators.Add(analyzer, analyzer.EnabledByDefault);
+          }
+        }
+      }
+    }
+
+    public override void Prepare() {
+      if (Problem == null) return;
+      base.Prepare();
+      results.Clear();
+      Context = null;
+      stopRequested = false;
+      OnPrepared();
+    }
+
+    private bool stopRequested = false;
+    public override void Start() {
+      base.Start();
+      CancellationTokenSource = new CancellationTokenSource();
+
+      OnStarted();
+      var task = Task.Run((Action)Run, cancellationTokenSource.Token);
+      var continuation = new Task[3];
+      continuation[0] = task.ContinueWith(t => {
+        if (t.Exception != null) {
+          OnExceptionOccurred(t.Exception.InnerExceptions.Count == 1 ? t.Exception.InnerExceptions[0] : t.Exception);
+        }
+        OnPaused();
+      }, TaskContinuationOptions.OnlyOnFaulted);
+      continuation[1] = task.ContinueWith(t => {
+        OnStopped();
+      }, TaskContinuationOptions.OnlyOnRanToCompletion);
+      continuation[2] = task.ContinueWith(t => {
+        if (stopRequested) OnStopped();
+        else OnPaused();
+      }, TaskContinuationOptions.OnlyOnCanceled);
+      Task.WhenAny(continuation).ContinueWith(_ => {
+        CancellationTokenSource.Dispose();
+        CancellationTokenSource = null;
+      });
+    }
+
+    public override void Pause() {
+      base.Pause();
+      CancellationTokenSource.Cancel();
+    }
+
+    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();
+      stopRequested = true;
+      if (CancellationTokenSource != null) {
+        try {
+          CancellationTokenSource.Cancel();
+        } catch {
+          OnStopped();
+        }
+      } else OnStopped();
+    }
+
+    private DateTime lastUpdateTime;
+    private void Run() {
+      var token = CancellationTokenSource.Token;
+      lastUpdateTime = DateTime.UtcNow;
+      System.Timers.Timer timer = new System.Timers.Timer(250);
+      timer.AutoReset = true;
+      timer.Elapsed += timer_Elapsed;
+      timer.Start();
+      try {
+        if (context == null) {
+          context = CreateContext();
+
+          IExecutionContext ctxt = null;
+          foreach (var item in Problem.ExecutionContextItems)
+            ctxt = new Core.ExecutionContext(ctxt, item, Context.Scope);
+          ctxt = new Core.ExecutionContext(ctxt, this, Context.Scope);
+
+          context.Parent = ctxt;
+
+          if (SetSeedRandomly) Seed = new System.Random().Next();
+          Context.Random.Reset(Seed);
+          Context.Scope.Variables.Add(new Variable("Results", Results));
+        } else context.CancellationToken = token;
+
+        if (!Context.Initialized) {
+          try {
+            PerformInitialize(token);
+          } catch {
+            context = null;
+            return;
+          }
+          Context.Initialized = true;
+        }
+
+        while (!CheckTerminate(token)) {
+          PerformIterate(token);
+          PerformAnalyze(token);
+          token.ThrowIfCancellationRequested();
+        }
+      } finally {
+        timer.Elapsed -= timer_Elapsed;
+        timer.Stop();
+        ExecutionTime += DateTime.UtcNow - lastUpdateTime;
+      }
+    }
+
+    protected virtual TContext CreateContext() {
+      return new TContext() { Problem = Problem, CancellationToken = CancellationTokenSource.Token };
+    }
+
+    protected virtual ISingleObjectiveSolutionScope<TSolution> CreateEmptySolutionScope() {
+      return new SingleObjectiveSolutionScope<TSolution>(null, Problem.Encoding.Name, double.NaN, Problem.Evaluator.QualityParameter.ActualName);
+    }
+
+    protected static bool IsBetter(bool maximization, double a, double b) {
+      return !double.IsNaN(a) && double.IsNaN(b) || maximization && a > b || !maximization && a < b;
+    }
+
+    protected virtual void Evaluate(ISingleObjectiveSolutionScope<TSolution> scope, CancellationToken token) {
+      scope.Fitness = Problem.Evaluate(scope.Solution, Context.Random);
+    }
+
+    protected abstract void PerformInitialize(CancellationToken token);
+    protected abstract void PerformIterate(CancellationToken token);
+    protected virtual void PerformAnalyze(CancellationToken token) {
+      IResult res;
+      if (!Results.TryGetValue("EvaluatedSolutions", out res)) {
+        res = new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions));
+        Results.Add(res);
+      } else ((IntValue)res.Value).Value = Context.EvaluatedSolutions;
+      if (!Results.TryGetValue("BestQuality", out res)) {
+        res = new Result("BestQuality", new DoubleValue(Context.BestQuality));
+        Results.Add(res);
+      } else ((DoubleValue)res.Value).Value = Context.BestQuality;
+
+      RunOperator(ProblemAnalyzer, Context.Scope, token);
+      RunOperator(AlgorithmAnalyzer, Context.Scope, token);
+    }
+
+    protected virtual bool CheckTerminate(CancellationToken token) {
+      return MaximumEvaluations.HasValue && Context.EvaluatedSolutions >= MaximumEvaluations.Value
+        || MaximumExecutionTime.HasValue && ExecutionTime >= MaximumExecutionTime.Value
+        || TargetQuality.HasValue && (Problem.Maximization && Context.BestQuality >= TargetQuality.Value
+                                  || !Problem.Maximization && Context.BestQuality <= TargetQuality.Value);
+    }
+
+    #region Engine Helper
+    protected void RunOperator(IOperator op, IScope scope, CancellationToken cancellationToken) {
+      var stack = new Stack<IOperation>();
+      stack.Push(Context.CreateChildOperation(op, scope));
+
+      while (stack.Count > 0) {
+        cancellationToken.ThrowIfCancellationRequested();
+
+        var next = stack.Pop();
+        if (next is OperationCollection) {
+          var coll = (OperationCollection)next;
+          for (int i = coll.Count - 1; i >= 0; i--)
+            if (coll[i] != null) stack.Push(coll[i]);
+        } else if (next is IAtomicOperation) {
+          var operation = (IAtomicOperation)next;
+          try {
+            next = operation.Operator.Execute((IExecutionContext)operation, cancellationToken);
+          } catch (Exception ex) {
+            stack.Push(operation);
+            if (ex is OperationCanceledException) throw ex;
+            else throw new OperatorExecutionException(operation.Operator, ex);
+          }
+          if (next != null) stack.Push(next);
+        }
+      }
+    }
+    #endregion
+
+    #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/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/SingleObjective/HeuristicAlgorithmContext.cs
===================================================================
--- branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/SingleObjective/HeuristicAlgorithmContext.cs	(revision 14429)
+++ branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/SingleObjective/HeuristicAlgorithmContext.cs	(revision 14429)
@@ -0,0 +1,147 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using ExecutionContext = HeuristicLab.Core.ExecutionContext;
+
+namespace HeuristicLab.Optimization.Algorithms.SingleObjective {
+  [Item("AlgorithmContext", "")]
+  [StorableClass]
+  public abstract class HeuristicAlgorithmContext<TProblem, TEncoding, TSolution> : ParameterizedNamedItem,
+      IProblemContext<TProblem, TEncoding, TSolution>, IStochasticContext,
+      IEvaluatedSolutionsContext, IBestQualityContext, IBestSolutionContext<TSolution>,
+      ILongRunningOperationContext
+      where TProblem : class, ISingleObjectiveProblem<TEncoding, TSolution>, ISingleObjectiveProblemDefinition<TEncoding, TSolution>
+      where TEncoding : class, IEncoding<TSolution>
+      where TSolution : class, ISolution {
+
+    private IExecutionContext parent;
+    public IExecutionContext Parent {
+      get { return parent; }
+      set { parent = value; }
+    }
+
+    IKeyedItemCollection<string, IParameter> IExecutionContext.Parameters {
+      get { return Parameters; }
+    }
+
+    public CancellationToken CancellationToken { get; set; }
+
+    [Storable]
+    private IValueParameter<TProblem> problem;
+    public TProblem Problem {
+      get { return problem.Value; }
+      set { problem.Value = value; }
+    }
+
+    [Storable]
+    private IScope scope;
+    public IScope Scope {
+      get { return scope; }
+    }
+
+    [Storable]
+    private IValueParameter<BoolValue> initialized;
+    public bool Initialized {
+      get { return initialized.Value.Value; }
+      set { initialized.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IRandom> random;
+    public IRandom Random {
+      get { return random.Value; }
+      set { random.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<IntValue> evaluatedSolutions;
+    public int EvaluatedSolutions {
+      get { return evaluatedSolutions.Value.Value; }
+      set { evaluatedSolutions.Value.Value = value; }
+    }
+
+    public void IncEvaluatedSolutions(int inc) {
+      EvaluatedSolutions += inc;
+    }
+
+    [Storable]
+    private IValueParameter<DoubleValue> bestQuality;
+    public double BestQuality {
+      get { return bestQuality.Value.Value; }
+      set { bestQuality.Value.Value = value; }
+    }
+
+    [Storable]
+    private IValueParameter<TSolution> bestSolution;
+    public TSolution BestSolution {
+      get { return bestSolution.Value; }
+      set { bestSolution.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected HeuristicAlgorithmContext(bool deserializing) : base(deserializing) { }
+    protected HeuristicAlgorithmContext(HeuristicAlgorithmContext<TProblem, TEncoding, TSolution> original, Cloner cloner)
+      : base(original, cloner) {
+      problem = cloner.Clone(original.problem);
+      scope = cloner.Clone(original.scope);
+      initialized = cloner.Clone(original.initialized);
+      random = cloner.Clone(original.random);
+      evaluatedSolutions = cloner.Clone(original.evaluatedSolutions);
+      bestQuality = cloner.Clone(original.bestQuality);
+      bestSolution = cloner.Clone(original.bestSolution);
+    }
+    protected HeuristicAlgorithmContext() : this(new Scope("Scope"), CancellationToken.None) { }
+    protected HeuristicAlgorithmContext(IScope s, CancellationToken token) {
+      scope = s;
+      CancellationToken = token;
+      Parameters.Add(problem = new ValueParameter<TProblem>("Problem", "The problem that is to be solved."));
+      Parameters.Add(initialized = new ValueParameter<BoolValue>("Initialized", "Whether the algorithm has finished the initialization phase.", new BoolValue(false)));
+      Parameters.Add(random = new ValueParameter<IRandom>("Random", "The random number generator.", new MersenneTwister()));
+      Parameters.Add(evaluatedSolutions = new ValueParameter<IntValue>("EvaluatedSolutions", "The number of evaluated solutions.", new IntValue(0)));
+      Parameters.Add(bestQuality = new ValueParameter<DoubleValue>("BestQuality", "The best quality found so far.", new DoubleValue(double.NaN)));
+      Parameters.Add(bestSolution = new OptionalValueParameter<TSolution>("BestSolution", "The best solution found so far."));
+
+    }
+
+    public IAtomicOperation CreateOperation(IOperator op) {
+      return new ExecutionContext(parent, op, scope);
+    }
+
+    public IAtomicOperation CreateOperation(IOperator op, IScope s) {
+      return new ExecutionContext(parent, op, s);
+    }
+
+    public IAtomicOperation CreateChildOperation(IOperator op) {
+      return new ExecutionContext(this, op, scope);
+    }
+
+    public IAtomicOperation CreateChildOperation(IOperator op, IScope s) {
+      return new ExecutionContext(this, op, s);
+    }
+  }
+}
Index: branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/SingleObjective/SingleObjectiveSolutionScope.cs
===================================================================
--- branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/SingleObjective/SingleObjectiveSolutionScope.cs	(revision 14429)
+++ branches/ScopedAlgorithms/HeuristicLab.Optimization/3.3/Algorithms/SingleObjective/SingleObjectiveSolutionScope.cs	(revision 14429)
@@ -0,0 +1,147 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Drawing;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Optimization.Algorithms.SingleObjective {
+  [Item("MemPRScope", "Scope for a MemPR individual.")]
+  [StorableClass]
+  public sealed class SingleObjectiveSolutionScope<T> : NamedItem, ISingleObjectiveSolutionScope<T> where T : class, IItem {
+    public new static Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.OrgChart; }
+    }
+
+    [Storable]
+    private IScope parent;
+    public IScope Parent {
+      get { return parent; }
+      set {
+        if (parent != value) {
+          parent = value;
+        }
+      }
+    }
+
+    [Storable]
+    private VariableCollection variables;
+    public VariableCollection Variables {
+      get { return variables; }
+    }
+
+    [Storable]
+    private ScopeList subScopes;
+    public ScopeList SubScopes {
+      get { return subScopes; }
+    }
+
+    [Storable]
+    private Variable solution;
+    public T Solution {
+      get { return (T)solution.Value; }
+      set { solution.Value = value; }
+    }
+
+    [Storable]
+    private Variable fitness;
+    public double Fitness {
+      get { return ((DoubleValue)fitness.Value).Value; }
+      set { ((DoubleValue)fitness.Value).Value = value; }
+    }
+
+    [StorableConstructor]
+    private SingleObjectiveSolutionScope(bool deserializing) : base(deserializing) { }
+    private SingleObjectiveSolutionScope(SingleObjectiveSolutionScope<T> original, Cloner cloner)
+      : base(original, cloner) {
+      // the parent will not be deep-cloned
+      parent = original.parent;
+      variables = cloner.Clone(original.variables);
+      subScopes = cloner.Clone(original.subScopes);
+      foreach (var child in SubScopes)
+        child.Parent = this;
+      solution = cloner.Clone(original.solution);
+      fitness = cloner.Clone(original.fitness);
+
+      RegisterSubScopesEvents();
+    }
+    public SingleObjectiveSolutionScope(T code, string codeName, double fitness, string fitnessName) {
+      this.solution = new Variable(codeName, code);
+      this.fitness = new Variable(fitnessName, new DoubleValue(fitness));
+      variables = new VariableCollection(2) { this.solution, this.fitness };
+      subScopes = new ScopeList(2);
+
+      RegisterSubScopesEvents();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectiveSolutionScope<T>(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterSubScopesEvents();
+    }
+
+    public void Clear() {
+      variables.Clear();
+      subScopes.Clear();
+    }
+
+    #region SubScopes Events
+    private void RegisterSubScopesEvents() {
+      if (subScopes != null) {
+        subScopes.ItemsAdded += SubScopes_ItemsAdded;
+        subScopes.ItemsRemoved += SubScopes_ItemsRemoved;
+        subScopes.ItemsReplaced += SubScopes_ItemsReplaced;
+        subScopes.CollectionReset += SubScopes_CollectionReset;
+      }
+    }
+    private void SubScopes_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IScope>> e) {
+      foreach (var item in e.Items) item.Value.Parent = this;
+    }
+    private void SubScopes_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IScope>> e) {
+      foreach (var item in e.Items) item.Value.Parent = null;
+    }
+    private void SubScopes_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IScope>> e) {
+      foreach (var oldItem in e.OldItems) oldItem.Value.Parent = null;
+      foreach (var item in e.Items) item.Value.Parent = this;
+    }
+    private void SubScopes_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IScope>> e) {
+      foreach (var oldItem in e.OldItems) oldItem.Value.Parent = null;
+      foreach (var item in e.Items) item.Value.Parent = this;
+    }
+    #endregion
+
+    public void Adopt(ISingleObjectiveSolutionScope<T> orphan) {
+      Solution = orphan.Solution;
+      Fitness = orphan.Fitness;
+    }
+
+    public void Adopt(ISolutionScope<T> orphan) {
+      Solution = orphan.Solution;
+      Fitness = double.NaN;
+    }
+  }
+}
