Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking/3.4/Analyzers/EvolutionTrackingAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking/3.4/Analyzers/EvolutionTrackingAnalyzer.cs	(revision 12156)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking/3.4/Analyzers/EvolutionTrackingAnalyzer.cs	(revision 12156)
@@ -0,0 +1,96 @@
+﻿#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.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.EvolutionTracking {
+  [Item("EvolutionTrackingAnalyzer", "Base class for analyzers that use the genealogy graph")]
+  [StorableClass]
+  public abstract class EvolutionTrackingAnalyzer<T> : SingleSuccessorOperator, IAnalyzer where T : class,IItem {
+    #region parameter names
+    private const string GenerationsParameterName = "Generations";
+    private const string ResultsParameterName = "Results";
+    private const string PopulationSizeParameterName = "PopulationSize";
+    private const string PopulationGraphResultName = "PopulationGraph";
+    #endregion
+
+    #region parameters
+    public ILookupParameter<IntValue> GenerationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[GenerationsParameterName]; }
+    }
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
+    }
+    public IValueParameter<IntValue> UpdateIntervalParameter {
+      get { return (IValueParameter<IntValue>)Parameters["UpdateInterval"]; }
+    }
+    public ILookupParameter<IntValue> UpdateCounterParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["UpdateCounter"]; }
+    }
+    public ILookupParameter<IntValue> PopulationSizeParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[PopulationSizeParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    public IntValue Generations { get { return GenerationsParameter.ActualValue; } }
+    public ResultCollection Results { get { return ResultsParameter.ActualValue; } }
+    public IntValue UpdateCounter { get { return UpdateCounterParameter.ActualValue; } }
+    public IntValue UpdateInterval { get { return UpdateIntervalParameter.Value; } }
+    public IntValue Generation { get { return GenerationsParameter.ActualValue; } }
+    public IntValue PopulationSize { get { return PopulationSizeParameter.ActualValue; } }
+    public IGenealogyGraph<T> PopulationGraph {
+      get {
+        if (Results.ContainsKey(PopulationGraphResultName))
+          return (IGenealogyGraph<T>)Results[PopulationGraphResultName].Value;
+        return null;
+      }
+    }
+
+    #endregion
+
+    public bool EnabledByDefault {
+      get { return false; }
+    }
+
+    protected EvolutionTrackingAnalyzer() {
+      Parameters.Add(new LookupParameter<IGenealogyGraph<T>>(PopulationGraphResultName, "The genealogy graph."));
+      Parameters.Add(new LookupParameter<IntValue>(GenerationsParameterName, "The number of generations."));
+      Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName, "The results collection."));
+      Parameters.Add(new ValueParameter<IntValue>("UpdateInterval", new IntValue(1)));
+      Parameters.Add(new LookupParameter<IntValue>("UpdateCounter"));
+      Parameters.Add(new LookupParameter<IntValue>(PopulationSizeParameterName, "The population size"));
+    }
+
+    protected EvolutionTrackingAnalyzer(EvolutionTrackingAnalyzer<T> original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableConstructor]
+    protected EvolutionTrackingAnalyzer(bool deserializing) : base(deserializing) { }
+  }
+}
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking/3.4/HeuristicLab.EvolutionTracking-3.4.csproj
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking/3.4/HeuristicLab.EvolutionTracking-3.4.csproj	(revision 12155)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking/3.4/HeuristicLab.EvolutionTracking-3.4.csproj	(revision 12156)
@@ -24,4 +24,5 @@
     <WarningLevel>4</WarningLevel>
     <Prefer32Bit>false</Prefer32Bit>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -109,4 +110,5 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Analyzers\EvolutionTrackingAnalyzer.cs" />
     <Compile Include="Analyzers\GenealogyAnalyzer.cs" />
     <Compile Include="Collections\CloneableCollection.cs" />
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisFragmentLengthAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisFragmentLengthAnalyzer.cs	(revision 12156)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisFragmentLengthAnalyzer.cs	(revision 12156)
@@ -0,0 +1,85 @@
+﻿#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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.EvolutionTracking;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tracking.Analyzers {
+  [Item("SymbolicDataAnalysisFragmentLengthAnalyzer", "An analyzer for fragment length.")]
+  [StorableClass]
+  public class SymbolicDataAnalysisFragmentLengthAnalyzer : EvolutionTrackingAnalyzer<ISymbolicExpressionTree> {
+    [StorableConstructor]
+    protected SymbolicDataAnalysisFragmentLengthAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public SymbolicDataAnalysisFragmentLengthAnalyzer() {
+      UpdateCounterParameter.ActualName = "FragmentLengthAnalyzerUpdateCounter";
+    }
+
+    protected SymbolicDataAnalysisFragmentLengthAnalyzer(SymbolicDataAnalysisFragmentLengthAnalyzer original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisFragmentLengthAnalyzer(this, cloner); }
+
+    public override IOperation Apply() {
+      int updateInterval = UpdateIntervalParameter.Value.Value;
+      IntValue updateCounter = UpdateCounterParameter.ActualValue;
+      // if counter does not yet exist then initialize it with update interval
+      // to make sure the solutions are analyzed on the first application of this operator
+      if (updateCounter == null) {
+        updateCounter = new IntValue(updateInterval);
+        UpdateCounterParameter.ActualValue = updateCounter;
+      }
+      //analyze solutions only every 'updateInterval' times
+      if (updateCounter.Value != updateInterval) {
+        updateCounter.Value++;
+        return base.Apply();
+      }
+      updateCounter.Value = 1;
+
+      if (PopulationGraph == null)
+        return base.Apply();
+
+      var children = PopulationGraph.GetByRank(Generation.Value).Where(x => x.InDegree > 0).ToList();
+      double avgFragmentLength = 0;
+      if (children.Any())
+        avgFragmentLength = children.Select(x => (IFragment<ISymbolicExpressionTreeNode>)x.InArcs.Last().Data).Where(f => f != null).Average(x => x.Root.GetLength());
+
+      DataTable table;
+      if (!Results.ContainsKey("AverageFragmentLength")) {
+        table = new DataTable("Average fragment length");
+        var row = new DataRow("Average fragment length") { VisualProperties = { StartIndexZero = true } };
+        row.Values.Add(avgFragmentLength);
+        table.Rows.Add(row);
+        Results.Add(new Result("AverageFragmentLength", table));
+      } else {
+        table = (DataTable)Results["AverageFragmentLength"].Value;
+        table.Rows["Average fragment length"].Values.Add(avgFragmentLength);
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisTraceOverlapAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisTraceOverlapAnalyzer.cs	(revision 12156)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisTraceOverlapAnalyzer.cs	(revision 12156)
@@ -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.Linq;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.EvolutionTracking;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tracking.Analyzers {
+  [Item("SymbolicDataAnalysisTraceOverlapAnalyzer", "An analyzer for trace graph overlap.")]
+  [StorableClass]
+  public class SymbolicDataAnalysisTraceOverlapAnalyzer : EvolutionTrackingAnalyzer<ISymbolicExpressionTree> {
+    private const string PercentageOfBestSolutionsParameterName = "PercentageOfBestSolutions";
+
+    #region parameters
+    public IFixedValueParameter<DoubleValue> PercentageOfBestSolutionsParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[PercentageOfBestSolutionsParameterName]; }
+    }
+    #endregion
+
+    public SymbolicDataAnalysisTraceOverlapAnalyzer() {
+      UpdateCounterParameter.ActualName = "TraceOverlapAnalyzerUpdateCounter";
+      Parameters.Add(new FixedValueParameter<DoubleValue>(PercentageOfBestSolutionsParameterName, new DoubleValue(1.0)));
+    }
+
+    private SymbolicDataAnalysisTraceOverlapAnalyzer(SymbolicDataAnalysisTraceOverlapAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisTraceOverlapAnalyzer(this, cloner);
+    }
+
+    [StorableConstructor]
+    private SymbolicDataAnalysisTraceOverlapAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public override IOperation Apply() {
+      int updateInterval = UpdateIntervalParameter.Value.Value;
+      IntValue updateCounter = UpdateCounterParameter.ActualValue;
+      // if counter does not yet exist then initialize it with update interval
+      // to make sure the solutions are analyzed on the first application of this operator
+      if (updateCounter == null) {
+        updateCounter = new IntValue(updateInterval);
+        UpdateCounterParameter.ActualValue = updateCounter;
+      }
+      //analyze solutions only every 'updateInterval' times
+      if (updateCounter.Value != updateInterval) {
+        updateCounter.Value++;
+        return base.Apply();
+      }
+      updateCounter.Value = 1;
+
+      if (PopulationGraph == null)
+        return base.Apply();
+
+      var bestSolutionsPercentage = PercentageOfBestSolutionsParameter.Value.Value;
+      int n = (int)Math.Round(bestSolutionsPercentage * PopulationSize.Value);
+      double avgTraceOverlap = 0;
+
+      if (Generation.Value > 0) {
+        var nodes = PopulationGraph.GetByRank(Generation.Value).Cast<IGenealogyGraphNode<ISymbolicExpressionTree>>().OrderByDescending(x => x.Quality).Take(n);
+        avgTraceOverlap = nodes.Average(x => TraceCalculator.TraceSubtree(x, 2).Vertices.Count());
+      }
+
+      DataTable table;
+      if (!Results.ContainsKey("AverageTraceOverlap")) {
+        table = new DataTable("Average trace overlap");
+        var row = new DataRow("Average trace overlap") { VisualProperties = { StartIndexZero = true } };
+        row.Values.Add(avgTraceOverlap);
+        table.Rows.Add(row);
+        Results.Add(new Result("AverageTraceOverlap", table));
+      } else {
+        table = (DataTable)Results["AverageTraceOverlap"].Value;
+        table.Rows["Average trace overlap"].Values.Add(avgTraceOverlap);
+      }
+      return base.Apply();
+    }
+  }
+}
