Changeset 17434 for branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching
- Timestamp:
- 02/11/20 13:36:02 (5 years ago)
- Location:
- branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeBottomUpSimilarityCalculator.cs
r16130 r17434 2 2 3 3 /* HeuristicLab 4 * Copyright (C) 2002-2018Heuristic and Evolutionary Algorithms Laboratory (HEAL)4 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 5 5 * 6 6 * This file is part of HeuristicLab. … … 24 24 using System; 25 25 using System.Collections.Generic; 26 using System.Diagnostics;27 26 using System.Globalization; 28 27 using System.Linq; … … 31 30 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 32 31 using HeuristicLab.Optimization.Operators; 33 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; 32 using HEAL.Attic; 33 34 using NodeMap = System.Collections.Generic.Dictionary<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode, HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>; 34 35 35 36 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 36 37 [StorableClass] 37 [StorableType("63ACB7A4-137F-468F-BE42-A4CA6B62C63B")] 38 38 [Item("SymbolicExpressionTreeBottomUpSimilarityCalculator", "A similarity calculator which uses the tree bottom-up distance as a similarity metric.")] 39 39 public class SymbolicExpressionTreeBottomUpSimilarityCalculator : SolutionSimilarityCalculator { … … 45 45 protected override bool IsCommutative { get { return true; } } 46 46 47 public bool MatchConstantValues { get; set; } 47 48 public bool MatchVariableWeights { get; set; } 48 public bool MatchConstantValues { get; set; }49 49 50 50 [StorableConstructor] 51 protected SymbolicExpressionTreeBottomUpSimilarityCalculator(bool deserializing) 52 : base(deserializing) { 51 protected SymbolicExpressionTreeBottomUpSimilarityCalculator(StorableConstructorFlag _) : base(_) { 53 52 } 54 53 … … 61 60 } 62 61 62 #region static methods 63 private static ISymbolicExpressionTreeNode ActualRoot(ISymbolicExpressionTree tree) { 64 return tree.Root.GetSubtree(0).GetSubtree(0); 65 } 66 67 public static double CalculateSimilarity(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, bool strict = false) { 68 return CalculateSimilarity(ActualRoot(t1), ActualRoot(t2), strict); 69 } 70 71 public static double CalculateSimilarity(ISymbolicExpressionTreeNode n1, ISymbolicExpressionTreeNode n2, bool strict = false) { 72 var calculator = new SymbolicExpressionTreeBottomUpSimilarityCalculator { MatchConstantValues = strict, MatchVariableWeights = strict }; 73 return CalculateSimilarity(n1, n2, strict); 74 } 75 76 public static Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> ComputeBottomUpMapping(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, bool strict = false) { 77 return ComputeBottomUpMapping(ActualRoot(t1), ActualRoot(t2), strict); 78 } 79 80 public static Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> ComputeBottomUpMapping(ISymbolicExpressionTreeNode n1, ISymbolicExpressionTreeNode n2, bool strict = false) { 81 var calculator = new SymbolicExpressionTreeBottomUpSimilarityCalculator { MatchConstantValues = strict, MatchVariableWeights = strict }; 82 return calculator.ComputeBottomUpMapping(n1, n2); 83 } 84 #endregion 85 63 86 public double CalculateSimilarity(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2) { 64 if (t1 == t2) 87 return CalculateSimilarity(t1, t2, out Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> map); 88 } 89 90 public double CalculateSimilarity(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, out NodeMap map) { 91 if (t1 == t2) { 92 map = null; 65 93 return 1; 66 67 var map = ComputeBottomUpMapping(t1.Root, t2.Root);68 return 2.0 * map.Count / (t1.Length + t2.Length );94 } 95 map = ComputeBottomUpMapping(t1, t2); 96 return 2.0 * map.Count / (t1.Length + t2.Length - 4); // -4 for skipping root and start symbols in the two trees 69 97 } 70 98 … … 86 114 } 87 115 116 public Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> ComputeBottomUpMapping(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2) { 117 return ComputeBottomUpMapping(ActualRoot(t1), ActualRoot(t2)); 118 } 119 88 120 public Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> ComputeBottomUpMapping(ISymbolicExpressionTreeNode n1, ISymbolicExpressionTreeNode n2) { 89 var comparer = new SymbolicExpressionTreeNodeComparer(); // use a node comparer because it's faster than calling node.ToString() (strings are expensive) and comparing strings90 121 var compactedGraph = Compact(n1, n2); 91 122 92 var forwardMap = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t1 => nodes of t2 93 var reverseMap = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t2 => nodes of t1 94 95 // visit nodes in order of decreasing height to ensure correct mapping 96 var nodes1 = n1.IterateNodesPrefix().OrderByDescending(x => x.GetDepth()).ToList(); 97 var nodes2 = n2.IterateNodesPrefix().ToList(); 98 for (int i = 0; i < nodes1.Count; ++i) { 99 var v = nodes1[i]; 100 if (forwardMap.ContainsKey(v)) 123 IEnumerable<ISymbolicExpressionTreeNode> Subtrees(ISymbolicExpressionTreeNode node, bool commutative) { 124 var subtrees = node.IterateNodesPrefix(); 125 return commutative ? subtrees.OrderBy(x => compactedGraph[x].Hash) : subtrees; 126 } 127 128 var nodes1 = n1.IterateNodesPostfix().OrderByDescending(x => x.GetLength()); // by descending length so that largest subtrees are mapped first 129 var nodes2 = (List<ISymbolicExpressionTreeNode>)n2.IterateNodesPostfix(); 130 131 var forward = new NodeMap(); 132 var reverse = new NodeMap(); 133 134 foreach (ISymbolicExpressionTreeNode v in nodes1) { 135 if (forward.ContainsKey(v)) 101 136 continue; 137 102 138 var kv = compactedGraph[v]; 103 ISymbolicExpressionTreeNode w = null;104 for (int j = 0; j < nodes2.Count; ++j) { 105 var t = nodes2[j];106 if ( reverseMap.ContainsKey(t) || compactedGraph[t] != kv)139 var commutative = v.SubtreeCount > 1 && commutativeSymbols.Contains(kv.Label); 140 141 foreach (ISymbolicExpressionTreeNode w in nodes2) { 142 if (w.GetLength() != kv.Length || w.GetDepth() != kv.Depth || reverse.ContainsKey(w) || compactedGraph[w] != kv) 107 143 continue; 108 w = t; 144 145 // map one whole subtree to the other 146 foreach (var t in Subtrees(v, commutative).Zip(Subtrees(w, commutative), Tuple.Create)) { 147 forward[t.Item1] = t.Item2; 148 reverse[t.Item2] = t.Item1; 149 } 150 109 151 break; 110 152 } 111 if (w == null) continue; 112 113 // at this point we know that v and w are isomorphic, however, the mapping cannot be done directly 114 // (as in the paper) because the trees are unordered (subtree order might differ). the solution is 115 // to sort subtrees from under commutative labels (this will work because the subtrees are isomorphic!) 116 // while iterating over the two subtrees 117 var vv = IterateBreadthOrdered(v, comparer).ToList(); 118 var ww = IterateBreadthOrdered(w, comparer).ToList(); 119 int len = Math.Min(vv.Count, ww.Count); 120 for (int j = 0; j < len; ++j) { 121 var s = vv[j]; 122 var t = ww[j]; 123 Debug.Assert(!reverseMap.ContainsKey(t)); 124 125 forwardMap[s] = t; 126 reverseMap[t] = s; 127 } 128 } 129 130 return forwardMap; 153 } 154 155 return forward; 131 156 } 132 157 … … 140 165 var nodeMap = new Dictionary<ISymbolicExpressionTreeNode, GraphNode>(); // K 141 166 var labelMap = new Dictionary<string, GraphNode>(); // L 142 var childrenCount = new Dictionary<ISymbolicExpressionTreeNode, int>(); // Children143 167 144 168 var nodes = n1.IterateNodesPostfix().Concat(n2.IterateNodesPostfix()); // the disjoint union F 145 var list = new List<GraphNode>(); 146 var queue = new Queue<ISymbolicExpressionTreeNode>(); 147 148 foreach (var n in nodes) { 149 if (n.SubtreeCount == 0) { 150 var label = GetLabel(n); 169 var graph = new List<GraphNode>(); 170 171 IEnumerable<GraphNode> Subtrees(GraphNode g, bool commutative) { 172 var subtrees = g.SymbolicExpressionTreeNode.Subtrees.Select(x => nodeMap[x]); 173 return commutative ? subtrees.OrderBy(x => x.Hash) : subtrees; 174 } 175 176 foreach (var node in nodes) { 177 var label = GetLabel(node); 178 179 if (node.SubtreeCount == 0) { 151 180 if (!labelMap.ContainsKey(label)) { 152 var z = new GraphNode { SymbolicExpressionTreeNode = n, Label = label }; 153 labelMap[z.Label] = z; 154 } 155 nodeMap[n] = labelMap[label]; 156 queue.Enqueue(n); 181 labelMap[label] = new GraphNode(node, label); 182 } 183 nodeMap[node] = labelMap[label]; 157 184 } else { 158 childrenCount[n] = n.SubtreeCount; 159 } 160 } 161 while (queue.Any()) { 162 var n = queue.Dequeue(); 163 if (n.SubtreeCount > 0) { 185 var v = new GraphNode(node, label); 164 186 bool found = false; 165 var label = n.Symbol.Name; 166 var depth = n.GetDepth(); 167 168 bool sort = n.SubtreeCount > 1 && commutativeSymbols.Contains(label); 169 var nSubtrees = n.Subtrees.Select(x => nodeMap[x]).ToList(); 170 if (sort) nSubtrees.Sort((a, b) => string.CompareOrdinal(a.Label, b.Label)); 171 172 for (int i = list.Count - 1; i >= 0; --i) { 173 var w = list[i]; 174 if (!(n.SubtreeCount == w.SubtreeCount && label == w.Label && depth == w.Depth)) 187 var commutative = node.SubtreeCount > 1 && commutativeSymbols.Contains(label); 188 189 var vv = Subtrees(v, commutative); 190 191 foreach (var w in graph) { 192 if (v.Depth != w.Depth || v.SubtreeCount != w.SubtreeCount || v.Length != w.Length || v.Label != w.Label) { 175 193 continue; 176 177 // sort V and W when the symbol is commutative because we are dealing with unordered trees 178 var m = w.SymbolicExpressionTreeNode; 179 var mSubtrees = m.Subtrees.Select(x => nodeMap[x]).ToList(); 180 if (sort) mSubtrees.Sort((a, b) => string.CompareOrdinal(a.Label, b.Label)); 181 182 found = nSubtrees.SequenceEqual(mSubtrees); 194 } 195 196 var ww = Subtrees(w, commutative); 197 found = vv.SequenceEqual(ww); 198 183 199 if (found) { 184 nodeMap[n ] = w;200 nodeMap[node] = w; 185 201 break; 186 202 } 187 203 } 188 189 204 if (!found) { 190 var w = new GraphNode { SymbolicExpressionTreeNode = n, Label = label, Depth = depth }; 191 list.Add(w); 192 nodeMap[n] = w; 205 nodeMap[node] = v; 206 graph.Add(v); 193 207 } 194 208 } 195 196 if (n == n1 || n == n2) 197 continue; 198 199 var p = n.Parent; 200 if (p == null) 201 continue; 202 203 childrenCount[p]--; 204 205 if (childrenCount[p] == 0) 206 queue.Enqueue(p); 207 } 208 209 } 209 210 return nodeMap; 210 }211 212 private IEnumerable<ISymbolicExpressionTreeNode> IterateBreadthOrdered(ISymbolicExpressionTreeNode node, ISymbolicExpressionTreeNodeComparer comparer) {213 var list = new List<ISymbolicExpressionTreeNode> { node };214 int i = 0;215 while (i < list.Count) {216 var n = list[i];217 if (n.SubtreeCount > 0) {218 var subtrees = commutativeSymbols.Contains(node.Symbol.Name) ? n.Subtrees.OrderBy(x => x, comparer) : n.Subtrees;219 list.AddRange(subtrees);220 }221 i++;222 }223 return list;224 211 } 225 212 … … 228 215 return node.Symbol.Name; 229 216 230 var constant = node as ConstantTreeNode; 231 if (constant != null) 232 return MatchConstantValues ? constant.Value.ToString(CultureInfo.InvariantCulture) : node.Symbol.Name; 233 234 var variable = node as VariableTreeNode; 235 if (variable != null) 217 if (node is ConstantTreeNode constant) 218 return MatchConstantValues ? constant.Value.ToString(CultureInfo.InvariantCulture) : constant.Symbol.Name; 219 220 if (node is VariableTreeNode variable) 236 221 return MatchVariableWeights ? variable.Weight + variable.VariableName : variable.VariableName; 237 222 … … 240 225 241 226 private class GraphNode { 242 public ISymbolicExpressionTreeNode SymbolicExpressionTreeNode; 243 public string Label; 244 public int Depth; 227 private GraphNode() { } 228 229 public GraphNode(ISymbolicExpressionTreeNode node, string label) { 230 SymbolicExpressionTreeNode = node; 231 Label = label; 232 Hash = GetHashCode(); 233 Depth = node.GetDepth(); 234 Length = node.GetLength(); 235 } 236 237 public int Hash { get; } 238 public ISymbolicExpressionTreeNode SymbolicExpressionTreeNode { get; } 239 public string Label { get; } 240 public int Depth { get; } 245 241 public int SubtreeCount { get { return SymbolicExpressionTreeNode.SubtreeCount; } } 242 public int Length { get; } 246 243 } 247 244 } -
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeEqualityComparer.cs
r11910 r17434 2 2 using System.Collections.Generic; 3 3 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 4 using HEAL.Attic; 4 5 5 6 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 7 [StorableType("535830d4-551e-4b53-97e3-9605bd7e785f")] 6 8 public class SymbolicExpressionTreeEqualityComparer : IEqualityComparer<ISymbolicExpressionTree> { 9 [Storable] 7 10 public SymbolicExpressionTreeNodeEqualityComparer SimilarityComparer { get; set; } 11 12 13 [StorableConstructor] 14 protected SymbolicExpressionTreeEqualityComparer(StorableConstructorFlag _) { } 15 public SymbolicExpressionTreeEqualityComparer() { } 8 16 9 17 public bool Equals(ISymbolicExpressionTree a, ISymbolicExpressionTree b) { … … 15 23 return (tree.Length << 8) % 12345; 16 24 } 25 17 26 } 18 27 } -
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMatching.cs
r16130 r17434 2 2 3 3 /* HeuristicLab 4 * Copyright (C) 2002-2018Heuristic and Evolutionary Algorithms Laboratory (HEAL)4 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 5 5 * 6 6 * This file is part of HeuristicLab. -
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator.cs
r16130 r17434 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-2018Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 25 25 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 26 26 using HeuristicLab.Optimization.Operators; 27 using H euristicLab.Persistence.Default.CompositeSerializers.Storable;27 using HEAL.Attic; 28 28 29 29 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 30 [Storable Class]30 [StorableType("2634824A-D8E6-4047-9146-79EDF50BEED8")] 31 31 [Item("SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator", "A similarity calculator based on the size of the maximum common subtree between two trees")] 32 32 public class SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator : SolutionSimilarityCalculator { … … 46 46 47 47 [StorableConstructor] 48 protected SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator( bool deserializing) : base(deserializing) { }48 protected SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator(StorableConstructorFlag _) : base(_) { } 49 49 50 50 public override IDeepCloneable Clone(Cloner cloner) { -
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeComparer.cs
r16130 r17434 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-2018Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 22 22 using System; 23 23 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 24 using HEAL.Attic; 24 25 25 26 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 27 [StorableType("eabf848e-d10c-499e-8c48-c771232ede0e")] 26 28 // this comparer considers that a < b if the type of a is "greater" than the type of b, for example: 27 29 // - A function node is "greater" than a terminal node -
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeEqualityComparer.cs
r16130 r17434 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-2018Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 23 23 using HeuristicLab.Core; 24 24 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 25 using H euristicLab.Persistence.Default.CompositeSerializers.Storable;25 using HEAL.Attic; 26 26 27 27 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 28 28 [Item("SymbolicExpressionTreeNodeEqualityComparer", "An operator that checks node equality based on different similarity measures.")] 29 [Storable Class]29 [StorableType("F5BC06AA-3F08-4692-93E8-E44CE8205A46")] 30 30 public class SymbolicExpressionTreeNodeEqualityComparer : Item, ISymbolicExpressionTreeNodeEqualityComparer { 31 31 [StorableConstructor] 32 protected SymbolicExpressionTreeNodeEqualityComparer( bool deserializing) : base(deserializing) { }32 protected SymbolicExpressionTreeNodeEqualityComparer(StorableConstructorFlag _) : base(_) { } 33 33 protected SymbolicExpressionTreeNodeEqualityComparer(SymbolicExpressionTreeNodeEqualityComparer original, Cloner cloner) 34 34 : base(original, cloner) { -
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreePhenotypicSimilarityCalculator.cs
r16130 r17434 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-2018Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 26 26 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 27 27 using HeuristicLab.Optimization.Operators; 28 using H euristicLab.Persistence.Default.CompositeSerializers.Storable;28 using HEAL.Attic; 29 29 30 30 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 31 31 [Item("SymbolicExpressionTreePhenotypicSimilarityCalculator", "An operator that calculates the similarity betweeon two trees based on the correlation of their outputs.")] 32 [Storable Class]32 [StorableType("163CE915-506E-472B-B77F-156ECC9D9C05")] 33 33 public class SymbolicExpressionTreePhenotypicSimilarityCalculator : SolutionSimilarityCalculator { 34 34 [Storable] … … 40 40 41 41 [StorableConstructor] 42 protected SymbolicExpressionTreePhenotypicSimilarityCalculator( bool deserializing) : base(deserializing) { }42 protected SymbolicExpressionTreePhenotypicSimilarityCalculator(StorableConstructorFlag _) : base(_) { } 43 43 44 44 public SymbolicExpressionTreePhenotypicSimilarityCalculator(SymbolicExpressionTreePhenotypicSimilarityCalculator original, Cloner cloner)
Note: See TracChangeset
for help on using the changeset viewer.