Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.GP.StructureIdentification.Networks/3.2/NetworkToFunctionTransformer.cs @ 2622

Last change on this file since 2622 was 2622, checked in by gkronber, 15 years ago

Worked on evaluation operators for multiple-target modeling. #833

File size: 12.6 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.Data;
28using HeuristicLab.GP.Interfaces;
29using HeuristicLab.Modeling;
30using HeuristicLab.DataAnalysis;
31using System.Diagnostics;
32
33namespace HeuristicLab.GP.StructureIdentification.Networks {
34  public class NetworkToFunctionTransformer : OperatorBase {
35    public NetworkToFunctionTransformer()
36      : base() {
37      AddVariableInfo(new VariableInfo("Network", "The network (open expression)", typeof(IGeneticProgrammingModel), VariableKind.In));
38      AddVariableInfo(new VariableInfo("TargetVariables", "Name of the target variables", typeof(ItemList<StringData>), VariableKind.In));
39      AddVariableInfo(new VariableInfo("FunctionTree", "The function tree with all targetvaribales", typeof(IGeneticProgrammingModel), VariableKind.New));
40    }
41
42    public override string Description {
43      get { return "Extracts the network (function tree with unbound parameters) and creates a closed form function tree for each target variable."; }
44    }
45
46    public override IOperation Apply(IScope scope) {
47      IGeneticProgrammingModel model = GetVariableValue<IGeneticProgrammingModel>("Network", scope, true);
48      ItemList<StringData> targetVariables = GetVariableValue<ItemList<StringData>>("TargetVariables", scope, true);
49      // clear old sub-scopes
50      while (scope.SubScopes.Count > 0) scope.RemoveSubScope(scope.SubScopes[0]);
51
52      // create a new sub-scope for each target variable with the transformed expression
53      foreach (IFunctionTree transformedTree in Transform(model.FunctionTree, targetVariables.Select(x => x.Data))) {
54        Scope exprScope = new Scope();
55        scope.AddSubScope(exprScope);
56        exprScope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), new GeneticProgrammingModel(transformedTree)));
57      }
58
59      return null;
60    }
61
62    private static IEnumerable<IFunctionTree> Transform(IFunctionTree networkDescription, IEnumerable<string> targetVariables) {
63      // bind open parameters of network to target variables
64      //IFunctionTree openExpression = RemoveOpenParameters(networkDescription);
65      IFunctionTree paritallyEvaluatedOpenExpression = ApplyMetaFunctions((IFunctionTree)networkDescription.Clone());
66      IFunctionTree boundExpression = BindVariables(paritallyEvaluatedOpenExpression, targetVariables.GetEnumerator());
67
68      // create a new sub-scope for each target variable with the transformed expression
69      foreach (var targetVariable in targetVariables) {
70        yield return TransformExpression(boundExpression, targetVariable);
71      }
72    }
73
74    private static IFunctionTree ApplyMetaFunctions(IFunctionTree tree) {
75      IFunctionTree root = ApplyCycles(tree);
76      List<IFunctionTree> subTrees = new List<IFunctionTree>(root.SubTrees);
77      while (root.SubTrees.Count > 0) root.RemoveSubTree(0);
78
79      foreach (IFunctionTree subTree in subTrees) {
80        root.AddSubTree(ApplyFlips(subTree));
81      }
82      return root;
83    }
84
85    private static IFunctionTree ApplyFlips(IFunctionTree tree) {
86      if (tree.SubTrees.Count == 0) {
87        return tree;
88      } else if (tree.Function is Flip) {
89        return InvertFunction(tree.SubTrees[0]);
90      } else {
91        IFunctionTree tmp = ApplyFlips(tree.SubTrees[0]);
92        tree.RemoveSubTree(0); tree.AddSubTree(tmp);
93        return tree;
94      }
95    }
96
97    private static IFunctionTree ApplyCycles(IFunctionTree tree) {
98      int nRotations = 0;
99      while (tree.Function is Cycle) {
100        nRotations++;
101        tree = tree.SubTrees[0];
102      }
103      if (nRotations > 0 && nRotations % tree.SubTrees.Count > 0) {
104        IFunctionTree[] subTrees = tree.SubTrees.ToArray();
105        while (tree.SubTrees.Count > 0) tree.RemoveSubTree(0);
106
107        nRotations = nRotations % subTrees.Length;
108        Array.Reverse(subTrees, 0, nRotations);
109        Array.Reverse(subTrees, nRotations, subTrees.Length - nRotations);
110        Array.Reverse(subTrees, 0, subTrees.Length);
111
112        for (int i = 0; i < subTrees.Length; i++) {
113          tree.AddSubTree(subTrees[i]);
114        }
115      }
116      return tree;
117    }
118
119    private static IFunctionTree InvertFunction(IFunctionTree tree) {
120      IFunctionTree invertedNode = null;
121      if (tree.Function is OpenParameter || tree.Function is Variable) {
122        return tree;
123      } else if (tree.Function is AdditionF1) {
124        invertedNode = (new SubtractionF1()).GetTreeNode();
125        invertedNode.AddSubTree(tree.SubTrees[1]);
126      } else if (tree.Function is DivisionF1) {
127        invertedNode = (new MultiplicationF1()).GetTreeNode();
128        invertedNode.AddSubTree(tree.SubTrees[1]);
129      } else if (tree.Function is MultiplicationF1) {
130        invertedNode = (new DivisionF1()).GetTreeNode();
131        invertedNode.AddSubTree(tree.SubTrees[1]);
132      } else if (tree.Function is SubtractionF1) {
133        invertedNode = (new AdditionF1()).GetTreeNode();
134        invertedNode.AddSubTree(tree.SubTrees[1]);
135      } else if (tree.Function is OpenExp) {
136        invertedNode = (new OpenLog()).GetTreeNode();
137      } else if (tree.Function is OpenLog) {
138        invertedNode = (new OpenLog()).GetTreeNode();
139      } else if (tree.Function is OpenSqrt) {
140        invertedNode = (new OpenSqr()).GetTreeNode();
141      } else {
142        throw new ArgumentException();
143      }
144      IFunctionTree invertedTail = ApplyFlips(tree.SubTrees[0]);
145      if (invertedTail.Function is OpenParameter || invertedTail.Function is Variable) {
146        invertedNode.InsertSubTree(0, invertedTail);
147        return invertedNode;
148      } else {
149        return AppendLeft(invertedTail, invertedNode);
150      }
151    }
152
153    private static IFunctionTree AppendLeft(IFunctionTree tree, IFunctionTree node) {
154      IFunctionTree originalTree = tree;
155      while (tree.SubTrees[0].SubTrees.Count > 0) tree = tree.SubTrees[0];
156      tree.InsertSubTree(0, node);
157      return originalTree;
158    }
159
160    private static IFunctionTree TransformExpression(IFunctionTree tree, string targetVariable) {
161      if (tree.SubTrees.Count >= 3) {
162        int targetIndex = -1;
163        IFunctionTree combinator;
164        List<IFunctionTree> subTrees = new List<IFunctionTree>(tree.SubTrees);
165        //while (tree.SubTrees.Count > 0) tree.RemoveSubTree(0);
166        if (HasTargetVariable(subTrees[0], targetVariable)) {
167          targetIndex = 0;
168          combinator = FunctionFromCombinator(tree);
169        } else {
170          for (int i = 1; i < subTrees.Count; i++) {
171            if (HasTargetVariable(subTrees[i], targetVariable)) {
172              targetIndex = i;
173              break;
174            }
175          }
176          combinator = FunctionFromCombinator(InvertCombinator(tree));
177        }
178        // not found
179        if (targetIndex == -1) throw new InvalidOperationException();
180        IFunctionTree targetChain = TransformToFunction(InvertFunction(subTrees[targetIndex]));
181        for (int i = 0; i < subTrees.Count; i++) {
182          if (i != targetIndex)
183            combinator.AddSubTree(TransformToFunction(subTrees[i]));
184        }
185        if (targetChain.Function is Variable) return combinator;
186        else {
187          AppendLeft(targetChain, combinator);
188          return targetChain;
189        }
190      }
191      throw new NotImplementedException();
192    }
193
194    private static IFunctionTree TransformToFunction(IFunctionTree tree) {
195      if (tree.SubTrees.Count == 0) return tree;
196      else if (tree.Function is AdditionF1) {
197        var addTree = (new Addition()).GetTreeNode();
198        foreach (var subTree in tree.SubTrees) {
199          addTree.AddSubTree(TransformToFunction(subTree));
200        }
201        return addTree;
202      } else if (tree.Function is SubtractionF1) {
203        var sTree = (new Subtraction()).GetTreeNode();
204        foreach (var subTree in tree.SubTrees) {
205          sTree.AddSubTree(TransformToFunction(subTree));
206        }
207        return sTree;
208      } else if (tree.Function is MultiplicationF1) {
209        var mulTree = (new Multiplication()).GetTreeNode();
210        foreach (var subTree in tree.SubTrees) {
211          mulTree.AddSubTree(TransformToFunction(subTree));
212        }
213        return mulTree;
214      } else if (tree.Function is DivisionF1) {
215        var divTree = (new Division()).GetTreeNode();
216        foreach (var subTree in tree.SubTrees) {
217          divTree.AddSubTree(TransformToFunction(subTree));
218        }
219        return divTree;
220      } else if (tree.Function is OpenExp) {
221        var expTree = (new Exponential()).GetTreeNode();
222        expTree.AddSubTree(TransformToFunction(tree.SubTrees[0]));
223        return expTree;
224      } else if (tree.Function is OpenLog) {
225        var logTree = (new Logarithm()).GetTreeNode();
226        logTree.AddSubTree(TransformToFunction(tree.SubTrees[0]));
227        return logTree;
228      } else if (tree.Function is OpenSqr) {
229        var powTree = (new Power()).GetTreeNode();
230        powTree.AddSubTree(TransformToFunction(tree.SubTrees[0]));
231        var const2 = (ConstantFunctionTree)(new Constant()).GetTreeNode();
232        const2.Value = 2.0;
233        powTree.AddSubTree(const2);
234        return powTree;
235      } else if (tree.Function is OpenSqrt) {
236        var sqrtTree = (new Sqrt()).GetTreeNode();
237        sqrtTree.AddSubTree(TransformToFunction(tree.SubTrees[0]));
238        return sqrtTree;
239      }
240      throw new ArgumentException();
241    }
242
243    private static IFunctionTree InvertCombinator(IFunctionTree tree) {
244      if (tree.Function is OpenAddition) {
245        return (new OpenSubtraction()).GetTreeNode();
246      } else if (tree.Function is OpenSubtraction) {
247        return (new OpenAddition()).GetTreeNode();
248      } else if (tree.Function is OpenMultiplication) {
249        return (new OpenDivision()).GetTreeNode();
250      } else if (tree.Function is OpenDivision) {
251        return (new OpenMultiplication()).GetTreeNode();
252      } else throw new InvalidOperationException();
253    }
254
255    private static IFunctionTree FunctionFromCombinator(IFunctionTree tree) {
256      if (tree.Function is OpenAddition) {
257        return (new Addition()).GetTreeNode();
258      } else if (tree.Function is OpenSubtraction) {
259        return (new Subtraction()).GetTreeNode();
260      } else if (tree.Function is OpenMultiplication) {
261        return (new Multiplication()).GetTreeNode();
262      } else if (tree.Function is OpenDivision) {
263        return (new Division()).GetTreeNode();
264      } else throw new InvalidOperationException();
265    }
266
267    private static bool HasTargetVariable(IFunctionTree tree, string targetVariable) {
268      if (tree.SubTrees.Count == 0) {
269        var varTree = tree as VariableFunctionTree;
270        if (varTree != null) return varTree.VariableName == targetVariable;
271        else return false;
272      } else return (from x in tree.SubTrees
273                     where HasTargetVariable(x, targetVariable)
274                     select true).Any();
275    }
276
277    private static IFunctionTree BindVariables(IFunctionTree tree, IEnumerator<string> targetVariables) {
278      if (tree.Function is OpenParameter && targetVariables.MoveNext()) {
279        var varTreeNode = (VariableFunctionTree)(new Variable()).GetTreeNode();
280        varTreeNode.VariableName = targetVariables.Current;
281        varTreeNode.SampleOffset = ((OpenParameterFunctionTree)tree).SampleOffset;
282        varTreeNode.Weight = 1.0;
283        return varTreeNode;
284      } else {
285        IList<IFunctionTree> subTrees = new List<IFunctionTree>(tree.SubTrees);
286        while (tree.SubTrees.Count > 0) tree.RemoveSubTree(0);
287        foreach (IFunctionTree subTree in subTrees) {
288          tree.AddSubTree(BindVariables(subTree, targetVariables));
289        }
290        return tree;
291      }
292    }
293  }
294}
Note: See TracBrowser for help on using the repository browser.