Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionaryTracking/3.4/Operators/SymbolicExpressionTreeSymbolGraphBuilder.cs @ 10264

Last change on this file since 10264 was 10264, checked in by bburlacu, 11 years ago

#1772: Created new branch for the redesigned version of the tracking plugin

File size: 10.5 KB
RevLine 
[10264]1using System;
2using System.Collections.Generic;
3using System.Linq;
4using HeuristicLab.Common;
5using HeuristicLab.Core;
6using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
7using HeuristicLab.Operators;
8using HeuristicLab.Optimization;
9using HeuristicLab.Parameters;
10using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
11using HeuristicLab.Problems.DataAnalysis.Symbolic;
12
13using GeneticExchangeMapType = HeuristicLab.Core.IItemList<HeuristicLab.Core.IItem>;
14
15namespace HeuristicLab.EvolutionaryTracking.Operators {
16  [Item("SymbolicExpressionTreeSymbolGraphBuilder", "An operator that builds a graph of pair-wise symbol relationships from the trees in the population.")]
17  [StorableClass]
18  class SymbolicExpressionTreeSymbolGraphBuilder : SingleSuccessorOperator {
19    #region Parameter names
20    private const string GlobalGeneticExchangeMapParameterName = "GlobalGeneticExchangeMap";
21    private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
22    private const string ResultsParameterName = "Results";
23    #endregion
24    #region Parameter properties
25    public ILookupParameter<GeneticExchangeMapType> GlobalGeneticExchangeMapParameter {
26      get { return (LookupParameter<GeneticExchangeMapType>)Parameters[GlobalGeneticExchangeMapParameterName]; }
27    }
28    #endregion
29    #region Properties
30    public GeneticExchangeMapType GlobalGeneticExchangeMap {
31      get { return GlobalGeneticExchangeMapParameter.ActualValue; }
32    }
33    #endregion
34
35    [StorableConstructor]
36    private SymbolicExpressionTreeSymbolGraphBuilder(bool deserializing) : base(deserializing) { }
37    private SymbolicExpressionTreeSymbolGraphBuilder(SymbolicExpressionTreeSymbolGraphBuilder original, Cloner cloner) : base(original, cloner) { }
38    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicExpressionTreeSymbolGraphBuilder(this, cloner); }
39    public SymbolicExpressionTreeSymbolGraphBuilder() {
40      Parameters.Add(new ScopeTreeLookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic expression trees to analyze."));
41      Parameters.Add(new LookupParameter<GeneticExchangeMapType>(GlobalGeneticExchangeMapParameterName, "Global map of genetic exchanges."));
42      Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName, "The results collection where the analysis values should be stored."));
43    }
44    #region Parameters
45    public IScopeTreeLookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
46      get { return (IScopeTreeLookupParameter<ISymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
47    }
48    public ILookupParameter<ResultCollection> ResultsParameter {
49      get { return (LookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
50    }
51    #endregion
52
53    [StorableHook(HookType.AfterDeserialization)]
54    private void AfterDeserialization() {
55      if (!Parameters.ContainsKey(ResultsParameterName))
56        Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName, "The results collection where the analysis values should be stored."));
57      if (!Parameters.ContainsKey(GlobalGeneticExchangeMapParameterName))
58        Parameters.Add(new LookupParameter<GeneticExchangeMapType>(GlobalGeneticExchangeMapParameterName, "Global map of genetic exchanges."));
59    }
60    public override IOperation Apply() {
61      if (!Parameters.ContainsKey("Results")) return base.Apply();
62
63      var trees = SymbolicExpressionTreeParameter.ActualValue.ToList();
64
65      var results = ResultsParameter.ActualValue;
66
67      //      if (!results.ContainsKey("SymbolGraph")) {
68      //        var graph = CreateSymbolGraph(trees);
69      //        results.Add(new Result("SymbolGraph", graph));
70      //      } else {
71      //        var graph = results["SymbolGraph"].Value as SymbolGraph;
72      //        var transactions = GlobalGeneticExchangeMap.Select(t => t as GeneticExchange);
73      //        UpdateGraph(graph, transactions);
74      //      }
75
76      var graph = CreateSymbolGraph(trees);
77      if (!results.ContainsKey("SymbolGraph")) {
78        results.Add(new Result("SymbolGraph", graph));
79      } else {
80        results["SymbolGraph"].Value = graph;
81      }
82
83      return base.Apply();
84    }
85    private SymbolGraph CreateSymbolGraph(IEnumerable<ISymbolicExpressionTree> trees) {
86      var list = trees as IList<ISymbolicExpressionTree> ?? trees.ToList();
87
88      var nodes = list.SelectMany(x => x.Root.GetSubtree(0).GetSubtree(0).IterateNodesBreadth()).ToList();
89      var graph = new SymbolGraph();
90
91      #region create symbol graph
92      foreach (var node in nodes) {
93        var nodeLabel = node.Label();
94        if (!graph.ContainsKey(nodeLabel)) {
95          graph.AddNode(new SymbolNode { Label = nodeLabel, Symbol = node.Symbol, Weight = 1.0, AverageArity = node.SubtreeCount });
96        } else {
97          double avgArity = graph.GetNode(nodeLabel).AverageArity;
98          double weight = graph.GetNode(nodeLabel).Weight;
99          graph.GetNode(nodeLabel).AverageArity = (avgArity * weight + node.SubtreeCount) / (weight + 1);
100          graph.GetNode(nodeLabel).Weight += 1.0;
101        }
102      }
103
104      foreach (var node in nodes) {
105        var n = graph.GetNode(node.Symbol.Name);
106        for (int i = 0; i != node.SubtreeCount; ++i) {
107          var child = node.GetSubtree(i);
108          var c = graph.GetNode(child.Label());
109
110          if (n == null || c == null)
111            throw new Exception("The node couldn't be found in the graph."); // should never happen
112
113          if (n.OutEdges == null) {
114            n.AddForwardArc(c, 1.0);
115          } else {
116            var arc = n.OutEdges.Find(x => x.Target == c);
117            if (arc == null) n.AddForwardArc(c, 1);
118            else arc.Weight += 1.0;
119          }
120          if (c.Positions == null) {
121            c.Positions = new Dictionary<int, int> { { i, 1 } };
122          } else if (c.Positions.ContainsKey(i)) {
123            c.Positions[i] += 1;
124          } else {
125            c.Positions.Add(i, 1);
126          }
127        }
128      }
129      #endregion
130
131      return graph;
132    }
133
134    private static void UpdateGraph(SymbolGraph graph, IEnumerable<GeneticExchange> exchanges) {
135      // we have the graph, and we have the list of genetic exchanges which allows us to update graph vertex and arc weights
136      exchanges = exchanges as IList<GeneticExchange> ?? exchanges.ToList();
137      var inFragments = exchanges.Select(t => t.FragmentIn).ToList();
138      var outFragments = exchanges.Select(t => t.FragmentOut).ToList();
139
140      // the idea is to add to the symbol graph everything that goes in (inFragments) and
141      // subtract everything that goes out (outFragments)
142
143      // might not be 100% correct because the trees change as well
144
145      foreach (var f in inFragments) {
146        foreach (var node in f.Root.IterateNodesPrefix()) {
147          var parentLabel = node.Label();
148          var parentVertex = graph.GetNode(parentLabel);
149          if (parentVertex == null) { // highly unlikely but it is possible
150            graph.AddNode(new SymbolNode { Label = parentLabel, Symbol = node.Symbol, Weight = 1.0, AverageArity = node.SubtreeCount });
151            parentVertex = graph.GetNode(parentLabel);
152          } else {
153            parentVertex.Weight++;
154          }
155
156          for (int i = 0; i != node.SubtreeCount; ++i) {
157            var child = node.GetSubtree(i);
158            var childLabel = child.Label();
159            var childVertex = graph.GetNode(childLabel);
160
161            if (childVertex == null) { // highly unlikely but it is possible
162              graph.AddNode(new SymbolNode { Label = childLabel, Symbol = child.Symbol, Weight = 1.0, AverageArity = node.SubtreeCount });
163              childVertex = graph.GetNode(childLabel);
164            }
165
166            if (parentVertex.OutEdges == null)
167              parentVertex.AddForwardArc(childVertex, 1.0);
168            else {
169              var arc = parentVertex.OutEdges.Find(x => x.Target == childVertex);
170              if (arc == null) childVertex.AddForwardArc(childVertex, 1.0);
171              else arc.Weight += 1.0;
172            }
173
174            if (childVertex.Positions == null) {
175              childVertex.Positions = new Dictionary<int, int> { { i, 1 } };
176            } else if (childVertex.Positions.ContainsKey(i)) {
177              childVertex.Positions[i] += 1;
178            } else {
179              childVertex.Positions.Add(i, 1);
180            }
181          }
182        }
183      }
184
185      foreach (var f in outFragments) {
186        foreach (var node in f.Root.IterateNodesPrefix()) {
187          var parentLabel = node.Label();
188          var parentVertex = graph.GetNode(parentLabel);
189          if (parentVertex == null)
190            throw new ArgumentException("parentVertex for node in outFragment can (should) not be null!");
191
192          parentVertex.Weight--;
193
194          for (int i = 0; i != node.SubtreeCount; ++i) {
195            var child = node.GetSubtree(i);
196            var childVertex = graph.GetNode(child.Label());
197            if (childVertex == null)
198              throw new ArgumentException("childVertex for node in outFragment can (should) not be null!");
199
200            //            childVertex.Weight--;
201
202            var arc = parentVertex.OutEdges.Find(x => x.Target == childVertex);
203            if (arc == null)
204              throw new Exception("An arc should already exist between the parent and the child.");
205
206            arc.Weight -= 1.0;
207
208            if (arc.Weight < 0.0)
209              throw new ArgumentException("Weight cannot be negative!");
210          }
211        }
212      }
213    }
214
215    private static void NormalizeGraph(SymbolGraph graph) {
216      var nodes = graph.Nodes;
217      var sum = nodes.Sum(n => n.Weight);
218      foreach (var n in nodes) {
219        n.Weight /= sum;
220        if (n.OutEdges == null || n.OutEdges.Count <= 0) continue;
221        var arcSum = n.OutEdges.Sum(arc => arc.Weight);
222        foreach (var arc in n.OutEdges)
223          arc.Weight /= arcSum;
224      }
225    }
226    private static void PruneGraph(SymbolGraph graph) {
227      var arcs = graph.Nodes.Where(node => node.OutEdges != null).SelectMany(node => node.OutEdges).ToList();
228      var arcWeights = arcs.Select(arc => arc.Weight).ToList();
229      var median = arcWeights.Median();
230      foreach (var node in graph.Nodes.Where(n => n.OutEdges != null)) {
231        node.OutEdges.RemoveAll(arc => arc.Weight < median || ((SymbolNode)arc.Target).Symbol is Constant);
232        node.OutEdges.RemoveAll(arc => arc.Weight < median);
233      }
234    }
235  }
236}
Note: See TracBrowser for help on using the repository browser.