Index: /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisInternalDiversityAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisInternalDiversityAnalyzer.cs	(revision 11238)
+++ /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisInternalDiversityAnalyzer.cs	(revision 11239)
@@ -42,8 +42,8 @@
 
     private const string ResultCollectionParameterName = "Results";
-    private readonly BottomUpSimilarityCalculator busCalculator;
+    private readonly BottomUpTreeSimilarityCalculator busCalculator;
 
     public SymbolicDataAnalysisInternalDiversityAnalyzer() {
-      busCalculator = new BottomUpSimilarityCalculator();
+      busCalculator = new BottomUpTreeSimilarityCalculator();
 
       Parameters.Add(new ScopeTreeLookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName));
Index: /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 11238)
+++ /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 11239)
@@ -225,5 +225,5 @@
     <Compile Include="Matching\SymbolicExpressionTreeNodeComparer.cs" />
     <Compile Include="Matching\SymbolicExpressionTreeNodeSimilarityComparer.cs" />
-    <Compile Include="SimilarityCalculators\BottomUpSimilarityCalculator.cs" />
+    <Compile Include="SimilarityCalculators\BottomUpTreeSimilarityCalculator.cs" />
     <Compile Include="SimilarityCalculators\MaxCommonSubtreeSimilarityCalculator.cs" />
     <Compile Include="SymbolicExpressionTreeBacktransformator.cs" />
Index: /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMatching.cs
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMatching.cs	(revision 11238)
+++ /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Matching/SymbolicExpressionTreeMatching.cs	(revision 11239)
@@ -1,3 +1,24 @@
-﻿using System;
+﻿#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;
@@ -29,5 +50,5 @@
     /// </summary>
     /// <returns>Number of pairs that were matched</returns>
-    public static int Match(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, SymbolicExpressionTreeNodeSimilarityComparer comp) {
+    public static int Match(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, ISymbolicExpressionTreeNodeSimilarityComparer comp) {
       if (!comp.Equals(a, b)) return 0;
       int m = a.SubtreeCount;
Index: anches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/BottomUpSimilarityCalculator.cs
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/BottomUpSimilarityCalculator.cs	(revision 11238)
+++ 	(revision )
@@ -1,210 +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 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.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/BottomUpTreeSimilarityCalculator.cs
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/BottomUpTreeSimilarityCalculator.cs	(revision 11239)
+++ /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/BottomUpTreeSimilarityCalculator.cs	(revision 11239)
@@ -0,0 +1,230 @@
+﻿#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("BottomUpTreeSimilarityCalculator", "A similarity calculator which uses the tree bottom-up distance as a similarity metric.")]
+  public class BottomUpTreeSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+    private readonly HashSet<string> commutativeSymbols;
+
+    public BottomUpTreeSimilarityCalculator() {
+      commutativeSymbols = new HashSet<string>();
+    }
+
+    public BottomUpTreeSimilarityCalculator(IEnumerable<string> commutativeSymbols) {
+      this.commutativeSymbols = new HashSet<string>(commutativeSymbols);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BottomUpTreeSimilarityCalculator(this, cloner);
+    }
+
+    protected BottomUpTreeSimilarityCalculator(BottomUpTreeSimilarityCalculator 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 bool AddCommutativeSymbol(string symbolName) {
+      return commutativeSymbols.Add(symbolName);
+    }
+
+    public bool RemoveCommutativeSymbol(string symbolName) {
+      return commutativeSymbols.Remove(symbolName);
+    }
+
+    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;
+    }
+
+    /// <summary>
+    /// This method iterates the nodes of a subtree in breadth order while also sorting the subtrees of commutative symbols based on their label.
+    /// This is necessary in order for the mapping to be realized correctly.
+    /// </summary>
+    /// <param name="node">The root of the subtree</param>
+    /// <returns>A list of nodes in breadth order (with children of commutative symbols sorted by label)</returns>
+    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.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/MaxCommonSubtreeSimilarityCalculator.cs
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/MaxCommonSubtreeSimilarityCalculator.cs	(revision 11238)
+++ /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SimilarityCalculators/MaxCommonSubtreeSimilarityCalculator.cs	(revision 11239)
@@ -56,5 +56,5 @@
     }
 
-    public static double MaxCommonSubtreeSimilarity(ISymbolicExpressionTree a, ISymbolicExpressionTree b, SymbolicExpressionTreeNodeSimilarityComparer comparer) {
+    public static double MaxCommonSubtreeSimilarity(ISymbolicExpressionTree a, ISymbolicExpressionTree b, ISymbolicExpressionTreeNodeSimilarityComparer comparer) {
       int max = 0;
       var rootA = a.Root.GetSubtree(0).GetSubtree(0);
Index: /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 11238)
+++ /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 11239)
@@ -234,5 +234,5 @@
       Operators.Add(new SymbolicExpressionTreeLengthAnalyzer());
       Operators.Add(new SingleObjectivePopulationDiversityAnalyzer());
-      Operators.Add(new BottomUpSimilarityCalculator());
+      Operators.Add(new BottomUpTreeSimilarityCalculator());
       ParameterizeOperators();
     }
