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 12894)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 12929)
@@ -184,4 +184,8 @@
     <Compile Include="Analyzers\SymbolicDataAnalysisBottomUpDiversityAnalyzer.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisGeneticOperatorImprovementAnalyzer.cs" />
+    <Compile Include="Symbols\Wildcards\AnyNode.cs" />
+    <Compile Include="Symbols\Wildcards\AnySubtreeSymbol.cs" />
+    <Compile Include="Symbols\Wildcards\AnySubtree.cs" />
+    <Compile Include="Symbols\Wildcards\AnyNodeSymbol.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisGenealogyAnalyzer.cs" />
@@ -318,4 +322,5 @@
     <Compile Include="Tracking\TraceCalculator.cs" />
     <Compile Include="TransformationToSymbolicTreeMapper.cs" />
+    <Compile Include="TreeMatching\QueryMatch.cs" />
     <Compile Include="TreeMatching\SymbolicExpressionTreeBottomUpSimilarityCalculator.cs" />
     <Compile Include="TreeMatching\SymbolicExpressionTreeCanonicalSorter.cs" />
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnyNode.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnyNode.cs	(revision 12929)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnyNode.cs	(revision 12929)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  public class AnyNode : SymbolicExpressionTreeNode {
+    protected AnyNode(bool deserializing) : base(deserializing) { }
+
+    protected AnyNode(AnyNode original, Cloner cloner) : base(original, cloner) { }
+
+    public AnyNode(AnyNodeSymbol symbol) : base(symbol) { }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnyNodeSymbol.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnyNodeSymbol.cs	(revision 12929)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnyNodeSymbol.cs	(revision 12929)
@@ -0,0 +1,58 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("AnyNodeSymbol", "A symbol that represents a '=' wildcard that can match any node of the same type (function or leaf)")]
+  public class AnyNodeSymbol : Symbol {
+    public AnyNodeSymbol(bool deserializing) : base(deserializing) { }
+
+    public AnyNodeSymbol(Symbol original, Cloner cloner) : base(original, cloner) { }
+
+    public AnyNodeSymbol(string name, string description) : base(name, description) { }
+
+    protected AnyNodeSymbol(AnyNodeSymbol original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AnyNodeSymbol(this, cloner);
+    }
+
+    private AnyNodeSymbol() : base("=", "A wildcard symbol that can match any node of the same type (function or leaf node)") { }
+
+    public AnyNodeSymbol(int minimumArity, int maximumArity)
+      : base("=", "A wildcard symbol that can match any node of the same type (function or leaf node)") {
+      MinimumArity = minimumArity;
+      MaximumArity = maximumArity;
+    }
+
+    public override ISymbolicExpressionTreeNode CreateTreeNode() {
+      return new AnyNode(this);
+    }
+
+    public override int MinimumArity { get; }
+    public override int MaximumArity { get; }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnySubtree.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnySubtree.cs	(revision 12929)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnySubtree.cs	(revision 12929)
@@ -0,0 +1,38 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  public class AnySubtree : SymbolicExpressionTreeNode {
+    protected AnySubtree(bool deserializing) : base(deserializing) {
+    }
+
+    protected AnySubtree(AnySubtree original, Cloner cloner) : base(original, cloner) {
+    }
+
+    public AnySubtree(AnySubtreeSymbol symbol) : base(symbol) {
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnySubtreeSymbol.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnySubtreeSymbol.cs	(revision 12929)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Wildcards/AnySubtreeSymbol.cs	(revision 12929)
@@ -0,0 +1,52 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("AnyNodeSymbol", "A symbol that represents a '=' wildcard that can match any node of the same type (function or leaf)")]
+  public class AnySubtreeSymbol : Symbol {
+    public AnySubtreeSymbol(bool deserializing) : base(deserializing) { }
+
+    public AnySubtreeSymbol(Symbol original, Cloner cloner) : base(original, cloner) { }
+
+    public AnySubtreeSymbol(string name, string description) : base(name, description) { }
+
+    protected AnySubtreeSymbol(AnySubtreeSymbol original, Cloner cloner) : base(original, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AnySubtreeSymbol(this, cloner);
+    }
+
+    public AnySubtreeSymbol() : base("#", "A wildcard symbol that can match any valid subtree") { }
+
+    public override ISymbolicExpressionTreeNode CreateTreeNode() {
+      return new AnySubtree(this);
+    }
+
+    public override int MinimumArity { get; }
+    public override int MaximumArity { get; }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/QueryMatch.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/QueryMatch.cs	(revision 12929)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/QueryMatch.cs	(revision 12929)
@@ -0,0 +1,310 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  // this class implements the decision version of the tree pattern query matching algorithm 
+  // by M. Götz, C. Koch and W. Martens in http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.182.5440
+  public class QueryMatch {
+    private List<NodeInfo> dNodes;
+    private List<NodeInfo> qNodes;
+    private readonly ISymbolicExpressionTreeNodeEqualityComparer comparer;
+
+    private QueryMatch() { }
+
+    private readonly Stack<string> stack = new Stack<string>();
+
+    public string Trace {
+      get {
+        var sb = new StringBuilder();
+        while (stack.Count > 0)
+          sb.Append(stack.Pop());
+        return sb.ToString();
+      }
+    }
+
+    public QueryMatch(ISymbolicExpressionTreeNodeEqualityComparer comparer) {
+      this.comparer = comparer;
+    }
+
+    public bool Match(ISymbolicExpressionTreeNode data, ISymbolicExpressionTreeNode query) {
+      stack.Clear();
+      dNodes = InitializePostOrder(data);
+      qNodes = InitializePostOrder(query);
+
+      var dRoot = dNodes.Last();
+      var qRoot = qNodes.Last();
+      var result = Tmatch(dRoot, qNodes.First(), qNodes.Last());
+      return result == qRoot;
+    }
+
+    private List<NodeInfo> InitializePostOrder(ISymbolicExpressionTreeNode node) {
+      var list = node.IterateNodesPostfix().Select((x, i) => new NodeInfo(x, i)).ToList();
+      foreach (var l in list)
+        l.Nodes = list;
+
+      return list;
+    }
+
+    private NodeInfo Tmatch(NodeInfo d, NodeInfo qFrom, NodeInfo qUntil, int tab = 0) {
+#if DEBUG
+      var sb = new StringBuilder();
+#endif
+      NodeInfo qBest = d.IsLeaf ? qFrom.Previous() : Hmatch(d.LastChild(), qFrom, qUntil, tab + 1);
+
+      var next = qBest.Next();
+      if (next.Index <= qUntil.Index && comparer.Equals(d.Node, next.Node)) {
+        qBest = next;
+        next = qBest.Next();
+        var lastSibling = qBest.LastSibling();
+        var result = next.Index <= lastSibling.Index ? Tmatch(d, next, lastSibling, tab + 1) : qBest;
+#if DEBUG
+        for (int i = 0; i < tab; ++i)
+          sb.Append("\t");
+        sb.AppendLine(string.Format("TM(d{0}, q{1}, q{2}) => q{3}", d.Index, qFrom.Index, qUntil.Index, result.Index));
+        stack.Push(sb.ToString());
+#endif
+        return result;
+      }
+#if DEBUG
+      for (int i = 0; i < tab; ++i)
+        sb.Append("\t");
+      sb.AppendLine(string.Format("TM(d{0}, q{1}, q{2}) => q{3}", d.Index, qFrom.Index, qUntil.Index, qBest.Index));
+      stack.Push(sb.ToString());
+#endif
+      return qBest;
+    }
+
+    private NodeInfo Hmatch(NodeInfo d, NodeInfo qFrom, NodeInfo qUntil, int tab = 0) {
+#if DEBUG
+      var sb = new StringBuilder();
+#endif
+      if (d.IsFirstSibling) {
+        var result = Tmatch(d, qFrom, qUntil, tab + 1);
+#if DEBUG
+        for (int i = 0; i < tab; ++i)
+          sb.Append("\t");
+        sb.AppendLine(string.Format("HM(d{0}, q{1}, q{2}) => q{3}", d.Index, qFrom.Index, qUntil.Index, result.Index));
+        stack.Push(sb.ToString());
+#endif
+        return result;
+      }
+
+      var qHedge = Hmatch(d.PreviousSibling(), qFrom, qUntil, tab + 1);
+      var qTree = Tmatch(d, qFrom, qUntil, tab + 1);
+
+      for (;;) {
+        if (qHedge == qTree) {
+#if DEBUG
+          for (int i = 0; i < tab; ++i)
+            sb.Append("\t");
+          sb.AppendLine(string.Format("HM(d{0}, q{1}, q{2}) => q{3}", d.Index, qFrom.Index, qUntil.Index, qHedge.Index));
+          stack.Push(sb.ToString());
+#endif
+          return qHedge;
+        }
+        if (qTree.Index < qHedge.Index) {
+          var rtop = Rtop(qTree.Next(), qHedge, tab);
+          while (rtop.Index < qHedge.Next().Index && qHedge.Index < rtop.LastSibling().Index) {
+            qTree = Tmatch(d, rtop.Next(), rtop.LastSibling(), tab + 1);
+            rtop = Rtop(qTree.Next(), qHedge, tab);
+          }
+          if (qTree.Index <= qHedge.Index) {
+#if DEBUG
+            for (int i = 0; i < tab; ++i)
+              sb.Append("\t");
+            sb.AppendLine(string.Format("HM(d{0}, q{1}, q{2}) => q{3}", d.Index, qFrom.Index, qUntil.Index, qHedge.Index));
+            stack.Push(sb.ToString());
+#endif
+            return qHedge;
+          }
+        } else {
+          var rtop = Rtop(qHedge.Next(), qTree, tab);
+          while (rtop.Index < qTree.Next().Index && qTree.Index < rtop.LastSibling().Index) {
+            qHedge = Hmatch(d.PreviousSibling(), rtop.Next(), rtop.LastSibling(), tab + 1);
+            rtop = Rtop(qHedge.Next(), qTree, tab);
+          }
+          if (qHedge.Index <= qTree.Index) {
+#if DEBUG
+            for (int i = 0; i < tab; ++i)
+              sb.Append("\t");
+            sb.AppendLine(string.Format("HM(d{0}, q{1}, q{2}) => q{3}", d.Index, qFrom.Index, qUntil.Index, qTree.Index));
+            stack.Push(sb.ToString());
+#endif
+            return qTree;
+          }
+        }
+      }
+    }
+
+    // returns the rightmost node from the topmost nodes in the interval [hFrom, hUntil]
+    private NodeInfo Rtop(NodeInfo hFrom, NodeInfo hUntil, int tab = 0) {
+#if DEBUG
+      var sb = new StringBuilder();
+      for (int i = 0; i < tab; ++i)
+        sb.Append("\t");
+      sb.Append(string.Format("Rtop(q{0}, q{1})", hFrom.Index, hUntil.Index));
+#endif
+
+      if (hFrom == hUntil) {
+#if DEBUG
+        sb.AppendLine(string.Format(" => q{0}", hUntil.Index));
+        stack.Push(sb.ToString());
+#endif
+        return hUntil;
+      }
+
+      if (hFrom.Nodes != hUntil.Nodes)
+        throw new ArgumentException("hFrom and hUntil must belong to the same tree/hedge");
+
+
+      NodeInfo rtop = null;
+      if (hFrom.Index > hUntil.Index) {
+        rtop = hFrom.Next(); // or return inf (inf is defined in the paper as the successor of the largest node in the hedge)
+#if DEBUG
+        sb.AppendLine(string.Format(" => q{0}", rtop.Index));
+        stack.Push(sb.ToString());
+#endif
+        return rtop;
+      }
+
+      // let u be the highest ancestor of hUntil that has a previous sibling s such that s >= hFrom
+      // if no such u exists, then Rtop(hFrom, hUntil) = hUntil. Otherwise, rtop(hFrom, hUntil) = s
+      var p = hUntil.Parent();
+      if (p == null)
+        return hUntil;
+      List<NodeInfo> ancestors = hUntil.Ancestors().ToList();
+      // ancestors list is ordered in decreasing depth therefore we start from the end
+      for (int i = ancestors.Count - 1; i >= 0; --i) {
+        var s = ancestors[i].PreviousSibling();
+        if (s.Index >= hFrom.Index) {
+          rtop = s;
+          break;
+        }
+      }
+      if (rtop == null)
+        rtop = hUntil;
+#if DEBUG
+      sb.AppendLine(string.Format(" => q{0}", rtop.Index));
+      stack.Push(sb.ToString());
+#endif
+      return rtop;
+    }
+
+    private class NodeInfo {
+      private NodeInfo() { }
+
+      public NodeInfo(ISymbolicExpressionTreeNode n, int i) {
+        Node = n;
+        Index = i;
+      }
+
+      public List<NodeInfo> Nodes { get; set; }
+      public ISymbolicExpressionTreeNode Node { get; }
+      public int Index { get; }
+
+      public bool IsLeaf {
+        get { return Node.SubtreeCount == 0; }
+      }
+
+      public bool IsFirstSibling {
+        get { return this.Node == this.Node.Parent.Subtrees.First(); }
+      }
+
+      public IEnumerable<NodeInfo> Ancestors() {
+        var p = Parent();
+        while (p != null) {
+          yield return p;
+          p = p.Parent();
+        }
+      }
+
+      public NodeInfo Parent() {
+        var p = Node.Parent;
+        if (p == null || p.Symbol is StartSymbol)
+          return null;
+        var index = Index + 1;
+        for (int i = p.SubtreeCount - 1; i >= 0; --i) {
+          var subtree = p.GetSubtree(i);
+          if (subtree == Node)
+            break;
+          index += subtree.GetLength();
+        }
+        return Nodes[index];
+      }
+
+      public NodeInfo Next() {
+        if (this == Nodes.Last())
+          return new NodeInfo(null, int.MaxValue) { Nodes = Nodes };
+        return Nodes[Index + 1];
+      }
+
+      public NodeInfo NextSibling() {
+        if (Node.Parent == null || Node == Node.Parent.Subtrees.Last())
+          return new NodeInfo(null, -1);
+
+        var s = Node.Parent.GetSubtree(Node.Parent.IndexOfSubtree(Node) + 1);
+        var nextSibling = Nodes[Index + s.GetLength()];
+        return nextSibling;
+      }
+
+      public NodeInfo LastSibling() {
+        if (Node.Parent == null)
+          return new NodeInfo(null, -1);
+
+        var last = Node.Parent.Subtrees.Last();
+        if (this.Node == last)
+          return this;
+
+        var n = this;
+        while (n.Node != last)
+          n = n.NextSibling();
+        return n;
+      }
+
+      public NodeInfo Previous() {
+        if (this == Nodes.First())
+          return new NodeInfo(null, -1) { Nodes = Nodes }; // return nil
+
+        return Nodes[Index - 1];
+      }
+
+      public NodeInfo PreviousSibling() {
+        if (Node.Parent == null || Node == Node.Parent.Subtrees.First())
+          return new NodeInfo(null, -1) { Nodes = Nodes };
+        var previousSibling = Nodes[Index - Node.GetLength()];
+        return previousSibling;
+      }
+
+      public NodeInfo LastChild() {
+        var nil = new NodeInfo(null, -1);
+        if (IsLeaf)
+          return nil;
+        return Previous();
+      }
+    }
+  }
+}
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMatching.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMatching.cs	(revision 12894)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMatching.cs	(revision 12929)
@@ -54,4 +54,10 @@
     public static int Match(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, ISymbolicExpressionTreeNodeEqualityComparer comp) {
       if (!comp.Equals(a, b)) return 0;
+      // AnySubtree wildcards mach everything
+      if (a is AnySubtree)
+        return b.GetLength();
+      if (b is AnySubtree)
+        return a.GetLength();
+
       int m = a.SubtreeCount;
       int n = b.SubtreeCount;
Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeEqualityComparer.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeEqualityComparer.cs	(revision 12894)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeEqualityComparer.cs	(revision 12929)
@@ -76,20 +76,42 @@
 
     public bool Equals(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
-      if (!(a is SymbolicExpressionTreeTerminalNode))
-        // if a and b are non terminal nodes, check equality of symbol names
-        return !(b is SymbolicExpressionTreeTerminalNode) && a.Symbol.Name.Equals(b.Symbol.Name);
-      var va = a as VariableTreeNode;
-      if (va != null) {
+      var sa = a as AnySubtree;
+      var sb = b as AnySubtree;
+
+      if (sa != null || sb != null)
+        return true;
+
+      if (a.SubtreeCount != b.SubtreeCount)
+        return false;
+
+      var na = a as AnyNode;
+      var nb = b as AnyNode;
+      if (na != null || nb != null)
+        return true;
+
+      var ta = a as SymbolicExpressionTreeTerminalNode;
+      var tb = b as SymbolicExpressionTreeTerminalNode;
+      if (ta != null && tb != null) {
+        var ca = a as ConstantTreeNode;
+        var cb = b as ConstantTreeNode;
+        if (ca != null && cb != null)
+          // both a and b are constants
+          return !MatchConstantValues || ca.Value.Equals(cb.Value);
+
+        var va = a as VariableTreeNode;
         var vb = b as VariableTreeNode;
-        if (vb == null) return false;
+        if (va != null && vb != null) {
+          // both a and b are variables
+          bool m1 = !MatchVariableNames || va.VariableName.Equals(vb.VariableName);
+          bool m2 = !MatchVariableWeights || va.Weight.IsAlmost(vb.Weight);
+          return m1 && m2;
+        }
+      }
+      if (ta == null && tb == null) {
+        // both a and b are non-terminal (function) nodes
+        return a.Symbol.Name.Equals(b.Symbol.Name);
+      }
 
-        return (!MatchVariableNames || va.VariableName.Equals(vb.VariableName)) && (!MatchVariableWeights || va.Weight.Equals(vb.Weight));
-      }
-      var ca = a as ConstantTreeNode;
-      if (ca != null) {
-        var cb = b as ConstantTreeNode;
-        if (cb == null) return false;
-        return (!MatchConstantValues || ca.Value.Equals(cb.Value));
-      }
+      // return false in all other cases
       return false;
     }
