Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/BuildingBlockAnalyzers/SymbolicDataAnalysisPoly10Analyzer.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/BuildingBlockAnalyzers/SymbolicDataAnalysisPoly10Analyzer.cs	(revision 11458)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/BuildingBlockAnalyzers/SymbolicDataAnalysisPoly10Analyzer.cs	(revision 11458)
@@ -0,0 +1,246 @@
+﻿#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.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using DataRow = HeuristicLab.Analysis.DataRow;
+using DataTable = HeuristicLab.Analysis.DataTable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Analyzers.BuidingBlocks {
+  [Item("Poly-10 building blocks analyzer", "An analyzer which attempts to identify parts of the Poly-10 formula")]
+  [StorableClass]
+  public class SymbolicDataAnalysisPoly10Analyzer : SingleSuccessorOperator, ISymbolicDataAnalysisAnalyzer {
+    private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
+    private const string ResultCollectionParameterName = "Results";
+    private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
+    private const string ProblemDataParameterName = "ProblemData";
+    private const string GenerationsParameterName = "Generations";
+    private const string PhenotypicSimilarityThresholdParameterName = "PhenotypicSimilarityThreshold";
+    private const string UpdateCounterParameterName = "UpdateCounter";
+    private const string UpdateIntervalParameterName = "UpdateInterval";
+    private const string buildingBlocksFrequenciesTableName = "Building blocks frequencies";
+
+
+    // store evaluations of building blocks for phenotypic matching
+    private readonly Dictionary<string, List<double>> evaluationMap = new Dictionary<string, List<double>>();
+    private readonly Dictionary<string, ISymbolicExpressionTreeNode> fragmentMap = new Dictionary<string, ISymbolicExpressionTreeNode>();
+    private readonly Dictionary<string, string> prettyLabels = new Dictionary<string, string>();
+    private readonly SymbolicExpressionImporter importer = new SymbolicExpressionImporter();
+
+    #region Parameters
+    public IValueParameter<DoubleValue> PhenotypicSimilarityThresholdParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters[PhenotypicSimilarityThresholdParameterName]; }
+    }
+
+    public IScopeTreeLookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
+      get { return (IScopeTreeLookupParameter<ISymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultCollectionParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters[ResultCollectionParameterName]; }
+    }
+
+    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter {
+      get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[SymbolicDataAnalysisTreeInterpreterParameterName]; }
+    }
+
+    public ILookupParameter<IDataAnalysisProblemData> ProblemDataParameter {
+      get { return (ILookupParameter<IDataAnalysisProblemData>)Parameters[ProblemDataParameterName]; }
+    }
+
+    public ILookupParameter<IntValue> GenerationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[GenerationsParameterName]; }
+    }
+
+    public ValueParameter<IntValue> UpdateCounterParameter {
+      get { return (ValueParameter<IntValue>)Parameters[UpdateCounterParameterName]; }
+    }
+
+    public ValueParameter<IntValue> UpdateIntervalParameter {
+      get { return (ValueParameter<IntValue>)Parameters[UpdateIntervalParameterName]; }
+    }
+    #endregion
+
+    #region Parameter properties
+    public double PhenotypicSimilarityThreshold {
+      get { return PhenotypicSimilarityThresholdParameter.Value.Value; }
+      set { PhenotypicSimilarityThresholdParameter.Value.Value = value; }
+    }
+
+    public int UpdateCounter {
+      get { return UpdateCounterParameter.Value.Value; }
+      set { UpdateCounterParameter.Value.Value = value; }
+    }
+
+    public int UpdateInterval {
+      get { return UpdateIntervalParameter.Value.Value; }
+      set { UpdateIntervalParameter.Value.Value = value; }
+    }
+    #endregion
+
+    public SymbolicDataAnalysisPoly10Analyzer() {
+      #region Add parameters
+      Parameters.Add(new ScopeTreeLookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName));
+      Parameters.Add(new LookupParameter<ResultCollection>(ResultCollectionParameterName));
+      Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName));
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName));
+      Parameters.Add(new LookupParameter<IntValue>(GenerationsParameterName));
+      Parameters.Add(new ValueParameter<DoubleValue>(PhenotypicSimilarityThresholdParameterName, "The phenotypic similarity threshold", new DoubleValue(0.9)));
+      Parameters.Add(new ValueParameter<IntValue>(UpdateCounterParameterName, new IntValue(0)));
+      Parameters.Add(new ValueParameter<IntValue>(UpdateIntervalParameterName, new IntValue(1)));
+      #endregion
+    }
+
+    [StorableConstructor]
+    protected SymbolicDataAnalysisPoly10Analyzer(bool deserializing)
+      : base(deserializing) {
+    }
+
+    protected SymbolicDataAnalysisPoly10Analyzer(SymbolicDataAnalysisPoly10Analyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisPoly10Analyzer(this, cloner);
+    }
+
+    public bool EnabledByDefault {
+      get { return false; }
+    }
+
+    public override IOperation Apply() {
+      #region Update counter & update interval
+      UpdateCounter++;
+      if (UpdateCounter != UpdateInterval) {
+        return base.Apply();
+      }
+      UpdateCounter = 0;
+      #endregion
+
+      int generations = GenerationsParameter.ActualValue.Value;
+      if (generations == 0)
+        InitializeBuildingBlockCollection();
+
+      var results = ResultCollectionParameter.ActualValue;
+      var trees = SymbolicExpressionTreeParameter.ActualValue;
+      var interpreter = (SymbolicDataAnalysisExpressionTreeLinearInterpreter)SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
+      var dataset = ProblemDataParameter.ActualValue.Dataset;
+      var rows = ProblemDataParameter.ActualValue.TrainingIndices.ToList();
+      OnlineCalculatorError error;
+      var formatter = new SymbolicExpressionTreeStringFormatter();
+      Dictionary<string, int> bbFrequencies = evaluationMap.Keys.ToDictionary(x => x, x => 0);
+
+      foreach (var key in evaluationMap.Keys) {
+        var bb = fragmentMap[key];
+        int len = bb.GetLength();
+        foreach (var t in trees) {
+          var root = t.Root.GetSubtree(0).GetSubtree(0);
+          var nodes = root.IterateNodesPrefix().Where(x => x.GetLength() > len).ToList();
+
+          for (int i = 0; i < nodes.Count; ++i) {
+            var s = nodes[i];
+            var values = interpreter.GetValues(s, dataset, rows);
+            var r2 = OnlinePearsonsRSquaredCalculator.Calculate(values, evaluationMap[key], out error);
+            if (error == OnlineCalculatorError.None && r2 >= PhenotypicSimilarityThreshold) {
+              bbFrequencies[key]++;
+              i += s.GetLength();
+            }
+          }
+        }
+      }
+      var table = (DataTable)results[buildingBlocksFrequenciesTableName].Value;
+      foreach (var pair in bbFrequencies) {
+        var label = prettyLabels[pair.Key];
+        table.Rows[label].Values.Add(pair.Value);
+      }
+
+      return base.Apply();
+    }
+
+    private void InitializeBuildingBlockCollection() {
+      #region Add building blocks
+      // building blocks
+      const string x1 = "(variable 1 X1)";
+      const string x2 = "(variable 1 X2)";
+      const string x3 = "(variable 1 X3)";
+      const string x4 = "(variable 1 X4)";
+      const string x5 = "(variable 1 X5)";
+      const string x6 = "(variable 1 X6)";
+      const string x7 = "(variable 1 X7)";
+      const string x8 = "(variable 1 X8)";
+      const string x9 = "(variable 1 X9)";
+      const string x10 = "(variable 1 X10)";
+      string s1 = String.Format("(* {0} {1})", x1, x2);
+      string s2 = String.Format("(* {0} {1})", x3, x4);
+      string s3 = String.Format("(* {0} {1})", x5, x6);
+      string s4 = String.Format("(* (* {0} {1}) {2})", x1, x7, x9);
+      string s5 = String.Format("(* (* {0} {1}) {2})", x3, x6, x10);
+      string s6 = String.Format("(+ {0} {1})", s1, s2); // x1x2 + x3x4
+      string s7 = String.Format("(+ {0} {1})", s1, s3); // x1x2 + x5x6
+      string s8 = String.Format("(+ {0} {1})", s2, s3); // x3x4 + x5x6
+      string s9 = String.Format("(+ (+ {0} {1}) {2})", s1, s2, s3); // x1x2 + x3x4 + x5x6
+      string s10 = String.Format("(+ (+ {0} {1}) {2})", s4, s5, s9); // x1x2 + x3x4 + x5x6 + x1x7x9 + x3x6x10
+      prettyLabels[s1] = "X1*X2";
+      prettyLabels[s2] = "X3*X4";
+      prettyLabels[s3] = "X5*X6";
+      prettyLabels[s4] = "X1*X7*X9";
+      prettyLabels[s5] = "X3*X6*X10";
+      prettyLabels[s6] = prettyLabels[s1] + " + " + prettyLabels[s2];
+      prettyLabels[s7] = prettyLabels[s1] + " + " + prettyLabels[s3];
+      prettyLabels[s8] = prettyLabels[s2] + " + " + prettyLabels[s3];
+      prettyLabels[s9] = prettyLabels[s1] + " + " + prettyLabels[s2] + " + " + prettyLabels[s3];
+      prettyLabels[s10] = prettyLabels[s9] + " + " + prettyLabels[s4] + " + " + prettyLabels[s5];
+      #endregion
+      var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
+      var dataset = ProblemDataParameter.ActualValue.Dataset;
+      var rows = ProblemDataParameter.ActualValue.TrainingIndices.ToList();
+
+      foreach (var s in new[] { s4, s5, s6, s7, s8, s9, s10 }) {
+        if (evaluationMap.ContainsKey(s)) continue;
+        var t = importer.Import(s);
+        evaluationMap.Add(s, interpreter.GetSymbolicExpressionTreeValues(t, dataset, rows).ToList());
+        fragmentMap.Add(s, t.Root.GetSubtree(0).GetSubtree(0));
+      }
+
+      var results = ResultCollectionParameter.ActualValue;
+      DataTable table;
+      if (!results.ContainsKey(buildingBlocksFrequenciesTableName)) {
+        table = new DataTable(buildingBlocksFrequenciesTableName);
+        results.Add(new Result(buildingBlocksFrequenciesTableName, table));
+      } else {
+        table = (DataTable)results[buildingBlocksFrequenciesTableName].Value;
+      }
+      table.Rows.Clear();
+      foreach (var key in evaluationMap.Keys) {
+        table.Rows.Add(new DataRow(prettyLabels[key]));
+      }
+    }
+  }
+}
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs	(revision 11458)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs	(revision 11458)
@@ -0,0 +1,105 @@
+﻿#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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Crossovers {
+  [Item("SymbolicDataAnalysisExpressionDiversityPreservingCrossover", "A crossover operator which tries to preserve diversity by favoring duplicate nodes as crossover points in the tree")]
+  [StorableClass]
+  public sealed class SymbolicDataAnalysisExpressionDiversityPreservingCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
+    private const string SimilarityCalculatorParameterName = "SimilarityCalculator";
+    private const string InternalCrossoverPointProbabilityParameterName = "InternalCrossoverPointProbability";
+
+    #region Parameter Properties
+    public IValueLookupParameter<PercentValue> InternalCrossoverPointProbabilityParameter {
+      get { return (IValueLookupParameter<PercentValue>)Parameters[InternalCrossoverPointProbabilityParameterName]; }
+    }
+    public IValueParameter<ISymbolicDataAnalysisExpressionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IValueParameter<ISymbolicDataAnalysisExpressionSimilarityCalculator>)Parameters[SimilarityCalculatorParameterName]; }
+    }
+    #endregion
+
+    public ISymbolicDataAnalysisExpressionSimilarityCalculator SimilarityCalculator {
+      get { return SimilarityCalculatorParameter.Value; }
+    }
+
+    private SymbolicDataAnalysisExpressionDiversityPreservingCrossover(SymbolicDataAnalysisExpressionDiversityPreservingCrossover<T> original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public SymbolicDataAnalysisExpressionDiversityPreservingCrossover() {
+      Parameters.Add(new ValueLookupParameter<PercentValue>(InternalCrossoverPointProbabilityParameterName, "The probability to select an internal crossover point (instead of a leaf node).", new PercentValue(0.9)));
+      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisExpressionSimilarityCalculator>(SimilarityCalculatorParameterName, "The similarity calculator", new BottomUpSimilarityCalculator()));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisExpressionDiversityPreservingCrossover<T>(this, cloner);
+    }
+
+    [StorableConstructor]
+    private SymbolicDataAnalysisExpressionDiversityPreservingCrossover(bool deserializing) : base(deserializing) { }
+
+    public override ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      int maximumTreeLength = MaximumSymbolicExpressionTreeLengthParameter.ActualValue.Value;
+      int maximumTreeDepth = MaximumSymbolicExpressionTreeDepthParameter.ActualValue.Value;
+      double internalCrossoverPointProbability = InternalCrossoverPointProbabilityParameter.ActualValue.Value;
+
+      return Cross(random, parent0, parent1, SimilarityCalculator, maximumTreeDepth, maximumTreeLength);
+    }
+
+    public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, ISymbolicDataAnalysisExpressionSimilarityCalculator similarityCalculator, int maxDepth, int maxLength) {
+      var actualRoot = parent0.Root.GetSubtree(0).GetSubtree(0);
+      while (actualRoot.SubtreeCount > 0 && actualRoot.SubtreeCount < 2) actualRoot = actualRoot.GetSubtree(0);
+      if (actualRoot.SubtreeCount == 0) return parent0;
+      var left = actualRoot.GetSubtree(0);
+      var right = actualRoot.GetSubtree(1);
+      var bus = (BottomUpSimilarityCalculator)similarityCalculator;
+      var map = bus.ComputeBottomUpMapping(left, right);
+
+      var crossoverPoints = parent0.IterateNodesPostfix().Where(x => x.Parent != null && x.Parent != parent0.Root).Select(x => new CutPoint(x.Parent, x)).ToList();
+      var weights = crossoverPoints.Select(x => map.ContainsKey(x.Child) ? 3D : x.Child.SubtreeCount > 0 ? 2D : 1D);
+
+      var cutpoint = crossoverPoints.SelectRandom(weights, random);
+      int level = parent0.Root.GetBranchLevel(cutpoint.Child);
+      int length = parent0.Root.GetLength() - cutpoint.Child.GetLength();
+
+      var allowedBranches = parent1.IterateNodesPostfix().Where(x => x.Parent != null &&
+                                                                x.Parent != parent1.Root &&
+                                                                x.GetDepth() + level <= maxDepth &&
+                                                                x.GetLength() + length <= maxLength &&
+                                                                cutpoint.IsMatchingPointType(x)).ToList();
+      if (!allowedBranches.Any())
+        return parent0;
+
+      var selectedBranch = allowedBranches.SelectRandom(random);
+
+      // swap the node that would create the best offspring
+      Swap(cutpoint, selectedBranch);
+      return parent0;
+    }
+  }
+}
Index: anches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSizefairCrossover.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSizefairCrossover.cs	(revision 11457)
+++ 	(revision )
@@ -1,46 +1,0 @@
-﻿#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 HeuristicLab.Data;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Crossovers {
-  [Item("SizeFairCrossover", "An operator which performs subtree swapping crossover.")]
-  class SymbolicDataAnalysisExpressionSizefairCrossover<T> : SubtreeCrossover, ISymbolicDataAnalysisExpressionCrossover<T> {
-    [StorableConstructor]
-    protected SymbolicDataAnalysisExpressionSizefairCrossover(bool deserializing) : base(deserializing) { }
-    protected SymbolicDataAnalysisExpressionSizefairCrossover(SubtreeCrossover original, Cloner cloner) : base(original, cloner) { }
-    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisExpressionSizefairCrossover<T>(this, cloner); }
-
-    public override bool CanChangeName {
-      get { return true; }
-    }
-
-    public SymbolicDataAnalysisExpressionSizefairCrossover()
-      : base() {
-      SymbolicDataAnalysisEvaluationPartitionParameter.Hidden = true;
-      Name = "SizeFairCrossover";
-    }
-  }
-}
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 11457)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 11458)
@@ -26,4 +26,6 @@
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols;
+
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   [StorableClass]
@@ -86,4 +88,5 @@
       var psi = new Psi();
       var sineIntegral = new SineIntegral();
