Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeDistance/BottomUpDistanceCalculator.cs @ 11021

Last change on this file since 11021 was 11021, checked in by bburlacu, 10 years ago

#1772: Added ExportDot method to DirectedGraph. Worked on the BottomUpDistanceCalculator.

File size: 7.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Globalization;
25using System.IO;
26using System.Linq;
27using System.Text;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
30using HeuristicLab.EvolutionTracking;
31
32namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
33  public static class BottomUpDistanceCalculator {
34    private static Dictionary<ISymbolicExpressionTreeNode, IVertex> Compact(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2) {
35      var G = new DirectedGraph();
36      var K = new Dictionary<ISymbolicExpressionTreeNode, IVertex>();
37      var F = new DisjointUnion(t1, t2);
38      var L = new Dictionary<string, IVertex>();
39      var Children = new Dictionary<ISymbolicExpressionTreeNode, int>();
40
41      var nodes = F.Nodes.ToList();
42
43      foreach (var l in nodes.Where(x => x.SubtreeCount == 0)) {
44        var label = Label(l);
45        var z = new Vertex { Content = l, Label = label };
46        L[z.Label] = z;
47        G.AddVertex(z);
48      }
49
50      var Q = new Queue<ISymbolicExpressionTreeNode>();
51      foreach (var v in nodes) {
52        Children[v] = v.SubtreeCount;
53        if (v.SubtreeCount == 0) {
54          Q.Enqueue(v);
55        }
56      }
57
58      while (Q.Any()) {
59        var v = Q.Dequeue();
60        if (v.SubtreeCount == 0) {
61          K[v] = L[Label(v)]; // 18
62        } else {
63          bool found = false;
64
65          foreach (var w in G.Vertices.Reverse()) {
66            if (Height(v) != Height(w))
67              break;
68            if (v.SubtreeCount != w.OutDegree)
69              break;
70            if (Label(v) != w.Label)
71              break;
72
73            var V = v.Subtrees.Select(s => K[s]).OrderBy(x => x.Label);
74            var W = w.OutArcs.Select(x => x.Target).OrderBy(x => x.Label);
75            if (V.SequenceEqual(W)) {
76              K[v] = w;
77              found = true;
78              break;
79            }
80          } // 32: end for
81
82          if (!found) {
83            var w = new Vertex { Content = v, Label = Label(v), Weight = Height(v) };
84            G.AddVertex(w);
85            K[v] = w;
86
87            foreach (var u in v.Subtrees) {
88              G.AddArc(w, K[u]);
89            } // 40: end for
90          } // 41: end if
91        } // 42: end if
92
93        if (v.Parent == null) continue;
94        var p = v.Parent;
95        Children[p]--;
96        if (Children[p] == 0)
97          Q.Enqueue(p);
98      };
99
100      using (var file = new StreamWriter(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "graph.dot"))) {
101        var str = G.ExportDot();
102        file.WriteLine(str);
103      }
104
105      return K;
106    }
107
108    private static Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> Mapping(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, Dictionary<ISymbolicExpressionTreeNode, IVertex> K) {
109      var M = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t1 => nodes of t2
110      var M_ = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t2 => nodes of t1
111      var plist2 = t2.IterateNodesPrefix().ToList();
112      foreach (var n in t1.IterateNodesBreadth()) {
113        ISymbolicExpressionTreeNode v = n;
114        if (!M.ContainsKey(v)) {
115          var w = plist2.Last();
116          var pw = plist2.IndexOf(w); // preorder index of node w
117          foreach (var u in plist2.Where(x => K[x] == K[v])) {
118            if (!M_.ContainsKey(u)) {
119              w = u;
120              //              if (plist2.IndexOf(u) < pw) {
121              //                w = u;
122              //              }
123            }
124          }
125          if (K[v] == K[w]) {
126            // simultaneous preorder traversal of the two subtrees
127            var nodesV = v.IterateNodesPrefix().ToList();
128            var nodesW = w.IterateNodesPrefix().ToList();
129            for (int i = 0; i < Math.Min(nodesV.Count, nodesW.Count); ++i) {
130              var s = nodesV[i];
131              var t = nodesW[i];
132              M[s] = t;
133              M_[t] = s;
134            }
135          }
136        }
137      }
138      return M;
139    }
140
141    public static double CalculateDistance(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, double p = 1, double q = 1, double r = 1) {
142      var K = Compact(t1, t2);
143      var M = Mapping(t1, t2, K);
144      int d = t1.Length - M.Count;
145      int s = M.Count(x => !Label(x.Key).Equals(Label(x.Value)));
146      int i = t2.Length - M.Count;
147
148      double distance = s * p + i * q + d * r;
149
150      if (distance / (t1.Length + t2.Length) > 0.5 && M.Count > 0) {
151        using (var file = new StreamWriter(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "map.tex"))) {
152          var str = FormatMapping(t1, t2, M);
153          file.WriteLine(str);
154        }
155      }
156
157      return distance;
158    }
159
160    private static string Label(ISymbolicExpressionTreeNode n) {
161      return n.ToString();
162    }
163
164    private static int Height(IVertex v) {
165      return (int)Math.Round(v.Weight); // use the vertex weight as height in this particular context
166    }
167
168    private static int Height(ISymbolicExpressionTreeNode n) {
169      var p = n;
170      while (p.Parent != null)
171        p = p.Parent;
172      return p.GetBranchLevel(n);
173    }
174
175    private class DisjointUnion : Tuple<ISymbolicExpressionTree, ISymbolicExpressionTree> {
176      public DisjointUnion(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2)
177        : base(t1, t2) {
178      }
179
180      public IEnumerable<ISymbolicExpressionTreeNode> Nodes {
181        get { return Item1.Root.IterateNodesPostfix().Concat(Item2.Root.IterateNodesPostfix()); }
182      }
183    }
184
185    // draw the mapping between t1 and t2
186    private static string FormatMapping(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> map) {
187      var formatter = new SymbolicExpressionTreeLatexFormatter();
188      var sb = new StringBuilder();
189
190      string s1, s2;
191      var m1 = formatter.Format(t1, out s1);
192      var m2 = formatter.Format(t2, out s2, 20);
193
194      sb.Append(s1);
195      sb.Append(s2);
196
197      foreach (var p in map) {
198        var id1 = m1[p.Key];
199        var id2 = m2[p.Value];
200
201        sb.Append(string.Format(CultureInfo.InvariantCulture, "\\path[draw,->] ({0}) edge[bend left,dashed] ({1});" + Environment.NewLine, id1, id2));
202      }
203
204      return sb.ToString();
205    }
206  }
207}
Note: See TracBrowser for help on using the repository browser.