Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Functions/BakedFunctionTree.cs @ 319

Last change on this file since 319 was 319, checked in by gkronber, 16 years ago

simplified symbol-table mechanism (ticket #168)

File size: 10.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 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.Linq;
25using System.Text;
26using HeuristicLab.Core;
27using HeuristicLab.DataAnalysis;
28using HeuristicLab.Data;
29using System.Xml;
30using System.Globalization;
31
32namespace HeuristicLab.Functions {
33
34  class LightWeightFunction {
35    public int arity = 0;
36    public IFunction functionType;
37    public List<double> data = new List<double>();
38
39    public LightWeightFunction Clone() {
40      LightWeightFunction clone = new LightWeightFunction();
41      clone.arity = arity;
42      clone.functionType = functionType;
43      clone.data.AddRange(data);
44      return clone;
45    }
46  }
47
48  class BakedFunctionTree : ItemBase, IFunctionTree {
49    private List<LightWeightFunction> linearRepresentation;
50    private bool treesExpanded = false;
51    private List<IFunctionTree> subTrees;
52    private bool variablesExpanded = false;
53    private List<IVariable> variables;
54    private BakedTreeEvaluator evaluator = null;
55
56    public BakedFunctionTree() {
57      linearRepresentation = new List<LightWeightFunction>();
58    }
59
60    internal BakedFunctionTree(IFunction function)
61      : this() {
62      LightWeightFunction fun = new LightWeightFunction();
63      fun.functionType = function;
64      linearRepresentation.Add(fun);
65      treesExpanded = true;
66      subTrees = new List<IFunctionTree>();
67      variables = new List<IVariable>();
68      variablesExpanded = true;
69      foreach(IVariableInfo variableInfo in function.VariableInfos) {
70        if(variableInfo.Local) {
71          variables.Add((IVariable)function.GetVariable(variableInfo.FormalName).Clone());
72        }
73      }
74    }
75
76    internal BakedFunctionTree(IFunctionTree tree)
77      : this() {
78      LightWeightFunction fun = new LightWeightFunction();
79      fun.functionType = tree.Function;
80      linearRepresentation.Add(fun);
81      foreach(IVariable variable in tree.LocalVariables) {
82        IItem value = variable.Value;
83        fun.data.Add(GetDoubleValue(value));
84      }
85      foreach(IFunctionTree subTree in tree.SubTrees) {
86        AddSubTree(new BakedFunctionTree(subTree));
87      }
88    }
89
90    private double GetDoubleValue(IItem value) {
91      if(value is DoubleData) {
92        return ((DoubleData)value).Data;
93      } else if(value is ConstrainedDoubleData) {
94        return ((ConstrainedDoubleData)value).Data;
95      } else if(value is IntData) {
96        return ((IntData)value).Data;
97      } else if(value is ConstrainedIntData) {
98        return ((ConstrainedIntData)value).Data;
99      } else throw new NotSupportedException("Invalid datatype of local variable for GP");
100    }
101
102    private int BranchLength(int branchRoot) {
103      int arity = linearRepresentation[branchRoot].arity;
104      int length = 1;
105      for(int i = 0; i < arity; i++) {
106        length += BranchLength(branchRoot + length);
107      }
108      return length;
109    }
110
111    private void FlattenTrees() {
112      if(treesExpanded) {
113        linearRepresentation[0].arity = subTrees.Count;
114        foreach(BakedFunctionTree subTree in subTrees) {
115          subTree.FlattenVariables();
116          subTree.FlattenTrees();
117          linearRepresentation.AddRange(subTree.linearRepresentation);
118        }
119        treesExpanded = false;
120        subTrees = null;
121      }
122    }
123
124    private void FlattenVariables() {
125      if(variablesExpanded) {
126        linearRepresentation[0].data.Clear();
127        foreach(IVariable variable in variables) {
128          linearRepresentation[0].data.Add(GetDoubleValue(variable.Value));
129        }
130        variablesExpanded = false;
131        variables = null;
132      }
133    }
134
135    public IList<IFunctionTree> SubTrees {
136      get {
137        if(!treesExpanded) {
138          subTrees = new List<IFunctionTree>();
139          int arity = linearRepresentation[0].arity;
140          int branchIndex = 1;
141          for(int i = 0; i < arity; i++) {
142            BakedFunctionTree subTree = new BakedFunctionTree();
143            int length = BranchLength(branchIndex);
144            for(int j = branchIndex; j < branchIndex + length; j++) {
145              subTree.linearRepresentation.Add(linearRepresentation[j].Clone());
146            }
147            branchIndex += length;
148            subTrees.Add(subTree);
149          }
150          treesExpanded = true;
151          linearRepresentation.RemoveRange(1, linearRepresentation.Count - 1);
152          linearRepresentation[0].arity = 0;
153        }
154        return subTrees;
155      }
156    }
157
158    public ICollection<IVariable> LocalVariables {
159      get {
160        if(!variablesExpanded) {
161          variables = new List<IVariable>();
162          IFunction function = Function;
163          int localVariableIndex = 0;
164          foreach(IVariableInfo variableInfo in function.VariableInfos) {
165            if(variableInfo.Local) {
166              IVariable clone = (IVariable)function.GetVariable(variableInfo.FormalName).Clone();
167              IItem value = clone.Value;
168              if(value is ConstrainedDoubleData) {
169                ((ConstrainedDoubleData)value).Data = linearRepresentation[0].data[localVariableIndex];
170              } else if(value is ConstrainedIntData) {
171                ((ConstrainedIntData)value).Data = (int)linearRepresentation[0].data[localVariableIndex];
172              } else if(value is DoubleData) {
173                ((DoubleData)value).Data = linearRepresentation[0].data[localVariableIndex];
174              } else if(value is IntData) {
175                ((IntData)value).Data = (int)linearRepresentation[0].data[localVariableIndex];
176              } else throw new NotSupportedException("Invalid local variable type for GP.");
177              variables.Add(clone);
178              localVariableIndex++;
179            }
180          }
181          variablesExpanded = true;
182          linearRepresentation[0].data.Clear();
183        }
184        return variables;
185      }
186    }
187
188    public IFunction Function {
189      get { return linearRepresentation[0].functionType; }
190    }
191
192    public IVariable GetLocalVariable(string name) {
193      foreach(IVariable var in LocalVariables) {
194        if(var.Name == name) return var;
195      }
196      return null;
197    }
198
199    public void AddVariable(IVariable variable) {
200      throw new NotSupportedException();
201    }
202
203    public void RemoveVariable(string name) {
204      throw new NotSupportedException();
205    }
206
207    public void AddSubTree(IFunctionTree tree) {
208      if(!treesExpanded) throw new InvalidOperationException();
209      subTrees.Add(tree);
210    }
211
212    public void InsertSubTree(int index, IFunctionTree tree) {
213      if(!treesExpanded) throw new InvalidOperationException();
214      subTrees.Insert(index, tree);
215    }
216
217    public void RemoveSubTree(int index) {
218      // sanity check
219      if(!treesExpanded) throw new InvalidOperationException();
220      subTrees.RemoveAt(index);
221    }
222
223    public double Evaluate(Dataset dataset, int sampleIndex) {
224      FlattenVariables();
225      FlattenTrees();
226      if(evaluator == null) evaluator = new BakedTreeEvaluator(linearRepresentation);
227      return evaluator.Evaluate(dataset, sampleIndex);
228    }
229
230
231    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
232      FlattenVariables();
233      FlattenTrees();
234      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
235      throw new NotImplementedException();
236      //XmlAttribute codeAttribute = document.CreateAttribute("LinearRepresentation");
237      //codeAttribute.Value = GetString<int>(code);
238      //node.Attributes.Append(codeAttribute);
239      //return node;
240    }
241
242    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
243      throw new NotImplementedException();
244      //base.Populate(node, restoredObjects);
245      //XmlNode evaluatorNode = node.SelectSingleNode("Evaluator");
246      //if(evaluatorNode != null) {
247      //  this.evaluator = (BakedTreeEvaluator)PersistenceManager.Restore(evaluatorNode, restoredObjects);
248      //}
249      //code = GetList<int>(node.Attributes["Code"].Value, s => int.Parse(s, CultureInfo.InvariantCulture));
250      //data = GetList<double>(node.Attributes["Data"].Value, s => double.Parse(s, CultureInfo.InvariantCulture));
251      //treesExpanded = false;
252      //variablesExpanded = false;
253    }
254
255    //private string GetString<T>(IEnumerable<T> xs) where T : IConvertible {
256    //  StringBuilder builder = new StringBuilder();
257    //  foreach(T x in xs) {
258    //    builder.Append(x.ToString(CultureInfo.InvariantCulture) + "; ");
259    //  }
260    //  if(builder.Length > 0) builder.Remove(builder.Length - 2, 2);
261    //  return builder.ToString();
262    //}
263
264    //private List<T> GetList<T>(string s, Converter<string, T> converter) {
265    //  List<T> result = new List<T>();
266    //  string[] tokens = s.Split(new char[] {';',' '}, StringSplitOptions.RemoveEmptyEntries);
267    //  foreach(string token in tokens) {
268    //    T x = converter(token.Trim());
269    //    result.Add(x);
270    //  }
271    //  return result;
272    //}
273
274    public override object Clone(IDictionary<Guid, object> clonedObjects) {
275      BakedFunctionTree clone = new BakedFunctionTree();
276      // in case the user (de)serialized the tree between evaluation and selection we have to flatten the tree again.
277      if(treesExpanded) FlattenTrees();
278      if(variablesExpanded) FlattenVariables();
279      foreach(LightWeightFunction f in linearRepresentation) {
280        clone.linearRepresentation.Add(f.Clone());
281      }
282      return clone;
283    }
284
285    public override IView CreateView() {
286      return new FunctionTreeView(this);
287    }
288  }
289}
Note: See TracBrowser for help on using the repository browser.