Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/SymbolicDataAnalysisExpressionTracing.cs @ 10827

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

#1772: Added default font, pen, and brush for the graphical components (the idea is to save memory by sharing default pens and brushes - not allocating new ones all the time), added support for tracing mutation operations

File size: 7.0 KB
Line 
1
2using System;
3using System.Collections.Generic;
4using System.IO;
5using System.Linq;
6using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
7using HeuristicLab.EvolutionTracking;
8using FragmentNode = HeuristicLab.EvolutionTracking.GenealogyGraphNode<HeuristicLab.EvolutionTracking.IFragment<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>>;
9using IFragmentNode = HeuristicLab.EvolutionTracking.IGenealogyGraphNode<HeuristicLab.EvolutionTracking.IFragment<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>>;
10using IGraphNode = HeuristicLab.EvolutionTracking.IGenealogyGraphNode<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTree>;
11
12namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
13  public static class SymbolicDataAnalysisExpressionTracing {
14    public static IGenealogyGraph<IFragment<ISymbolicExpressionTreeNode>> TraceSubtree(IGenealogyGraphNode<ISymbolicExpressionTree> graphNode, int subtreeIndex) {
15      var graph = new GenealogyGraph<IFragment<ISymbolicExpressionTreeNode>>();
16      var nodes = Trace(graphNode, subtreeIndex);
17      foreach (var n in nodes) {
18        graph.AddVertex(n);
19      }
20      return graph;
21    }
22
23    private static IEnumerable<IFragmentNode> Trace(IGraphNode graphNode, int subtreeIndex, FragmentNode parentNode = null) {
24      var node = graphNode; // current node
25      var index = subtreeIndex; // current index
26      var parent = parentNode; // current parent
27
28      while (true) {
29        if (!node.Parents.Any()) {
30          var fragmentNode = new FragmentNode {
31            Content = new Fragment<ISymbolicExpressionTreeNode> { Root = node.Content.NodeAt(index) },
32            Rank = node.Rank
33          };
34          if (parent != null) {
35            var arc = new GenealogyGraphArc { Source = parent, Target = fragmentNode };
36            parent.AddForwardArc(arc);
37            //            fragmentNode.Content.Index1 = parent.Content.Index1;
38          }
39          yield return fragmentNode; // no tracing if there are no parents
40          break;
41        }
42        var parents = node.Parents.ToList();
43        if (node.IsElite) {
44          // skip elite, go up the graph to original individual
45          node = parents[0];
46          continue;
47        }
48        var fragment = (IFragment<ISymbolicExpressionTreeNode>)node.InArcs.Last().Data;
49        if (fragment == null) {
50          // the fragment can be null when crossover or mutation did not actually make any change => then we skip
51          node = parents[0];
52          continue;
53        }
54        var fragmentLength = fragment.Root.GetLength();
55        var tree = node.Content;
56        var subtree = tree.NodeAt(index);
57        var subtreeLength = subtree.GetLength();
58
59        if (parents.Count == 1) {
60          // we are tracing a mutation operation
61          var fragmentNode = new FragmentNode {
62            Content = new Fragment<ISymbolicExpressionTreeNode> { Root = subtree },
63            Rank = node.Rank
64          };
65          if (parent != null) {
66            var arc = new GenealogyGraphArc { Source = parent, Target = fragmentNode };
67            parent.AddForwardArc(arc);
68          }
69          yield return fragmentNode;
70          var up = Trace(parents[0], fragment.Index1, fragmentNode);
71          foreach (var v in up) { yield return v; }
72          break;
73        }
74
75        if (parents.Count == 2) {
76          // we are tracing a crossover operation
77          if (fragment.Index1 == index) {
78            node = parents[1]; // take second parent which contains the fragment
79            index = fragment.Index2;
80            continue;
81          }
82
83          if (fragment.Index1 < index) {
84            if (fragment.Index1 + fragmentLength > index) {
85              node = parents[1]; // fragment contains subtree, take second parent
86              index += fragment.Index2 - fragment.Index1; // the subtree has the same index relative to the fragment
87            } else {
88              // fragment distinct from subtree
89              node = parents[0]; // take first parent which contains the subtree
90              index += node.Content.NodeAt(fragment.Index1).GetLength() - fragmentLength; // subtreeIndex must be adjusted according to swapped fragments sizes
91            }
92            continue;
93          }
94
95          if (fragment.Index1 > index) {
96            if (fragment.Index1 < index + subtreeLength) {
97              // subtree contains fragment => bifurcation point in the fragment graph
98              var fragmentNode = new FragmentNode {
99                Content = new Fragment<ISymbolicExpressionTreeNode> { Root = subtree },
100                Rank = node.Rank
101              };
102              if (parent != null) {
103                var arc = new GenealogyGraphArc { Source = parent, Target = fragmentNode };
104                parent.AddForwardArc(arc);
105              }
106              fragmentNode.Content.Index1 = fragment.Index1 - index;
107              yield return fragmentNode;
108
109              if (parents[1].Content.NodeAt(fragment.Index2).GetLength() != fragmentLength) {
110                throw new Exception("Fragment lengths should match!");
111              }
112              // the two paths below ("left" and "right") correspond to the subtree and the fragment, respectively
113              var left = Trace(parents[0], index, fragmentNode); // trace subtree
114              var right = Trace(parents[1], fragment.Index2, fragmentNode); // trace fragment
115              foreach (var v in left.Concat(right)) { yield return v; }
116              break;
117            } else {
118              node = parents[0]; // fragment distinct from subtree: update node, index remains unchanged
119            }
120          }
121        }
122      }
123    }
124
125    private static string ViewAsText(this ISymbolicExpressionTreeNode root) {
126      var writer = new StringWriter();
127      SymbolicExpressionTreeHierarchicalFormatter.RenderNode(writer, root, string.Empty);
128      return writer.ToString();
129    }
130    #region some helper methods for shortening the tracing code
131    private static void AddChild(this IGenealogyGraphNode parent, IGenealogyGraphNode child) {
132      parent.AddForwardArc(child);
133      child.AddReverseArc(parent);
134      child.Rank = parent.Rank - 1;
135    }
136    private static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTree tree, int position) {
137      return NodeAt(tree.Root, position);
138    }
139    private static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTreeNode root, int position) {
140      return root.IterateNodesPrefix().ElementAt(position);
141    }
142    private static int IndexOf(this ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode node) {
143      return IndexOf(tree.Root, node);
144    }
145    private static int IndexOf(this ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node) {
146      int i = 0;
147      foreach (var n in root.IterateNodesPrefix()) {
148        if (n == node) return i;
149        ++i;
150      }
151      return -1;
152    }
153    #endregion
154  }
155}
Note: See TracBrowser for help on using the repository browser.