+      var passthrough = new Passthrough();
 
       var @if = new IfThenElse();
@@ -113,5 +116,5 @@
       var exponentialAndLogarithmicSymbols = new GroupSymbol(ExponentialFunctionsName, new List<ISymbol> { exp, log });
       var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, 
-        fresnelCosineIntegral,fresnelSineIntegral,gamma,hypCosineIntegral,hypSineIntegral,norm, psi, sineIntegral});
+        fresnelCosineIntegral,fresnelSineIntegral,gamma,hypCosineIntegral,hypSineIntegral,norm, psi, sineIntegral, passthrough});
       var terminalSymbols = new GroupSymbol(TerminalsName, new List<ISymbol> { constant, variableSymbol });
       var realValuedSymbols = new GroupSymbol(RealValuedSymbolsName, new List<ISymbol>() { arithmeticSymbols, trigonometricSymbols, exponentialAndLogarithmicSymbols, specialFunctions, terminalSymbols });
@@ -156,4 +159,5 @@
       SetSubtreeCount(laggedVariable, 0, 0);
       SetSubtreeCount(autoregressiveVariable, 0, 0);
+      SetSubtreeCount(passthrough, 1, 1);
       #endregion
 
@@ -224,4 +228,10 @@
       AddAllowedChildSymbol(derivative, powerSymbols);
       AddAllowedChildSymbol(derivative, conditionSymbols);
