Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/VectorTreeSimplifier.cs @ 17604

Last change on this file since 17604 was 17604, checked in by pfleck, 4 years ago

#3040 Stores the datatype of a tree node (e.g. variable nodes) in the tree itself for the interpreter to derive the datatypes for subtrees. This way, the interpreter (and simplifier) do not need an actual dataset to figure out datatypes for subtrees.

File size: 82.1 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#endregion
23
24using System;
25using System.Collections.Generic;
26using System.Linq;
27using HeuristicLab.Common;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29
30using DoubleVector = MathNet.Numerics.LinearAlgebra.Vector<double>;
31
32namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
33  /// <summary>
34  /// Simplifier for symbolic expressions
35  /// </summary>
36  public class VectorTreeSimplifier {
37    private static readonly Addition addSymbol = new Addition();
38    private static readonly Multiplication mulSymbol = new Multiplication();
39    private static readonly Division divSymbol = new Division();
40    private static readonly Constant constSymbol = new Constant();
41    private static readonly Absolute absSymbol = new Absolute();
42    private static readonly Logarithm logSymbol = new Logarithm();
43    private static readonly Exponential expSymbol = new Exponential();
44    private static readonly Root rootSymbol = new Root();
45    private static readonly Square sqrSymbol = new Square();
46    private static readonly SquareRoot sqrtSymbol = new SquareRoot();
47    private static readonly AnalyticQuotient aqSymbol = new AnalyticQuotient();
48    private static readonly Cube cubeSymbol = new Cube();
49    private static readonly CubeRoot cubeRootSymbol = new CubeRoot();
50    private static readonly Power powSymbol = new Power();
51    private static readonly Sine sineSymbol = new Sine();
52    private static readonly Cosine cosineSymbol = new Cosine();
53    private static readonly Tangent tanSymbol = new Tangent();
54    private static readonly IfThenElse ifThenElseSymbol = new IfThenElse();
55    private static readonly And andSymbol = new And();
56    private static readonly Or orSymbol = new Or();
57    private static readonly Not notSymbol = new Not();
58    private static readonly GreaterThan gtSymbol = new GreaterThan();
59    private static readonly LessThan ltSymbol = new LessThan();
60    private static readonly Integral integralSymbol = new Integral();
61    private static readonly LaggedVariable laggedVariableSymbol = new LaggedVariable();
62    private static readonly TimeLag timeLagSymbol = new TimeLag();
63    private static readonly Sum sumSymbol = new Sum();
64    private static readonly Mean meanSymbol = new Mean();
65    private static readonly Length lengthSymbol = new Length();
66    private static readonly StandardDeviation standardDeviationSymbol = new StandardDeviation();
67    private static readonly Variance varianceSymbol = new Variance();
68
69    private readonly SymbolicDataAnalysisExpressionTreeVectorInterpreter interpreter;
70
71    public VectorTreeSimplifier(SymbolicDataAnalysisExpressionTreeVectorInterpreter interpreter) {
72      this.interpreter = interpreter;
73    }
74
75    public ISymbolicExpressionTree Simplify(ISymbolicExpressionTree originalTree) {
76      var clone = (ISymbolicExpressionTreeNode)originalTree.Root.Clone();
77      // macro expand (initially no argument trees)
78      var macroExpandedTree = MacroExpand(clone, clone.GetSubtree(0), new List<ISymbolicExpressionTreeNode>());
79      ISymbolicExpressionTreeNode rootNode = (new ProgramRootSymbol()).CreateTreeNode();
80      rootNode.AddSubtree(GetSimplifiedTree(macroExpandedTree));
81
82#if DEBUG
83      // check that each node is only referenced once
84      var nodes = rootNode.IterateNodesPrefix().ToArray();
85      foreach (var n in nodes) if (nodes.Count(ni => ni == n) > 1) throw new InvalidOperationException();
86#endif
87      return new SymbolicExpressionTree(rootNode);
88    }
89
90    // the argumentTrees list contains already expanded trees used as arguments for invocations
91    private static ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node,
92      IList<ISymbolicExpressionTreeNode> argumentTrees) {
93      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
94      while (node.SubtreeCount > 0) node.RemoveSubtree(0);
95      if (node.Symbol is InvokeFunction) {
96        var invokeSym = node.Symbol as InvokeFunction;
97        var defunNode = FindFunctionDefinition(root, invokeSym.FunctionName);
98        var macroExpandedArguments = new List<ISymbolicExpressionTreeNode>();
99        foreach (var subtree in subtrees) {
100          macroExpandedArguments.Add(MacroExpand(root, subtree, argumentTrees));
101        }
102        return MacroExpand(root, defunNode, macroExpandedArguments);
103      } else if (node.Symbol is Argument) {
104        var argSym = node.Symbol as Argument;
105        // return the correct argument sub-tree (already macro-expanded)
106        return (SymbolicExpressionTreeNode)argumentTrees[argSym.ArgumentIndex].Clone();
107      } else {
108        // recursive application
109        foreach (var subtree in subtrees) {
110          node.AddSubtree(MacroExpand(root, subtree, argumentTrees));
111        }
112        return node;
113      }
114    }
115
116    private static ISymbolicExpressionTreeNode FindFunctionDefinition(ISymbolicExpressionTreeNode root, string functionName) {
117      foreach (var subtree in root.Subtrees.OfType<DefunTreeNode>()) {
118        if (subtree.FunctionName == functionName) return subtree.GetSubtree(0);
119      }
120
121      throw new ArgumentException("Definition of function " + functionName + " not found.");
122    }
123
124    #region symbol predicates
125
126    // arithmetic
127    private static bool IsDivision(ISymbolicExpressionTreeNode node) {
128      return node.Symbol is Division;
129    }
130
131    private static bool IsMultiplication(ISymbolicExpressionTreeNode node) {
132      return node.Symbol is Multiplication;
133    }
134
135    private static bool IsSubtraction(ISymbolicExpressionTreeNode node) {
136      return node.Symbol is Subtraction;
137    }
138
139    private static bool IsAddition(ISymbolicExpressionTreeNode node) {
140      return node.Symbol is Addition;
141    }
142
143    private static bool IsAverage(ISymbolicExpressionTreeNode node) {
144      return node.Symbol is Average;
145    }
146
147    private static bool IsAbsolute(ISymbolicExpressionTreeNode node) {
148      return node.Symbol is Absolute;
149    }
150
151    // exponential
152    private static bool IsLog(ISymbolicExpressionTreeNode node) {
153      return node.Symbol is Logarithm;
154    }
155
156    private static bool IsExp(ISymbolicExpressionTreeNode node) {
157      return node.Symbol is Exponential;
158    }
159
160    private static bool IsRoot(ISymbolicExpressionTreeNode node) {
161      return node.Symbol is Root;
162    }
163
164    private static bool IsSquare(ISymbolicExpressionTreeNode node) {
165      return node.Symbol is Square;
166    }
167
168    private static bool IsSquareRoot(ISymbolicExpressionTreeNode node) {
169      return node.Symbol is SquareRoot;
170    }
171
172    private static bool IsCube(ISymbolicExpressionTreeNode node) {
173      return node.Symbol is Cube;
174    }
175
176    private static bool IsCubeRoot(ISymbolicExpressionTreeNode node) {
177      return node.Symbol is CubeRoot;
178    }
179
180    private static bool IsPower(ISymbolicExpressionTreeNode node) {
181      return node.Symbol is Power;
182    }
183
184    // trigonometric
185    private static bool IsSine(ISymbolicExpressionTreeNode node) {
186      return node.Symbol is Sine;
187    }
188
189    private static bool IsCosine(ISymbolicExpressionTreeNode node) {
190      return node.Symbol is Cosine;
191    }
192
193    private static bool IsTangent(ISymbolicExpressionTreeNode node) {
194      return node.Symbol is Tangent;
195    }
196
197    private static bool IsAnalyticalQuotient(ISymbolicExpressionTreeNode node) {
198      return node.Symbol is AnalyticQuotient;
199    }
200
201    // boolean
202    private static bool IsIfThenElse(ISymbolicExpressionTreeNode node) {
203      return node.Symbol is IfThenElse;
204    }
205
206    private static bool IsAnd(ISymbolicExpressionTreeNode node) {
207      return node.Symbol is And;
208    }
209
210    private static bool IsOr(ISymbolicExpressionTreeNode node) {
211      return node.Symbol is Or;
212    }
213
214    private static bool IsNot(ISymbolicExpressionTreeNode node) {
215      return node.Symbol is Not;
216    }
217
218    // comparison
219    private static bool IsGreaterThan(ISymbolicExpressionTreeNode node) {
220      return node.Symbol is GreaterThan;
221    }
222
223    private static bool IsLessThan(ISymbolicExpressionTreeNode node) {
224      return node.Symbol is LessThan;
225    }
226
227    private static bool IsBoolean(ISymbolicExpressionTreeNode node) {
228      return
229        node.Symbol is GreaterThan ||
230        node.Symbol is LessThan ||
231        node.Symbol is And ||
232        node.Symbol is Or;
233    }
234
235    // terminals
236    private static bool IsVariable(ISymbolicExpressionTreeNode node) {
237      return node.Symbol is Variable;
238    }
239
240    private static bool IsVariableBase(ISymbolicExpressionTreeNode node) {
241      return node is VariableTreeNodeBase;
242    }
243
244    private static bool IsFactor(ISymbolicExpressionTreeNode node) {
245      return node is FactorVariableTreeNode;
246    }
247
248    private static bool IsBinFactor(ISymbolicExpressionTreeNode node) {
249      return node is BinaryFactorVariableTreeNode;
250    }
251
252    private static bool IsConstant(ISymbolicExpressionTreeNode node) {
253      return node.Symbol is Constant;
254    }
255
256    // dynamic
257    private static bool IsTimeLag(ISymbolicExpressionTreeNode node) {
258      return node.Symbol is TimeLag;
259    }
260
261    private static bool IsIntegral(ISymbolicExpressionTreeNode node) {
262      return node.Symbol is Integral;
263    }
264
265    private static bool IsSum(ISymbolicExpressionTreeNode node) {
266      return node.Symbol is Sum;
267    }
268
269    private static bool IsMean(ISymbolicExpressionTreeNode node) {
270      return node.Symbol is Mean;
271    }
272
273    private static bool IsLength(ISymbolicExpressionTreeNode node) {
274      return node.Symbol is Length;
275    }
276
277    private static bool IsStandardDeviation(ISymbolicExpressionTreeNode node) {
278      return node.Symbol is StandardDeviation;
279    }
280
281    private static bool IsVariance(ISymbolicExpressionTreeNode node) {
282      return node.Symbol is Variance;
283    }
284    #endregion
285
286    #region type predicates
287    public bool IsScalarNode(ISymbolicExpressionTreeNode node) {
288      return interpreter.GetNodeType(node) == typeof(double);
289    }
290    public bool IsVectorNode(ISymbolicExpressionTreeNode node) {
291      return interpreter.GetNodeType(node) == typeof(DoubleVector);
292    }
293    #endregion
294
295    /// <summary>
296    /// Creates a new simplified tree
297    /// </summary>
298    /// <param name="original"></param>
299    /// <returns></returns>
300    public ISymbolicExpressionTreeNode GetSimplifiedTree(ISymbolicExpressionTreeNode original) {
301      if (IsConstant(original) || IsVariableBase(original)) {
302        return (ISymbolicExpressionTreeNode)original.Clone();
303      } else if (IsAbsolute(original)) {
304        return SimplifyAbsolute(original);
305      } else if (IsAddition(original)) {
306        return SimplifyAddition(original);
307      } else if (IsSubtraction(original)) {
308        return SimplifySubtraction(original);
309      } else if (IsMultiplication(original)) {
310        return SimplifyMultiplication(original);
311      } else if (IsDivision(original)) {
312        return SimplifyDivision(original);
313      } else if (IsAverage(original)) {
314        return SimplifyAverage(original);
315      } else if (IsLog(original)) {
316        return SimplifyLog(original);
317      } else if (IsExp(original)) {
318        return SimplifyExp(original);
319      } else if (IsSquare(original)) {
320        return SimplifySquare(original);
321      } else if (IsSquareRoot(original)) {
322        return SimplifySquareRoot(original);
323      } else if (IsCube(original)) {
324        return SimplifyCube(original);
325      } else if (IsCubeRoot(original)) {
326        return SimplifyCubeRoot(original);
327      } else if (IsPower(original)) {
328        return SimplifyPower(original);
329      } else if (IsRoot(original)) {
330        return SimplifyRoot(original);
331      } else if (IsSine(original)) {
332        return SimplifySine(original);
333      } else if (IsCosine(original)) {
334        return SimplifyCosine(original);
335      } else if (IsTangent(original)) {
336        return SimplifyTangent(original);
337      } else if (IsAnalyticalQuotient(original)) {
338        return SimplifyAnalyticalQuotient(original);
339      } else if (IsIfThenElse(original)) {
340        return SimplifyIfThenElse(original);
341      } else if (IsGreaterThan(original)) {
342        return SimplifyGreaterThan(original);
343      } else if (IsLessThan(original)) {
344        return SimplifyLessThan(original);
345      } else if (IsAnd(original)) {
346        return SimplifyAnd(original);
347      } else if (IsOr(original)) {
348        return SimplifyOr(original);
349      } else if (IsNot(original)) {
350        return SimplifyNot(original);
351      } else if (IsTimeLag(original)) {
352        return SimplifyTimeLag(original);
353      } else if (IsIntegral(original)) {
354        return SimplifyIntegral(original);
355      } else if (IsSum(original)) {
356        return SimplifySumAggregation(original);
357      } else if (IsMean(original)) {
358        return SimplifyMeanAggregation(original);
359      } else if (IsLength(original)) {
360        return SimplifyLengthAggregation(original);
361      } else if (IsStandardDeviation(original)) {
362        return SimplifyStandardDeviationAggregation(original);
363      } else if (IsVariance(original)) {
364        return SimplifyVarianceAggregation(original);
365      } else {
366        return SimplifyAny(original);
367      }
368    }
369
370    #region specific simplification routines
371
372    private ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) {
373      // can't simplify this function but simplify all subtrees
374      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees);
375      while (original.Subtrees.Count() > 0) original.RemoveSubtree(0);
376      var clone = (SymbolicExpressionTreeNode)original.Clone();
377      List<ISymbolicExpressionTreeNode> simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>();
378      foreach (var subtree in subtrees) {
379        simplifiedSubtrees.Add(GetSimplifiedTree(subtree));
380        original.AddSubtree(subtree);
381      }
382      foreach (var simplifiedSubtree in simplifiedSubtrees) {
383        clone.AddSubtree(simplifiedSubtree);
384      }
385      if (simplifiedSubtrees.TrueForAll(t => IsConstant(t))) {
386        SimplifyConstantExpression(clone);
387      }
388      return clone;
389    }
390
391    private ISymbolicExpressionTreeNode SimplifyConstantExpression(ISymbolicExpressionTreeNode original) {
392      // not yet implemented
393      return original;
394    }
395
396    private ISymbolicExpressionTreeNode SimplifyAverage(ISymbolicExpressionTreeNode original) {
397      if (original.Subtrees.Count() == 1) {
398        return GetSimplifiedTree(original.GetSubtree(0));
399      } else {
400        // simplify expressions x0..xn
401        // make sum(x0..xn) / n
402        var sum = original.Subtrees
403          .Select(GetSimplifiedTree)
404          .Aggregate(MakeSum);
405        return MakeFraction(sum, MakeConstant(original.Subtrees.Count()));
406      }
407    }
408
409    private ISymbolicExpressionTreeNode SimplifyDivision(ISymbolicExpressionTreeNode original) {
410      if (original.Subtrees.Count() == 1) {
411        return Invert(GetSimplifiedTree(original.GetSubtree(0)));
412      } else {
413        // simplify expressions x0..xn
414        // make multiplication (x0 * 1/(x1 * x1 * .. * xn))
415        var first = original.GetSubtree(0);
416        var second = original.GetSubtree(1);
417        var remaining = original.Subtrees.Skip(2);
418        return
419          MakeProduct(GetSimplifiedTree(first),
420            Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => MakeProduct(a, GetSimplifiedTree(b)))));
421      }
422    }
423
424    private ISymbolicExpressionTreeNode SimplifyMultiplication(ISymbolicExpressionTreeNode original) {
425      if (original.Subtrees.Count() == 1) {
426        return GetSimplifiedTree(original.GetSubtree(0));
427      } else {
428        return original.Subtrees
429          .Select(GetSimplifiedTree)
430          .Aggregate(MakeProduct);
431      }
432    }
433
434    private ISymbolicExpressionTreeNode SimplifySubtraction(ISymbolicExpressionTreeNode original) {
435      if (original.Subtrees.Count() == 1) {
436        return Negate(GetSimplifiedTree(original.GetSubtree(0)));
437      } else {
438        // simplify expressions x0..xn
439        // make addition (x0,-x1..-xn)
440        var first = original.Subtrees.First();
441        var remaining = original.Subtrees.Skip(1);
442        return remaining.Aggregate(GetSimplifiedTree(first), (a, b) => MakeSum(a, Negate(GetSimplifiedTree(b))));
443      }
444    }
445
446    private ISymbolicExpressionTreeNode SimplifyAddition(ISymbolicExpressionTreeNode original) {
447      if (original.Subtrees.Count() == 1) {
448        return GetSimplifiedTree(original.GetSubtree(0));
449      } else {
450        // simplify expression x0..xn
451        // make addition (x0..xn)
452        return original.Subtrees
453          .Select(GetSimplifiedTree)
454          .Aggregate(MakeSum);
455      }
456    }
457
458    private ISymbolicExpressionTreeNode SimplifyAbsolute(ISymbolicExpressionTreeNode original) {
459      return MakeAbs(GetSimplifiedTree(original.GetSubtree(0)));
460    }
461
462    private ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) {
463      return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
464    }
465
466    private ISymbolicExpressionTreeNode SimplifyOr(ISymbolicExpressionTreeNode original) {
467      return original.Subtrees
468        .Select(GetSimplifiedTree)
469        .Aggregate(MakeOr);
470    }
471
472    private ISymbolicExpressionTreeNode SimplifyAnd(ISymbolicExpressionTreeNode original) {
473      return original.Subtrees
474        .Select(GetSimplifiedTree)
475        .Aggregate(MakeAnd);
476    }
477
478    private ISymbolicExpressionTreeNode SimplifyLessThan(ISymbolicExpressionTreeNode original) {
479      return MakeLessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
480    }
481
482    private ISymbolicExpressionTreeNode SimplifyGreaterThan(ISymbolicExpressionTreeNode original) {
483      return MakeGreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
484    }
485
486    private ISymbolicExpressionTreeNode SimplifyIfThenElse(ISymbolicExpressionTreeNode original) {
487      return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)),
488        GetSimplifiedTree(original.GetSubtree(2)));
489    }
490
491    private ISymbolicExpressionTreeNode SimplifyTangent(ISymbolicExpressionTreeNode original) {
492      return MakeTangent(GetSimplifiedTree(original.GetSubtree(0)));
493    }
494
495    private ISymbolicExpressionTreeNode SimplifyCosine(ISymbolicExpressionTreeNode original) {
496      return MakeCosine(GetSimplifiedTree(original.GetSubtree(0)));
497    }
498
499    private ISymbolicExpressionTreeNode SimplifySine(ISymbolicExpressionTreeNode original) {
500      return MakeSine(GetSimplifiedTree(original.GetSubtree(0)));
501    }
502
503    private ISymbolicExpressionTreeNode SimplifyExp(ISymbolicExpressionTreeNode original) {
504      return MakeExp(GetSimplifiedTree(original.GetSubtree(0)));
505    }
506
507    private ISymbolicExpressionTreeNode SimplifySquare(ISymbolicExpressionTreeNode original) {
508      return MakeSquare(GetSimplifiedTree(original.GetSubtree(0)));
509    }
510
511    private ISymbolicExpressionTreeNode SimplifySquareRoot(ISymbolicExpressionTreeNode original) {
512      return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
513    }
514    private ISymbolicExpressionTreeNode SimplifyCube(ISymbolicExpressionTreeNode original) {
515      return MakeCube(GetSimplifiedTree(original.GetSubtree(0)));
516    }
517
518    private ISymbolicExpressionTreeNode SimplifyCubeRoot(ISymbolicExpressionTreeNode original) {
519      return MakeCubeRoot(GetSimplifiedTree(original.GetSubtree(0)));
520    }
521
522    private ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) {
523      return MakeLog(GetSimplifiedTree(original.GetSubtree(0)));
524    }
525
526    private ISymbolicExpressionTreeNode SimplifyRoot(ISymbolicExpressionTreeNode original) {
527      return MakeRoot(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
528    }
529
530    private ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) {
531      return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
532    }
533
534    private ISymbolicExpressionTreeNode SimplifyAnalyticalQuotient(ISymbolicExpressionTreeNode original) {
535      return MakeAnalyticalQuotient(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
536    }
537
538    private ISymbolicExpressionTreeNode SimplifyTimeLag(ISymbolicExpressionTreeNode original) {
539      var laggedTreeNode = original as ILaggedTreeNode;
540      var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0));
541      if (!ContainsVariableCondition(simplifiedSubtree)) {
542        return AddLagToDynamicNodes(simplifiedSubtree, laggedTreeNode.Lag);
543      } else {
544        return MakeTimeLag(simplifiedSubtree, laggedTreeNode.Lag);
545      }
546    }
547
548    private ISymbolicExpressionTreeNode SimplifyIntegral(ISymbolicExpressionTreeNode original) {
549      var laggedTreeNode = original as ILaggedTreeNode;
550      var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0));
551      if (IsConstant(simplifiedSubtree)) {
552        return GetSimplifiedTree(MakeProduct(simplifiedSubtree, MakeConstant(-laggedTreeNode.Lag)));
553      } else {
554        return MakeIntegral(simplifiedSubtree, laggedTreeNode.Lag);
555      }
556    }
557
558    private ISymbolicExpressionTreeNode SimplifySumAggregation(ISymbolicExpressionTreeNode original) {
559      return MakeSumAggregation(GetSimplifiedTree(original.GetSubtree(0)));
560    }
561
562    private ISymbolicExpressionTreeNode SimplifyMeanAggregation(ISymbolicExpressionTreeNode original) {
563      return MakeMeanAggregation(GetSimplifiedTree(original.GetSubtree(0)));
564    }
565
566    private ISymbolicExpressionTreeNode SimplifyLengthAggregation(ISymbolicExpressionTreeNode original) {
567      return MakeLengthAggregation(GetSimplifiedTree(original.GetSubtree(0)));
568    }
569
570    private ISymbolicExpressionTreeNode SimplifyStandardDeviationAggregation(ISymbolicExpressionTreeNode original) {
571      return MakeStandardDeviationAggregation(GetSimplifiedTree(original.GetSubtree(0)));
572    }
573
574    private ISymbolicExpressionTreeNode SimplifyVarianceAggregation(ISymbolicExpressionTreeNode original) {
575      return MakeVarianceAggregation(GetSimplifiedTree(original.GetSubtree(0)));
576    }
577    #endregion
578
579    #region low level tree restructuring
580
581    private ISymbolicExpressionTreeNode MakeTimeLag(ISymbolicExpressionTreeNode subtree, int lag) {
582      if (lag == 0) return subtree;
583      if (IsConstant(subtree)) return subtree;
584      var lagNode = (LaggedTreeNode)timeLagSymbol.CreateTreeNode();
585      lagNode.Lag = lag;
586      lagNode.AddSubtree(subtree);
587      return lagNode;
588    }
589
590    private ISymbolicExpressionTreeNode MakeIntegral(ISymbolicExpressionTreeNode subtree, int lag) {
591      if (lag == 0) return subtree;
592      else if (lag == -1 || lag == 1) {
593        return MakeSum(subtree, AddLagToDynamicNodes((ISymbolicExpressionTreeNode)subtree.Clone(), lag));
594      } else {
595        var node = (LaggedTreeNode)integralSymbol.CreateTreeNode();
596        node.Lag = lag;
597        node.AddSubtree(subtree);
598        return node;
599      }
600    }
601
602    private ISymbolicExpressionTreeNode MakeNot(ISymbolicExpressionTreeNode t) {
603      if (IsConstant(t)) {
604        var constNode = t as ConstantTreeNode;
605        if (constNode.Value > 0) return MakeConstant(-1.0);
606        else return MakeConstant(1.0);
607      } else if (IsNot(t)) {
608        return t.GetSubtree(0);
609      } else if (!IsBoolean(t)) {
610        var gtNode = gtSymbol.CreateTreeNode();
611        gtNode.AddSubtree(t);
612        gtNode.AddSubtree(MakeConstant(0.0));
613        var notNode = notSymbol.CreateTreeNode();
614        notNode.AddSubtree(gtNode);
615        return notNode;
616      } else {
617        var notNode = notSymbol.CreateTreeNode();
618        notNode.AddSubtree(t);
619        return notNode;
620      }
621    }
622
623    private ISymbolicExpressionTreeNode MakeOr(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
624      if (IsConstant(a) && IsConstant(b)) {
625        var constA = a as ConstantTreeNode;
626        var constB = b as ConstantTreeNode;
627        if (constA.Value > 0.0 || constB.Value > 0.0) {
628          return MakeConstant(1.0);
629        } else {
630          return MakeConstant(-1.0);
631        }
632      } else if (IsConstant(a)) {
633        return MakeOr(b, a);
634      } else if (IsConstant(b)) {
635        var constT = b as ConstantTreeNode;
636        if (constT.Value > 0.0) {
637          // boolean expression is necessarily true
638          return MakeConstant(1.0);
639        } else {
640          // the constant value has no effect on the result of the boolean condition so we can drop the constant term
641          var orNode = orSymbol.CreateTreeNode();
642          orNode.AddSubtree(a);
643          return orNode;
644        }
645      } else {
646        var orNode = orSymbol.CreateTreeNode();
647        orNode.AddSubtree(a);
648        orNode.AddSubtree(b);
649        return orNode;
650      }
651    }
652
653    private ISymbolicExpressionTreeNode MakeAnd(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
654      if (IsConstant(a) && IsConstant(b)) {
655        var constA = a as ConstantTreeNode;
656        var constB = b as ConstantTreeNode;
657        if (constA.Value > 0.0 && constB.Value > 0.0) {
658          return MakeConstant(1.0);
659        } else {
660          return MakeConstant(-1.0);
661        }
662      } else if (IsConstant(a)) {
663        return MakeAnd(b, a);
664      } else if (IsConstant(b)) {
665        var constB = b as ConstantTreeNode;
666        if (constB.Value > 0.0) {
667          // the constant value has no effect on the result of the boolean condition so we can drop the constant term
668          var andNode = andSymbol.CreateTreeNode();
669          andNode.AddSubtree(a);
670          return andNode;
671        } else {
672          // boolean expression is necessarily false
673          return MakeConstant(-1.0);
674        }
675      } else {
676        var andNode = andSymbol.CreateTreeNode();
677        andNode.AddSubtree(a);
678        andNode.AddSubtree(b);
679        return andNode;
680      }
681    }
682
683    private ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide,
684      ISymbolicExpressionTreeNode rightSide) {
685      if (IsConstant(leftSide) && IsConstant(rightSide)) {
686        var lsConst = leftSide as ConstantTreeNode;
687        var rsConst = rightSide as ConstantTreeNode;
688        if (lsConst.Value < rsConst.Value) return MakeConstant(1.0);
689        else return MakeConstant(-1.0);
690      } else {
691        var ltNode = ltSymbol.CreateTreeNode();
692        ltNode.AddSubtree(leftSide);
693        ltNode.AddSubtree(rightSide);
694        return ltNode;
695      }
696    }
697
698    private ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide,
699      ISymbolicExpressionTreeNode rightSide) {
700      if (IsConstant(leftSide) && IsConstant(rightSide)) {
701        var lsConst = leftSide as ConstantTreeNode;
702        var rsConst = rightSide as ConstantTreeNode;
703        if (lsConst.Value > rsConst.Value) return MakeConstant(1.0);
704        else return MakeConstant(-1.0);
705      } else {
706        var gtNode = gtSymbol.CreateTreeNode();
707        gtNode.AddSubtree(leftSide);
708        gtNode.AddSubtree(rightSide);
709        return gtNode;
710      }
711    }
712
713    private ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition,
714      ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) {
715      if (IsConstant(condition)) {
716        var constT = condition as ConstantTreeNode;
717        if (constT.Value > 0.0) return trueBranch;
718        else return falseBranch;
719      } else {
720        var ifNode = ifThenElseSymbol.CreateTreeNode();
721        if (IsBoolean(condition)) {
722          ifNode.AddSubtree(condition);
723        } else {
724          var gtNode = gtSymbol.CreateTreeNode();
725          gtNode.AddSubtree(condition);
726          gtNode.AddSubtree(MakeConstant(0.0));
727          ifNode.AddSubtree(gtNode);
728        }
729        ifNode.AddSubtree(trueBranch);
730        ifNode.AddSubtree(falseBranch);
731        return ifNode;
732      }
733    }
734
735    private ISymbolicExpressionTreeNode MakeSine(ISymbolicExpressionTreeNode node) {
736      if (IsConstant(node)) {
737        var constT = node as ConstantTreeNode;
738        return MakeConstant(Math.Sin(constT.Value));
739      } else if (IsFactor(node)) {
740        var factor = node as FactorVariableTreeNode;
741        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin));
742      } else if (IsBinFactor(node)) {
743        var binFactor = node as BinaryFactorVariableTreeNode;
744        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight));
745      } else {
746        var sineNode = sineSymbol.CreateTreeNode();
747        sineNode.AddSubtree(node);
748        return sineNode;
749      }
750    }
751
752    private ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) {
753      if (IsConstant(node)) {
754        var constT = node as ConstantTreeNode;
755        return MakeConstant(Math.Tan(constT.Value));
756      } else if (IsFactor(node)) {
757        var factor = node as FactorVariableTreeNode;
758        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan));
759      } else if (IsBinFactor(node)) {
760        var binFactor = node as BinaryFactorVariableTreeNode;
761        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight));
762      } else {
763        var tanNode = tanSymbol.CreateTreeNode();
764        tanNode.AddSubtree(node);
765        return tanNode;
766      }
767    }
768
769    private ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) {
770      if (IsConstant(node)) {
771        var constT = node as ConstantTreeNode;
772        return MakeConstant(Math.Cos(constT.Value));
773      } else if (IsFactor(node)) {
774        var factor = node as FactorVariableTreeNode;
775        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos));
776      } else if (IsBinFactor(node)) {
777        var binFactor = node as BinaryFactorVariableTreeNode;
778        // cos(0) = 1 see similar case for Exp(binfactor)
779        return MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight) - 1),
780          MakeConstant(1.0));
781      } else {
782        var cosNode = cosineSymbol.CreateTreeNode();
783        cosNode.AddSubtree(node);
784        return cosNode;
785      }
786    }
787
788    private ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) {
789      if (IsConstant(node)) {
790        var constT = node as ConstantTreeNode;
791        return MakeConstant(Math.Exp(constT.Value));
792      } else if (IsFactor(node)) {
793        var factNode = node as FactorVariableTreeNode;
794        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w)));
795      } else if (IsBinFactor(node)) {
796        // exp( binfactor w val=a) = if(val=a) exp(w) else exp(0) = binfactor( (exp(w) - 1) val a) + 1
797        var binFactor = node as BinaryFactorVariableTreeNode;
798        return
799          MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight) - 1), MakeConstant(1.0));
800      } else if (IsLog(node)) {
801        return node.GetSubtree(0);
802      } else if (IsAddition(node)) {
803        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));
804      } else if (IsSubtraction(node)) {
805        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));
806      } else {
807        var expNode = expSymbol.CreateTreeNode();
808        expNode.AddSubtree(node);
809        return expNode;
810      }
811    }
812    private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {
813      if (IsConstant(node)) {
814        var constT = node as ConstantTreeNode;
815        return MakeConstant(Math.Log(constT.Value));
816      } else if (IsFactor(node)) {
817        var factNode = node as FactorVariableTreeNode;
818        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));
819      } else if (IsExp(node)) {
820        return node.GetSubtree(0);
821      } else if (IsSquareRoot(node)) {
822        return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));
823      } else {
824        var logNode = logSymbol.CreateTreeNode();
825        logNode.AddSubtree(node);
826        return logNode;
827      }
828    }
829
830    private ISymbolicExpressionTreeNode MakeSquare(ISymbolicExpressionTreeNode node) {
831      if (IsConstant(node)) {
832        var constT = node as ConstantTreeNode;
833        return MakeConstant(constT.Value * constT.Value);
834      } else if (IsFactor(node)) {
835        var factNode = node as FactorVariableTreeNode;
836        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w));
837      } else if (IsBinFactor(node)) {
838        var binFactor = node as BinaryFactorVariableTreeNode;
839        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight);
840      } else if (IsSquareRoot(node)) {
841        return node.GetSubtree(0);
842      } else if (IsMultiplication(node)) {
843        // sqr( x * y ) = sqr(x) * sqr(y)
844        var mulNode = mulSymbol.CreateTreeNode();
845        foreach (var subtree in node.Subtrees) {
846          mulNode.AddSubtree(MakeSquare(subtree));
847        }
848        return mulNode;
849      } else if (IsAbsolute(node)) {
850        return MakeSquare(node.GetSubtree(0)); // sqr(abs(x)) = sqr(x)
851      } else if (IsExp(node)) {
852        return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(2.0))); // sqr(exp(x)) = exp(2x)
853      } else if (IsCube(node)) {
854        return MakePower(node.GetSubtree(0), MakeConstant(6));
855      } else {
856        var sqrNode = sqrSymbol.CreateTreeNode();
857        sqrNode.AddSubtree(node);
858        return sqrNode;
859      }
860    }
861
862    private ISymbolicExpressionTreeNode MakeCube(ISymbolicExpressionTreeNode node) {
863      if (IsConstant(node)) {
864        var constT = node as ConstantTreeNode;
865        return MakeConstant(constT.Value * constT.Value * constT.Value);
866      } else if (IsFactor(node)) {
867        var factNode = node as FactorVariableTreeNode;
868        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w * w));
869      } else if (IsBinFactor(node)) {
870        var binFactor = node as BinaryFactorVariableTreeNode;
871        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight * binFactor.Weight);
872      } else if (IsCubeRoot(node)) {
873        return node.GetSubtree(0); // NOTE: not really accurate because cuberoot(x) with negative x is evaluated to NaN and after this simplification we evaluate as x
874      } else if (IsExp(node)) {
875        return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(3)));
876      } else if (IsSquare(node)) {
877        return MakePower(node.GetSubtree(0), MakeConstant(6));
878      } else {
879        var cubeNode = cubeSymbol.CreateTreeNode();
880        cubeNode.AddSubtree(node);
881        return cubeNode;
882      }
883    }
884
885    private ISymbolicExpressionTreeNode MakeAbs(ISymbolicExpressionTreeNode node) {
886      if (IsConstant(node)) {
887        var constT = node as ConstantTreeNode;
888        return MakeConstant(Math.Abs(constT.Value));
889      } else if (IsFactor(node)) {
890        var factNode = node as FactorVariableTreeNode;
891        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Abs(w)));
892      } else if (IsBinFactor(node)) {
893        var binFactor = node as BinaryFactorVariableTreeNode;
894        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Abs(binFactor.Weight));
895      } else if (IsSquare(node) || IsExp(node) || IsSquareRoot(node) || IsCubeRoot(node)) {
896        return node; // abs(sqr(x)) = sqr(x), abs(exp(x)) = exp(x) ...
897      } else if (IsMultiplication(node)) {
898        var mul = mulSymbol.CreateTreeNode();
899        foreach (var st in node.Subtrees) {
900          mul.AddSubtree(MakeAbs(st));
901        }
902        return mul;
903      } else if (IsDivision(node)) {
904        var div = divSymbol.CreateTreeNode();
905        foreach (var st in node.Subtrees) {
906          div.AddSubtree(MakeAbs(st));
907        }
908        return div;
909      } else {
910        var absNode = absSymbol.CreateTreeNode();
911        absNode.AddSubtree(node);
912        return absNode;
913      }
914    }
915
916    // constant folding only
917    private ISymbolicExpressionTreeNode MakeAnalyticalQuotient(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
918      if (IsConstant(b)) {
919        var c = b as ConstantTreeNode;
920        return MakeFraction(a, MakeConstant(Math.Sqrt(1.0 + c.Value * c.Value)));
921      } else if (IsFactor(b)) {
922        var factNode = b as FactorVariableTreeNode;
923        return MakeFraction(a, MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(1.0 + w * w))));
924      } else if (IsBinFactor(b)) {
925        var binFactor = b as BinaryFactorVariableTreeNode;
926        return MakeFraction(a, MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(1.0 + binFactor.Weight * binFactor.Weight)));
927      } else {
928        var aqNode = aqSymbol.CreateTreeNode();
929        aqNode.AddSubtree(a);
930        aqNode.AddSubtree(b);
931        return aqNode;
932      }
933    }
934
935    private ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) {
936      if (IsConstant(node)) {
937        var constT = node as ConstantTreeNode;
938        return MakeConstant(Math.Sqrt(constT.Value));
939      } else if (IsFactor(node)) {
940        var factNode = node as FactorVariableTreeNode;
941        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w)));
942      } else if (IsBinFactor(node)) {
943        var binFactor = node as BinaryFactorVariableTreeNode;
944        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
945      } else if (IsSquare(node)) {
946        return node.GetSubtree(0); // NOTE: not really accurate because sqrt(x) with negative x is evaluated to NaN and after this simplification we evaluate as x
947      } else {
948        var sqrtNode = sqrtSymbol.CreateTreeNode();
949        sqrtNode.AddSubtree(node);
950        return sqrtNode;
951      }
952    }
953
954    private ISymbolicExpressionTreeNode MakeCubeRoot(ISymbolicExpressionTreeNode node) {
955      if (IsConstant(node)) {
956        var constT = node as ConstantTreeNode;
957        return MakeConstant(Math.Pow(constT.Value, 1.0 / 3.0));
958      } else if (IsFactor(node)) {
959        var factNode = node as FactorVariableTreeNode;
960        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, 1.0 / 3.0)));
961      } else if (IsBinFactor(node)) {
962        var binFactor = node as BinaryFactorVariableTreeNode;
963        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(Math.Pow(binFactor.Weight, 1.0 / 3.0)));
964      } else if (IsCube(node)) {
965        return node.GetSubtree(0);
966      } else {
967        var cubeRootNode = cubeRootSymbol.CreateTreeNode();
968        cubeRootNode.AddSubtree(node);
969        return cubeRootNode;
970      }
971    }
972
973    private ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
974      if (IsConstant(a) && IsConstant(b)) {
975        var constA = a as ConstantTreeNode;
976        var constB = b as ConstantTreeNode;
977        return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value)));
978      } else if (IsFactor(a) && IsConstant(b)) {
979        var factNode = a as FactorVariableTreeNode;
980        var constNode = b as ConstantTreeNode;
981        return MakeFactor(factNode.Symbol, factNode.VariableName,
982          factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(constNode.Value))));
983      } else if (IsBinFactor(a) && IsConstant(b)) {
984        var binFactor = a as BinaryFactorVariableTreeNode;
985        var constNode = b as ConstantTreeNode;
986        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(constNode.Value)));
987      } else if (IsConstant(a) && IsFactor(b)) {
988        var constNode = a as ConstantTreeNode;
989        var factNode = b as FactorVariableTreeNode;
990        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, 1.0 / Math.Round(w))));
991      } else if (IsConstant(a) && IsBinFactor(b)) {
992        var constNode = a as ConstantTreeNode;
993        var factNode = b as BinaryFactorVariableTreeNode;
994        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weight)));
995      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
996        var node0 = a as FactorVariableTreeNode;
997        var node1 = b as FactorVariableTreeNode;
998        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v))));
999      } else if (IsConstant(b)) {
1000        var constB = b as ConstantTreeNode;
1001        var constBValue = Math.Round(constB.Value);
1002        if (constBValue.IsAlmost(1.0)) {
1003          return a;
1004        } else if (constBValue.IsAlmost(0.0)) {
1005          return MakeConstant(1.0);
1006        } else if (constBValue.IsAlmost(-1.0)) {
1007          return MakeFraction(MakeConstant(1.0), a);
1008        } else if (constBValue < 0) {
1009          var rootNode = rootSymbol.CreateTreeNode();
1010          rootNode.AddSubtree(a);
1011          rootNode.AddSubtree(MakeConstant(-1.0 * constBValue));
1012          return MakeFraction(MakeConstant(1.0), rootNode);
1013        } else {
1014          var rootNode = rootSymbol.CreateTreeNode();
1015          rootNode.AddSubtree(a);
1016          rootNode.AddSubtree(MakeConstant(constBValue));
1017          return rootNode;
1018        }
1019      } else {
1020        var rootNode = rootSymbol.CreateTreeNode();
1021        rootNode.AddSubtree(a);
1022        rootNode.AddSubtree(b);
1023        return rootNode;
1024      }
1025    }
1026
1027
1028    private ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
1029      if (IsConstant(a) && IsConstant(b)) {
1030        var constA = a as ConstantTreeNode;
1031        var constB = b as ConstantTreeNode;
1032        return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value)));
1033      } else if (IsFactor(a) && IsConstant(b)) {
1034        var factNode = a as FactorVariableTreeNode;
1035        var constNode = b as ConstantTreeNode;
1036        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(constNode.Value))));
1037      } else if (IsBinFactor(a) && IsConstant(b)) {
1038        var binFactor = a as BinaryFactorVariableTreeNode;
1039        var constNode = b as ConstantTreeNode;
1040        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(constNode.Value)));
1041      } else if (IsConstant(a) && IsFactor(b)) {
1042        var constNode = a as ConstantTreeNode;
1043        var factNode = b as FactorVariableTreeNode;
1044        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, Math.Round(w))));
1045      } else if (IsConstant(a) && IsBinFactor(b)) {
1046        var constNode = a as ConstantTreeNode;
1047        var factNode = b as BinaryFactorVariableTreeNode;
1048        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, Math.Round(factNode.Weight)));
1049      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
1050        var node0 = a as FactorVariableTreeNode;
1051        var node1 = b as FactorVariableTreeNode;
1052        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v))));
1053      } else if (IsConstant(b)) {
1054        var constB = b as ConstantTreeNode;
1055        double exponent = Math.Round(constB.Value);
1056        if (exponent.IsAlmost(0.0)) {
1057          return MakeConstant(1.0);
1058        } else if (exponent.IsAlmost(1.0)) {
1059          return a;
1060        } else if (exponent.IsAlmost(-1.0)) {
1061          return MakeFraction(MakeConstant(1.0), a);
1062        } else if (exponent < 0) {
1063          var powNode = powSymbol.CreateTreeNode();
1064          powNode.AddSubtree(a);
1065          powNode.AddSubtree(MakeConstant(-1.0 * exponent));
1066          return MakeFraction(MakeConstant(1.0), powNode);
1067        } else {
1068          var powNode = powSymbol.CreateTreeNode();
1069          powNode.AddSubtree(a);
1070          powNode.AddSubtree(MakeConstant(exponent));
1071          return powNode;
1072        }
1073      } else {
1074        var powNode = powSymbol.CreateTreeNode();
1075        powNode.AddSubtree(a);
1076        powNode.AddSubtree(b);
1077        return powNode;
1078      }
1079    }
1080
1081
1082    // MakeFraction, MakeProduct and MakeSum take two already simplified trees and create a new simplified tree
1083    private ISymbolicExpressionTreeNode MakeFraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
1084      if (IsConstant(a) && IsConstant(b)) {
1085        // fold constants
1086        return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value);
1087      } else if ((IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0))) {
1088        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
1089      } else if (IsVariableBase(a) && IsConstant(b)) {
1090        // merge constant values into variable weights
1091        var constB = ((ConstantTreeNode)b).Value;
1092        ((VariableTreeNodeBase)a).Weight /= constB;
1093        return a;
1094      } else if (IsFactor(a) && IsConstant(b)) {
1095        var factNode = a as FactorVariableTreeNode;
1096        var constNode = b as ConstantTreeNode;
1097        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / constNode.Value));
1098      } else if (IsBinFactor(a) && IsConstant(b)) {
1099        var factNode = a as BinaryFactorVariableTreeNode;
1100        var constNode = b as ConstantTreeNode;
1101        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / constNode.Value);
1102      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
1103        var node0 = a as FactorVariableTreeNode;
1104        var node1 = b as FactorVariableTreeNode;
1105        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v));
1106      } else if (IsFactor(a) && IsBinFactor(b) && ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
1107        var node0 = a as FactorVariableTreeNode;
1108        var node1 = b as BinaryFactorVariableTreeNode;
1109        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
1110        var wi = Array.IndexOf(varValues, node1.VariableValue);
1111        if (wi < 0) throw new ArgumentException();
1112        var newWeighs = new double[varValues.Length];
1113        node0.Weights.CopyTo(newWeighs, 0);
1114        for (int i = 0; i < newWeighs.Length; i++)
1115          if (wi == i) newWeighs[i] /= node1.Weight;
1116          else newWeighs[i] /= 0.0;
1117        return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
1118      } else if (IsFactor(a)) {
1119        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
1120      } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameTypeAndVariable(a, b) && !IsBinFactor(b)) {
1121        // cancel variables (not allowed for bin factors because of division by zero)
1122        var aVar = a as VariableTreeNode;
1123        var bVar = b as VariableTreeNode;
1124        return MakeConstant(aVar.Weight / bVar.Weight);
1125      } else if (IsAddition(a) && IsConstant(b)) {
1126        return a.Subtrees
1127          .Select(x => GetSimplifiedTree(x))
1128          .Select(x => MakeFraction(x, GetSimplifiedTree(b)))
1129          .Aggregate((c, d) => MakeSum(c, d));
1130      } else if (IsMultiplication(a) && IsConstant(b)) {
1131        return MakeProduct(a, Invert(b));
1132      } else if (IsDivision(a) && IsConstant(b)) {
1133        // (a1 / a2) / c => (a1 / (a2 * c))
1134        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
1135      } else if (IsDivision(a) && IsDivision(b)) {
1136        // (a1 / a2) / (b1 / b2) =>
1137        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(1)), MakeProduct(a.GetSubtree(1), b.GetSubtree(0)));
1138      } else if (IsDivision(a)) {
1139        // (a1 / a2) / b => (a1 / (a2 * b))
1140        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
1141      } else if (IsDivision(b)) {
1142        // a / (b1 / b2) => (a * b2) / b1
1143        return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));
1144      } else if (IsAnalyticalQuotient(a)) {
1145        return MakeAnalyticalQuotient(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
1146      } else {
1147        var div = divSymbol.CreateTreeNode();
1148        div.AddSubtree(a);
1149        div.AddSubtree(b);
1150        return div;
1151      }
1152    }
1153
1154    private ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
1155      if (IsConstant(a) && IsConstant(b)) {
1156        // fold constants
1157        ((ConstantTreeNode)a).Value += ((ConstantTreeNode)b).Value;
1158        return a;
1159      } else if (IsConstant(a)) {
1160        // c + x => x + c
1161        // b is not constant => make sure constant is on the right
1162        return MakeSum(b, a);
1163      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) {
1164        // x + 0 => x
1165        return a;
1166      } else if (IsFactor(a) && IsConstant(b)) {
1167        var factNode = a as FactorVariableTreeNode;
1168        var constNode = b as ConstantTreeNode;
1169        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + constNode.Value));
1170      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
1171        var node0 = a as FactorVariableTreeNode;
1172        var node1 = b as FactorVariableTreeNode;
1173        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v));
1174      } else if (IsBinFactor(a) && IsFactor(b)) {
1175        return MakeSum(b, a);
1176      } else if (IsFactor(a) && IsBinFactor(b) &&
1177        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
1178        var node0 = a as FactorVariableTreeNode;
1179        var node1 = b as BinaryFactorVariableTreeNode;
1180        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
1181        var wi = Array.IndexOf(varValues, node1.VariableValue);
1182        if (wi < 0) throw new ArgumentException();
1183        var newWeighs = new double[varValues.Length];
1184        node0.Weights.CopyTo(newWeighs, 0);
1185        newWeighs[wi] += node1.Weight;
1186        return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
1187      } else if (IsAddition(a) && IsAddition(b)) {
1188        // merge additions
1189        var add = addSymbol.CreateTreeNode();
1190        // add all sub trees except for the last
1191        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
1192        for (int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i));
1193        if (IsConstant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) {
1194          add.AddSubtree(MakeSum(a.Subtrees.Last(), b.Subtrees.Last()));
1195        } else if (IsConstant(a.Subtrees.Last())) {
1196          add.AddSubtree(b.Subtrees.Last());
1197          add.AddSubtree(a.Subtrees.Last());
1198        } else {
1199          add.AddSubtree(a.Subtrees.Last());
1200          add.AddSubtree(b.Subtrees.Last());
1201        }
1202        MergeVariablesInSum(add);
1203        if (add.Subtrees.Count() == 1) {
1204          return add.GetSubtree(0);
1205        } else {
1206          return add;
1207        }
1208      } else if (IsAddition(b)) {
1209        return MakeSum(b, a);
1210      } else if (IsAddition(a) && IsConstant(b)) {
1211        // a is an addition and b is a constant => append b to a and make sure the constants are merged
1212        var add = addSymbol.CreateTreeNode();
1213        // add all sub trees except for the last
1214        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
1215        if (IsConstant(a.Subtrees.Last()))
1216          add.AddSubtree(MakeSum(a.Subtrees.Last(), b));
1217        else {
1218          add.AddSubtree(a.Subtrees.Last());
1219          add.AddSubtree(b);
1220        }
1221        return add;
1222      } else if (IsAddition(a)) {
1223        // a is already an addition => append b
1224        var add = addSymbol.CreateTreeNode();
1225        add.AddSubtree(b);
1226        foreach (var subtree in a.Subtrees) {
1227          add.AddSubtree(subtree);
1228        }
1229        MergeVariablesInSum(add);
1230        if (add.Subtrees.Count() == 1) {
1231          return add.GetSubtree(0);
1232        } else {
1233          return add;
1234        }
1235      } else {
1236        var add = addSymbol.CreateTreeNode();
1237        add.AddSubtree(a);
1238        add.AddSubtree(b);
1239        MergeVariablesInSum(add);
1240        if (add.Subtrees.Count() == 1) {
1241          return add.GetSubtree(0);
1242        } else {
1243          return add;
1244        }
1245      }
1246    }
1247
1248    // makes sure variable symbols in sums are combined
1249    private void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) {
1250      var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees);
1251      while (sum.Subtrees.Any()) sum.RemoveSubtree(0);
1252      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
1253                            where node.SubtreeCount == 0
1254                            group node by GroupId(node) into g
1255                            select g;
1256      var constant = (from node in subtrees.OfType<ConstantTreeNode>()
1257                      select node.Value).DefaultIfEmpty(0.0).Sum();
1258      var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode));
1259
1260      foreach (var variableNodeGroup in groupedVarNodes) {
1261        var firstNode = variableNodeGroup.First();
1262        if (firstNode is VariableTreeNodeBase) {
1263          var representative = firstNode as VariableTreeNodeBase;
1264          var weightSum = variableNodeGroup.Cast<VariableTreeNodeBase>().Select(t => t.Weight).Sum();
1265          representative.Weight = weightSum;
1266          sum.AddSubtree(representative);
1267        } else if (firstNode is FactorVariableTreeNode) {
1268          var representative = firstNode as FactorVariableTreeNode;
1269          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
1270            for (int j = 0; j < representative.Weights.Length; j++) {
1271              representative.Weights[j] += node.Weights[j];
1272            }
1273          }
1274          sum.AddSubtree(representative);
1275        }
1276      }
1277      foreach (var unchangedSubtree in unchangedSubtrees)
1278        sum.AddSubtree(unchangedSubtree);
1279      if (!constant.IsAlmost(0.0)) {
1280        sum.AddSubtree(MakeConstant(constant));
1281      }
1282    }
1283
1284    // nodes referencing variables can be grouped if they have
1285    private string GroupId(IVariableTreeNode node) {
1286      var binaryFactorNode = node as BinaryFactorVariableTreeNode;
1287      var factorNode = node as FactorVariableTreeNode;
1288      var variableNode = node as VariableTreeNode;
1289      var laggedVarNode = node as LaggedVariableTreeNode;
1290      if (variableNode != null) {
1291        return "var " + variableNode.VariableName;
1292      } else if (binaryFactorNode != null) {
1293        return "binfactor " + binaryFactorNode.VariableName + " " + binaryFactorNode.VariableValue;
1294      } else if (factorNode != null) {
1295        return "factor " + factorNode.VariableName;
1296      } else if (laggedVarNode != null) {
1297        return "lagged " + laggedVarNode.VariableName + " " + laggedVarNode.Lag;
1298      } else {
1299        throw new NotSupportedException();
1300      }
1301    }
1302
1303
1304    private ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
1305      if (IsConstant(a) && IsConstant(b)) {
1306        // fold constants
1307        return MakeConstant(((ConstantTreeNode)a).Value * ((ConstantTreeNode)b).Value);
1308      } else if (IsConstant(a)) {
1309        // a * $ => $ * a
1310        return MakeProduct(b, a);
1311      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
1312        var node0 = a as FactorVariableTreeNode;
1313        var node1 = b as FactorVariableTreeNode;
1314        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v));
1315      } else if (IsBinFactor(a) && IsBinFactor(b) && AreSameTypeAndVariable(a, b)) {
1316        var node0 = a as BinaryFactorVariableTreeNode;
1317        var node1 = b as BinaryFactorVariableTreeNode;
1318        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight);
1319      } else if (IsFactor(a) && IsConstant(b)) {
1320        var node0 = a as FactorVariableTreeNode;
1321        var node1 = b as ConstantTreeNode;
1322        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value));
1323      } else if (IsBinFactor(a) && IsConstant(b)) {
1324        var node0 = a as BinaryFactorVariableTreeNode;
1325        var node1 = b as ConstantTreeNode;
1326        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value);
1327      } else if (IsBinFactor(a) && IsFactor(b)) {
1328        return MakeProduct(b, a);
1329      } else if (IsFactor(a) && IsBinFactor(b) &&
1330        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
1331        var node0 = a as FactorVariableTreeNode;
1332        var node1 = b as BinaryFactorVariableTreeNode;
1333        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
1334        var wi = Array.IndexOf(varValues, node1.VariableValue);
1335        if (wi < 0) throw new ArgumentException();
1336        return MakeBinFactor(node1.Symbol, node1.VariableName, node1.VariableValue, node1.Weight * node0.Weights[wi]);
1337      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) {
1338        // $ * 1.0 => $
1339        return a;
1340      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) {
1341        return MakeConstant(0);
1342      } else if (IsConstant(b) && IsVariableBase(a)) {
1343        // multiply constants into variables weights
1344        ((VariableTreeNodeBase)a).Weight *= ((ConstantTreeNode)b).Value;
1345        return a;
1346      } else if (IsConstant(b) && IsAddition(a) ||
1347          IsFactor(b) && IsAddition(a) ||
1348          IsBinFactor(b) && IsAddition(a)) {
1349        // multiply constants into additions
1350        return a.Subtrees.Select(x => MakeProduct(GetSimplifiedTree(x), GetSimplifiedTree(b))).Aggregate((c, d) => MakeSum(c, d));
1351      } else if (IsDivision(a) && IsDivision(b)) {
1352        // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2)
1353        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1)));
1354      } else if (IsDivision(a)) {
1355        // (a1 / a2) * b => (a1 * b) / a2
1356        return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
1357      } else if (IsDivision(b)) {
1358        // a * (b1 / b2) => (b1 * a) / b2
1359        return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1));
1360      } else if (IsMultiplication(a) && IsMultiplication(b)) {
1361        // merge multiplications (make sure constants are merged)
1362        var mul = mulSymbol.CreateTreeNode();
1363        for (int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i));
1364        for (int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i));
1365        MergeVariablesAndConstantsInProduct(mul);
1366        return mul;
1367      } else if (IsMultiplication(b)) {
1368        return MakeProduct(b, a);
1369      } else if (IsMultiplication(a)) {
1370        // a is already an multiplication => append b
1371        a.AddSubtree(GetSimplifiedTree(b));
1372        MergeVariablesAndConstantsInProduct(a);
1373        return a;
1374      } else if (IsAbsolute(a) && IsAbsolute(b)) {
1375        return MakeAbs(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)));
1376      } else if (IsAbsolute(a) && IsConstant(b)) {
1377        var constNode = b as ConstantTreeNode;
1378        var posF = Math.Abs(constNode.Value);
1379        if (constNode.Value > 0) {
1380          return MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF)));
1381        } else {
1382          var mul = mulSymbol.CreateTreeNode();
1383          mul.AddSubtree(MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF))));
1384          mul.AddSubtree(MakeConstant(-1.0));
1385          return mul;
1386        }
1387      } else if (IsAnalyticalQuotient(a)) {
1388        return MakeAnalyticalQuotient(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
1389      } else {
1390        var mul = mulSymbol.CreateTreeNode();
1391        mul.AddSubtree(a);
1392        mul.AddSubtree(b);
1393        MergeVariablesAndConstantsInProduct(mul);
1394        return mul;
1395      }
1396    }
1397
1398    private ISymbolicExpressionTreeNode MakeSumAggregation(ISymbolicExpressionTreeNode node) {
1399      if (IsScalarNode(node)) {
1400        return node;
1401      } else if (IsAddition(node) || IsSubtraction(node)) {
1402        var terms = node.Subtrees;
1403        if (IsSubtraction(node)) terms = InvertNodes(terms, Negate);
1404
1405        var scalarTerms = terms.Where(IsScalarNode).ToList();
1406        var remainingTerms = terms.Except(scalarTerms).ToList();
1407
1408        if (scalarTerms.Any() && remainingTerms.Any()) {
1409          var scalarNode = scalarTerms.Aggregate(MakeSum);
1410          var vectorNode = remainingTerms.Aggregate(MakeSum);
1411
1412          var lengthNode = MakeLengthAggregation((ISymbolicExpressionTreeNode)vectorNode.Clone());
1413          var scalarMulNode = MakeProduct(scalarNode, lengthNode);
1414
1415          var sumNode = MakeSumAggregation(vectorNode);
1416
1417          return MakeSum(scalarMulNode, sumNode);
1418        } else if (scalarTerms.Any()) {
1419          var scalarNode = scalarTerms.Aggregate(MakeSum);
1420          return scalarNode;
1421        } else if (remainingTerms.Any()) {
1422          var vectorNode = remainingTerms.Aggregate(MakeSum);
1423          var sumNode = sumSymbol.CreateTreeNode();
1424          sumNode.AddSubtree(vectorNode);
1425          return sumNode;
1426        } else
1427          throw new InvalidOperationException("Addition does not contain any terms to simplify.");
1428      } else if (IsMultiplication(node) || IsDivision(node)) {
1429        var factors = node.Subtrees;
1430        if (IsDivision(node)) factors = InvertNodes(factors, Invert);
1431
1432        var scalarFactors = factors.Where(IsScalarNode).ToList();
1433        var remainingFactors = factors.Except(scalarFactors).ToList();
1434
1435        if (scalarFactors.Any() && remainingFactors.Any()) {
1436          var scalarNode = scalarFactors.Aggregate(MakeProduct);
1437          var vectorNode = remainingFactors.Aggregate(MakeProduct);
1438
1439          var sumNode = MakeSumAggregation(vectorNode);
1440
1441          return MakeProduct(scalarNode, sumNode);
1442        } else if (scalarFactors.Any()) {
1443          var scalarNode = scalarFactors.Aggregate(MakeProduct);
1444          return scalarNode;
1445        } else if (remainingFactors.Any()) {
1446          var vectorNode = remainingFactors.Aggregate(MakeProduct);
1447          var sumNode = sumSymbol.CreateTreeNode();
1448          sumNode.AddSubtree(vectorNode);
1449          return sumNode;
1450        } else
1451          throw new InvalidOperationException("Multiplication does not contain any terms to simplify.");
1452      } else if (IsVariableBase(node)) { // weight is like multiplication
1453        var variableNode = (VariableTreeNodeBase)node;
1454        var weight = variableNode.Weight;
1455        variableNode.Weight = 1.0;
1456        var sumNode = sumSymbol.CreateTreeNode();
1457        sumNode.AddSubtree(node);
1458        return MakeProduct(MakeConstant(weight), sumNode);
1459      } else {
1460        var sumNode = sumSymbol.CreateTreeNode();
1461        sumNode.AddSubtree(node);
1462        return sumNode;
1463      }
1464    }
1465
1466    private ISymbolicExpressionTreeNode MakeMeanAggregation(ISymbolicExpressionTreeNode node) {
1467      if (IsScalarNode(node)) {
1468        return node;
1469      } else if (IsAddition(node) || IsSubtraction(node)) {
1470        var terms = node.Subtrees;
1471        if (IsSubtraction(node)) terms = InvertNodes(terms, Negate);
1472
1473        var scalarTerms = terms.Where(IsScalarNode).ToList();
1474        var remainingTerms = terms.Except(scalarTerms).ToList();
1475
1476        if (scalarTerms.Any() && remainingTerms.Any()) {
1477          var scalarNode = scalarTerms.Aggregate(MakeSum);
1478          var vectorNode = remainingTerms.Aggregate(MakeSum);
1479
1480          var meanNode = MakeMeanAggregation(vectorNode);
1481
1482          return MakeSum(scalarNode, meanNode);
1483        } else if (scalarTerms.Any()) {
1484          var scalarNode = scalarTerms.Aggregate(MakeSum);
1485          return scalarNode;
1486        } else if (remainingTerms.Any()) {
1487          var vectorNode = remainingTerms.Aggregate(MakeSum);
1488          var meanNode = meanSymbol.CreateTreeNode();
1489          meanNode.AddSubtree(vectorNode);
1490          return meanNode;
1491        } else
1492          throw new InvalidOperationException("Addition does not contain any terms to simplify.");
1493      } else if (IsMultiplication(node) || IsDivision(node)) {
1494        var factors = node.Subtrees;
1495        if (IsDivision(node)) factors = InvertNodes(factors, Invert);
1496
1497        var scalarFactors = factors.Where(IsScalarNode).ToList();
1498        var remainingFactors = factors.Except(scalarFactors).ToList();
1499
1500        if (scalarFactors.Any() && remainingFactors.Any()) {
1501          var scalarNode = scalarFactors.Aggregate(MakeProduct);
1502          var vectorNode = remainingFactors.Aggregate(MakeProduct);
1503
1504          var meanNode = MakeMeanAggregation(vectorNode);
1505
1506          return MakeProduct(scalarNode, meanNode);
1507        } else if (scalarFactors.Any()) {
1508          var scalarNode = scalarFactors.Aggregate(MakeProduct);
1509          return scalarNode;
1510        } else if (remainingFactors.Any()) {
1511          var vectorNode = remainingFactors.Aggregate(MakeProduct);
1512          var meanNode = meanSymbol.CreateTreeNode();
1513          meanNode.AddSubtree(vectorNode);
1514          return meanNode;
1515        } else
1516          throw new InvalidOperationException("Multiplication does not contain any terms to simplify.");
1517      } else if (IsVariableBase(node)) { // weight is like multiplication
1518        var variableNode = (VariableTreeNodeBase)node;
1519        var weight = variableNode.Weight;
1520        variableNode.Weight = 1.0;
1521        var meanNode = meanSymbol.CreateTreeNode();
1522        meanNode.AddSubtree(node);
1523        return MakeProduct(MakeConstant(weight), meanNode);
1524      } else {
1525        var meanNode = meanSymbol.CreateTreeNode();
1526        meanNode.AddSubtree(node);
1527        return meanNode;
1528      }
1529    }
1530
1531    private ISymbolicExpressionTreeNode MakeLengthAggregation(ISymbolicExpressionTreeNode node) {
1532      if (IsScalarNode(node)) {
1533        return MakeConstant(1.0);
1534      } else if (IsAddition(node) || IsSubtraction(node)) {
1535        var terms = node.Subtrees;
1536        if (IsSubtraction(node)) terms = InvertNodes(terms, Negate);
1537
1538        var scalarTerms = terms.Where(IsScalarNode).ToList();
1539        var remainingTerms = terms.Except(scalarTerms).ToList();
1540
1541        if (remainingTerms.Any()) {
1542          var vectorNode = remainingTerms.Aggregate(MakeSum);
1543
1544          var lengthNode = lengthSymbol.CreateTreeNode();
1545          lengthNode.AddSubtree(vectorNode);
1546
1547          return lengthNode;
1548        } else if (scalarTerms.Any()) {
1549          return MakeConstant(1.0);
1550        } else
1551          throw new InvalidOperationException("Addition does not contain any terms to simplify.");
1552      } else if (IsMultiplication(node) || IsDivision(node)) {
1553        var factors = node.Subtrees;
1554        if (IsDivision(node)) factors = InvertNodes(factors, Invert);
1555
1556        var scalarFactors = factors.Where(IsScalarNode).ToList();
1557        var remainingFactors = factors.Except(scalarFactors).ToList();
1558
1559        if (remainingFactors.Any()) {
1560          var vectorNode = remainingFactors.Aggregate(MakeProduct);
1561
1562          var lengthNode = lengthSymbol.CreateTreeNode();
1563          lengthNode.AddSubtree(vectorNode);
1564
1565          return lengthNode;
1566        } else if (scalarFactors.Any()) {
1567          return MakeConstant(1.0);
1568        } else
1569          throw new InvalidOperationException("Multiplication does not contain any terms to simplify.");
1570      } else if (IsVariableBase(node)) { // weight is like multiplication
1571        var variableNode = (VariableTreeNodeBase)node;
1572        variableNode.Weight = 1.0;
1573        var lengthNode = lengthSymbol.CreateTreeNode();
1574        lengthNode.AddSubtree(node);
1575        return lengthNode;
1576      } else {
1577        var lengthNode = lengthSymbol.CreateTreeNode();
1578        lengthNode.AddSubtree(node);
1579        return lengthNode;
1580      }
1581    }
1582
1583    private ISymbolicExpressionTreeNode MakeStandardDeviationAggregation(ISymbolicExpressionTreeNode node) {
1584      if (IsScalarNode(node)) {
1585        return MakeConstant(0.0);
1586      } else if (IsAddition(node) || IsSubtraction(node)) { // scalars drop out
1587        var terms = node.Subtrees;
1588
1589        var scalarTerms = terms.Where(IsScalarNode).ToList();
1590        var remainingTerms = terms.Except(scalarTerms).ToList();
1591
1592        if (remainingTerms.Any()) {
1593          var vectorNode = remainingTerms.Aggregate(MakeSum);
1594
1595          var stdevNode = standardDeviationSymbol.CreateTreeNode();
1596          stdevNode.AddSubtree(vectorNode);
1597
1598          return stdevNode;
1599        } else if (scalarTerms.Any()) {
1600          return MakeConstant(0.0);
1601        } else
1602          throw new InvalidOperationException("Addition does not contain any terms to simplify.");
1603      } else if (IsMultiplication(node) || IsDivision(node)) {
1604        var factors = node.Subtrees;
1605        if (IsDivision(node)) factors = InvertNodes(factors, Invert);
1606
1607        var scalarFactors = factors.Where(IsScalarNode).ToList();
1608        var remainingFactors = factors.Except(scalarFactors).ToList();
1609
1610        if (scalarFactors.Any() && remainingFactors.Any()) {
1611          var scalarNode = scalarFactors.Aggregate(MakeProduct);
1612          var vectorNode = remainingFactors.Aggregate(MakeProduct);
1613
1614          var stdevNode = MakeStandardDeviationAggregation(vectorNode);
1615
1616          return MakeProduct(scalarNode, stdevNode);
1617        } else if (scalarFactors.Any()) {
1618          var scalarNode = scalarFactors.Aggregate(MakeProduct);
1619          return scalarNode;
1620        } else if (remainingFactors.Any()) {
1621          var vectorNode = remainingFactors.Aggregate(MakeProduct);
1622          var stdevNode = standardDeviationSymbol.CreateTreeNode();
1623          stdevNode.AddSubtree(vectorNode);
1624          return stdevNode;
1625        } else
1626          throw new InvalidOperationException("Multiplication does not contain any terms to simplify.");
1627      } else if (IsVariableBase(node)) { // weight is like multiplication
1628        var variableNode = (VariableTreeNodeBase)node;
1629        var weight = variableNode.Weight;
1630        variableNode.Weight = 1.0;
1631        var stdevNode = standardDeviationSymbol.CreateTreeNode();
1632        stdevNode.AddSubtree(node);
1633        return MakeProduct(MakeConstant(weight), stdevNode);
1634      } else {
1635        var stdevNode = standardDeviationSymbol.CreateTreeNode();
1636        stdevNode.AddSubtree(node);
1637        return stdevNode;
1638      }
1639    }
1640
1641    private ISymbolicExpressionTreeNode MakeVarianceAggregation(ISymbolicExpressionTreeNode node) {
1642      if (IsScalarNode(node)) {
1643        return MakeConstant(0.0);
1644      } else if (IsAddition(node) || IsSubtraction(node)) { // scalars drop out
1645        var terms = node.Subtrees;
1646
1647        var scalarTerms = terms.Where(IsScalarNode).ToList();
1648        var remainingTerms = terms.Except(scalarTerms).ToList();
1649
1650        if (remainingTerms.Any()) {
1651          var vectorNode = remainingTerms.Aggregate(MakeSum);
1652
1653          var varNode = varianceSymbol.CreateTreeNode();
1654          varNode.AddSubtree(vectorNode);
1655
1656          return varNode;
1657        } else if (scalarTerms.Any()) {
1658          return MakeConstant(0.0);
1659        } else
1660          throw new InvalidOperationException("Addition does not contain any terms to simplify.");
1661      } else if (IsMultiplication(node) || IsDivision(node)) {
1662        var factors = node.Subtrees;
1663        if (IsDivision(node)) factors = InvertNodes(factors, Invert);
1664
1665        var scalarFactors = factors.Where(IsScalarNode).ToList();
1666        var remainingFactors = factors.Except(scalarFactors).ToList();
1667
1668        if (scalarFactors.Any() && remainingFactors.Any()) {
1669          var scalarNode = scalarFactors.Aggregate(MakeProduct);
1670          var vectorNode = remainingFactors.Aggregate(MakeProduct);
1671
1672          var varNode = MakeVarianceAggregation(vectorNode);
1673
1674          return MakeProduct(MakeSquare(scalarNode), varNode);
1675        } else if (scalarFactors.Any()) {
1676          var scalarNode = scalarFactors.Aggregate(MakeProduct);
1677          return MakeSquare(scalarNode);
1678        } else if (remainingFactors.Any()) {
1679          var vectorNode = remainingFactors.Aggregate(MakeProduct);
1680          var varNode = varianceSymbol.CreateTreeNode();
1681          varNode.AddSubtree(vectorNode);
1682          return varNode;
1683        } else
1684          throw new InvalidOperationException("Multiplication does not contain any terms to simplify.");
1685      } else if (IsVariableBase(node)) { // weight is like multiplication
1686        var variableNode = (VariableTreeNodeBase)node;
1687        var weight = variableNode.Weight;
1688        variableNode.Weight = 1.0;
1689        var varNode = varianceSymbol.CreateTreeNode();
1690        varNode.AddSubtree(node);
1691        return MakeProduct(MakeSquare(MakeConstant(weight)), varNode);
1692      } else {
1693        var varNode = varianceSymbol.CreateTreeNode();
1694        varNode.AddSubtree(node);
1695        return varNode;
1696      }
1697    }
1698    #endregion
1699
1700    #region helper functions
1701
1702    private bool ContainsVariableCondition(ISymbolicExpressionTreeNode node) {
1703      if (node.Symbol is VariableCondition) return true;
1704      foreach (var subtree in node.Subtrees)
1705        if (ContainsVariableCondition(subtree)) return true;
1706      return false;
1707    }
1708
1709    private ISymbolicExpressionTreeNode AddLagToDynamicNodes(ISymbolicExpressionTreeNode node, int lag) {
1710      var laggedTreeNode = node as ILaggedTreeNode;
1711      var variableNode = node as VariableTreeNode;
1712      var variableConditionNode = node as VariableConditionTreeNode;
1713      if (laggedTreeNode != null)
1714        laggedTreeNode.Lag += lag;
1715      else if (variableNode != null) {
1716        var laggedVariableNode = (LaggedVariableTreeNode)laggedVariableSymbol.CreateTreeNode();
1717        laggedVariableNode.Lag = lag;
1718        laggedVariableNode.VariableName = variableNode.VariableName;
1719        return laggedVariableNode;
1720      } else if (variableConditionNode != null) {
1721        throw new NotSupportedException("Removal of time lags around variable condition symbols is not allowed.");
1722      }
1723      var subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
1724      while (node.SubtreeCount > 0) node.RemoveSubtree(0);
1725      foreach (var subtree in subtrees) {
1726        node.AddSubtree(AddLagToDynamicNodes(subtree, lag));
1727      }
1728      return node;
1729    }
1730
1731    private bool AreSameTypeAndVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
1732      return GroupId((IVariableTreeNode)a) == GroupId((IVariableTreeNode)b);
1733    }
1734
1735    // helper to combine the constant factors in products and to combine variables (powers of 2, 3...)
1736    private void MergeVariablesAndConstantsInProduct(ISymbolicExpressionTreeNode prod) {
1737      var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees);
1738      while (prod.Subtrees.Any()) prod.RemoveSubtree(0);
1739      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
1740                            where node.SubtreeCount == 0
1741                            group node by GroupId(node) into g
1742                            orderby g.Count()
1743                            select g;
1744      var constantProduct = (from node in subtrees.OfType<VariableTreeNodeBase>()
1745                             select node.Weight)
1746        .Concat(from node in subtrees.OfType<ConstantTreeNode>()
1747                select node.Value)
1748        .DefaultIfEmpty(1.0)
1749        .Aggregate((c1, c2) => c1 * c2);
1750
1751      var unchangedSubtrees = from tree in subtrees
1752                              where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is ConstantTreeNode)
1753                              select tree;
1754
1755      foreach (var variableNodeGroup in groupedVarNodes) {
1756        var firstNode = variableNodeGroup.First();
1757        if (firstNode is VariableTreeNodeBase) {
1758          var representative = (VariableTreeNodeBase)firstNode;
1759          representative.Weight = 1.0;
1760          if (variableNodeGroup.Count() > 1) {
1761            var poly = mulSymbol.CreateTreeNode();
1762            for (int p = 0; p < variableNodeGroup.Count(); p++) {
1763              poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone());
1764            }
1765            prod.AddSubtree(poly);
1766          } else {
1767            prod.AddSubtree(representative);
1768          }
1769        } else if (firstNode is FactorVariableTreeNode) {
1770          var representative = (FactorVariableTreeNode)firstNode;
1771          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
1772            for (int j = 0; j < representative.Weights.Length; j++) {
1773              representative.Weights[j] *= node.Weights[j];
1774            }
1775          }
1776          for (int j = 0; j < representative.Weights.Length; j++) {
1777            representative.Weights[j] *= constantProduct;
1778          }
1779          constantProduct = 1.0;
1780          // if the product already contains a factor it is not necessary to multiply a constant below
1781          prod.AddSubtree(representative);
1782        }
1783      }
1784
1785      foreach (var unchangedSubtree in unchangedSubtrees)
1786        prod.AddSubtree(unchangedSubtree);
1787
1788      if (!constantProduct.IsAlmost(1.0)) {
1789        prod.AddSubtree(MakeConstant(constantProduct));
1790      }
1791    }
1792
1793
1794    /// <summary>
1795    /// x => x * -1
1796    /// Is only used in cases where it is not necessary to create new tree nodes. Manipulates x directly.
1797    /// </summary>
1798    /// <param name="x"></param>
1799    /// <returns>-x</returns>
1800    private ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) {
1801      if (IsConstant(x)) {
1802        ((ConstantTreeNode)x).Value *= -1;
1803      } else if (IsVariableBase(x)) {
1804        var variableTree = (VariableTreeNodeBase)x;
1805        variableTree.Weight *= -1.0;
1806      } else if (IsFactor(x)) {
1807        var factorNode = (FactorVariableTreeNode)x;
1808        for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1;
1809      } else if (IsBinFactor(x)) {
1810        var factorNode = (BinaryFactorVariableTreeNode)x;
1811        factorNode.Weight *= -1;
1812      } else if (IsAddition(x)) {
1813        // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn)       
1814        var subtrees = new List<ISymbolicExpressionTreeNode>(x.Subtrees);
1815        while (x.Subtrees.Any()) x.RemoveSubtree(0);
1816        foreach (var subtree in subtrees) {
1817          x.AddSubtree(Negate(subtree));
1818        }
1819      } else if (IsMultiplication(x) || IsDivision(x)) {
1820        // x0 * x1 * .. * xn * -1 => x0 * x1 * .. * -xn
1821        var lastSubTree = x.Subtrees.Last();
1822        x.RemoveSubtree(x.SubtreeCount - 1);
1823        x.AddSubtree(Negate(lastSubTree)); // last is maybe a constant, prefer to negate the constant
1824      } else {
1825        // any other function
1826        return MakeProduct(x, MakeConstant(-1));
1827      }
1828      return x;
1829    }
1830
1831    /// <summary>
1832    /// x => 1/x
1833    /// Must create new tree nodes
1834    /// </summary>
1835    /// <param name="x"></param>
1836    /// <returns></returns>
1837    private ISymbolicExpressionTreeNode Invert(ISymbolicExpressionTreeNode x) {
1838      if (IsConstant(x)) {
1839        return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);
1840      } else if (IsFactor(x)) {
1841        var factorNode = (FactorVariableTreeNode)x;
1842        return MakeFactor(factorNode.Symbol, factorNode.VariableName, factorNode.Weights.Select(w => 1.0 / w));
1843      } else if (IsDivision(x)) {
1844        return MakeFraction(x.GetSubtree(1), x.GetSubtree(0));
1845      } else {
1846        // any other function
1847        return MakeFraction(MakeConstant(1), x);
1848      }
1849    }
1850
1851    private static ISymbolicExpressionTreeNode MakeConstant(double value) {
1852      ConstantTreeNode constantTreeNode = (ConstantTreeNode)(constSymbol.CreateTreeNode());
1853      constantTreeNode.Value = value;
1854      return constantTreeNode;
1855    }
1856
1857    private static ISymbolicExpressionTreeNode MakeFactor(FactorVariable sy, string variableName, IEnumerable<double> weights) {
1858      var tree = (FactorVariableTreeNode)sy.CreateTreeNode();
1859      tree.VariableName = variableName;
1860      tree.Weights = weights.ToArray();
1861      return tree;
1862    }
1863    private static ISymbolicExpressionTreeNode MakeBinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) {
1864      var tree = (BinaryFactorVariableTreeNode)sy.CreateTreeNode();
1865      tree.VariableName = variableName;
1866      tree.VariableValue = variableValue;
1867      tree.Weight = weight;
1868      return tree;
1869    }
1870    private static IEnumerable<ISymbolicExpressionTreeNode> InvertNodes(IEnumerable<ISymbolicExpressionTreeNode> nodes, Func<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> invertFunc) {
1871      if (nodes.Count() == 1)
1872        return nodes.Select(invertFunc);
1873      var first = nodes.First().ToEnumerable();
1874      var remaining = nodes.Skip(1).Select(invertFunc);
1875      return first.Concat(remaining);
1876    }
1877
1878    #endregion
1879  }
1880}
Note: See TracBrowser for help on using the repository browser.