@@ -359,5 +359,5 @@
       }
       foreach (var op in operators.OfType<SingleObjectivePopulationDiversityAnalyzer>()) {
-        op.SimilarityCalculator = operators.OfType<BottomUpSimilarityCalculator>().SingleOrDefault();
+        op.SimilarityCalculator = operators.OfType<BottomUpTreeSimilarityCalculator>().SingleOrDefault();
       }
     }
Index: anches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/BottomUpSimilarityCalculatorTest.cs
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/BottomUpSimilarityCalculatorTest.cs	(revision 11238)
+++ 	(revision )
@@ -1,172 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.Globalization;
-using System.Linq;
-using System.Text;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
-using HeuristicLab.Random;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tests {
-  [TestClass]
-  public class BottomUpSimilarityCalculatorTest {
-    private readonly BottomUpSimilarityCalculator busCalculator;
-    private readonly SymbolicExpressionImporter importer;
-
-    private const int N = 100;
-    private const int Rows = 1;
-    private const int Columns = 10;
-
-    public BottomUpSimilarityCalculatorTest() {
-      busCalculator = new BottomUpSimilarityCalculator();
-      importer = new SymbolicExpressionImporter();
-    }
-
-    [TestMethod]
-    [TestCategory("Problems.DataAnalysis.Symbolic")]
-    [TestProperty("Time", "short")]
-    public void TestBottomUpMatching() {
-      TestMatchedNodes("(+ 1 2)", "(+ 2 1)", 5);
-      TestMatchedNodes("(- 2 1)", "(- 1 2)", 2);
-      TestMatchedNodes("(* (variable 1 X1) (variable 1 X2))", "(* (+ (variable 1 X1) 1) (+ (variable 1 X2) 1))", 2);
-
-      TestMatchedNodes("(* (variable 1 X1) (variable 1 X2))", "(* (+ (variable 1 X1) 1) (variable 1 X2))", 2);
-
-      TestMatchedNodes("(+ (variable 1 a) (variable 1 b))", "(+ (variable 1 a) (variable 1 a))", 1);
-      TestMatchedNodes("(+ (+ (variable 1 a) (variable 1 b)) (variable 1 b))", "(+ (* (+ (variable 1 a) (variable 1 b)) (variable 1 b)) (+ (+ (variable 1 a) (variable 1 b)) (variable 1 b)))", 5);
-
-      TestMatchedNodes(
-        "(* (+ 2.84 (exp (+ (log (/ (variable 2.0539 X5) (variable -9.2452e-1 X6))) (/ (variable 2.0539 X5) (variable -9.2452e-1 X6))))) 2.9081)",
-        "(* (- (variable 9.581e-1 X6) (+ (- (variable 5.1491e-1 X5) 1.614e+1) (+ (/ (variable 2.0539 X5) (variable -9.2452e-1 X6)) (log (/ (variable 2.0539 X5) (variable -9.2452e-1 X6)))))) 2.9081)",
-        9);
-
-      TestMatchedNodes("(+ (exp 2.1033) (/ -4.3072 (variable 2.4691 X7)))", "(/ 1 (+ (/ -4.3072 (variable 2.4691 X7)) (exp 2.1033)))", 6);
-      TestMatchedNodes("(+ (exp 2.1033) (/ -4.3072 (variable 2.4691 X7)))", "(/ 1 (+ (/ (variable 2.4691 X7) -4.3072) (exp 2.1033)))", 4);
-
-      const string expr1 = "(* (- 1.2175e+1 (+ (/ (exp -1.4134e+1) (exp 9.2013)) (exp (log (exp (/ (exp (- (* -4.2461 (variable 2.2634 X5)) (- -9.6267e-1 3.3243))) (- (/ (/ (variable 1.0883 X1) (variable 6.9620e-1 X2)) (log 1.3011e+1)) (variable -4.3098e-1 X7)))))))) (log 1.3011e+1))";
-      const string expr2 = "(* (- 1.2175e+1 (+ (/ (/ (+ (variable 3.0140 X9) (variable 1.3430 X8)) -1.0864e+1) (exp 9.2013)) (exp (log (exp (/ (exp (- (* -4.2461 (variable 2.2634 X5)) (- -9.6267e-1 3.3243))) (- (/ (/ (variable 1.0883 X1) (variable 6.9620e-1 X2)) (log 1.3011e+1)) (variable -4.3098e-1 X7)))))))) (exp (variable 4.0899e-1 X7)))";
-
-      TestMatchedNodes(expr1, expr2, 23);
-
-    }
-
-    private void TestMatchedNodes(string expr1, string expr2, int expected) {
-      var t1 = importer.Import(expr1);
-      var t2 = importer.Import(expr2);
-
-      var mapping = busCalculator.ComputeBottomUpMapping(t1.Root, t2.Root);
-      var c = mapping.Count;
-
-      if (c != expected) {
-        throw new Exception("Match count " + c + " is different than expected value " + expected);
-      }
-    }
-
-    [TestMethod]
-    [TestCategory("Problems.DataAnalysis.Symbolic")]
-    [TestProperty("Time", "long")]
-    public void TestBottomUpSimilarityCalculatorPerformance() {
-      var grammar = new TypeCoherentExpressionGrammar();
-      grammar.ConfigureAsDefaultRegressionGrammar();
-      var twister = new MersenneTwister(31415);
-      var ds = Util.CreateRandomDataset(twister, Rows, Columns);
-      var trees = Util.CreateRandomTrees(twister, ds, grammar, N, 1, 100, 0, 0);
-
-      double s = 0;
-      var sw = new Stopwatch();
-
-      sw.Start();
-      for (int i = 0; i < trees.Length - 1; ++i) {
-        for (int j = i + 1; j < trees.Length; ++j) {
-          s += busCalculator.CalculateSolutionSimilarity(trees[i], trees[j]);
-        }
-      }
-      sw.Stop();
-      Console.WriteLine("Elapsed time: " + sw.ElapsedMilliseconds / 1000.0 + ", Avg. similarity: " + s);
-      Console.WriteLine(N * (N + 1) / (2 * sw.ElapsedMilliseconds / 1000.0) + " similarity calculations per second.");
-    }
-
-    private static string FormatMapping(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> map) {
-      var symbolNameMap = new Dictionary<string, string>
-    {
-      {"ProgramRootSymbol", "Prog"},
-      {"StartSymbol","RPB"},
-      {"Multiplication", "$\\times$"},
-      {"Division", "$\\div$"},
-      {"Addition", "$+$"},
-      {"Subtraction", "$-$"},
-      {"Exponential", "$\\exp$"},
-      {"Logarithm", "$\\log$"}
-    };
-
-      var sb = new StringBuilder();
-      var nodeIds = new Dictionary<ISymbolicExpressionTreeNode, string>();
-      int offset = 0;
-      var layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(x => x.Subtrees);
-      var nodeCoordinates = layoutEngine.CalculateLayout(t1.Root).ToDictionary(n => n.Content, n => new PointF(n.X, n.Y));
-
-      double ws = 0.5;
-      double hs = 0.5;
-
-      var nl = Environment.NewLine;
-      sb.Append("\\documentclass[class=minimal,border=0pt]{standalone}" + nl +
-                 "\\usepackage{tikz}" + nl +
-                 "\\begin{document}" + nl +
-                 "\\begin{tikzpicture}" + nl +
-                 "\\def\\ws{1}" + nl +
-                 "\\def\\hs{0.7}" + nl +
-                 "\\def\\offs{" + offset + "}" + nl);
-
-      foreach (var node in t1.IterateNodesBreadth()) {
-        var id = Guid.NewGuid().ToString();
-        nodeIds[node] = id;
-        var coord = nodeCoordinates[node];
-        var nodeName = symbolNameMap.ContainsKey(node.Symbol.Name) ? symbolNameMap[node.Symbol.Name] : node.ToString();
-        sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\node ({0}) at (\\ws*{1} + \\offs,\\hs*{2}) {{{3}}};", nodeIds[node], ws * coord.X, -hs * coord.Y, EscapeLatexString(nodeName)));
-      }
-
-      foreach (ISymbolicExpressionTreeNode t in t1.IterateNodesBreadth()) {
-        var n = t;
-        foreach (var s in t.Subtrees) {
-          sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\draw ({0}) -- ({1});", nodeIds[n], nodeIds[s]));
-        }
-      }
-
-      nodeCoordinates = layoutEngine.CalculateLayout(t2.Root).ToDictionary(n => n.Content, n => new PointF(n.X, n.Y));
-
-      offset = 20;
-      sb.Append("\\def\\offs{" + offset + "}" + nl);
-      foreach (var node in t2.IterateNodesBreadth()) {
-        var id = Guid.NewGuid().ToString();
-        nodeIds[node] = id;
-        var coord = nodeCoordinates[node];
-        var nodeName = symbolNameMap.ContainsKey(node.Symbol.Name) ? symbolNameMap[node.Symbol.Name] : node.ToString();
-        sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\node ({0}) at (\\ws*{1} + \\offs,\\hs*{2}) {{{3}}};", nodeIds[node], ws * coord.X, -hs * coord.Y, EscapeLatexString(nodeName)));
-      }
-
-      foreach (ISymbolicExpressionTreeNode t in t2.IterateNodesBreadth()) {
-        var n = t;
-        foreach (var s in t.Subtrees) {
-          sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\draw ({0}) -- ({1});", nodeIds[n], nodeIds[s]));
-        }
-      }
-
-      foreach (var p in map) {
-        var id1 = nodeIds[p.Key];
-        var id2 = nodeIds[p.Value];
-
-        sb.Append(string.Format(CultureInfo.InvariantCulture, "\\path[draw,->,color=gray] ({0}) edge[bend left,dashed] ({1});" + Environment.NewLine, id1, id2));
-      }
-      sb.Append("\\end{tikzpicture}" + nl +
-                "\\end{document}" + nl);
-      return sb.ToString();
-    }
-
-    private static string EscapeLatexString(string s) {
-      return s.Replace("\\", "\\\\").Replace("{", "\\{").Replace("}", "\\}").Replace("_", "\\_");
-    }
-  }
-}
Index: /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/BottomUpTreeSimilarityCalculatorTest.cs
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/BottomUpTreeSimilarityCalculatorTest.cs	(revision 11239)
+++ /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/BottomUpTreeSimilarityCalculatorTest.cs	(revision 11239)
@@ -0,0 +1,173 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
+using HeuristicLab.Random;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tests {
+  [TestClass]
+  public class BottomUpSimilarityCalculatorTest {
+    private readonly BottomUpTreeSimilarityCalculator busCalculator;
+    private readonly SymbolicExpressionImporter importer;
+
+    private const int N = 100;
+    private const int Rows = 1;
+    private const int Columns = 10;
+
+    public BottomUpSimilarityCalculatorTest() {
+      busCalculator = new BottomUpTreeSimilarityCalculator(new List<string> { "Addition", "Multiplication", "And", "Or", "Xor" });
+      importer = new SymbolicExpressionImporter();
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestBottomUpMatching() {
+      TestMatchedNodes("(+ 1 2)", "(+ 2 1)", 5);
+      TestMatchedNodes("(- 2 1)", "(- 1 2)", 2);
+      TestMatchedNodes("(* (variable 1 X1) (variable 1 X2))", "(* (+ (variable 1 X1) 1) (+ (variable 1 X2) 1))", 2);
+
+      TestMatchedNodes("(* (variable 1 X1) (variable 1 X2))", "(* (+ (variable 1 X1) 1) (variable 1 X2))", 2);
+
+      TestMatchedNodes("(+ (variable 1 a) (variable 1 b))", "(+ (variable 1 a) (variable 1 a))", 1);
+      TestMatchedNodes("(+ (+ (variable 1 a) (variable 1 b)) (variable 1 b))", "(+ (* (+ (variable 1 a) (variable 1 b)) (variable 1 b)) (+ (+ (variable 1 a) (variable 1 b)) (variable 1 b)))", 5);
+
+      TestMatchedNodes(
+        "(* (+ 2.84 (exp (+ (log (/ (variable 2.0539 X5) (variable -9.2452e-1 X6))) (/ (variable 2.0539 X5) (variable -9.2452e-1 X6))))) 2.9081)",
+        "(* (- (variable 9.581e-1 X6) (+ (- (variable 5.1491e-1 X5) 1.614e+1) (+ (/ (variable 2.0539 X5) (variable -9.2452e-1 X6)) (log (/ (variable 2.0539 X5) (variable -9.2452e-1 X6)))))) 2.9081)",
+        9);
+
+      TestMatchedNodes("(+ (exp 2.1033) (/ -4.3072 (variable 2.4691 X7)))", "(/ 1 (+ (/ -4.3072 (variable 2.4691 X7)) (exp 2.1033)))", 6);
+      TestMatchedNodes("(+ (exp 2.1033) (/ -4.3072 (variable 2.4691 X7)))", "(/ 1 (+ (/ (variable 2.4691 X7) -4.3072) (exp 2.1033)))", 4);
+
+      const string expr1 = "(* (- 1.2175e+1 (+ (/ (exp -1.4134e+1) (exp 9.2013)) (exp (log (exp (/ (exp (- (* -4.2461 (variable 2.2634 X5)) (- -9.6267e-1 3.3243))) (- (/ (/ (variable 1.0883 X1) (variable 6.9620e-1 X2)) (log 1.3011e+1)) (variable -4.3098e-1 X7)))))))) (log 1.3011e+1))";
+      const string expr2 = "(* (- 1.2175e+1 (+ (/ (/ (+ (variable 3.0140 X9) (variable 1.3430 X8)) -1.0864e+1) (exp 9.2013)) (exp (log (exp (/ (exp (- (* -4.2461 (variable 2.2634 X5)) (- -9.6267e-1 3.3243))) (- (/ (/ (variable 1.0883 X1) (variable 6.9620e-1 X2)) (log 1.3011e+1)) (variable -4.3098e-1 X7)))))))) (exp (variable 4.0899e-1 X7)))";
+
+      TestMatchedNodes(expr1, expr2, 23);
+
+    }
+
+    private void TestMatchedNodes(string expr1, string expr2, int expected) {
+      var t1 = importer.Import(expr1);
+      var t2 = importer.Import(expr2);
+
+      var mapping = busCalculator.ComputeBottomUpMapping(t1.Root, t2.Root);
+      var c = mapping.Count;
+
+      if (c != expected) {
+        throw new Exception("Match count " + c + " is different than expected value " + expected);
+      }
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "long")]
+    public void TestBottomUpSimilarityCalculatorPerformance() {
+      var grammar = new TypeCoherentExpressionGrammar();
+      grammar.ConfigureAsDefaultRegressionGrammar();
+      var twister = new MersenneTwister(31415);
+      var ds = Util.CreateRandomDataset(twister, Rows, Columns);
+      var trees = Util.CreateRandomTrees(twister, ds, grammar, N, 1, 100, 0, 0);
+
+      double s = 0;
+      var sw = new Stopwatch();
+
+      sw.Start();
+      for (int i = 0; i < trees.Length - 1; ++i) {
+        for (int j = i + 1; j < trees.Length; ++j) {
+          s += busCalculator.CalculateSolutionSimilarity(trees[i], trees[j]);
+        }
+      }
+
+      sw.Stop();
+      Console.WriteLine("Elapsed time: " + sw.ElapsedMilliseconds / 1000.0 + ", Avg. similarity: " + s / (N * (N - 1) / 2));
+      Console.WriteLine(N * (N + 1) / (2 * sw.ElapsedMilliseconds / 1000.0) + " similarity calculations per second.");
+    }
+
+    private static string FormatMapping(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> map) {
+      var symbolNameMap = new Dictionary<string, string>
+    {
+      {"ProgramRootSymbol", "Prog"},
+      {"StartSymbol","RPB"},
+      {"Multiplication", "$\\times$"},
+      {"Division", "$\\div$"},
+      {"Addition", "$+$"},
+      {"Subtraction", "$-$"},
+      {"Exponential", "$\\exp$"},
+      {"Logarithm", "$\\log$"}
+    };
+
+      var sb = new StringBuilder();
+      var nodeIds = new Dictionary<ISymbolicExpressionTreeNode, string>();
+      int offset = 0;
+      var layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(x => x.Subtrees);
+      var nodeCoordinates = layoutEngine.CalculateLayout(t1.Root).ToDictionary(n => n.Content, n => new PointF(n.X, n.Y));
+
+      double ws = 0.5;
+      double hs = 0.5;
+
+      var nl = Environment.NewLine;
+      sb.Append("\\documentclass[class=minimal,border=0pt]{standalone}" + nl +
+                 "\\usepackage{tikz}" + nl +
+                 "\\begin{document}" + nl +
+                 "\\begin{tikzpicture}" + nl +
+                 "\\def\\ws{1}" + nl +
+                 "\\def\\hs{0.7}" + nl +
+                 "\\def\\offs{" + offset + "}" + nl);
+
+      foreach (var node in t1.IterateNodesBreadth()) {
+        var id = Guid.NewGuid().ToString();
+        nodeIds[node] = id;
+        var coord = nodeCoordinates[node];
+        var nodeName = symbolNameMap.ContainsKey(node.Symbol.Name) ? symbolNameMap[node.Symbol.Name] : node.ToString();
+        sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\node ({0}) at (\\ws*{1} + \\offs,\\hs*{2}) {{{3}}};", nodeIds[node], ws * coord.X, -hs * coord.Y, EscapeLatexString(nodeName)));
+      }
+
+      foreach (ISymbolicExpressionTreeNode t in t1.IterateNodesBreadth()) {
+        var n = t;
+        foreach (var s in t.Subtrees) {
+          sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\draw ({0}) -- ({1});", nodeIds[n], nodeIds[s]));
+        }
+      }
+
+      nodeCoordinates = layoutEngine.CalculateLayout(t2.Root).ToDictionary(n => n.Content, n => new PointF(n.X, n.Y));
+
+      offset = 20;
+      sb.Append("\\def\\offs{" + offset + "}" + nl);
+      foreach (var node in t2.IterateNodesBreadth()) {
+        var id = Guid.NewGuid().ToString();
+        nodeIds[node] = id;
+        var coord = nodeCoordinates[node];
+        var nodeName = symbolNameMap.ContainsKey(node.Symbol.Name) ? symbolNameMap[node.Symbol.Name] : node.ToString();
+        sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\node ({0}) at (\\ws*{1} + \\offs,\\hs*{2}) {{{3}}};", nodeIds[node], ws * coord.X, -hs * coord.Y, EscapeLatexString(nodeName)));
+      }
+
+      foreach (ISymbolicExpressionTreeNode t in t2.IterateNodesBreadth()) {
+        var n = t;
+        foreach (var s in t.Subtrees) {
+          sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\draw ({0}) -- ({1});", nodeIds[n], nodeIds[s]));
+        }
+      }
+
+      foreach (var p in map) {
+        var id1 = nodeIds[p.Key];
+        var id2 = nodeIds[p.Value];
+
+        sb.Append(string.Format(CultureInfo.InvariantCulture, "\\path[draw,->,color=gray] ({0}) edge[bend left,dashed] ({1});" + Environment.NewLine, id1, id2));
+      }
+      sb.Append("\\end{tikzpicture}" + nl +
+                "\\end{document}" + nl);
+      return sb.ToString();
+    }
+
+    private static string EscapeLatexString(string s) {
+      return s.Replace("\\", "\\\\").Replace("{", "\\{").Replace("}", "\\}").Replace("_", "\\_");
+    }
+  }
+}
Index: /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/HeuristicLab.Tests.csproj
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 11238)
+++ /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 11239)
@@ -97,6 +97,6 @@
   </Choose>
   <ItemGroup>