+
+      AddAllowedChildSymbol(passthrough, realValuedSymbols);
+      AddAllowedChildSymbol(passthrough, powerSymbols);
+      AddAllowedChildSymbol(passthrough, conditionSymbols);
+      AddAllowedChildSymbol(passthrough, timeSeriesSymbols);
+      AddAllowedChildSymbol(passthrough, specialFunctions);
       #endregion
     }
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 11457)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 11458)
@@ -105,5 +105,6 @@
       <Private>False</Private>
     </Reference>
-    <Reference Include="HeuristicLab.Common-3.3">
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
       <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Common-3.3.dll</HintPath>
       <Private>False</Private>
@@ -190,6 +191,9 @@
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Crossovers\SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs" />
+    <Compile Include="Importer\SymbolicExpressionImporter.cs" />
+    <Compile Include="Importer\Token.cs" />
     <Compile Include="Interfaces\IModelBacktransformator.cs" />
-    <Compile Include="Interfaces\IDistanceCalculator.cs" />
+    <Compile Include="Interfaces\ISymbolicDataAnalysisExpressionSimilarityCalculator.cs" />
     <Compile Include="Matching\SymbolicExpressionTreeCanonicalSorter.cs" />
     <Compile Include="Matching\SymbolicExpressionTreeEqualityComparer.cs" />
@@ -263,4 +267,5 @@
     <Compile Include="Symbols\AiryB.cs" />
     <Compile Include="Symbols\Bessel.cs" />
