Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisInternalDiversityAnalyzer.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisInternalDiversityAnalyzer.cs	(revision 11232)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisInternalDiversityAnalyzer.cs	(revision 11232)
@@ -0,0 +1,144 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Analyzers {
+  [StorableClass]
+  [Item("SymbolicDataAnalysisInternalDiversityAnalyzer", "An analyzer that determines the average diversity of symbolic expression trees.")]
+  public class SymbolicDataAnalysisInternalDiversityAnalyzer : SingleSuccessorOperator, ISymbolicDataAnalysisAnalyzer {
+    private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
+    private const string QualityParameterName = "Quality";
+    private const string PercentageOfBestSolutionsParameterName = "PercentageOfBestSolutions";
+
+    private const string ResultCollectionParameterName = "Results";
+    private readonly BottomUpSimilarityCalculator busCalculator;
+
+    public SymbolicDataAnalysisInternalDiversityAnalyzer() {
+      busCalculator = new BottomUpSimilarityCalculator();
+
+      Parameters.Add(new ScopeTreeLookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>(QualityParameterName));
+      Parameters.Add(new LookupParameter<ResultCollection>(ResultCollectionParameterName));
+      Parameters.Add(new FixedValueParameter<PercentValue>(PercentageOfBestSolutionsParameterName));
+    }
+
+    protected SymbolicDataAnalysisInternalDiversityAnalyzer(SymbolicDataAnalysisInternalDiversityAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisInternalDiversityAnalyzer(this, cloner);
+    }
+
+    #region parameter properties
+    public IScopeTreeLookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
+      get { return (IScopeTreeLookupParameter<ISymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
+    }
+
+    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters[QualityParameterName]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultCollectionParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters[ResultCollectionParameterName]; }
+    }
+
+    public IFixedValueParameter<PercentValue> PercentageOfBestSolutionsParameter {
+      get { return (IFixedValueParameter<PercentValue>)Parameters[PercentageOfBestSolutionsParameterName]; }
+    }
+    #endregion
+
+    public double PercentageOfBestSolutions {
+      get { return PercentageOfBestSolutionsParameter.Value.Value; }
+      set { PercentageOfBestSolutionsParameter.Value.Value = value; }
+    }
+
+    public bool EnabledByDefault { get { return true; } }
+
+    public override IOperation Apply() {
+
+      var results = ResultCollectionParameter.ActualValue;
+
+      DataTable table;
+      if (!results.ContainsKey("Avg. Internal Diversity")) {
+        table = new DataTable("Internal Diversity") { VisualProperties = { YAxisTitle = "Internal Diversity" } };
+        var row = new DataRow("Avg. Internal Diversity") { VisualProperties = { StartIndexZero = true } };
+        table.Rows.Add(row);
+        results.Add(new Result("Avg. Internal Diversity", table));
+      } else {
+        table = (DataTable)results["Avg. Internal Diversity"].Value;
+      }
+
+      var trees = SymbolicExpressionTreeParameter.ActualValue.ToArray();
+      var qualities = QualityParameter.ActualValue.ToArray();
+
+      Array.Sort(qualities, trees, new ReverseComparer());
+      int n = (int)Math.Floor(trees.Length * PercentageOfBestSolutions);
+
+      double avgInternalDiversity = trees.Take(n).Average(tree => CalculateInternalDiversity(tree));
+
+      table.Rows["Avg. Internal Diversity"].Values.Add(avgInternalDiversity);
+      return base.Apply();
+    }
+
+    private double CalculateInternalDiversity(ISymbolicExpressionTree tree) {
+      var branchPoint = tree.IterateNodesPrefix().FirstOrDefault(x => x.SubtreeCount == 2);
+      if (branchPoint == null)
+        return 1;
+
+      var s1 = branchPoint.GetSubtree(0);
+      var s2 = branchPoint.GetSubtree(1);
+
+      // set parents to null because otherwise the bottom-up calculator will throw an exception
+      var p1 = s1.Parent;
+      s1.Parent = null;
+      var p2 = s2.Parent;
+      s2.Parent = null;
+
+      var m = busCalculator.ComputeBottomUpMapping(s1, s2);
+      var diversity = 1 - 2.0 * m.Count / (s1.GetLength() + s2.GetLength());
+
+      // restore parents
+      s1.Parent = p1;
+      s2.Parent = p2;
+
+      return diversity;
+    }
+  }
+
+  internal class ReverseComparer : IComparer<DoubleValue> {
+    public int Compare(DoubleValue x, DoubleValue y) {
+      return y.CompareTo(x);
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Arc.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Arc.cs	(revision 11232)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Arc.cs	(revision 11232)
@@ -0,0 +1,119 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.Problems.DataAnalysis.Symbolic {
+  /// <summary>
+  /// An arc that can have a weight, a label, and a data object for holding additional info
+  /// </summary>
+  [StorableClass]
+  public class Arc : Item, IArc {
+    public event EventHandler Changed;
+    protected virtual void OnChanged(object sender, EventArgs args) {
+      var changed = Changed;
+      if (changed != null)
+        changed(sender, args);
+    }
+
+    [Storable]
+    public IVertex Source { get; private set; }
+
+    [Storable]
+    public IVertex Target { get; private set; }
+
+    [Storable]
+    protected string label;
+    public string Label {
+      get { return label; }
+      set {
+        label = value;
+        OnChanged(this, EventArgs.Empty);
+      }
+    }
+
+    [Storable]
+    protected double weight;
+    public double Weight {
+      get { return weight; }
+      set {
+        weight = value;
+        OnChanged(this, EventArgs.Empty);
+      }
+    }
+
+    [Storable]
+    protected object data;
+    public object Data {
+      get { return data; }
+      set {
+        data = value;
+        OnChanged(this, EventArgs.Empty);
+      }
+    }
+
+    [StorableConstructor]
+    public Arc(bool deserializing) : base(deserializing) { }
+
+    public Arc(IVertex source, IVertex target) {
+      Source = source;
+      Target = target;
+    }
+
+    protected Arc(Arc original, Cloner cloner)
+      : base(original, cloner) {
+      Source = cloner.Clone(original.Source);
+      Target = cloner.Clone(original.Target);
+      label = original.Label;
+      weight = original.Weight;
+      data = original;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Arc(this, cloner);
+    }
+  }
+
+  [StorableClass]
+  public class Arc<T> : Arc, IArc<T> where T : class,IItem {
+    public Arc(bool deserializing)
+      : base(deserializing) {
+    }
+
+    public Arc(IVertex source, IVertex target)
+      : base(source, target) {
+    }
+
+    protected Arc(Arc original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    new public IVertex<T> Source {
+      get { return (IVertex<T>)base.Source; }
+    }
+    new public IVertex<T> Target {
+      get { return (IVertex<T>)base.Target; }
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/DirectedGraph.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/DirectedGraph.cs	(revision 11232)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/DirectedGraph.cs	(revision 11232)
@@ -0,0 +1,177 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [Item("DirectedGraph", "Generic class representing a directed graph with custom vertices and content")]
+  [StorableClass]
+  public class DirectedGraph : Item, IDirectedGraph {
+    protected HashSet<IVertex> vertices;
+    [Storable]
+    public IEnumerable<IVertex> Vertices {
+      get { return vertices; }
+      private set { vertices = new HashSet<IVertex>(value); }
+    }
+
+    protected HashSet<IArc> arcs;
+    [Storable]
+    public IEnumerable<IArc> Arcs {
+      get { return arcs; }
+      private set { arcs = new HashSet<IArc>(value); }
+    }
+
+    [StorableConstructor]
+    protected DirectedGraph(bool serializing)
+      : base(serializing) {
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      foreach (var vertex in vertices) {
+        vertex.ArcAdded += OnArcAdded;
+        vertex.ArcRemoved += OnArcRemoved;
+        vertex.Changed += OnVertexChanged;
+      }
+
+      foreach (var arc in arcs) {
+        var source = arc.Source;
+        var target = arc.Target;
+        source.AddArc(arc);
+        target.AddArc(arc);
+        arc.Changed += OnArcChanged;
+      }
+    }
+
+    public DirectedGraph() {
+      vertices = new HashSet<IVertex>();
+      arcs = new HashSet<IArc>();
+    }
+
+    protected DirectedGraph(DirectedGraph original, Cloner cloner)
+      : base(original, cloner) {
+      vertices = new HashSet<IVertex>(original.vertices.Select(cloner.Clone));
+      arcs = new HashSet<IArc>(original.arcs.Select(cloner.Clone));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DirectedGraph(this, cloner);
+    }
+
+    public virtual void Clear() {
+      vertices.Clear();
+      arcs.Clear();
+    }
+
+    public virtual void AddVertex(IVertex vertex) {
+      vertices.Add(vertex);
+      // register event handlers
+      vertex.Changed += OnVertexChanged;
+      vertex.ArcAdded += OnArcAdded;
+      vertex.ArcRemoved += OnArcRemoved;
+      OnVertexAdded(this, EventArgs.Empty);
+    }
+
+    public virtual void RemoveVertex(IVertex vertex) {
+      vertices.Remove(vertex);
+      // remove connections to/from the removed vertex
+      foreach (var arc in vertex.InArcs.Concat(vertex.OutArcs))
+        RemoveArc(arc);
+      // deregister event handlers
+      vertex.ArcAdded -= OnArcAdded;
+      vertex.ArcRemoved -= OnArcRemoved;
+      vertex.Changed -= OnVertexChanged;
+      OnVertexRemoved(this, EventArgs.Empty);
+    }
+
+    public IArc AddArc(IVertex source, IVertex target) {
+      var arc = new Arc(source, target);
+      AddArc(arc);
+      return arc;
+    }
+
+    public void AddArc(IArc arc) {
+      var source = (Vertex)arc.Source;
+      var target = (Vertex)arc.Target;
+      source.AddArc(arc);
+      target.AddArc(arc);
+      arcs.Add(arc);
+    }
+
+    public void RemoveArc(IArc arc) {
+      arcs.Remove(arc);
+      var source = (Vertex)arc.Source;
+      var target = (Vertex)arc.Target;
+      source.RemoveArc(arc);
+      target.RemoveArc(arc);
+    }
+
+    public event EventHandler VertexAdded;
+    protected virtual void OnVertexAdded(object sender, EventArgs args) {
+      var added = VertexAdded;
+      if (added != null)
+        added(sender, args);
+    }
+
+    public event EventHandler VertexChanged;
+    protected virtual void OnVertexChanged(object sender, EventArgs args) {
+      var changed = VertexChanged;
+      if (changed != null)
+        changed(sender, args);
+    }
+
+    public event EventHandler VertexRemoved;
+    protected virtual void OnVertexRemoved(object sender, EventArgs args) {
+      var removed = VertexRemoved;
+      if (removed != null)
+        removed(sender, args);
+    }
+
+    protected virtual void OnArcAdded(object sender, EventArgs<IArc> args) {
+      var arc = args.Value;
+      // the ArcAdded event is fired by a vertex when an arc from or towards another vertex is added to his list of connections
+      // because the arc is added in both directions by both the source and the target, this event will get fired twice 
+      // here, we only want to add the arc once, so if its already contained, we return without complaining
+      if (arcs.Contains(arc)) return;
+      arcs.Add(arc);
+      arc.Changed += OnArcChanged;
+    }
+
+    protected virtual void OnArcRemoved(object sender, EventArgs<IArc> args) {
+      var arc = args.Value;
+      if (!arcs.Contains(arc)) return; // the same rationale as above 
+      arcs.Remove(arc);
+      arc.Changed -= OnArcChanged;
+    }
+
+    protected virtual void OnArcChanged(object sender, EventArgs args) { }
+
+    public override Image ItemImage {
+      get { return Common.Resources.VSImageLibrary.Graph; }
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Interfaces/IArc.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Interfaces/IArc.cs	(revision 11232)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Interfaces/IArc.cs	(revision 11232)
@@ -0,0 +1,39 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.Problems.DataAnalysis.Symbolic {
+  public interface IArc : IItem {
+    event EventHandler Changed; // generic event for when the label, weight or data were changed
+    IVertex Source { get; }
+    IVertex Target { get; }
+    string Label { get; set; }
+    double Weight { get; set; }
+    object Data { get; set; }
+  }
+
+  public interface IArc<T> : IArc where T : class,IItem {
+    new IVertex<T> Source { get; }
+    new IVertex<T> Target { get; }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Interfaces/IDirectedGraph.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Interfaces/IDirectedGraph.cs	(revision 11232)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Interfaces/IDirectedGraph.cs	(revision 11232)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Problems.DataAnalysis.Symbolic {
+  public interface IDirectedGraph : IItem {
+    void Clear();
+    void AddVertex(IVertex vertex);
+    IArc AddArc(IVertex source, IVertex target);
+    void AddArc(IArc arc);
+    void RemoveVertex(IVertex vertex);
+    void RemoveArc(IArc arc);
+    IEnumerable<IVertex> Vertices { get; }
+    IEnumerable<IArc> Arcs { get; }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Interfaces/IVertex.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Interfaces/IVertex.cs	(revision 11232)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Interfaces/IVertex.cs	(revision 11232)
@@ -0,0 +1,54 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public interface IVertex : IItem {
+    event EventHandler Changed; // generic event for when the content, label or weight have changed
+    event EventHandler<EventArgs<IArc>> ArcAdded;
+    event EventHandler<EventArgs<IArc>> ArcRemoved;
+
+    IEnumerable<IArc> InArcs { get; }
+    IEnumerable<IArc> OutArcs { get; }
+
+    int InDegree { get; }
+    int OutDegree { get; }
+    int Degree { get; }
+
+    string Label { get; set; }
+    double Weight { get; set; }
+
+    object Content { get; set; }
+
+    void AddArc(IArc arc);
+    void RemoveArc(IArc arc);
+    void RemoveArc(IVertex vertex);
+  }
+
+  public interface IVertex<T> : IVertex
+  where T : class {
+    new T Content { get; set; }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Vertex.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Vertex.cs	(revision 11232)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/DirectedGraph/Vertex.cs	(revision 11232)
@@ -0,0 +1,188 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  public class Vertex : Item, IVertex {
+    // use the same event to signal a change in the content, weight or label
+    public event EventHandler Changed;
+    protected virtual void OnChanged(object sender, EventArgs args) {
+      var changed = Changed;
+      if (changed != null)
+        changed(sender, args);
+    }
+
+    public event EventHandler<EventArgs<IArc>> ArcAdded;
+    protected virtual void OnArcAdded(object sender, EventArgs<IArc> args) {
+      var added = ArcAdded;
+      if (added != null)
+        added(sender, args);
+    }
+
+    public event EventHandler<EventArgs<IArc>> ArcRemoved;
+    protected virtual void OnArcRemoved(object sender, EventArgs<IArc> args) {
+      var removed = ArcRemoved;
+      if (removed != null)
+        removed(sender, args);
+    }
+
+    [Storable]
+    protected string label;
+    public string Label {
+      get { return label; }
+      set {
+        label = value;
+        OnChanged(this, EventArgs.Empty);
+      }
+    }
+
+    [Storable]
+    protected double weight;
+    public double Weight {
+      get { return weight; }
+      set {
+        weight = value;
+        OnChanged(this, EventArgs.Empty);
+      }
+    }
+
+    [Storable]
+    protected object content;
+    public object Content {
+      get { return content; }
+      set {
+        content = value;
+        OnChanged(this, EventArgs.Empty);
+      }
+    }
+
+    private List<IArc> inArcs;
+    public IEnumerable<IArc> InArcs {
+      get { return inArcs ?? Enumerable.Empty<IArc>(); }
+    }
+
+    private List<IArc> outArcs;
+    public IEnumerable<IArc> OutArcs {
+      get { return outArcs ?? Enumerable.Empty<IArc>(); }
+    }
+
+    [StorableConstructor]
+    public Vertex(bool deserializing) : base(deserializing) { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+
+    private Vertex() { }
+
+    public Vertex(object content)
+      : this() {
+      this.content = content;
+    }
+
+    protected Vertex(Vertex original, Cloner cloner)
+      : base(original, cloner) {
+      content = original.content;
+      label = original.Label;
+      weight = original.Weight;
+
+      inArcs = original.InArcs.Select(cloner.Clone).ToList();
+      outArcs = original.OutArcs.Select(cloner.Clone).ToList();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Vertex(this, cloner);
+    }
+
+    public void AddArc(IArc arc) {
+      if (this != arc.Source && this != arc.Target)
+        throw new InvalidOperationException("The current vertex must be either the arc source or the arc target.");
+
+      if (this == arc.Source) {
+        if (outArcs == null)
+          outArcs = new List<IArc>();
+        else if (outArcs.Contains(arc) || outArcs.Any(a => a.Target == arc.Target && a.Source == arc.Source))
+          throw new InvalidOperationException("Arc already added.");
+        outArcs.Add(arc);
+      } else if (this == arc.Target) {
+        if (inArcs == null)
+          inArcs = new List<IArc>();
+        else if (inArcs.Contains(arc) || inArcs.Any(a => a.Target == arc.Target && a.Source == arc.Source))
+          throw new InvalidOperationException("Arc already added.");
+        inArcs.Add(arc);
+      }
+      OnArcAdded(this, new EventArgs<IArc>(arc));
+    }
+
+    public void RemoveArc(IVertex vertex) {
+      try {
+        var arc = inArcs.Concat(outArcs).SingleOrDefault(x => x.Target == vertex || x.Source == vertex);
+        RemoveArc(arc);
+      }
+      catch (Exception) {
+        throw new InvalidOperationException("Only one arc allowed between two vertices");
+      }
+    }
+
+    public void RemoveArc(IArc arc) {
+      if (this != arc.Source && this != arc.Target)
+        throw new InvalidOperationException("The current vertex must be either the arc source or the arc target.");
+
+      if (this == arc.Source && outArcs != null) {
+        if (!outArcs.Remove(arc))
+          throw new InvalidOperationException("Arc is not present in this vertex' outgoing arcs.");
+      } else if (this == arc.Target && inArcs != null) {
+        if (!inArcs.Remove(arc))
+          throw new InvalidOperationException("Arc is not present in this vertex' incoming arcs.");
+      }
+      OnArcRemoved(this, new EventArgs<IArc>(arc));
+    }
+
+    public int InDegree { get { return InArcs.Count(); } }
+    public int OutDegree { get { return OutArcs.Count(); } }
+    public int Degree { get { return InDegree + OutDegree; } }
+  }
+
+  [StorableClass]
+  public class Vertex<T> : Vertex, IVertex<T> where T : class,IItem {
+    public new T Content {
+      get { return (T)base.Content; }
+      set { base.Content = value; }
+    }
+
+    [StorableConstructor]
+    protected Vertex(bool deserializing) : base(deserializing) { }
+
+    protected Vertex(Vertex<T> original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Vertex<T>(this, cloner);
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 11231)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 11232)
@@ -173,4 +173,5 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Analyzers\SymbolicDataAnalysisInternalDiversityAnalyzer.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisGenealogyAnalyzer.cs" />
@@ -189,6 +190,13 @@
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="DirectedGraph\Arc.cs" />
+    <Compile Include="DirectedGraph\DirectedGraph.cs" />
+    <Compile Include="DirectedGraph\Interfaces\IArc.cs" />
+    <Compile Include="DirectedGraph\Interfaces\IDirectedGraph.cs" />
+    <Compile Include="DirectedGraph\Interfaces\IVertex.cs" />
+    <Compile Include="DirectedGraph\Vertex.cs" />
     <Compile Include="Interfaces\IModelBacktransformator.cs" />
-    <Compile Include="Interfaces\IDistanceCalculator.cs" />    <Compile Include="Matching\SymbolicExpressionTreeCanonicalSorter.cs" />
+    <Compile Include="Interfaces\IDistanceCalculator.cs" />
+    <Compile Include="Matching\SymbolicExpressionTreeCanonicalSorter.cs" />
     <Compile Include="Matching\SymbolicExpressionTreeEqualityComparer.cs" />
     <Compile Include="Matching\SymbolicExpressionTreeMatching.cs" />
@@ -196,6 +204,8 @@
     <Compile Include="Matching\SymbolicExpressionTreeNodeComparer.cs" />
     <Compile Include="Matching\SymbolicExpressionTreeNodeSimilarityComparer.cs" />
-
-    <Compile Include="SymbolicExpressionTreeBacktransformator.cs" />    <Compile Include="SlidingWindow\GenerationalSlidingWindowAnalyzer.cs" />
+    <Compile Include="SimilarityCalculators\BottomUpSimilarityCalculator.cs" />
+    <Compile Include="SimilarityCalculators\MaxCommonSubtreeSimilarityCalculator.cs" />
+    <Compile Include="SymbolicExpressionTreeBacktransformator.cs" />
+    <Compile Include="SlidingWindow\GenerationalSlidingWindowAnalyzer.cs" />
     <Compile Include="SlidingWindow\OffspringSelectionSlidingWindowAnalyzer.cs" />
     <Compile Include="SlidingWindow\SlidingWindowAnalyzer.cs" />
@@ -204,5 +214,6 @@
     <Compile Include="SlidingWindow\SlidingWindowVisualizer.cs" />
     <Compile Include="SymbolGraph\FPGraph.cs" />
-    <Compile Include="SymbolGraph\SymbolGraph.cs" />    <Compile Include="SymbolicDataAnalysisExpressionPruningOperator.cs" />
+    <Compile Include="SymbolGraph\SymbolGraph.cs" />
+    <Compile Include="SymbolicDataAnalysisExpressionPruningOperator.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionTreeSimilarityCalculator.cs" />
     <Compile Include="SymbolicDataAnalysisSolutionPruningOptimizer.cs" />
@@ -302,6 +313,6 @@
     <Compile Include="Symbols\VariableConditionTreeNode.cs" />
     <Compile Include="Symbols\VariableTreeNode.cs" />
-
-    <Compile Include="TransformationToSymbolicTreeMapper.cs" />    <Compile Include="Tracking\FragmentGraph\FragmentGraph.cs" />
+    <Compile Include="TransformationToSymbolicTreeMapper.cs" />
+    <Compile Include="Tracking\FragmentGraph\FragmentGraph.cs" />
     <Compile Include="Tracking\SymbolicDataAnalysisExpressionAfterCrossoverOperator.cs" />
     <Compile Include="Tracking\SymbolicDataAnalysisExpressionBeforeCrossoverOperator.cs" />
@@ -309,6 +320,5 @@
     <Compile Include="Tracking\SymbolicDataAnalysisExpressionBeforeManipulatorOperator.cs" />
     <Compile Include="Tracking\SymbolicDataAnalysisExpressionTracing.cs" />
-    <Compile Include="TreeDistance\BottomUpDistanceCalculator.cs" />
-    <Compile Include="TreeDistance\IsomorphicTreeDistance.cs" />    <None Include="HeuristicLab.snk" />
+    <None Include="HeuristicLab.snk" />
     <None Include="Plugin.cs.frame" />
     <None Include="Properties\AssemblyInfo.cs.frame" />
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 11231)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 11232)
@@ -352,5 +352,5 @@
     }
 
-    private static void PrepareInstructions(LinearInstruction[] code, Dataset dataset) {
+    public static void PrepareInstructions(LinearInstruction[] code, Dataset dataset) {
       for (int i = 0; i != code.Length; ++i) {
         var instr = code[i];
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMaxCommonSequenceCalculator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMaxCommonSequenceCalculator.cs	(revision 11231)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMaxCommonSequenceCalculator.cs	(revision 11232)
@@ -23,5 +23,5 @@
 using System.Collections.Generic;
 
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Matching {
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   public class MaxCommonSequenceCalculator<T, TComp>
     where T : class
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/BottomUpSimilarityCalculator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/BottomUpSimilarityCalculator.cs	(revision 11232)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/BottomUpSimilarityCalculator.cs	(revision 11232)
@@ -0,0 +1,210 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("BottomUpSimilarityCalculator", "A similarity calculator which uses the tree bottom-up distance as a similarity metric.")]
+  public class BottomUpSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    private readonly HashSet<string> commutativeSymbols = new HashSet<string> { "Addition", "Multiplication", "Average", "And", "Or", "Xor" };
+
+    public BottomUpSimilarityCalculator() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BottomUpSimilarityCalculator(this, cloner);
+    }
+
+    protected BottomUpSimilarityCalculator(BottomUpSimilarityCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution) {
+      var t1 = leftSolution.Variables[SolutionVariableName].Value as ISymbolicExpressionTree;
+      var t2 = rightSolution.Variables[SolutionVariableName].Value as ISymbolicExpressionTree;
+
+      if (t1 == null || t2 == null)
+        throw new ArgumentException("Cannot calculate similarity when one of the arguments is null.");
+
+      var similarity = CalculateSolutionSimilarity(t1, t2);
+      if (similarity > 1.0)
+        throw new Exception("Similarity value cannot be greater than 1");
+
+      return similarity;
+    }
+
+    public double CalculateSolutionSimilarity(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2) {
+      if (t1 == t2)
+        return 1;
+
+      var map = ComputeBottomUpMapping(t1.Root, t2.Root);
+      return 2.0 * map.Count / (t1.Length + t2.Length);
+    }
+
+    public Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> ComputeBottomUpMapping(ISymbolicExpressionTreeNode n1, ISymbolicExpressionTreeNode n2) {
+      var compactedGraph = Compact(n1, n2);
+
+      var forwardMap = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t1 => nodes of t2
+      var reverseMap = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t2 => nodes of t1
+
+      // visit nodes in order of decreasing height to ensure correct mapping
+      foreach (var v in n1.IterateNodesPrefix().OrderByDescending(x => compactedGraph[x].Depth)) {
+        if (forwardMap.ContainsKey(v))
+          continue;
+        var kv = compactedGraph[v];
+        ISymbolicExpressionTreeNode w = null;
+        foreach (var t in n2.IterateNodesPrefix()) {
+          if (reverseMap.ContainsKey(t) || compactedGraph[t] != kv)
+            continue;
+          w = t;
+          break;
+        }
+        if (w == null) continue;
+
+        // at this point we know that v and w are isomorphic, however, the mapping cannot be done directly (as in the paper) because the trees are unordered (subtree order might differ)
+        // the solution is to sort subtrees by label using IterateBreadthOrdered (this will work because the subtrees are isomorphic!) and simultaneously iterate over the two subtrees
+        var eV = IterateBreadthOrdered(v).GetEnumerator();
+        var eW = IterateBreadthOrdered(w).GetEnumerator();
+
+        while (eV.MoveNext() && eW.MoveNext()) {
+          var s = eV.Current;
+          var t = eW.Current;
+
+          if (reverseMap.ContainsKey(t)) {
+            throw new Exception("A mapping to this node already exists.");
+          }
+
+          forwardMap[s] = t;
+          reverseMap[t] = s;
+        }
+      }
+
+      return forwardMap;
+    }
+
+    /// <summary>
+    /// Creates a compact representation of the two trees as a directed acyclic graph
+    /// </summary>
+    /// <param name="n1">The root of the first tree</param>
+    /// <param name="n2">The root of the second tree</param>
+    /// <returns>The compacted DAG representing the two trees</returns>
+    private Dictionary<ISymbolicExpressionTreeNode, GraphNode> Compact(ISymbolicExpressionTreeNode n1, ISymbolicExpressionTreeNode n2) {
+      var nodeMap = new Dictionary<ISymbolicExpressionTreeNode, GraphNode>(); // K
+      var labelMap = new Dictionary<string, GraphNode>(); // L
+      var childrenCount = new Dictionary<ISymbolicExpressionTreeNode, int>(); // Children
+
+      var nodes = n1.IterateNodesPostfix().Concat(n2.IterateNodesPostfix()); // the disjoint union F
+      var list = new List<GraphNode>();
+      var queue = new Queue<ISymbolicExpressionTreeNode>();
+
+      foreach (var n in nodes) {
+        if (n.SubtreeCount == 0) {
+          var label = n.ToString();
+          if (!labelMap.ContainsKey(label)) {
+            var z = new GraphNode { SymbolicExpressionTreeNode = n, Label = label };
+            labelMap[z.Label] = z;
+            list.Add(z);
+          }
+          nodeMap[n] = labelMap[label];
+          queue.Enqueue(n);
+        } else {
+          childrenCount[n] = n.SubtreeCount;
+        }
+      }
+      while (queue.Any()) {
+        var n = queue.Dequeue();
+
+        if (n.SubtreeCount > 0) {
+          var label = n.Symbol.Name;
+          bool found = false;
+          var depth = n.GetDepth();
+
+          bool sort = commutativeSymbols.Contains(label);
+          var nNodes = n.Subtrees.Select(x => nodeMap[x]).ToList();
+          if (sort) nNodes.Sort((a, b) => String.Compare(a.Label, b.Label, StringComparison.Ordinal));
+
+          for (int i = list.Count - 1; i >= 0; --i) {
+            var w = list[i];
+
+            if (!(n.SubtreeCount == w.ChildrenCount && label == w.Label && depth == w.Depth))
+              continue;
+
+            // sort V and W when the symbol is commutative because we are dealing with unordered trees
+            var m = w.SymbolicExpressionTreeNode;
+            var mNodes = m.Subtrees.Select(x => nodeMap[x]).ToList();
+            if (sort) mNodes.Sort((a, b) => String.Compare(a.Label, b.Label, StringComparison.Ordinal));
+
+            if (nNodes.SequenceEqual(mNodes)) {
+              nodeMap[n] = w;
+              found = true;
+              break;
+            }
+          }
+
+          if (!found) {
+            var w = new GraphNode { SymbolicExpressionTreeNode = n, Label = label, Depth = depth, ChildrenCount = n.SubtreeCount };
+            list.Add(w);
+            nodeMap[n] = w;
+          }
+        }
+
+        var p = n.Parent;
+        if (p == null)
+          continue;
+
+        childrenCount[p]--;
+
+        if (childrenCount[p] == 0)
+          queue.Enqueue(p);
+      }
+
+      return nodeMap;
+    }
+
+    private IEnumerable<ISymbolicExpressionTreeNode> IterateBreadthOrdered(ISymbolicExpressionTreeNode node) {
+      var list = new List<ISymbolicExpressionTreeNode> { node };
+      int i = 0;
+      while (i < list.Count) {
+        var n = list[i];
+        if (n.SubtreeCount > 0) {
+          var subtrees = commutativeSymbols.Contains(node.Symbol.Name) ? n.Subtrees.OrderBy(x => x.ToString(), StringComparer.Ordinal) : n.Subtrees;
+          list.AddRange(subtrees);
+        }
+        i++;
+      }
+      return list;
+    }
+
+    private class GraphNode {
+      public ISymbolicExpressionTreeNode SymbolicExpressionTreeNode;
+      public string Label;
+      public int Depth;
+      public int ChildrenCount;
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/MaxCommonSubtreeSimilarityCalculator.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/MaxCommonSubtreeSimilarityCalculator.cs	(revision 11232)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/MaxCommonSubtreeSimilarityCalculator.cs	(revision 11232)
@@ -0,0 +1,76 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("MaxCommonSubtreeSimilarityCalculator", "A similarity calculator based on the size of the maximum common subtree between two trees")]
+  public class MaxCommonSubtreeSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    public MaxCommonSubtreeSimilarityCalculator() { }
+
+    protected MaxCommonSubtreeSimilarityCalculator(MaxCommonSubtreeSimilarityCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MaxCommonSubtreeSimilarityCalculator(this, cloner);
+    }
+
+    public override double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution) {
+      var t1 = leftSolution.Variables[SolutionVariableName].Value as ISymbolicExpressionTree;
+      var t2 = rightSolution.Variables[SolutionVariableName].Value as ISymbolicExpressionTree;
+
+      if (t1 == null || t2 == null)
+        throw new ArgumentException("Cannot calculate similarity when one of the arguments is null.");
+      var comparer = new SymbolicExpressionTreeNodeSimilarityComparer {
+        MatchConstantValues = true,
+        MatchVariableNames = true,
+        MatchVariableWeights = true
+      };
+
+      return MaxCommonSubtreeSimilarity(t1, t2, comparer);
+    }
+
+    public static double MaxCommonSubtreeSimilarity(ISymbolicExpressionTree a, ISymbolicExpressionTree b, SymbolicExpressionTreeNodeSimilarityComparer comparer) {
+      int max = 0;
+      var rootA = a.Root.GetSubtree(0).GetSubtree(0);
+      var rootB = b.Root.GetSubtree(0).GetSubtree(0);
+      foreach (var aa in rootA.IterateNodesBreadth()) {
+        int lenA = aa.GetLength();
+        if (lenA <= max) continue;
+        foreach (var bb in rootB.IterateNodesBreadth()) {
+          int lenB = bb.GetLength();
+          if (lenB <= max) continue;
+          int matches = SymbolicExpressionTreeMatching.Match(aa, bb, comparer);
+          if (matches == lenB && max < matches)
+            max = matches;
+        }
+      }
+      return 2.0 * max / (rootA.GetLength() + rootB.GetLength());
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 11231)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 11232)
@@ -23,4 +23,5 @@
 using System.Drawing;
 using System.Linq;
+using HeuristicLab.Analysis;
 using HeuristicLab.Common;
 using HeuristicLab.Common.Resources;
@@ -29,10 +30,9 @@
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.PluginInfrastructure;
-using HeuristicLab.Problems.DataAnalysis.Symbolic.Analyzers;
 using HeuristicLab.Problems.Instances;
-
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
@@ -233,5 +233,6 @@
       Operators.Add(new MinAverageMaxSymbolicExpressionTreeLengthAnalyzer());
       Operators.Add(new SymbolicExpressionTreeLengthAnalyzer());
-      Operators.Add(new SymbolicDataAnalysisGenealogyAnalyzer());
+      Operators.Add(new SingleObjectivePopulationDiversityAnalyzer());
+      Operators.Add(new BottomUpSimilarityCalculator());
       ParameterizeOperators();
     }
@@ -353,28 +354,10 @@
         op.EvaluatorParameter.ActualName = EvaluatorParameter.Name;
       }
-      // add tracking analyzer
-      foreach (var op in operators.OfType<SymbolicDataAnalysisGenealogyAnalyzer>()) {
-        op.BeforeCrossoverOperatorParameter.ActualValue = new SymbolicDataAnalysisExpressionBeforeCrossoverOperator();
-        op.AfterCrossoverOperatorParameter.ActualValue = new SymbolicDataAnalysisExpressionAfterCrossoverOperator();
-        op.BeforeManipulatorOperatorParameter.ActualValue = new SymbolicDataAnalysisExpressionBeforeManipulatorOperator();
-        op.AfterManipulatorOperatorParameter.ActualValue = new SymbolicDataAnalysisExpressionAfterManipulatorOperator();
-        // get crossover parameter names
-        var crossover = operators.OfType<ISymbolicExpressionTreeCrossover>().FirstOrDefault();
-        if (crossover != null) {
-          op.BeforeCrossoverOperator.ParentsParameter.ActualName = crossover.ParentsParameter.Name;
-          op.AfterCrossoverOperator.ParentsParameter.ActualName = crossover.ParentsParameter.Name;
-          op.BeforeCrossoverOperator.ChildParameter.ActualName = crossover.ChildParameter.Name;
-          op.AfterCrossoverOperator.ChildParameter.ActualName = crossover.ChildParameter.Name;
-        }
-        // get manipulator parameter names
-        var manipulator = operators.OfType<ISymbolicExpressionTreeManipulator>().FirstOrDefault();
-        if (manipulator != null) {
-          op.BeforeManipulatorOperator.ChildParameter.ActualName = manipulator.SymbolicExpressionTreeParameter.Name;
-          op.AfterManipulatorOperator.ChildParameter.ActualName = manipulator.SymbolicExpressionTreeParameter.Name;
-        }
-        var creator = operators.OfType<ISymbolicExpressionTreeCreator>().FirstOrDefault();
-        if (creator != null) {
-          op.PopulationParameter.ActualName = creator.SymbolicExpressionTreeParameter.ActualName;
-        }
+      foreach (var op in operators.OfType<SingleObjectiveSolutionSimilarityCalculator>()) {
+        op.QualityVariableName = "Quality";
+        op.SolutionVariableName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+      }
+      foreach (var op in operators.OfType<SingleObjectivePopulationDiversityAnalyzer>()) {
+        op.SimilarityCalculator = operators.OfType<BottomUpSimilarityCalculator>().SingleOrDefault();
       }
     }
