Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.BottomUpTreeDistance/HeuristicLab.Tests/BottomUpSimilarityCalculatorTest.cs @ 11219

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

#2215: Refactored the tree distance calculators as similarity calculators (extending SingleObjectiveSolutionSimilarityCalculator). Removed ISymbolicExpressionTreeDistanceCalculator interface. Made small performance enhancements to the BottomUpSimilarityCalculator. Added unit tests to check correctness and performance of bottom up similarity. Added SingleObjectivePopulationDiversityAnalyzer in the default operators list along with the BottomUpSimilarityCalculator.

File size: 6.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Drawing;
5using System.Globalization;
6using System.Linq;
7using System.Text;
8using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
9using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
10using HeuristicLab.Problems.DataAnalysis.Symbolic.SimilarityCalculators;
11using HeuristicLab.Random;
12using Microsoft.VisualStudio.TestTools.UnitTesting;
13
14namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Tests {
15  [TestClass]
16  public class BottomUpSimilarityCalculatorTest {
17    private readonly BottomUpSimilarityCalculator busCalculator;
18    private readonly SymbolicExpressionImporter importer;
19
20    private const int N = 100;
21    private const int Rows = 1;
22    private const int Columns = 10;
23
24    public BottomUpSimilarityCalculatorTest() {
25      busCalculator = new BottomUpSimilarityCalculator();
26      importer = new SymbolicExpressionImporter();
27    }
28
29    [TestMethod]
30    [TestCategory("Problems.DataAnalysis.Symbolic")]
31    [TestProperty("Time", "short")]
32    public void TestBottomUpMatching() {
33      TestMatchedNodes("(+ 1 2)", "(+ 2 1)", 5);
34      TestMatchedNodes("(- 2 1)", "(- 1 2)", 2);
35
36      TestMatchedNodes(
37        "(* (+ 2.84 (exp (+ (log (/ (variable 2.0539 X5) (variable -9.2452e-1 X6))) (/ (variable 2.0539 X5) (variable -9.2452e-1 X6))))) 2.9081)",
38        "(* (- (variable 9.581e-1 X6) (+ (- (variable 5.1491e-1 X5) 1.614e+1) (+ (/ (variable 2.0539 X5) (variable -9.2452e-1 X6)) (log (/ (variable 2.0539 X5) (variable -9.2452e-1 X6)))))) 2.9081)",
39        9);
40
41      TestMatchedNodes("(+ (exp 2.1033) (/ -4.3072 (variable 2.4691 X7)))", "(/ 1 (+ (/ -4.3072 (variable 2.4691 X7)) (exp 2.1033)))", 6);
42      TestMatchedNodes("(+ (exp 2.1033) (/ -4.3072 (variable 2.4691 X7)))", "(/ 1 (+ (/ (variable 2.4691 X7) -4.3072) (exp 2.1033)))", 4);
43    }
44
45    private void TestMatchedNodes(string expr1, string expr2, int expected) {
46      var t1 = importer.Import(expr1);
47      var t2 = importer.Import(expr2);
48
49      var mapping = busCalculator.ComputeBottomUpMapping(t1, t2);
50      var c = mapping.Count;
51
52      if (c != expected) {
53        throw new Exception("Match count " + c + " is different than expected value " + expected);
54      }
55    }
56
57    [TestMethod]
58    [TestCategory("Problems.DataAnalysis.Symbolic")]
59    [TestProperty("Time", "long")]
60    public void TestBottomUpSimilarityCalculatorPerformance() {
61      var grammar = new TypeCoherentExpressionGrammar();
62      grammar.ConfigureAsDefaultRegressionGrammar();
63      var twister = new MersenneTwister(31415);
64      var ds = Util.CreateRandomDataset(twister, Rows, Columns);
65      var trees = Util.CreateRandomTrees(twister, ds, grammar, N, 1, 100, 0, 0);
66
67      double s = 0;
68      var sw = new Stopwatch();
69
70      sw.Start();
71      for (int i = 0; i < trees.Length - 1; ++i) {
72        for (int j = i + 1; j < trees.Length; ++j) {
73          s += busCalculator.CalculateSolutionSimilarity(trees[i], trees[j]);
74        }
75      }
76      sw.Stop();
77      Console.WriteLine("Elapsed time: " + sw.ElapsedMilliseconds / 1000.0 + ", Avg. similarity: " + s);
78      Console.WriteLine(N * (N + 1) / (2 * sw.ElapsedMilliseconds / 1000.0) + " similarity calculations per second.");
79    }
80
81    private static string FormatMapping(ISymbolicExpressionTree t1, ISymbolicExpressionTree t2, Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> map) {
82      var symbolNameMap = new Dictionary<string, string>
83    {
84      {"ProgramRootSymbol", "Prog"},
85      {"StartSymbol","RPB"},
86      {"Multiplication", "$\\times$"},
87      {"Division", "$\\div$"},
88      {"Addition", "$+$"},
89      {"Subtraction", "$-$"},
90      {"Exponential", "$\\exp$"},
91      {"Logarithm", "$\\log$"}
92    };
93
94      var sb = new StringBuilder();
95      var nodeIds = new Dictionary<ISymbolicExpressionTreeNode, string>();
96      int offset = 0;
97      var layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(x => x.Subtrees);
98      var nodeCoordinates = layoutEngine.CalculateLayout(t1.Root).ToDictionary(n => n.Content, n => new PointF(n.X, n.Y));
99
100      double ws = 0.5;
101      double hs = 0.5;
102
103      var nl = Environment.NewLine;
104      sb.Append("\\documentclass[class=minimal,border=0pt]{standalone}" + nl +
105                 "\\usepackage{tikz}" + nl +
106                 "\\begin{document}" + nl +
107                 "\\begin{tikzpicture}" + nl +
108                 "\\def\\ws{1}" + nl +
109                 "\\def\\hs{0.7}" + nl +
110                 "\\def\\offs{" + offset + "}" + nl);
111
112      foreach (var node in t1.IterateNodesBreadth()) {
113        var id = Guid.NewGuid().ToString();
114        nodeIds[node] = id;
115        var coord = nodeCoordinates[node];
116        var nodeName = symbolNameMap.ContainsKey(node.Symbol.Name) ? symbolNameMap[node.Symbol.Name] : node.ToString();
117        sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\node ({0}) at (\\ws*{1} + \\offs,\\hs*{2}) {{{3}}};", nodeIds[node], ws * coord.X, -hs * coord.Y, EscapeLatexString(nodeName)));
118      }
119
120      foreach (ISymbolicExpressionTreeNode t in t1.IterateNodesBreadth()) {
121        var n = t;
122        foreach (var s in t.Subtrees) {
123          sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\draw ({0}) -- ({1});", nodeIds[n], nodeIds[s]));
124        }
125      }
126
127      nodeCoordinates = layoutEngine.CalculateLayout(t2.Root).ToDictionary(n => n.Content, n => new PointF(n.X, n.Y));
128
129      offset = 20;
130      sb.Append("\\def\\offs{" + offset + "}" + nl);
131      foreach (var node in t2.IterateNodesBreadth()) {
132        var id = Guid.NewGuid().ToString();
133        nodeIds[node] = id;
134        var coord = nodeCoordinates[node];
135        var nodeName = symbolNameMap.ContainsKey(node.Symbol.Name) ? symbolNameMap[node.Symbol.Name] : node.ToString();
136        sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\node ({0}) at (\\ws*{1} + \\offs,\\hs*{2}) {{{3}}};", nodeIds[node], ws * coord.X, -hs * coord.Y, EscapeLatexString(nodeName)));
137      }
138
139      foreach (ISymbolicExpressionTreeNode t in t2.IterateNodesBreadth()) {
140        var n = t;
141        foreach (var s in t.Subtrees) {
142          sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\draw ({0}) -- ({1});", nodeIds[n], nodeIds[s]));
143        }
144      }
145
146      foreach (var p in map) {
147        var id1 = nodeIds[p.Key];
148        var id2 = nodeIds[p.Value];
149
150        sb.Append(string.Format(CultureInfo.InvariantCulture, "\\path[draw,->,color=gray] ({0}) edge[bend left,dashed] ({1});" + Environment.NewLine, id1, id2));
151      }
152      sb.Append("\\end{tikzpicture}" + nl +
153                "\\end{document}" + nl);
154      return sb.ToString();
155    }
156
157    private static string EscapeLatexString(string s) {
158      return s.Replace("\\", "\\\\").Replace("{", "\\{").Replace("}", "\\}").Replace("_", "\\_");
159    }
160  }
161}
Note: See TracBrowser for help on using the repository browser.