+    <Compile Include="Symbols\Passthrough.cs" />
     <Compile Include="Symbols\Xor.cs" />
     <Compile Include="Symbols\Erf.cs" />
@@ -305,4 +310,5 @@
     <Compile Include="Symbols\VariableConditionTreeNode.cs" />
     <Compile Include="Symbols\VariableTreeNode.cs" />
+    <Compile Include="Tracking\TraceCalculator.cs" />
     <Compile Include="TransformationToSymbolicTreeMapper.cs" />
     <Compile Include="Tracking\FragmentGraph\FragmentGraph.cs" />
@@ -349,4 +355,5 @@
       <Project>{423bd94f-963a-438e-ba45-3bb3d61cd03b}</Project>
       <Name>HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views-3.4</Name>
+      <Private>False</Private>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding\3.4\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj">
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 11458)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 11458)
@@ -0,0 +1,223 @@
+#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.Diagnostics;
+using System.Linq;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class SymbolicExpressionImporter {
+    private const string VARSTART = "VAR";
+    private const string LAGGEDVARSTART = "LAGVARIABLE";
+    private const string INTEGRALSTART = "INTEG";
+    private const string DEFUNSTART = "DEFUN";
+    private const string ARGSTART = "ARG";
+    private const string INVOKESTART = "CALL";
+    private const string TIMELAGSTART = "LAG";
+    private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>() 
+      {
+        {"+", new Addition()},
+        {"/", new Division()},
+        {"*", new Multiplication()},
+        {"-", new Subtraction()},
+        {"EXP", new Exponential()},
+        {"LOG", new Logarithm()},
+        {"POW", new Power()},
+        {"ROOT", new Root()},
+        {"SIN",new Sine()},
+        {"COS", new Cosine()},
+        {"TAN", new Tangent()},
+        {"AIRYA", new AiryA()},
+        {"AIRYB", new AiryB()},
+        {"BESSEL", new Bessel()},
+        {"COSINT", new CosineIntegral()},
+        {"SININT", new SineIntegral()},
+        {"HYPCOSINT", new HyperbolicCosineIntegral()},
+        {"HYPSININT", new HyperbolicSineIntegral()},
+        {"FRESNELSININT", new FresnelSineIntegral()},
+        {"FRESNELCOSINT", new FresnelCosineIntegral()},
+        {"NORM", new Norm()},
+        {"ERF", new Erf()},
+        {"GAMMA", new Gamma()},
+        {"PSI", new Psi()},
+        {"DAWSON", new Dawson()},
+        {"EXPINT", new ExponentialIntegralEi()},
+        {"MEAN", new Average()},
+        {"IF", new IfThenElse()},
+        {">", new GreaterThan()},
+        {"<", new LessThan()},
+        {"AND", new And()},
+        {"OR", new Or()},
+        {"NOT", new Not()},
+        {"XOR", new Xor()},
+        {"DIFF", new Derivative()},
+        {"PROG", new ProgramRootSymbol()},
+        {"MAIN", new StartSymbol()},
+      };
+
+    Constant constant = new Constant();
+    Variable variable = new Variable();
+    LaggedVariable laggedVariable = new LaggedVariable();
+    Defun defun = new Defun();
+    TimeLag timeLag = new TimeLag();
+    Integral integral = new Integral();
+
+    ProgramRootSymbol programRootSymbol = new ProgramRootSymbol();
+    StartSymbol startSymbol = new StartSymbol();
+
+    public ISymbolicExpressionTree Import(string str) {
+      str = str.Replace("(", " ( ").Replace(")", " ) ");
+      ISymbolicExpressionTreeNode root = programRootSymbol.CreateTreeNode();
+      ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode();
+      ISymbolicExpressionTreeNode mainBranch = ParseSexp(new Queue<Token>(GetTokenStream(str)));
+      if (mainBranch.Symbol is ProgramRootSymbol) {
+        // when a root symbol was parsed => use main branch as root
+        root = mainBranch;
+      } else {
+        // only a main branch was given => insert the main branch into the default tree template
+        root.AddSubtree(start);
+        start.AddSubtree(mainBranch);
+      }
+      return new SymbolicExpressionTree(root);
+    }
+
+    private IEnumerable<Token> GetTokenStream(string str) {
+      return
+             from strToken in str.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).AsEnumerable()
+             let t = Token.Parse(strToken)
+             where t != null
+             select t;
+    }
+
+    private ISymbolicExpressionTreeNode ParseSexp(Queue<Token> tokens) {
+      if (tokens.Peek().Symbol == TokenSymbol.LPAR) {
+        ISymbolicExpressionTreeNode tree;
+        Expect(Token.LPAR, tokens);
+        if (tokens.Peek().StringValue.StartsWith(VARSTART)) {
+          tree = ParseVariable(tokens);
+        } else if (tokens.Peek().StringValue.StartsWith(LAGGEDVARSTART)) {
+          tree = ParseLaggedVariable(tokens);
+        } else if (tokens.Peek().StringValue.StartsWith(TIMELAGSTART)) {
+          tree = ParseTimeLag(tokens);
+          tree.AddSubtree(ParseSexp(tokens));
+        } else if (tokens.Peek().StringValue.StartsWith(INTEGRALSTART)) {
+          tree = ParseIntegral(tokens);
+          tree.AddSubtree(ParseSexp(tokens));
+        } else if (tokens.Peek().StringValue.StartsWith(DEFUNSTART)) {
+          tree = ParseDefun(tokens);
+          while (!tokens.Peek().Equals(Token.RPAR)) {
+            tree.AddSubtree(ParseSexp(tokens));
+          }
+        } else if (tokens.Peek().StringValue.StartsWith(ARGSTART)) {
+          tree = ParseArgument(tokens);
+        } else if (tokens.Peek().StringValue.StartsWith(INVOKESTART)) {
+          tree = ParseInvoke(tokens);
+          while (!tokens.Peek().Equals(Token.RPAR)) {
+            tree.AddSubtree(ParseSexp(tokens));
+          }
+        } else {
+          Token curToken = tokens.Dequeue();
+          tree = CreateTree(curToken);
+          while (!tokens.Peek().Equals(Token.RPAR)) {
+            tree.AddSubtree(ParseSexp(tokens));
+          }
+        }
+        Expect(Token.RPAR, tokens);
+        return tree;
+      } else if (tokens.Peek().Symbol == TokenSymbol.NUMBER) {
+        ConstantTreeNode t = (ConstantTreeNode)constant.CreateTreeNode();
+        t.Value = tokens.Dequeue().DoubleValue;
+        return t;
+      } else throw new FormatException("Expected function or constant symbol");
+    }
+
+    private ISymbolicExpressionTreeNode ParseInvoke(Queue<Token> tokens) {
+      Token invokeTok = tokens.Dequeue();
+      Debug.Assert(invokeTok.StringValue == "CALL");
+      InvokeFunction invokeSym = new InvokeFunction(tokens.Dequeue().StringValue);
+      ISymbolicExpressionTreeNode invokeNode = invokeSym.CreateTreeNode();
+      return invokeNode;
+    }
+
+    private ISymbolicExpressionTreeNode ParseArgument(Queue<Token> tokens) {
+      Token argTok = tokens.Dequeue();
+      Debug.Assert(argTok.StringValue == "ARG");
+      Argument argument = new Argument((int)tokens.Dequeue().DoubleValue);
+      ISymbolicExpressionTreeNode argNode = argument.CreateTreeNode();
+      return argNode;
+    }
+
+    private ISymbolicExpressionTreeNode ParseDefun(Queue<Token> tokens) {
+      Token defTok = tokens.Dequeue();
+      Debug.Assert(defTok.StringValue == "DEFUN");
+      DefunTreeNode t = (DefunTreeNode)defun.CreateTreeNode();
+      t.FunctionName = tokens.Dequeue().StringValue;
+      return t;
+    }
+
+    private ISymbolicExpressionTreeNode ParseTimeLag(Queue<Token> tokens) {
+      Token varTok = tokens.Dequeue();
+      Debug.Assert(varTok.StringValue == "LAG");
+      LaggedTreeNode t = (LaggedTreeNode)timeLag.CreateTreeNode();
+      t.Lag = (int)tokens.Dequeue().DoubleValue;
+      return t;
+    }
+
+    private ISymbolicExpressionTreeNode ParseIntegral(Queue<Token> tokens) {
+      Token varTok = tokens.Dequeue();
+      Debug.Assert(varTok.StringValue == "INTEGRAL");
+      LaggedTreeNode t = (LaggedTreeNode)integral.CreateTreeNode();
+      t.Lag = (int)tokens.Dequeue().DoubleValue;
+      return t;
+    }
+
+    private ISymbolicExpressionTreeNode ParseVariable(Queue<Token> tokens) {
+      Token varTok = tokens.Dequeue();
+      Debug.Assert(varTok.StringValue == "VARIABLE");
+      VariableTreeNode t = (VariableTreeNode)variable.CreateTreeNode();
+      t.Weight = tokens.Dequeue().DoubleValue;
+      t.VariableName = tokens.Dequeue().StringValue;
+      return t;
+    }
+
+    private ISymbolicExpressionTreeNode ParseLaggedVariable(Queue<Token> tokens) {
+      Token varTok = tokens.Dequeue();
+      Debug.Assert(varTok.StringValue == "LAGVARIABLE");
+      LaggedVariableTreeNode t = (LaggedVariableTreeNode)laggedVariable.CreateTreeNode();
+      t.Weight = tokens.Dequeue().DoubleValue;
+      t.VariableName = tokens.Dequeue().StringValue;
+      t.Lag = (int)tokens.Dequeue().DoubleValue;
+      return t;
+    }
+
+    private ISymbolicExpressionTreeNode CreateTree(Token token) {
+      if (token.Symbol != TokenSymbol.SYMB) throw new FormatException("Expected function symbol, but got: " + token.StringValue);
+      return knownSymbols[token.StringValue].CreateTreeNode();
+    }
+
+    private void Expect(Token token, Queue<Token> tokens) {
+      Token cur = tokens.Dequeue();
+      if (!token.Equals(cur)) throw new FormatException("Expected: " + token.StringValue + ", but got: " + cur.StringValue);
+    }
+  }
+}
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/Token.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/Token.cs	(revision 11458)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/Token.cs	(revision 11458)
@@ -0,0 +1,67 @@
+#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.Globalization;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  internal enum TokenSymbol { LPAR, RPAR, SYMB, NUMBER };
+  internal class Token {
+    public static readonly Token LPAR = Token.Parse("(");
+    public static readonly Token RPAR = Token.Parse(")");
+
+    public TokenSymbol Symbol { get; set; }
+    public string StringValue { get; set; }
+    public double DoubleValue { get; set; }
+    public Token() { }
+
+    public override bool Equals(object obj) {
+      Token other = (obj as Token);
+      if (other == null) return false;
+      if (other.Symbol != Symbol) return false;
+      return other.StringValue == this.StringValue;
+    }
+
+    public override int GetHashCode() {
+      return Symbol.GetHashCode() & StringValue.GetHashCode();
+    }
+
+    public static Token Parse(string strToken) {
+      strToken = strToken.Trim();
+      Token t = new Token();
+      t.StringValue = strToken.Trim();
+      double temp;
+      if (strToken == "") {
+        t = null;
+      } else if (strToken == "(") {
+        t.Symbol = TokenSymbol.LPAR;
+      } else if (strToken == ")") {
+        t.Symbol = TokenSymbol.RPAR;
+      } else if (double.TryParse(strToken, NumberStyles.Float, CultureInfo.InvariantCulture.NumberFormat, out temp)) {
+        t.Symbol = TokenSymbol.NUMBER;
+        t.DoubleValue = double.Parse(strToken, CultureInfo.InvariantCulture.NumberFormat);
+      } else {
+        t.Symbol = TokenSymbol.SYMB;
+        t.StringValue = t.StringValue.ToUpper();
+      }
+      return t;
+    }
+  }
+}
Index: anches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IDistanceCalculator.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IDistanceCalculator.cs	(revision 11457)
+++ 	(revision )
@@ -1,8 +1,0 @@
-﻿using HeuristicLab.Core;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public interface IDistanceCalculator : IItem {
-    double CalculateDistance(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2);
-  }
-}
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionSimilarityCalculator.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionSimilarityCalculator.cs	(revision 11458)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionSimilarityCalculator.cs	(revision 11458)
@@ -0,0 +1,29 @@
+﻿#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 HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public interface ISymbolicDataAnalysisExpressionSimilarityCalculator : IItem {
+    double CalculateSimilarity(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2);
+  }
+}
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 11457)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 11458)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
@@ -83,4 +84,5 @@
     public const byte Erf = 43;
     public const byte Bessel = 44;
