Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeMatching.cs @ 8423

Last change on this file since 8423 was 8213, checked in by bburlacu, 12 years ago

#1772: Performance improvements for the GenealogyGraph. Minor refactoring to VisualGenealogyGraphArc and VisualGenealogyGraphNode classes. Added new functionality to the SymbolicExpressionTreeFragmentsAnalyzer, minor refactoring in the other two analyzers. Refactored View code. Updated project references and plugin dependencies and added HeuristicLab.Problems.DataAnalysis.Symbolic to the branch.

File size: 6.5 KB
Line 
1using System.Collections.Generic;
2using System.Linq;
3using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
4
5namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
6  public class SymbolicExpressionTreeNodeSimilarityComparer : IEqualityComparer<ISymbolicExpressionTreeNode> {
7
8    public SymbolicExpressionTreeNodeSimilarityComparer(int similarityLevel) {
9      _similarityLevel = similarityLevel;
10    }
11
12    public int GetHashCode(ISymbolicExpressionTreeNode n) {
13      return n.ToString().ToLower().GetHashCode();
14    }
15
16    public bool Equals(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
17      if (a.SubtreeCount != b.SubtreeCount) { return false; }
18      if (a.SubtreeCount > 0) { return a.Symbol.ToString().Equals(b.Symbol.ToString()); }
19      // compare leaf nodes according to desired similarity level
20      switch (_similarityLevel) {
21        case ((int)SymbolicExpressionTreeMatching.SimilarityLevel.Exact):
22          if (a is ConstantTreeNode && b is ConstantTreeNode) {
23            return ((ConstantTreeNode)a).Value.Equals(((ConstantTreeNode)b).Value);
24          }
25          if (a is VariableTreeNode && b is VariableTreeNode) {
26            return (a as VariableTreeNode).Weight.Equals((b as VariableTreeNode).Weight);
27          }
28          return false;
29
30        case ((int)SymbolicExpressionTreeMatching.SimilarityLevel.High):
31          return (a is ConstantTreeNode && b is ConstantTreeNode) || (a is VariableTreeNode && b is VariableTreeNode);
32
33        case ((int)SymbolicExpressionTreeMatching.SimilarityLevel.Relaxed):
34          return true;
35
36        default:
37          return false;
38      }
39    }
40
41    private readonly int _similarityLevel;
42  }
43
44  public class SymbolicExpressionTreeNodeOrderingComparer : IComparer<ISymbolicExpressionTreeNode> {
45    public int Compare(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
46      if (a is ConstantTreeNode) {
47        if (b is ConstantTreeNode)
48          return a.Symbol.ToString().Equals(b.Symbol.ToString()) ?
49            (a as ConstantTreeNode).Value.CompareTo((b as ConstantTreeNode).Value) : System.String.Compare(a.Symbol.ToString(), b.Symbol.ToString());
50        return -1; // if b is not constant then we consider a < b because by convention Constant < Variable < Function
51      }
52      if (a is VariableTreeNode) {
53        if (b is ConstantTreeNode)
54          return 1;
55        if (b is VariableTreeNode)
56          return a.Symbol.ToString().Equals(b.Symbol.ToString()) ?
57            (a as VariableTreeNode).Weight.CompareTo((b as VariableTreeNode).Weight) : System.String.Compare(a.Symbol.ToString(), b.Symbol.ToString());
58        return -1;
59      }
60      if (b is ConstantTreeNode || b is VariableTreeNode)
61        return 1; // a is a Function node and is greater than Constants or Variables
62
63      return a.Symbol.ToString().Equals(b.Symbol.ToString()) ? a.SubtreeCount.CompareTo(b.SubtreeCount) : System.String.Compare(a.Symbol.ToString(), b.Symbol.ToString());
64    }
65  }
66
67  // tree equality
68  public class SymbolicExpressionTreeEqualityComparer : IEqualityComparer<ISymbolicExpressionTree> {
69    public bool Equals(ISymbolicExpressionTree a, ISymbolicExpressionTree b) {
70      return SymbolicExpressionTreeMatching.FindMatch(a, b, _mode) == 0;
71    }
72
73    public int GetHashCode(ISymbolicExpressionTree tree) {
74      return tree.Length;
75    }
76
77    private int _mode;
78    public void SetComparisonMode(int mode) {
79      _mode = mode;
80    }
81  }
82
83  public static class SymbolicExpressionTreeMatching {
84    public enum SimilarityLevel {
85      Exact,   // everything is matched bit by bit (functions and terminals)
86      High,    // symbols are matched. leaf node types are matched
87      Relaxed  // only symbols are matched, leafs count as wildcards
88    }
89
90    public static bool IsSimilarTo(this ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, int mode) {
91      return FindMatch(t1, t2, mode) == 0;
92    }
93    public static bool IsSimilarTo(this ISymbolicExpressionTreeNode t1, ISymbolicExpressionTreeNode t2, int mode) {
94      return FindMatch(t1, t2, mode) == 0;
95    }
96
97    public static bool ContainsFragment(this ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode fragment, int mode) {
98      var nodes = tree.IterateNodesPostfix() as List<ISymbolicExpressionTreeNode>;
99      var fragments = fragment.IterateNodesPostfix() as List<ISymbolicExpressionTreeNode>;
100      return FindMatch(nodes, fragments, mode) != -1;
101    }
102
103    public static void SortSubtrees(this ISymbolicExpressionTree tree) {
104      SortSubtrees(tree.Root);
105    }
106
107    public static void SortSubtrees(this ISymbolicExpressionTreeNode node) {
108      if (node.SubtreeCount > 0) {
109        var subtrees = node.Subtrees as List<ISymbolicExpressionTreeNode>;
110        if (subtrees == null) return;
111        subtrees.Sort(new SymbolicExpressionTreeNodeOrderingComparer());
112        foreach (var subtree in subtrees)
113          subtree.SortSubtrees();
114      }
115    }
116
117    public static int FindMatch(ISymbolicExpressionTree a, ISymbolicExpressionTree b, int mode) {
118      var nodesA = a.IterateNodesPostfix() as List<ISymbolicExpressionTreeNode>;
119      var nodesB = b.IterateNodesPostfix() as List<ISymbolicExpressionTreeNode>;
120      return FindMatch(nodesA, nodesB, mode);
121    }
122    public static int FindMatch(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, int mode) {
123      var nodesA = a.IterateNodesPostfix() as List<ISymbolicExpressionTreeNode>;
124      var nodesB = b.IterateNodesPostfix() as List<ISymbolicExpressionTreeNode>;
125      return FindMatch(nodesA, nodesB, mode);
126    }
127    // returns the index in the sequence 'seq', where pattern 'pat' is matched, or -1 for no match
128    // -1 means no match, 0 means perfect match (the sequences overlap, hence the match index is 0)
129    public static int FindMatch(List<ISymbolicExpressionTreeNode> seq, List<ISymbolicExpressionTreeNode> pat, int mode) {
130      int patlen = pat.Count;
131      int seqlen = seq.Count;
132      if (patlen == 0 || seqlen == 0) return -1;
133      var comparer = new SymbolicExpressionTreeNodeSimilarityComparer(mode);
134      if (patlen == seqlen) return seq.SequenceEqual(pat, comparer) ? 0 : -1;
135      for (int i = patlen; i <= seqlen; ++i) {
136        if (comparer.Equals(seq[i - 1], pat.Last())) // first check if last element is a match
137          if (seq.Skip(i - patlen).Take(patlen).SequenceEqual(pat, comparer)) // then check the whole sequence
138            return i - patlen;
139      }
140      return -1;
141    }
142  }
143}
Note: See TracBrowser for help on using the repository browser.