+    <Compile Include="BottomUpTreeSimilarityCalculatorTest.cs" />
     <Compile Include="MaxCommonSubtreeSimilarityCalculatorTest.cs" />
-    <Compile Include="BottomUpSimilarityCalculatorTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="SymbolicExpressionImporter.cs" />
Index: /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/MaxCommonSubtreeSimilarityCalculatorTest.cs
===================================================================
--- /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/MaxCommonSubtreeSimilarityCalculatorTest.cs	(revision 11239)
+++ /branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/MaxCommonSubtreeSimilarityCalculatorTest.cs	(revision 11239)
@@ -0,0 +1,84 @@
+﻿using System;
+using System.Diagnostics;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Tests;
+using HeuristicLab.Random;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Tests {
+  /// <summary>
+  /// Summary description for MaxCommonSubtreeSimilarityCalculatorTest
+  /// </summary>
+  [TestClass]
+  public class MaxCommonSubtreeSimilarityCalculatorTest {
+    private ISymbolicExpressionTreeNodeSimilarityComparer comparer;
+
+    private const int N = 100;
+    private const int Rows = 1;
+    private const int Columns = 10;
+
+    public MaxCommonSubtreeSimilarityCalculatorTest() {
+      comparer = new SymbolicExpressionTreeNodeSimilarityComparer();
+    }
+
+    private TestContext testContextInstance;
+
+    //    /// <summary>
+    //    ///Gets or sets the test context which provides
+    //    ///information about and functionality for the current test run.
+    //    ///</summary>
+    //    public TestContext TestContext {
+    //      get {
+    //        return testContextInstance;
+    //      }
+    //      set {
+    //        testContextInstance = value;
+    //      }
+    //    }
+
+    #region Additional test attributes
+    //
+    // You can use the following additional attributes as you write your tests:
+    //
+    // Use ClassInitialize to run code before running the first test in the class
+    // [ClassInitialize()]
+    // public static void MyClassInitialize(TestContext testContext) { }
+    //
+    // Use ClassCleanup to run code after all tests in a class have run
+    // [ClassCleanup()]
+    // public static void MyClassCleanup() { }
+    //
+    // Use TestInitialize to run code before running each test 
+    // [TestInitialize()]
+    // public void MyTestInitialize() { }
+    //
+    // Use TestCleanup to run code after each test has run
+    // [TestCleanup()]
+    // public void MyTestCleanup() { }
+    //
+    #endregion
+
+    [TestMethod]
+    public void TestMaxCommonSubtreeSimilarityCalculatorPerformance() {
+      var grammar = new TypeCoherentExpressionGrammar();
+      grammar.ConfigureAsDefaultRegressionGrammar();
+      var twister = new MersenneTwister(31415);
+      var ds = Util.CreateRandomDataset(twister, Rows, Columns);
+      var trees = Util.CreateRandomTrees(twister, ds, grammar, N, 1, 100, 0, 0);
+
+      double s = 0;
+      var sw = new Stopwatch();
+
+      sw.Start();
+      for (int i = 0; i < trees.Length - 1; ++i) {
+        for (int j = i + 1; j < trees.Length; ++j) {
+          s += MaxCommonSubtreeSimilarityCalculator.MaxCommonSubtreeSimilarity(trees[i], trees[j], comparer);
+        }
+      }
+      sw.Stop();
+      Console.WriteLine("Elapsed time: " + sw.ElapsedMilliseconds / 1000.0 + ", Avg. similarity: " + s / (N * (N - 1) / 2));
+      Console.WriteLine(N * (N + 1) / (2 * sw.ElapsedMilliseconds / 1000.0) + " similarity calculations per second.");
+    }
+  }
+}