+    public const byte Passthrough = 45;
 
     private static Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
@@ -130,5 +132,6 @@
       { typeof(Norm), OpCodes.Norm},
       { typeof(Erf), OpCodes.Erf},
-      { typeof(Bessel), OpCodes.Bessel}   
+      { typeof(Bessel), OpCodes.Bessel},
+      { typeof(Passthrough), OpCodes.Passthrough}
     };
 
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 11457)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 11458)
@@ -111,4 +111,11 @@
 
       var code = SymbolicExpressionTreeLinearCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
+      PrepareInstructions(code, dataset);
+      return rows.Select(row => Evaluate(dataset, row, code));
+    }
+
+    // NOTE: do not use this method when evaluating trees. this method is provided as a shortcut for evaluating subtrees ad-hoc
+    public IEnumerable<double> GetValues(ISymbolicExpressionTreeNode node, Dataset dataset, IEnumerable<int> rows) {
+      var code = SymbolicExpressionTreeLinearCompiler.Compile(node, OpCodes.MapSymbolToOpCode);
       PrepareInstructions(code, dataset);
       return rows.Select(row => Evaluate(dataset, row, code));
@@ -329,4 +336,6 @@
           state.Reset();
           instr.value = interpreter.Evaluate(dataset, ref row, state);
+        } else if (instr.opCode == OpCodes.Passthrough) {
+          instr.value = code[instr.childIndex].value;
         } else {
           var errorText = string.Format("The {0} symbol is not supported by the linear interpreter. To support this symbol, please use the SymbolicDataAnalysisExpressionTreeInterpreter.", instr.dynamicNode.Symbol.Name);
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMatching.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMatching.cs	(revision 11457)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMatching.cs	(revision 11458)
@@ -77,16 +77,18 @@
 
     public static ISymbolicExpressionTreeNode Difference(this ISymbolicExpressionTreeNode node, ISymbolicExpressionTreeNode other) {
-      var these = node.IterateNodesPrefix().ToList();
-      var others = other.IterateNodesPrefix().ToList();
-
-      var minCount = Math.Min(these.Count, others.Count);
+      var a = node.IterateNodesPrefix().ToList();
+      var b = other.IterateNodesPrefix().ToList();
       var list = new List<ISymbolicExpressionTreeNode>();
-
-      for (int i = 0; i < minCount; ++i) {
-        if (these[i].ToString() != others[i].ToString())
-          list.Add(these[i]);
+      for (int i = 0, j = 0; i < a.Count && j < b.Count; ++i, ++j) {
+        var s1 = a[i].ToString();
+        var s2 = b[j].ToString();
+        if (s1 == s2) continue;
+        list.Add(a[i]);
+        // skip subtrees since the parents are already different
+        i += a[i].SubtreeCount;
+        j += b[j].SubtreeCount;
       }
-
-      return list.Count > 0 ? LowestCommonAncestor(node, list) : null;
+      ISymbolicExpressionTreeNode result = list.Count > 0 ? LowestCommonAncestor(node, list) : null;
+      return result;
     }
 
@@ -98,5 +100,5 @@
         return nodes[0];
 
-      int lowestLevel = nodes.Min(x => root.GetBranchLevel(x));
+      int minLevel = nodes.Min(x => root.GetBranchLevel(x));
 
       // bring the nodes in the nodes to the same level (relative to the root)
@@ -104,5 +106,5 @@
         var node = nodes[i];
         var level = root.GetBranchLevel(node);
-        for (int j = lowestLevel; j < level; ++j)
+        for (int j = minLevel; j < level; ++j)
           node = node.Parent;
         nodes[i] = node;
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 11457)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/BottomUpSimilarityCalculator.cs	(revision 11458)
@@ -32,5 +32,5 @@
   [StorableClass]
   [Item("BottomUpSimilarityCalculator", "A similarity calculator which uses the tree bottom-up distance as a similarity metric.")]
-  public class BottomUpSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+  public class BottomUpSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator, ISymbolicDataAnalysisExpressionSimilarityCalculator {
     private readonly HashSet<string> commutativeSymbols = new HashSet<string> { "Addition", "Multiplication", "Average", "And", "Or", "Xor" };
 
@@ -39,4 +39,12 @@
     public override IDeepCloneable Clone(Cloner cloner) {
       return new BottomUpSimilarityCalculator(this, cloner);
+    }
+
+    public double CalculateSimilarity(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);
     }
 
@@ -52,17 +60,9 @@
         throw new ArgumentException("Cannot calculate similarity when one of the arguments is null.");
 
-      var similarity = CalculateSolutionSimilarity(t1, t2);
+      var similarity = CalculateSimilarity(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);
     }
 
