Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
10/07/16 00:04:21 (8 years ago)
Author:
bburlacu
Message:

#1772: Refactor QueryMatch class to make the code more readable and easier to understand.

File:
1 edited

Legend:

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

    r13877 r14326  
    2020#endregion
    2121
     22using System;
    2223using System.Collections.Generic;
    2324using System.Linq;
     
    2829  // by M. Götz, C. Koch and W. Martens in http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.182.5440
    2930  public class QueryMatch {
    30     public ISymbolicExpressionTreeNodeEqualityComparer Comparer { get; }
     31    public ISymbolicExpressionTreeNodeEqualityComparer Comparer { get; private set; }
     32    private readonly NodeInfo Inf = new NodeInfo { Index = int.MaxValue };
     33    private readonly NodeInfo Nil = new NodeInfo { Index = -1 };
    3134
    3235    private QueryMatch() { }
     
    3942
    4043    public QueryMatch(ISymbolicExpressionTreeNodeEqualityComparer comparer) {
    41       this.Comparer = comparer;
     44      Comparer = comparer;
    4245    }
    4346
     
    9396
    9497    private NodeInfo Tmatch(NodeInfo d, NodeInfo qFrom, NodeInfo qUntil) {
    95       NodeInfo qBest = d.IsLeaf ? qFrom.Previous : Hmatch(d.LastChild, qFrom, qUntil);
     98      var qBest = d.IsLeaf ? qFrom.Previous : Hmatch(d.LastChild, qFrom, qUntil);
    9699      var next = qBest.Next;
    97       if (next.Index <= qUntil.Index && AreMatching(d, next)) {
     100      if (next <= qUntil && AreMatching(d, next)) {
    98101        qBest = next;
    99102        next = qBest.Next;
    100103        var lastSibling = qBest.LastSibling;
    101         return next.Index <= lastSibling.Index ? Tmatch(d, next, lastSibling) : qBest;
     104        return next <= lastSibling ? Tmatch(d, next, lastSibling) : qBest;
    102105      }
    103106      return qBest;
     
    114117        if (qHedge == qTree)
    115118          return qHedge;
    116         if (qTree.Index < qHedge.Index) {
     119        if (qTree < qHedge) {
    117120          var rtop = Rtop(qTree.Next, qHedge);
    118           while (rtop.Index < int.MaxValue && qHedge.Index < rtop.LastSibling.Index) {
     121          while (rtop < Inf && qHedge < rtop.LastSibling) {
    119122            qTree = Tmatch(d, rtop.Next, rtop.LastSibling);
    120123            rtop = Rtop(qTree.Next, qHedge);
    121124          }
    122           if (qTree.Index <= qHedge.Index)
     125          if (qTree <= qHedge)
    123126            return qHedge;
    124127        } else {
    125128          var rtop = Rtop(qHedge.Next, qTree);
    126           while (rtop.Index < int.MaxValue && qTree.Index < rtop.LastSibling.Index) {
     129          while (rtop < Inf && qTree < rtop.LastSibling) {
    127130            qHedge = Hmatch(d.PreviousSibling, rtop.Next, rtop.LastSibling);
    128131            rtop = Rtop(qHedge.Next, qTree);
    129132          }
    130           if (qHedge.Index <= qTree.Index)
     133          if (qHedge <= qTree)
    131134            return qTree;
    132135        }
     
    134137    }
    135138
    136     // returns the rightmost node from the topmost nodes in the interval [hFrom, hUntil]
     139    /// <summary>
     140    /// Description from Götz et al. - Efficient Algorithms for Descendant-only Tree Pattern Queries, 2009:
     141    /// Given two nodes hFrom and hUntil, returns the rightmost node among the topmost nodes in the interval [hFrom, hUntil]
     142    /// More formally, Rtop(hFrom,hUntil) is the node u such that depth(u) is minimal and u is larger than every other node v
     143    /// in [hFrom, hUntil] with depth(u)==depth(v).
     144    /// </summary>
     145    /// <param name="hFrom">The interval start</param>
     146    /// <param name="hUntil">The interval end</param>
     147    /// <returns>The rightmost node from the topmost nodes in the interval [hFrom, hUntil]</returns>
    137148    private NodeInfo Rtop(NodeInfo hFrom, NodeInfo hUntil) {
    138149      if (hFrom == hUntil)
    139150        return hUntil;
    140151      if (hFrom.Index > hUntil.Index)
    141         return new NodeInfo { Node = null, Index = int.MaxValue };
     152        return Inf;
    142153      // let u be the highest ancestor of hUntil that has a previous sibling s such that s >= hFrom
    143154      // if no such u exists, then Rtop(hFrom, hUntil) = hUntil. Otherwise, rtop(hFrom, hUntil) = s
    144       NodeInfo rtop = null;
    145       List<NodeInfo> ancestors = hUntil.Ancestors.ToList();
    146       // ancestors list is ordered in decreasing depth therefore we start from the end
    147       for (int i = ancestors.Count - 1; i >= 0; --i) {
    148         if (ancestors[i].Parent == null || ancestors[i].IsFirstSibling)
    149           continue;
    150         var s = ancestors[i].PreviousSibling;
    151         if (s != null && s.Index >= hFrom.Index) {
    152           rtop = s;
    153           break;
    154         }
    155       }
     155      var rtop = hUntil.Ancestors.OrderBy(x => x.Level).Select(x => x.PreviousSibling).FirstOrDefault(x => x != null && x >= hFrom);
    156156      return rtop ?? hUntil;
    157157    }
    158158
    159159    internal static List<NodeInfo> InitializePostOrder(ISymbolicExpressionTreeNode node) {
     160      // levels will be computed below
    160161      var nodes = node.IterateNodesPostfix().Select((x, i) => new NodeInfo { Node = x, Index = i, Level = 0 }).ToList();
    161162      var map = nodes.ToDictionary(x => x.Node, x => x);
    162 
    163       var inf = new NodeInfo { Node = null, Index = int.MaxValue, Previous = nodes.Last() };
    164       var nil = new NodeInfo { Node = null, Index = -1, Next = nodes.First() };
    165 
     163      nodes.First().Previous = new NodeInfo { Node = null, Index = -1, Next = nodes.First() };
     164      nodes.Last().Next = new NodeInfo { Node = null, Index = int.MaxValue, Previous = nodes.Last() };
    166165      for (int i = nodes.Count - 1; i >= 0; --i) {
    167166        var n = nodes[i];
    168         n.Parent = n.Node.Parent != null && map.ContainsKey(n.Node.Parent) ? map[n.Node.Parent] : null;
    169         n.Level = n.Parent?.Level + 1 ?? -1;
    170         n.Next = n == nodes.Last() ? inf : nodes[n.Index + 1];
    171         n.Previous = n == nodes.First() ? nil : nodes[n.Index - 1];
     167        if (n != nodes.Last()) n.Next = nodes[n.Index + 1];
     168        if (n != nodes.First()) n.Previous = nodes[n.Index - 1];
     169        NodeInfo parentInfo;
     170        map.TryGetValue(n.Node.Parent, out parentInfo);
     171        n.Parent = parentInfo;
    172172        if (n.Parent == null) {
    173           n.PreviousSibling = n.NextSibling = null;
    174           n.LastSibling = nil;
     173          n.PreviousSibling = n.NextSibling = n.LastSibling = null;
    175174        } else {
    176175          var parent = n.Parent.Node;
     
    179178          n.NextSibling = n.IsLastSibling ? null : map[parent.GetSubtree(si + 1)];
    180179          n.LastSibling = map[parent.Subtrees.Last()];
     180          n.Level = n.Parent.Level + 1;
    181181        }
    182182        n.LastChild = n.IsLeaf ? null : n.Previous;
     
    186186  }
    187187
    188   internal class NodeInfo {
     188  /// <summary>
     189  /// NodeInfo objects are useful for keeping sibling, parent, index and depth information for tree nodes
     190  /// </summary>
     191  internal class NodeInfo : IComparable<NodeInfo> {
    189192    public ISymbolicExpressionTreeNode Node { get; set; }
    190193    public int Index { get; set; }
     
    219222      }
    220223    }
     224
     225    public int CompareTo(NodeInfo other) {
     226      return other == null ? 1 : Index.CompareTo(other.Index);
     227    }
     228
     229    public static bool operator <(NodeInfo lsh, NodeInfo rhs) {
     230      return lsh.CompareTo(rhs) == -1;
     231    }
     232
     233    public static bool operator >(NodeInfo lhs, NodeInfo rhs) {
     234      return lhs.CompareTo(rhs) == 1;
     235    }
     236
     237    public static bool operator <=(NodeInfo lhs, NodeInfo rhs) {
     238      return lhs.CompareTo(rhs) <= 0;
     239    }
     240
     241    public static bool operator >=(NodeInfo lhs, NodeInfo rhs) {
     242      return lhs.CompareTo(rhs) >= 0;
     243    }
    221244  }
    222245}
Note: See TracChangeset for help on using the changeset viewer.