Free cookie consent management tool by TermsFeed Policy Generator

Changeset 14426 for branches


Ignore:
Timestamp:
11/28/16 17:51:37 (8 years ago)
Author:
bburlacu
Message:

#1772: QueryMatch: implement more elaborate node comparison (better accuracy when matching schemas).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/QueryMatch.cs

    r14326 r14426  
    2929  // by M. Götz, C. Koch and W. Martens in http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.182.5440
    3030  public class QueryMatch {
    31     public ISymbolicExpressionTreeNodeEqualityComparer Comparer { get; private set; }
     31    public ISymbolicExpressionTreeNodeEqualityComparer EqualityComparer { get; private set; }
    3232    private readonly NodeInfo Inf = new NodeInfo { Index = int.MaxValue };
    3333    private readonly NodeInfo Nil = new NodeInfo { Index = -1 };
     34    private readonly HashSet<string> commutativeSymbols = new HashSet<string> { "Addition", "Multiplication", "Average", "And", "Or", "Xor" };
     35    private readonly ISymbolicExpressionTreeNodeComparer nodeComparer = new SymbolicExpressionTreeNodeComparer();
    3436
    3537    private QueryMatch() { }
     
    4143    public bool MatchParents { get; set; }
    4244
    43     public QueryMatch(ISymbolicExpressionTreeNodeEqualityComparer comparer) {
    44       Comparer = comparer;
     45    public QueryMatch(ISymbolicExpressionTreeNodeEqualityComparer equalityComparer) {
     46      EqualityComparer = equalityComparer;
    4547    }
    4648
     
    5860
    5961    public bool Match(ISymbolicExpressionTreeNode data, ISymbolicExpressionTreeNode query) {
    60       if (!Comparer.Equals(data, query))
     62      if (!EqualityComparer.Equals(data, query))
    6163        return false;
    6264
     
    7274    public IEnumerable<ISymbolicExpressionTree> GetMatchingTrees(IEnumerable<ISymbolicExpressionTree> data, ISymbolicExpressionTree query) {
    7375      var qRoot = query.Root.GetSubtree(0).GetSubtree(0);
    74       var filtered = data.Where(x => x.Length >= query.Length && Comparer.Equals(x.Root.GetSubtree(0).GetSubtree(0), qRoot));
     76      var filtered = data.Where(x => x.Length >= query.Length && EqualityComparer.Equals(x.Root.GetSubtree(0).GetSubtree(0), qRoot));
    7577      var qNodes = InitializePostOrder(query.Root.GetSubtree(0).GetSubtree(0));
    7678      return from d in filtered let dNodes = InitializePostOrder(d.Root.GetSubtree(0).GetSubtree(0)) where Match(dNodes, qNodes) select d;
    7779    }
    7880
    79     private bool AreMatching(NodeInfo a, NodeInfo b) {
     81    private bool AreMatching(NodeInfo d, NodeInfo q) {
    8082      // force the nodes to be on the same level
    81       if (a.Level != b.Level)
    82         return false;
    83 
    84       bool equals = Comparer.Equals(a.Node, b.Node);
    85       if (equals && MatchParents) {
    86         var pa = a.Parent;
    87         var pb = b.Parent;
    88         if (pa == null && pb == null)
    89           return true;
    90         if (pa == null || pb == null)
    91           return false;
    92         return pa.Level == pb.Level && Comparer.Equals(pa.Node, pb.Node);
    93       }
    94       return equals;
     83      if (d.Level != q.Level)
     84        return false;
     85
     86      // compare nodes
     87      bool equals = EqualityComparer.Equals(d.Node, q.Node);
     88
     89      if (!equals)
     90        return false;
     91
     92      // compare node parents
     93      if (MatchParents && !EqualityComparer.Equals(d.Node.Parent, q.Node.Parent))
     94        return false;
     95
     96      // compare children to make sure they are the same
     97      if (d.Node.SubtreeCount > 0 && q.Node.SubtreeCount > 0) {
     98        var dSubtrees = d.Node.Subtrees.ToList();
     99
     100        if (commutativeSymbols.Contains(d.Node.Symbol.Name)) {
     101          var qSubtrees = q.Node.Subtrees.Where(x => !(x is AnyNode || x is AnySubtree)).ToList();
     102
     103          dSubtrees.Sort(nodeComparer);
     104          qSubtrees.Sort(nodeComparer);
     105
     106          var nw = q.Node.SubtreeCount - qSubtrees.Count; // number of wildcards
     107          if (nw == 0)
     108            return dSubtrees.SequenceEqual(qSubtrees, EqualityComparer);
     109
     110          for (int i = 0, j = 0; i < dSubtrees.Count && j < qSubtrees.Count;) {
     111            if (EqualityComparer.Equals(dSubtrees[i], qSubtrees[j])) {
     112              ++i;
     113              ++j;
     114            } else {
     115              if (nw == 0)
     116                return false;
     117              ++i;
     118              --nw;
     119            }
     120          }
     121        } else {
     122          var qSubtrees = q.Node.Subtrees;
     123          return dSubtrees.SequenceEqual(qSubtrees, EqualityComparer);
     124        }
     125      }
     126      return true;
    95127    }
    96128
     
    167199        if (n != nodes.Last()) n.Next = nodes[n.Index + 1];
    168200        if (n != nodes.First()) n.Previous = nodes[n.Index - 1];
    169         NodeInfo parentInfo;
    170         map.TryGetValue(n.Node.Parent, out parentInfo);
     201        NodeInfo parentInfo = null;
     202        if (n.Node.Parent != null)
     203          map.TryGetValue(n.Node.Parent, out parentInfo);
    171204        n.Parent = parentInfo;
    172205        if (n.Parent == null) {
Note: See TracChangeset for help on using the changeset viewer.