@@ -174,4 +174,7 @@
         }
 
+        if (n == n1 || n == n2)
+          continue;
+
         var p = n.Parent;
         if (p == null)
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 11457)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/MaxCommonSubtreeSimilarityCalculator.cs	(revision 11458)
@@ -30,6 +30,27 @@
   [StorableClass]
   [Item("MaxCommonSubtreeSimilarityCalculator", "A similarity calculator based on the size of the maximum common subtree between two trees")]
-  public class MaxCommonSubtreeSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
-    public MaxCommonSubtreeSimilarityCalculator() { }
+  public class MaxCommonSubtreeSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator, ISymbolicDataAnalysisExpressionSimilarityCalculator {
+    private readonly SymbolicExpressionTreeNodeSimilarityComparer comparer;
+    public bool MatchVariableNames {
+      get { return comparer.MatchVariableNames; }
+      set { comparer.MatchVariableNames = value; }
+    }
+
+    public bool MatchVariableWeights {
+      get { return comparer.MatchVariableWeights; }
+      set { comparer.MatchVariableWeights = value; }
+    }
+
+    public bool MatchConstantValues {
+      get { return comparer.MatchConstantValues; }
+      set { comparer.MatchConstantValues = value; }
+    }
+
+    [StorableConstructor]
+    protected MaxCommonSubtreeSimilarityCalculator(bool deserializing) : base(deserializing) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MaxCommonSubtreeSimilarityCalculator(this, cloner);
+    }
 
     protected MaxCommonSubtreeSimilarityCalculator(MaxCommonSubtreeSimilarityCalculator original, Cloner cloner)
