Changeset 8557 for branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Problems.DataAnalysis.Symbolic
- Timestamp:
- 09/03/12 15:26:04 (12 years ago)
- Location:
- branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
r8213 r8557 169 169 </ItemGroup> 170 170 <ItemGroup> 171 <Compile Include="Analyzers\SymbolicDataAnalysisComplexityAnalyzer.cs" /> 171 172 <Compile Include="Analyzers\SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs" /> 172 173 <Compile Include="Analyzers\SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs" /> -
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeMatching.cs
r8213 r8557 1 using System.Collections.Generic; 1 using System; 2 using System.Collections.Generic; 3 using System.IO; 2 4 using System.Linq; 5 using HeuristicLab.Common; 6 using HeuristicLab.Core; 3 7 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 8 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; 4 9 5 10 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 6 public class SymbolicExpressionTreeNodeSimilarityComparer : IEqualityComparer<ISymbolicExpressionTreeNode> { 7 8 public SymbolicExpressionTreeNodeSimilarityComparer(int similarityLevel) { 9 _similarityLevel = similarityLevel; 11 public enum SimilarityLevel { 12 Exact, // everything is matched bit by bit (functions and terminals) 13 High, // symbols are matched. leaf node types are matched 14 Relaxed // only symbols are matched, leafs count as wildcards 15 } 16 [Item("SymbolicExpressionTreeNodeSimilarityComparer", "A comparison operator that checks node equality based on different similarity measures.")] 17 [StorableClass] 18 public class SymbolicExpressionTreeNodeSimilarityComparer : Item, ISymbolicExpressionTreeNodeComparer { 19 [StorableConstructor] 20 private SymbolicExpressionTreeNodeSimilarityComparer(bool deserializing) : base(deserializing) { } 21 private SymbolicExpressionTreeNodeSimilarityComparer(SymbolicExpressionTreeNodeSimilarityComparer original, Cloner cloner) : base(original, cloner) { } 22 public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicExpressionTreeNodeSimilarityComparer(this, cloner); } 23 24 private SimilarityLevel similarityLevel; 25 public SimilarityLevel SimilarityLevel { 26 get { return similarityLevel; } 27 set { similarityLevel = value; } 28 } 29 30 public SymbolicExpressionTreeNodeSimilarityComparer() { 31 this.similarityLevel = SimilarityLevel.Exact; 32 } 33 34 public SymbolicExpressionTreeNodeSimilarityComparer(SimilarityLevel similarityLevel) { 35 this.similarityLevel = similarityLevel; 10 36 } 11 37 … … 15 41 16 42 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 } 43 var ca = a as ConstantTreeNode; 44 var cb = b as ConstantTreeNode; 45 var va = a as VariableTreeNode; 46 var vb = b as VariableTreeNode; 47 48 var aIsConstant = ca != null; 49 var aIsVariable = va != null; 50 var bIsConstant = cb != null; 51 var bIsVariable = vb != null; 52 var aIsFunction = (!(aIsConstant | aIsVariable)); 53 var bIsFunction = (!(bIsConstant | bIsVariable)); 54 55 if (aIsFunction) 56 return bIsFunction && a.Symbol.Name.Equals(b.Symbol.Name); 57 if (bIsFunction) // one is function and the other is not, return false 58 return false; 59 60 switch (similarityLevel) { 61 case (SimilarityLevel.Exact): 62 if (aIsConstant & bIsConstant) 63 return ca.Value.Equals(cb.Value); 64 if (aIsVariable & bIsVariable) 65 return va.Weight.Equals(vb.Weight); 28 66 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): 67 case (SimilarityLevel.High): 68 return ((aIsConstant & bIsConstant) || (aIsVariable & bIsVariable)); 69 case (SimilarityLevel.Relaxed): 34 70 return true; 35 36 71 default: 37 72 return false; … … 39 74 } 40 75 41 private readonly int _similarityLevel; 76 public static bool ExactlySimilar(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 77 return Similar(a, b, SimilarityLevel.Exact); 78 } 79 80 public static bool Similar(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, SimilarityLevel level) { 81 var comp = new SymbolicExpressionTreeNodeSimilarityComparer(level); 82 return comp.Equals(a, b); 83 } 42 84 } 43 85 44 86 public class SymbolicExpressionTreeNodeOrderingComparer : IComparer<ISymbolicExpressionTreeNode> { 45 87 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()); 88 var ca = a as ConstantTreeNode; 89 var cb = b as ConstantTreeNode; 90 var va = a as VariableTreeNode; 91 var vb = b as VariableTreeNode; 92 93 var aIsConstant = ca != null; 94 var aIsVariable = va != null; 95 var bIsConstant = cb != null; 96 var bIsVariable = vb != null; 97 var aIsFunction = (!(aIsConstant | aIsVariable)); 98 var bIsFunction = (!(bIsConstant | bIsVariable)); 99 100 if (aIsFunction) 101 return bIsFunction ? a.Symbol.Name.CompareTo(b.Symbol.Name) : -1; 102 if (bIsFunction) // a is Constant or Variables 103 return 1; 104 if (aIsVariable) 105 return bIsVariable ? va.Weight.CompareTo(vb.Weight) : -1; 106 return 107 bIsVariable ? 1 : ca.Value.CompareTo(cb.Value); 64 108 } 65 109 } … … 68 112 public class SymbolicExpressionTreeEqualityComparer : IEqualityComparer<ISymbolicExpressionTree> { 69 113 public bool Equals(ISymbolicExpressionTree a, ISymbolicExpressionTree b) { 70 return SymbolicExpressionTreeMatching.FindMatch(a, b, _mode) == 0;114 return SymbolicExpressionTreeMatching.FindMatch(a, b, similarityLevel) == 0; 71 115 } 72 116 73 117 public int GetHashCode(ISymbolicExpressionTree tree) { 74 return tree.Length;75 } 76 77 private int _mode;78 public void SetComparisonMode( int mode) {79 _mode = mode;118 return (tree.Length << 8) % 12345; 119 } 120 121 private SimilarityLevel similarityLevel; 122 public void SetComparisonMode(SimilarityLevel simLevel) { 123 similarityLevel = simLevel; 80 124 } 81 125 } 82 126 83 127 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) { 128 public static bool IsSimilarTo(this ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, SimilarityLevel mode) { 91 129 return FindMatch(t1, t2, mode) == 0; 92 130 } 93 public static bool IsSimilarTo(this ISymbolicExpressionTreeNode t1, ISymbolicExpressionTreeNode t2, int mode) { 131 132 public static bool IsSimilarTo(this ISymbolicExpressionTreeNode t1, ISymbolicExpressionTreeNode t2, SimilarityLevel mode) { 94 133 return FindMatch(t1, t2, mode) == 0; 95 134 } 96 135 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; 136 public static bool ContainsFragment(this ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode fragment, SimilarityLevel mode) { 137 var matches = FindMatches(tree, fragment, mode); 138 return matches.Count > 0; 101 139 } 102 140 … … 106 144 107 145 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) { 146 if (node.SubtreeCount == 0) return; 147 var subtrees = node.Subtrees as List<ISymbolicExpressionTreeNode>; 148 if (subtrees == null) return; 149 var comparer = new SymbolicExpressionTreeNodeOrderingComparer(); 150 subtrees.Sort(comparer); 151 foreach (var subtree in subtrees) 152 subtree.SortSubtrees(); 153 } 154 155 // return child that is the same as node 156 public static ISymbolicExpressionTreeNode FindChild(this ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode node) { 157 var subtrees = parent.Subtrees as List<ISymbolicExpressionTreeNode>; 158 var comparer = new SymbolicExpressionTreeNodeSimilarityComparer(SimilarityLevel.Exact); 159 return subtrees.Find(x => comparer.Equals(x, node)); 160 } 161 162 public static int FindMatch(ISymbolicExpressionTree a, ISymbolicExpressionTree b, SimilarityLevel similarityLevel) { 118 163 var nodesA = a.IterateNodesPostfix() as List<ISymbolicExpressionTreeNode>; 119 164 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) { 165 return FindMatch(nodesA, nodesB, similarityLevel); 166 } 167 168 public static int FindMatch(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, SimilarityLevel similarityLevel) { 123 169 var nodesA = a.IterateNodesPostfix() as List<ISymbolicExpressionTreeNode>; 124 170 var nodesB = b.IterateNodesPostfix() as List<ISymbolicExpressionTreeNode>; 125 return FindMatch(nodesA, nodesB, mode); 126 } 171 return FindMatch(nodesA, nodesB, similarityLevel); 172 } 173 127 174 // returns the index in the sequence 'seq', where pattern 'pat' is matched, or -1 for no match 128 175 // -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) {176 public static int FindMatch(List<ISymbolicExpressionTreeNode> seq, List<ISymbolicExpressionTreeNode> pat, SimilarityLevel similarityLevel) { 130 177 int patlen = pat.Count; 131 178 int seqlen = seq.Count; 132 179 if (patlen == 0 || seqlen == 0) return -1; 133 var comparer = new SymbolicExpressionTreeNodeSimilarityComparer( mode);180 var comparer = new SymbolicExpressionTreeNodeSimilarityComparer(similarityLevel); 134 181 if (patlen == seqlen) return seq.SequenceEqual(pat, comparer) ? 0 : -1; 135 182 for (int i = patlen; i <= seqlen; ++i) { … … 140 187 return -1; 141 188 } 189 190 public static List<ISymbolicExpressionTreeNode> FindMatches(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode fragment, SimilarityLevel similarityLevel) { 191 var comp = new SymbolicExpressionTreeNodeSimilarityComparer(similarityLevel); 192 return FindMatches(tree.Root, fragment, comp); 193 } 194 195 public static List<ISymbolicExpressionTreeNode> 196 FindMatches(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode fragment, SymbolicExpressionTreeNodeSimilarityComparer comp) { 197 var matches = new List<ISymbolicExpressionTreeNode>(); 198 root.ForEachNodePostfix(node => { 199 if (Match(node, fragment, comp) == fragment.GetLength()) matches.Add(node); 200 }); 201 return matches; 202 } 203 204 ///<summary> 205 /// Finds the longest common subsequence in quadratic time and linear space 206 /// Variant of: 207 /// D . S. Hirschberg. A linear space algorithm for or computing maximal common subsequences. 1975. 208 /// http://dl.acm.org/citation.cfm?id=360861 209 /// </summary> 210 /// <returns>Number of pairs that were matched</returns> 211 public static int 212 Match(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, SymbolicExpressionTreeNodeSimilarityComparer comp) { 213 if (!comp.Equals(a, b)) 214 return 0; 215 216 int m = a.SubtreeCount; 217 int n = b.SubtreeCount; 218 if (m == 0 || n == 0) return 1; 219 220 var matrix = new int[m + 1, n + 1]; 221 for (int i = 1; i <= m; ++i) 222 for (int j = 1; j <= n; ++j) { 223 var ai = a.GetSubtree(i - 1); 224 var bj = b.GetSubtree(j - 1); 225 int match = Match(ai, bj, comp); 226 matrix[i, j] = Math.Max(Math.Max(matrix[i, j - 1], matrix[i - 1, j]), matrix[i - 1, j - 1] + match); 227 } 228 return matrix[m, n] + 1; 229 } 230 231 public static int 232 LCS(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, SymbolicExpressionTreeNodeSimilarityComparer comp) { 233 var nodesA = a.IterateNodesPrefix().ToList(); 234 var nodesB = b.IterateNodesPrefix().ToList(); 235 int m = nodesA.Count; 236 int n = nodesB.Count; 237 var matrix = new int[m + 1, n + 1]; 238 for (int i = 1; i <= m; ++i) { 239 for (int j = 1; j <= n; ++j) { 240 int w = comp.Equals(a, b) ? 1 : 0; 241 matrix[i, j] = Math.Max(Math.Max(matrix[i, j - 1], matrix[i - 1, j]), matrix[i - 1, j - 1] + w); 242 } 243 } 244 return matrix[m, n]; 245 } 246 247 public static void RenderTree(TextWriter writer, ISymbolicExpressionTree tree) { 248 RenderNode(writer, tree.Root, string.Empty); 249 } 250 251 public static void RenderNode(TextWriter writer, ISymbolicExpressionTreeNode node, string prefix) { 252 string label; 253 if (node is VariableTreeNode) { 254 var variable = node as VariableTreeNode; 255 label = string.Concat(string.Format("{0:0.000}", variable.Weight), '·', variable.VariableName); 256 } else if (node is ConstantTreeNode) { 257 var constant = node as ConstantTreeNode; 258 label = string.Format("{0:0.000}", constant.Value); 259 } else { 260 label = node.Symbol.ToString(); 261 } 262 263 writer.Write(label); 264 if (node.SubtreeCount > 0) { 265 char connector, extender = ' '; 266 var padding = prefix + new string(' ', label.Length); 267 for (int i = 0; i != node.SubtreeCount; ++i) { 268 if (i == 0) { 269 if (node.SubtreeCount > 1) { 270 connector = RenderChars.JunctionDown; 271 extender = RenderChars.VerticalLine; 272 } else { 273 connector = RenderChars.HorizontalLine; 274 extender = ' '; 275 } 276 } else { 277 writer.Write(padding); 278 if (i == node.SubtreeCount - 1) { 279 connector = RenderChars.CornerRight; 280 extender = ' '; 281 } else { 282 connector = RenderChars.JunctionRight; 283 extender = RenderChars.VerticalLine; 284 } 285 } 286 writer.Write(string.Concat(connector, RenderChars.HorizontalLine)); 287 var newPrefix = string.Concat(padding, extender, ' '); 288 RenderNode(writer, node.GetSubtree(i), newPrefix); 289 } 290 } else 291 writer.WriteLine(); 292 } 293 } 294 295 // helper class providing characters for displaying a tree in the console 296 public static class RenderChars { 297 public const char JunctionDown = '┬'; 298 public const char HorizontalLine = '─'; 299 public const char VerticalLine = '│'; 300 public const char JunctionRight = '├'; 301 public const char CornerRight = '└'; 142 302 } 143 303 } -
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
r8213 r8557 319 319 op.EvaluatorParameter.ActualName = EvaluatorParameter.Name; 320 320 } 321 var comparers = ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeNodeComparer>().ToList(); 322 if (comparers.Count > 0) 323 foreach (var op in operators.OfType<ITracingSymbolicExpressionTreeOperator>()) { 324 op.SymbolicExpressionTreeNodeComparerParameter.ActualValue = comparers.First(); 325 } 321 326 } 322 327
Note: See TracChangeset
for help on using the changeset viewer.