Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/CrowdingAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/CrowdingAnalyzer.cs	(revision 17225)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/CrowdingAnalyzer.cs	(revision 17225)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Analysis {
+  [StorableType("6f09f028-039d-4da8-9585-2575f9aef074")]
+  [Item("CrowdingAnalyzer", "The mean crowding distance for each point of the Front (see Multi-Objective Performance Metrics - Shodhganga for more information)")]
+  public class CrowdingAnalyzer : MultiObjectiveSuccessAnalyzer {
+    public override string ResultName {
+      get { return "Crowding"; }
+    }
+
+    [StorableConstructor]
+    protected CrowdingAnalyzer(StorableConstructorFlag _) : base(_) { }
+    public CrowdingAnalyzer(CrowdingAnalyzer original, Cloner cloner)
+      : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CrowdingAnalyzer(this, cloner);
+    }
+
+    public CrowdingAnalyzer() {
+      Parameters.Add(new ResultParameter<DoubleValue>("Crowding", "The average corwding distance of all points (excluding infinities)", "Results", new DoubleValue(double.NaN)));
+    }
+
+    public override IOperation Apply() {
+      var qualities = QualitiesParameter.ActualValue;
+      var crowdingDistance = CrowdingCalculator.CalculateCrowding(qualities.Select(x => x.ToArray()));
+      ResultParameter.ActualValue.Value = crowdingDistance;
+      return base.Apply();
+    }
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/GenerationalDistanceAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/GenerationalDistanceAnalyzer.cs	(revision 17225)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/GenerationalDistanceAnalyzer.cs	(revision 17225)
@@ -0,0 +1,105 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Analysis {
+  [StorableType("f8ae6c1c-5f8f-45d6-b513-bb8041546808")]
+  [Item("GenerationalDistanceAnalyzer", "The generational distance between the current and the optimal front (if known)(see Multi-Objective Performance Metrics - Shodhganga for more information). The calculation of generational distance requires a known optimal pareto front")]
+  public class GenerationalDistanceAnalyzer : MultiObjectiveSuccessAnalyzer {
+    public override string ResultName {
+      get { return "Generational Distance"; }
+    }
+
+    public IFixedValueParameter<DoubleValue> DampeningParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters["Dampening"]; }
+    }
+
+    public double Dampening {
+      get { return DampeningParameter.Value.Value; }
+      set { DampeningParameter.Value.Value = value; }
+    }
+
+    public ILookupParameter<DoubleMatrix> OptimalParetoFrontParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["BestKnownFront"]; }
+    }
+
+
+    [StorableConstructor]
+    protected GenerationalDistanceAnalyzer(StorableConstructorFlag _) : base(_) { }
+    protected GenerationalDistanceAnalyzer(GenerationalDistanceAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GenerationalDistanceAnalyzer(this, cloner);
+    }
+
+    public GenerationalDistanceAnalyzer() : base() {
+      Parameters.Add(new FixedValueParameter<DoubleValue>("Dampening", "", new DoubleValue(1)));
+      Parameters.Add(new LookupParameter<ItemArray<DoubleArray>>("OptimalParetoFront", "The analytically best known Pareto front"));
+      Parameters.Add(new ResultParameter<DoubleValue>(ResultName, "The generational distance between the current front and the optimal front", "Results", new DoubleValue(double.NaN)));
+    }
+
+    public override IOperation Apply() {
+      var qualities = QualitiesParameter.ActualValue;
+      var optimalFront = OptimalParetoFrontParameter.ActualValue;
+      if (optimalFront == null) return base.Apply();
+      var front = Enumerable.Range(0, optimalFront.Rows).Select(r => Enumerable.Range(0, optimalFront.Columns).Select(c => optimalFront[r, c]).ToArray()).ToList();
+      ResultParameter.ActualValue.Value = CalculateDistance(qualities, front);
+      return base.Apply();
+    }
+
+    protected virtual double CalculateDistance(ItemArray<DoubleArray> qualities, IEnumerable<double[]> optimalFront) {
+      return CalculateGenerationalDistance(qualities.Select(x => x.ToArray()), optimalFront, Dampening);
+    }
+
+    public static double CalculateGenerationalDistance(IEnumerable<double[]> qualities, IEnumerable<double[]> bestKnownFront, double p) {
+      if (qualities == null || bestKnownFront == null) throw new ArgumentNullException("qualities");
+      if (p.IsAlmost(0.0)) throw new ArgumentException("p must not be zero.");
+      var mat = bestKnownFront.ToMatrix();
+      if (mat.GetLength(0) == 0) throw new ArgumentException("Fronts must not be empty.");
+      alglib.kdtree tree;
+      alglib.kdtreebuild(mat, mat.GetLength(0), mat.GetLength(1), 0, 2, out tree);
+      var sum = 0.0;
+      var summand = new double[1];
+      var count = 0;
+      foreach (var point in qualities) {
+        alglib.kdtreequeryknn(tree, point.ToArray(), 1, true);
+        alglib.kdtreequeryresultsdistances(tree, ref summand);
+        sum += Math.Pow(summand[0], p);
+        count++;
+      }
+
+      if (count == 0) throw new ArgumentException("Fronts must not be empty.");
+      return Math.Pow(sum, 1 / p) / count;
+    }
+
+    public static double CalculateInverseGenerationalDistance(IEnumerable<double[]> qualities, IEnumerable<double[]> bestKnownFront, double p) {
+      return CalculateGenerationalDistance(bestKnownFront, qualities, p);
+    }
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/HypervolumeAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/HypervolumeAnalyzer.cs	(revision 17225)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/HypervolumeAnalyzer.cs	(revision 17225)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Analysis {
+  [StorableType("fc42ed56-15de-41df-bf59-0e5b11cd4f9b")]
+  [Item("HypervolumeAnalyzer", "Computes the enclosed Hypervolume between the current front and a given reference Point")]
+  public class HypervolumeAnalyzer : MultiObjectiveSuccessAnalyzer {
+    public override string ResultName {
+      get { return "Hypervolume"; }
+    }
+
+    public ILookupParameter<DoubleArray> ReferencePointParameter {
+      get { return (ILookupParameter<DoubleArray>)Parameters["ReferencePoint"]; }
+    }
+
+    public IResultParameter<DoubleValue> BestKnownHypervolumeResultParameter {
+      get { return (IResultParameter<DoubleValue>)Parameters["Best known hypervolume"]; }
+    }
+
+    public IResultParameter<DoubleValue> HypervolumeDistanceResultParameter {
+      get { return (IResultParameter<DoubleValue>)Parameters["Absolute Distance to BestKnownHypervolume"]; }
+    }
+
+
+    [StorableConstructor]
+    protected HypervolumeAnalyzer(StorableConstructorFlag _) : base(_) { }
+
+    protected HypervolumeAnalyzer(HypervolumeAnalyzer original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new HypervolumeAnalyzer(this, cloner);
+    }
+
+    public HypervolumeAnalyzer() {
+      Parameters.Add(new LookupParameter<DoubleArray>("ReferencePoint", "The reference point for hypervolume calculation"));
+      Parameters.Add(new ResultParameter<DoubleValue>("Hypervolume", "The hypervolume of the current generation", "Results", new DoubleValue(double.NaN)));
+      Parameters.Add(new ResultParameter<DoubleValue>("Best known hypervolume", "The optimal hypervolume"));
+      Parameters.Add(new ResultParameter<DoubleValue>("Absolute Distance to BestKnownHypervolume", "The difference between the best known and the current hypervolume"));
+      BestKnownHypervolumeResultParameter.DefaultValue = new DoubleValue(double.NaN);
+      HypervolumeDistanceResultParameter.DefaultValue = new DoubleValue(double.NaN);
+    }
+
+    public override IOperation Apply() {
+      var qualities = QualitiesParameter.ActualValue.Select(x => x.CloneAsArray()).ToArray();
+      var referencePoint = ReferencePointParameter.ActualValue.ToArray();
+      var best = BestKnownHypervolumeResultParameter.ActualValue.Value;
+      var maximization = MaximizationParameter.ActualValue.ToArray();
+
+      var hv = HypervolumeCalculator.CalculateHypervolume(qualities, referencePoint, maximization);
+      if (hv > best || double.IsNaN(best)) best = hv;
+      ResultParameter.ActualValue.Value = hv;
+      BestKnownHypervolumeResultParameter.ActualValue.Value = best;
+      HypervolumeDistanceResultParameter.ActualValue.Value = best - hv;
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/InvertedGenerationalDistanceAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/InvertedGenerationalDistanceAnalyzer.cs	(revision 17225)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/InvertedGenerationalDistanceAnalyzer.cs	(revision 17225)
@@ -0,0 +1,58 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Analysis {
+  [StorableType("1004980a-9b3d-4b6f-b5bf-81e75d288344")]
+  [Item("InvertedGenerationalDistanceAnalyzer", "The inverted generational distance between the current and the best known front (see Multi-Objective Performance Metrics - Shodhganga for more information)")]
+  public class InvertedGenerationalDistanceAnalyzer : GenerationalDistanceAnalyzer {
+    public override bool EnabledByDefault {
+      get { return false; }
+    }
+    public override string ResultName {
+      get { return "Inverted Generational Distance"; }
+    }
+
+    public IResultParameter<DoubleValue> InvertedGenerationalDistanceResultParameter {
+      get { return (IResultParameter<DoubleValue>)Parameters["Inverted Generational Distance"]; }
+    }
+
+    [StorableConstructor]
+    protected InvertedGenerationalDistanceAnalyzer(StorableConstructorFlag _) : base(_) { }
+    protected InvertedGenerationalDistanceAnalyzer(InvertedGenerationalDistanceAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new InvertedGenerationalDistanceAnalyzer(this, cloner);
+    }
+
+    public InvertedGenerationalDistanceAnalyzer() : base() { }
+
+    protected override double CalculateDistance(ItemArray<DoubleArray> qualities, IEnumerable<double[]> optimalFront) {
+      return CalculateGenerationalDistance(optimalFront, qualities.Select(x => x.ToArray()), Dampening);
+    }
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/MultiObjectiveSuccessAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/MultiObjectiveSuccessAnalyzer.cs	(revision 17225)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/MultiObjectiveSuccessAnalyzer.cs	(revision 17225)
@@ -0,0 +1,61 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+
+namespace HeuristicLab.Analysis {
+  [StorableType("3659291a-927c-4016-88be-8a0f65476660")]
+  public abstract class MultiObjectiveSuccessAnalyzer : SingleSuccessorOperator, IAnalyzer, IMultiObjectiveOperator {
+    public virtual bool EnabledByDefault {
+      get { return true; }
+    }
+    public abstract string ResultName { get; }
+
+    public IScopeTreeLookupParameter<DoubleArray> QualitiesParameter {
+      get { return (IScopeTreeLookupParameter<DoubleArray>)Parameters["Qualities"]; }
+    }
+
+    public ILookupParameter<BoolArray> MaximizationParameter {
+      get { return (ILookupParameter<BoolArray>)Parameters["Maximization"]; }
+    }
+
+    public ResultParameter<DoubleValue> ResultParameter {
+      get { return (ResultParameter<DoubleValue>)Parameters[ResultName]; }
+    }
+
+    protected MultiObjectiveSuccessAnalyzer(MultiObjectiveSuccessAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    [StorableConstructor]
+    protected MultiObjectiveSuccessAnalyzer(StorableConstructorFlag _) : base(_) { }
+    protected MultiObjectiveSuccessAnalyzer() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>("Qualities", "The qualities of the parameter vector."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("BestKnownFront", "The currently best known Pareto front"));
+      Parameters.Add(new LookupParameter<BoolArray>("Maximization", ""));
+    }
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/SpacingAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/SpacingAnalyzer.cs	(revision 17225)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/SpacingAnalyzer.cs	(revision 17225)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Analysis {
+  [StorableType("d84ac1f1-a6d4-425f-bcff-28472ef7529a")]
+  [Item("SpacingAnalyzer", "The spacing of the current front (see Multi-Objective Performance Metrics - Shodhganga for more information)")]
+  public class SpacingAnalyzer : MultiObjectiveSuccessAnalyzer {
+    public override string ResultName {
+      get { return "Spacing"; }
+    }
+
+    [StorableConstructor]
+    protected SpacingAnalyzer(StorableConstructorFlag _) : base(_) { }
+
+
+    protected SpacingAnalyzer(SpacingAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SpacingAnalyzer(this, cloner);
+    }
+
+    public SpacingAnalyzer() {
+      Parameters.Add(new ResultParameter<DoubleValue>("Spacing", "The spacing of the current front", "Results", new DoubleValue(double.NaN)));
+    }
+
+    public override IOperation Apply() {
+      var qualities = QualitiesParameter.ActualValue;
+      ResultParameter.ActualValue.Value = CalculateSpacing(qualities.Select(x => x.ToArray()));
+      return base.Apply();
+    }
+
+    public static double CalculateSpacing(IEnumerable<double[]> qualities) {
+      if (qualities == null) throw new ArgumentNullException("qualities");
+      var l = qualities.ToList();
+      if (l.Count == 0) throw new ArgumentException("Front must not be empty.");
+      if (l.Count == 1) return 0;
+
+      var mat = l.ToMatrix();
+      alglib.kdtree tree;
+      alglib.kdtreebuild(mat, mat.GetLength(0), mat.GetLength(1), 0, 2, out tree);
+      var summand = new double[2];
+      var dists = new List<double>();
+      foreach (var point in l) {
+        alglib.kdtreequeryknn(tree, point.ToArray(), 2, true);
+        alglib.kdtreequeryresultsdistances(tree, ref summand);
+        dists.Add(summand[1]);
+      }
+      return dists.StandardDeviationPop();
+    }
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/TimelineAnalyzer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/TimelineAnalyzer.cs	(revision 17225)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Analysis/3.3/MultiObjective/TimelineAnalyzer.cs	(revision 17225)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
+
+namespace HeuristicLab.Analysis {
+  [StorableType("48fc7ff7-a8ab-4ef9-8c01-cc6fbbe3da0b")]
+  [Item("TimelineAnalyzer", "Collects the specified double values from the results and displays them as a timeline")]
+  public class TimelineAnalyzer : SingleSuccessorOperator, IAnalyzer, IMultiObjectiveOperator {
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    public string ResultName {
+      get { return "Timeline"; }
+    }
+
+    public IFixedValueParameter<CheckedItemList<StringValue>> CollectedSuccessMeasuresParameter {
+      get { return (IFixedValueParameter<CheckedItemList<StringValue>>)Parameters["CollectedSuccessMeasures"]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ResultParameter<DataTable> ResultParameter {
+      get { return (ResultParameter<DataTable>)Parameters[ResultName]; }
+    }
+
+    public CheckedItemList<StringValue> CollectedSuccessMeasures {
+      get { return CollectedSuccessMeasuresParameter.Value; }
+    }
+
+    [StorableConstructor]
+    protected TimelineAnalyzer(StorableConstructorFlag _) : base(_) { }
+
+
+    protected TimelineAnalyzer(TimelineAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TimelineAnalyzer(this, cloner);
+    }
+
+    public TimelineAnalyzer() {
+      var names = new List<string> {
+        new CrowdingAnalyzer().ResultName,
+        new GenerationalDistanceAnalyzer().ResultName,
+        new InvertedGenerationalDistanceAnalyzer().ResultName,
+        new HypervolumeAnalyzer().ResultName,
+        new SpacingAnalyzer().ResultName
+      };
+      var analyzers = new CheckedItemList<StringValue>(names.Select(n => new StringValue(n)));
+      Parameters.Add(new FixedValueParameter<CheckedItemList<StringValue>>("CollectedSuccessMeasures", analyzers));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results"));
+      Parameters.Add(new ResultParameter<DataTable>("Timeline", "The development of the success measures over the generations", "Results", new DataTable("Timeline", "")));
+    }
+
+    public override IOperation Apply() {
+      if (ResultParameter.ActualValue == null) ResultParameter.ActualValue = new DataTable(ResultName, "");
+      var plot = ResultParameter.ActualValue;
+      var resultCollection = ResultsParameter.ActualValue;
+      foreach (var resultName in CollectedSuccessMeasures.CheckedItems.Select(i => i.Value.Value)) {
+        if (!resultCollection.ContainsKey(resultName)) continue;
+        var res = resultCollection[resultName].Value as DoubleValue;
+        if (res == null) continue;
+        if (!plot.Rows.ContainsKey(resultName)) plot.Rows.Add(new DataRow(resultName));
+        plot.Rows[resultName].Values.Add(res.Value);
+      }
+      return base.Apply();
+    }
+  }
+}