@@ -37,6 +58,22 @@
     }
 
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new MaxCommonSubtreeSimilarityCalculator(this, cloner);
+    public MaxCommonSubtreeSimilarityCalculator() {
+      comparer = new SymbolicExpressionTreeNodeSimilarityComparer {
+        MatchConstantValues = true,
+        MatchVariableNames = true,
+        MatchVariableWeights = true
+      };
+    }
+
+    public MaxCommonSubtreeSimilarityCalculator(bool matchVariableNames, bool matchVariableWeights, bool matchConstantValues) {
+      comparer = new SymbolicExpressionTreeNodeSimilarityComparer {
+        MatchConstantValues = matchConstantValues,
+        MatchVariableNames = matchVariableNames,
+        MatchVariableWeights = matchVariableWeights
+      };
+    }
+
+    public double CalculateSimilarity(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2) {
+      return MaxCommonSubtreeSimilarity(t1, t2, comparer);
     }
 
@@ -47,9 +84,4 @@
       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);
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/PhenotypicSimilarityCalculator.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/PhenotypicSimilarityCalculator.cs	(revision 11457)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/PhenotypicSimilarityCalculator.cs	(revision 11458)
@@ -23,4 +23,5 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -29,5 +30,5 @@
   [Item("PhenotypicSimilarityCalculator", "An operator that calculates the similarity betweeon two trees based on the correlation of their outputs.")]
   [StorableClass]
-  public class PhenotypicSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+  public class PhenotypicSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator, ISymbolicDataAnalysisExpressionSimilarityCalculator {
     public PhenotypicSimilarityCalculator(PhenotypicSimilarityCalculator original, Cloner cloner)
       : base(original, cloner) {
@@ -41,4 +42,8 @@
     public override IDeepCloneable Clone(Cloner cloner) {
       return new PhenotypicSimilarityCalculator(this, cloner);
+    }
+
+    public double CalculateSimilarity(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2) {
+      throw new System.NotImplementedException();
     }
 
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Passthrough.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Passthrough.cs	(revision 11458)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Passthrough.cs	(revision 11458)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 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.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols {
+  [StorableClass]
+  [Item("Passthrough", "A symbol that does not perform any operation (just passes the input). Useful for tweaking tree shape and crossover probabilities (serves as placeholder)")]
+  public sealed class Passthrough : Symbol {
+    private const int minimumArity = 1;
+    private const int maximumArity = 1;
+
+    public override int MinimumArity { get { return minimumArity; } }
+
+    public override int MaximumArity { get { return maximumArity; } }
+
+    [StorableConstructor]
+    private Passthrough(bool deserializing) : base(deserializing) { }
+    private Passthrough(Passthrough original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Passthrough(this, cloner);
+    }
+
+    public Passthrough()
+      : base("Passthrough", "A symbol that does not perform any operation (just passes the input). Useful for tweaking tree shape and crossover probabilities (serves as placeholder)") {
+    }
+  }
+}
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionTracing.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionTracing.cs	(revision 11457)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionTracing.cs	(revision 11458)
@@ -48,10 +48,19 @@
       var parent = parentNode; // current parent
 
+      IGenealogyGraphNode<ISymbolicExpressionTree> n1 = null;
+      int i1 = -1;
+
       while (true) {
+        if (node == n1 && index == i1)
+          throw new InvalidOperationException("Infinite loop detected");
+
+        n1 = node;
+        i1 = index;
+
         if (!node.Parents.Any()) {
           // no tracing if there are no parents, return a fragment node representing the current trace
-          var fragmentNode = new FragmentNode(node) { SubtreeIndex = index };
+          var fragmentNode = new FragmentNode(node.Data) { SubtreeIndex = index };
           if (parent != null) {
-            var arc = new Arc(parent, fragmentNode);
+            var arc = new GenealogyGraphArc(parent, fragmentNode);
             parent.AddArc(arc);
             fragmentNode.AddArc(arc);
@@ -82,5 +91,5 @@
         if (parents.Count == 1) {
           // we are tracing a mutation operation
-          var fragmentNode = new FragmentNode(node) {
+          var fragmentNode = new FragmentNode(node.Data) {
             SubtreeIndex = index,
             FragmentIndex = fragment.Index1
@@ -91,9 +100,13 @@
             fragmentNode.AddArc(arc);
           }
+          if (node == parents[0])
+            throw new InvalidOperationException("Node == parents[0]");
+
           node = parents[0];
-          if (subtreeIndex == fragment.Index1) {
+
+          if (index == fragment.Index1) {
             // index stays the same
-          } else if (fragment.Index1 < subtreeIndex) {
-            if (subtreeIndex < fragment.Index1 + fragmentLength) {
+          } else if (fragment.Index1 < index) {
+            if (index < fragment.Index1 + fragmentLength) {
               // in the case of mutation, the fragment could have been introduced via a node replacement
               // there is no guarantee the subtree exists above this level, therefore the index is set to the fragment index
@@ -103,6 +116,6 @@
               index += node.Data.NodeAt(fragment.Index1).GetLength() - fragmentLength;
             }
-          } else if (subtreeIndex < fragment.Index1) {
-            if (fragment.Index1 < subtreeIndex + subtreeLength) {
+          } else if (index < fragment.Index1) {
+            if (fragment.Index1 < index + subtreeLength) {
               // subtree contains fragment
               index = fragment.Index1;
@@ -111,7 +124,8 @@
             }
           }
-
           yield return fragmentNode;
-          var up = Trace(node, index, fragmentNode); // force immediate query execution
+          if (node == graphNode && index == subtreeIndex)
+            throw new ArgumentException("Infinite recursion detected");
+          var up = Trace(node, index, fragmentNode).ToList(); // force immediate query execution
           foreach (var v in up) { yield return v; }
           break;
@@ -121,4 +135,8 @@
         #region crossover tracing
         if (parents.Count == 2) {
+          if (node == parents[0])
+            throw new InvalidOperationException("Node == parents[0]");
+          if (node == parents[1])
+            throw new InvalidOperationException("Node == parents[1]");
           // we are tracing a crossover operation
           if (fragment.Index1 == index) {
@@ -143,10 +161,10 @@
             if (fragment.Index1 < index + subtreeLength) {
               // subtree contains fragment => branching point in the fragment graph
-              var fragmentNode = new FragmentNode(node) {
+              var fragmentNode = new FragmentNode(node.Data) {
                 SubtreeIndex = index,
                 FragmentIndex = fragment.Index1
               };
               if (parent != null) {
-                var arc = new Arc(parent, fragmentNode);
+                var arc = new GenealogyGraphArc(parent, fragmentNode);
                 parent.AddArc(arc);
                 fragmentNode.AddArc(arc);
@@ -176,12 +194,4 @@
       return writer.ToString();
     }
-    #region some helper methods for shortening the tracing code
-    private static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTree tree, int position) {
-      return NodeAt(tree.Root, position);
-    }
-    private static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTreeNode root, int position) {
-      return root.IterateNodesPrefix().ElementAt(position);
-    }
-    #endregion
   }
 }
Index: /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/TraceCalculator.cs
===================================================================
--- /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/TraceCalculator.cs	(revision 11458)
+++ /branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/TraceCalculator.cs	(revision 11458)
@@ -0,0 +1,162 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.EvolutionTracking;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+
+
+  [Item("TraceCalculator", "Walks a genealogy graph and produces a trace of the specified subtree")]
+  [StorableClass]
+  public class TraceCalculator : Item {
+    private IGenealogyGraphNode<ISymbolicExpressionTree> lastVisited;
+    private readonly IGenealogyGraph<ISymbolicExpressionTree> traceGraph;
+    private readonly Dictionary<IGenealogyGraphNode<ISymbolicExpressionTree>, Tuple<int, int>> traceMap;
+
+    public IGenealogyGraph<ISymbolicExpressionTree> TraceGraph { get { return traceGraph; } }
+
+    public TraceCalculator() {
+      traceGraph = new GenealogyGraph<ISymbolicExpressionTree>();
+      traceMap = new Dictionary<IGenealogyGraphNode<ISymbolicExpressionTree>, Tuple<int, int>>();
+    }
+
+    protected TraceCalculator(TraceCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TraceCalculator(this, cloner);
+    }
+
+    public static IGenealogyGraph<ISymbolicExpressionTree> TraceSubtree(IGenealogyGraphNode<ISymbolicExpressionTree> node, int subtreeIndex) {
+      var tc = new TraceCalculator();
+      tc.Trace(node, subtreeIndex);
+      return tc.TraceGraph;
+    }
+
+    public void Trace(IGenealogyGraphNode<ISymbolicExpressionTree> node, int subtreeIndex) {
+      while (true) {
+        if (!node.Parents.Any()) {
+          if (node.Rank.IsAlmost(0) && lastVisited != null) {
+            var n = traceGraph.GetByContent(node.Data);
+            if (n == null) {
+              n = node.Copy();
+              traceGraph.AddVertex(n);
+            }
+            if (n.InArcs.All(x => x.Source != lastVisited)) {
+              traceGraph.AddArc(lastVisited, n);
+            }
+          }
+          return;
+        }
+
+        var parents = node.Parents.ToList();
+
+        var fragment = (IFragment<ISymbolicExpressionTreeNode>)node.InArcs.Last().Data;
+        if (fragment == null) {
+          // the node is either an elite node or (in rare cases) no fragment was transferred
+          node = parents[0];
+          continue;
+        }
+
+        int fragmentLength = fragment.Root.GetLength();
+        int subtreeLength = node.Data.NodeAt(subtreeIndex).GetLength();
+
+        #region trace crossover
+        if (parents.Count == 2) {
+          if (fragment.Index1 == subtreeIndex) {
+            node = parents[1];
+            subtreeIndex = fragment.Index2;
+            continue;
+          }
+          if (fragment.Index1 < subtreeIndex) {
+            if (fragment.Index1 + fragmentLength > subtreeIndex) {
+              // fragment contains subtree
+              node = parents[1];
+              subtreeIndex += fragment.Index2 - fragment.Index1;
+            } else {
+              // fragment distinct from subtree
+              node = parents[0];
+              subtreeIndex += node.Data.NodeAt(fragment.Index1).GetLength() - fragmentLength;
+            }
+            continue;
+          }
+          if (fragment.Index1 > subtreeIndex) {
+            if (fragment.Index1 < subtreeIndex + subtreeLength) {
+              // subtree contains fragment => branching point in the fragment graph
+              var n = traceGraph.GetByContent(node.Data);
+              if (n == null) {
+                n = node.Copy();
+                traceGraph.AddVertex(n);
+                traceMap[n] = new Tuple<int, int>(subtreeIndex, fragment.Index1);
+              }
+
+              if (lastVisited != null) {
+                var lastTraceData = traceMap[lastVisited];
+                int lastSi = lastTraceData.Item1;
+                int lastFi = lastTraceData.Item2;
+                var traceData = new Tuple<int, int, int, int>(lastSi, lastFi, subtreeIndex, fragment.Index1);
+                if (!n.InArcs.Any(a => a.Source == lastVisited && a.Data.Equals(traceData))) {
+                  var arc = traceGraph.AddArc(lastVisited, n);
+                  arc.Data = traceData;
+                }
+              }
+
+              lastVisited = n;
+              Trace(parents[0], subtreeIndex);
+              lastVisited = n;
+              Trace(parents[1], fragment.Index2);
+              break;
+            } else {
+              // subtree and fragment are distinct. 
+              node = parents[0];
+              continue;
+            }
+          }
+        }
+        #endregion
+        #region trace mutation
+        if (parents.Count == 1) {
+          if (subtreeIndex == fragment.Index1) {
+            //            node = parents[0];
+            var n = traceGraph.GetByContent(node.Data);
+            if (n == null) {
+              n = node.Copy();
+              traceGraph.AddVertex(n);
+            }
+
+            if (lastVisited != null) {
+              var arc = traceGraph.AddArc(lastVisited, n);
+              var lastTraceData = traceMap[lastVisited];
+              int lastSi = lastTraceData.Item1;
+              int lastFi = lastTraceData.Item2;
+              var td = new Tuple<int, int, int, int>(lastSi, lastFi, subtreeIndex, fragment.Index1);
+            }
+          }
+        #endregion
+        } else {
+          throw new InvalidOperationException("A node cannot have more than two parents");
+        }
+      }
+    }
+  }
+
+  internal static class Util {
+    // shallow copy which does not clone the data and completely ignores arcs
+    public static IGenealogyGraphNode<ISymbolicExpressionTree> Copy(this IGenealogyGraphNode<ISymbolicExpressionTree> node) {
+      return new GenealogyGraphNode<ISymbolicExpressionTree>(node.Data) { Rank = node.Rank, Quality = node.Quality };
+    }
+    #region some helper methods for shortening the tracing code
+    public static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTree tree, int index) {
+      return NodeAt(tree.Root, index);
+    }
+    public static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTreeNode root, int index) {
+      return root.IterateNodesPrefix().ElementAt(index);
+    }
+    #endregion
+  }
+}
