Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
12/15/21 11:50:57 (2 years ago)
Author:
gkronber
Message:

#3140: merged r18091:18131 from branch to trunk

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic

  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs

    r17963 r18132  
    3636    private static readonly Multiplication mulSymbol = new Multiplication();
    3737    private static readonly Division divSymbol = new Division();
    38     private static readonly Constant constSymbol = new Constant();
     38    private static readonly Number numberSymbol = new Number();
    3939    private static readonly Absolute absSymbol = new Absolute();
    4040    private static readonly Logarithm logSymbol = new Logarithm();
     
    8181    private static ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node,
    8282      IList<ISymbolicExpressionTreeNode> argumentTrees) {
    83       List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
     83      var subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
    8484      while (node.SubtreeCount > 0) node.RemoveSubtree(0);
    8585      if (node.Symbol is InvokeFunction) {
     
    240240    }
    241241
     242    private static bool IsNumber(ISymbolicExpressionTreeNode node) {
     243      return node.Symbol is Number;
     244    }
    242245    private static bool IsConstant(ISymbolicExpressionTreeNode node) {
    243246      return node.Symbol is Constant;
    244247    }
    245 
    246     // dynamic
     248    private static bool IsConstantOrNumber(ISymbolicExpressionTreeNode node) {
     249      return node is INumericTreeNode;
     250    }
     251
    247252    private static bool IsTimeLag(ISymbolicExpressionTreeNode node) {
    248253      return node.Symbol is TimeLag;
     
    261266    /// <returns></returns>
    262267    public static ISymbolicExpressionTreeNode GetSimplifiedTree(ISymbolicExpressionTreeNode original) {
    263       if (IsConstant(original) || IsVariableBase(original)) {
     268      if (IsConstantOrNumber(original) || IsVariableBase(original)) {
    264269        return (ISymbolicExpressionTreeNode)original.Clone();
    265270      } else if (IsAbsolute(original)) {
     
    324329    private static ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) {
    325330      // can't simplify this function but simplify all subtrees
    326       List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees);
     331      var subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees);
    327332      while (original.Subtrees.Count() > 0) original.RemoveSubtree(0);
    328333      var clone = (SymbolicExpressionTreeNode)original.Clone();
    329       List<ISymbolicExpressionTreeNode> simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>();
     334      var simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>();
    330335      foreach (var subtree in subtrees) {
    331336        simplifiedSubtrees.Add(GetSimplifiedTree(subtree));
     
    335340        clone.AddSubtree(simplifiedSubtree);
    336341      }
    337       if (simplifiedSubtrees.TrueForAll(t => IsConstant(t))) {
    338         SimplifyConstantExpression(clone);
     342      if (simplifiedSubtrees.TrueForAll(IsNumber)) {
     343        FoldNumbers(clone);
    339344      }
    340345      return clone;
    341346    }
    342347
    343     private static ISymbolicExpressionTreeNode SimplifyConstantExpression(ISymbolicExpressionTreeNode original) {
    344       // not yet implemented
     348    private static ISymbolicExpressionTreeNode FoldNumbers(ISymbolicExpressionTreeNode original) {
     349      // TODO not implemented
    345350      return original;
    346351    }
     
    354359        var sum = original.Subtrees
    355360          .Select(GetSimplifiedTree)
    356           .Aggregate(MakeSum);
    357         return MakeFraction(sum, MakeConstant(original.Subtrees.Count()));
     361          .Aggregate(Sum);
     362        return Fraction(sum, Number(original.Subtrees.Count()));
    358363      }
    359364    }
     
    369374        var remaining = original.Subtrees.Skip(2);
    370375        return
    371           MakeProduct(GetSimplifiedTree(first),
    372             Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => MakeProduct(a, GetSimplifiedTree(b)))));
     376          Product(GetSimplifiedTree(first),
     377            Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => Product(a, GetSimplifiedTree(b)))));
    373378      }
    374379    }
     
    380385        return original.Subtrees
    381386          .Select(GetSimplifiedTree)
    382           .Aggregate(MakeProduct);
     387          .Aggregate(Product);
    383388      }
    384389    }
     
    392397        var first = original.Subtrees.First();
    393398        var remaining = original.Subtrees.Skip(1);
    394         return remaining.Aggregate(GetSimplifiedTree(first), (a, b) => MakeSum(a, Negate(GetSimplifiedTree(b))));
     399        return remaining.Aggregate(GetSimplifiedTree(first), (a, b) => Sum(a, Negate(GetSimplifiedTree(b))));
    395400      }
    396401    }
     
    404409        return original.Subtrees
    405410          .Select(GetSimplifiedTree)
    406           .Aggregate(MakeSum);
     411          .Aggregate(Sum);
    407412      }
    408413    }
    409414
    410415    private static ISymbolicExpressionTreeNode SimplifyAbsolute(ISymbolicExpressionTreeNode original) {
    411       return MakeAbs(GetSimplifiedTree(original.GetSubtree(0)));
     416      return Abs(GetSimplifiedTree(original.GetSubtree(0)));
    412417    }
    413418
    414419    private static ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) {
    415       return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
     420      return Not(GetSimplifiedTree(original.GetSubtree(0)));
    416421    }
    417422
     
    419424      return original.Subtrees
    420425        .Select(GetSimplifiedTree)
    421         .Aggregate(MakeOr);
     426        .Aggregate(Or);
    422427    }
    423428
     
    425430      return original.Subtrees
    426431        .Select(GetSimplifiedTree)
    427         .Aggregate(MakeAnd);
     432        .Aggregate(And);
    428433    }
    429434
    430435    private static ISymbolicExpressionTreeNode SimplifyLessThan(ISymbolicExpressionTreeNode original) {
    431       return MakeLessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
     436      return LessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    432437    }
    433438
    434439    private static ISymbolicExpressionTreeNode SimplifyGreaterThan(ISymbolicExpressionTreeNode original) {
    435       return MakeGreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
     440      return GreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    436441    }
    437442
    438443    private static ISymbolicExpressionTreeNode SimplifyIfThenElse(ISymbolicExpressionTreeNode original) {
    439       return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)),
     444      return IfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)),
    440445        GetSimplifiedTree(original.GetSubtree(2)));
    441446    }
    442447
    443448    private static ISymbolicExpressionTreeNode SimplifyTangent(ISymbolicExpressionTreeNode original) {
    444       return MakeTangent(GetSimplifiedTree(original.GetSubtree(0)));
     449      return Tangent(GetSimplifiedTree(original.GetSubtree(0)));
    445450    }
    446451
    447452    private static ISymbolicExpressionTreeNode SimplifyCosine(ISymbolicExpressionTreeNode original) {
    448       return MakeCosine(GetSimplifiedTree(original.GetSubtree(0)));
     453      return Cosine(GetSimplifiedTree(original.GetSubtree(0)));
    449454    }
    450455
    451456    private static ISymbolicExpressionTreeNode SimplifySine(ISymbolicExpressionTreeNode original) {
    452       return MakeSine(GetSimplifiedTree(original.GetSubtree(0)));
     457      return Sine(GetSimplifiedTree(original.GetSubtree(0)));
    453458    }
    454459
    455460    private static ISymbolicExpressionTreeNode SimplifyExp(ISymbolicExpressionTreeNode original) {
    456       return MakeExp(GetSimplifiedTree(original.GetSubtree(0)));
     461      return Exp(GetSimplifiedTree(original.GetSubtree(0)));
    457462    }
    458463
    459464    private static ISymbolicExpressionTreeNode SimplifySquare(ISymbolicExpressionTreeNode original) {
    460       return MakeSquare(GetSimplifiedTree(original.GetSubtree(0)));
     465      return Square(GetSimplifiedTree(original.GetSubtree(0)));
    461466    }
    462467
    463468    private static ISymbolicExpressionTreeNode SimplifySquareRoot(ISymbolicExpressionTreeNode original) {
    464       return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
     469      return SquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
    465470    }
    466471    private static ISymbolicExpressionTreeNode SimplifyCube(ISymbolicExpressionTreeNode original) {
    467       return MakeCube(GetSimplifiedTree(original.GetSubtree(0)));
     472      return Cube(GetSimplifiedTree(original.GetSubtree(0)));
    468473    }
    469474
    470475    private static ISymbolicExpressionTreeNode SimplifyCubeRoot(ISymbolicExpressionTreeNode original) {
    471       return MakeCubeRoot(GetSimplifiedTree(original.GetSubtree(0)));
     476      return CubeRoot(GetSimplifiedTree(original.GetSubtree(0)));
    472477    }
    473478
    474479    private static ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) {
    475       return MakeLog(GetSimplifiedTree(original.GetSubtree(0)));
     480      return Log(GetSimplifiedTree(original.GetSubtree(0)));
    476481    }
    477482
    478483    private static ISymbolicExpressionTreeNode SimplifyRoot(ISymbolicExpressionTreeNode original) {
    479       return MakeRoot(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
     484      return Root(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    480485    }
    481486
    482487    private static ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) {
    483       return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
     488      return Power(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    484489    }
    485490
    486491    private static ISymbolicExpressionTreeNode SimplifyAnalyticalQuotient(ISymbolicExpressionTreeNode original) {
    487       return MakeAnalyticalQuotient(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
     492      return AQ(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    488493    }
    489494
     
    494499        return AddLagToDynamicNodes(simplifiedSubtree, laggedTreeNode.Lag);
    495500      } else {
    496         return MakeTimeLag(simplifiedSubtree, laggedTreeNode.Lag);
     501        return Lag(simplifiedSubtree, laggedTreeNode.Lag);
    497502      }
    498503    }
     
    501506      var laggedTreeNode = original as ILaggedTreeNode;
    502507      var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0));
    503       if (IsConstant(simplifiedSubtree)) {
    504         return GetSimplifiedTree(MakeProduct(simplifiedSubtree, MakeConstant(-laggedTreeNode.Lag)));
    505       } else {
    506         return MakeIntegral(simplifiedSubtree, laggedTreeNode.Lag);
     508      if (IsConstantOrNumber(simplifiedSubtree)) {
     509        return GetSimplifiedTree(Product(simplifiedSubtree, Number(-laggedTreeNode.Lag)));
     510      } else {
     511        return Integral(simplifiedSubtree, laggedTreeNode.Lag);
    507512      }
    508513    }
     
    512517    #region low level tree restructuring
    513518
    514     private static ISymbolicExpressionTreeNode MakeTimeLag(ISymbolicExpressionTreeNode subtree, int lag) {
     519    private static ISymbolicExpressionTreeNode Lag(ISymbolicExpressionTreeNode subtree, int lag) {
    515520      if (lag == 0) return subtree;
    516       if (IsConstant(subtree)) return subtree;
     521      if (IsConstantOrNumber(subtree)) return subtree;
    517522      var lagNode = (LaggedTreeNode)timeLagSymbol.CreateTreeNode();
    518523      lagNode.Lag = lag;
     
    521526    }
    522527
    523     private static ISymbolicExpressionTreeNode MakeIntegral(ISymbolicExpressionTreeNode subtree, int lag) {
     528    private static ISymbolicExpressionTreeNode Integral(ISymbolicExpressionTreeNode subtree, int lag) {
    524529      if (lag == 0) return subtree;
    525530      else if (lag == -1 || lag == 1) {
    526         return MakeSum(subtree, AddLagToDynamicNodes((ISymbolicExpressionTreeNode)subtree.Clone(), lag));
     531        return Sum(subtree, AddLagToDynamicNodes((ISymbolicExpressionTreeNode)subtree.Clone(), lag));
    527532      } else {
    528533        var node = (LaggedTreeNode)integralSymbol.CreateTreeNode();
     
    533538    }
    534539
    535     private static ISymbolicExpressionTreeNode MakeNot(ISymbolicExpressionTreeNode t) {
    536       if (IsConstant(t)) {
    537         var constNode = t as ConstantTreeNode;
    538         if (constNode.Value > 0) return MakeConstant(-1.0);
    539         else return MakeConstant(1.0);
     540    private static ISymbolicExpressionTreeNode Not(ISymbolicExpressionTreeNode t) {
     541      if (IsNumber(t)) {
     542        var numNode = t as NumberTreeNode;
     543        if (numNode.Value > 0) return Number(-1.0);
     544        else return Number(1.0);
    540545      } else if (IsNot(t)) {
    541546        return t.GetSubtree(0);
     
    543548        var gtNode = gtSymbol.CreateTreeNode();
    544549        gtNode.AddSubtree(t);
    545         gtNode.AddSubtree(MakeConstant(0.0));
     550        gtNode.AddSubtree(Number(0.0));
    546551        var notNode = notSymbol.CreateTreeNode();
    547552        notNode.AddSubtree(gtNode);
     
    554559    }
    555560
    556     private static ISymbolicExpressionTreeNode MakeOr(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    557       if (IsConstant(a) && IsConstant(b)) {
    558         var constA = a as ConstantTreeNode;
    559         var constB = b as ConstantTreeNode;
    560         if (constA.Value > 0.0 || constB.Value > 0.0) {
    561           return MakeConstant(1.0);
     561    private static ISymbolicExpressionTreeNode Or(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     562      if (IsNumber(a) && IsNumber(b)) {
     563        var aNode = a as NumberTreeNode;
     564        var bNode = b as NumberTreeNode;
     565        if (aNode.Value > 0.0 || bNode.Value > 0.0) {
     566          return Number(1.0);
    562567        } else {
    563           return MakeConstant(-1.0);
    564         }
    565       } else if (IsConstant(a)) {
    566         return MakeOr(b, a);
    567       } else if (IsConstant(b)) {
    568         var constT = b as ConstantTreeNode;
    569         if (constT.Value > 0.0) {
     568          return Number(-1.0);
     569        }
     570      } else if (IsNumber(a)) {
     571        return Or(b, a);
     572      } else if (IsNumber(b)) {
     573        var bNode = b as NumberTreeNode;
     574        if (bNode.Value > 0.0) {
    570575          // boolean expression is necessarily true
    571           return MakeConstant(1.0);
     576          return Number(1.0);
    572577        } else {
    573           // the constant value has no effect on the result of the boolean condition so we can drop the constant term
     578          // the value has no effect on the result of the boolean condition so we can drop the number
    574579          var orNode = orSymbol.CreateTreeNode();
    575580          orNode.AddSubtree(a);
     
    584589    }
    585590
    586     private static ISymbolicExpressionTreeNode MakeAnd(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    587       if (IsConstant(a) && IsConstant(b)) {
    588         var constA = a as ConstantTreeNode;
    589         var constB = b as ConstantTreeNode;
    590         if (constA.Value > 0.0 && constB.Value > 0.0) {
    591           return MakeConstant(1.0);
     591    private static ISymbolicExpressionTreeNode And(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     592      if (IsNumber(a) && IsNumber(b)) {
     593        var aNode = a as NumberTreeNode;
     594        var bNode = b as NumberTreeNode;
     595        if (aNode.Value > 0.0 && bNode.Value > 0.0) {
     596          return Number(1.0);
    592597        } else {
    593           return MakeConstant(-1.0);
    594         }
    595       } else if (IsConstant(a)) {
    596         return MakeAnd(b, a);
    597       } else if (IsConstant(b)) {
    598         var constB = b as ConstantTreeNode;
    599         if (constB.Value > 0.0) {
    600           // the constant value has no effect on the result of the boolean condition so we can drop the constant term
     598          return Number(-1.0);
     599        }
     600      } else if (IsNumber(a)) {
     601        return And(b, a);
     602      } else if (IsNumber(b)) {
     603        var bNode = b as NumberTreeNode;
     604        if (bNode.Value > 0.0) {
     605          // the value has no effect on the result of the boolean condition so we can drop the number
    601606          var andNode = andSymbol.CreateTreeNode();
    602607          andNode.AddSubtree(a);
     
    604609        } else {
    605610          // boolean expression is necessarily false
    606           return MakeConstant(-1.0);
     611          return Number(-1.0);
    607612        }
    608613      } else {
     
    614619    }
    615620
    616     private static ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide,
     621    private static ISymbolicExpressionTreeNode LessThan(ISymbolicExpressionTreeNode leftSide,
    617622      ISymbolicExpressionTreeNode rightSide) {
    618       if (IsConstant(leftSide) && IsConstant(rightSide)) {
    619         var lsConst = leftSide as ConstantTreeNode;
    620         var rsConst = rightSide as ConstantTreeNode;
    621         if (lsConst.Value < rsConst.Value) return MakeConstant(1.0);
    622         else return MakeConstant(-1.0);
     623      if (IsNumber(leftSide) && IsNumber(rightSide)) {
     624        var lsNode = leftSide as NumberTreeNode;
     625        var rsNode = rightSide as NumberTreeNode;
     626        if (lsNode.Value < rsNode.Value) return Number(1.0);
     627        else return Number(-1.0);
    623628      } else {
    624629        var ltNode = ltSymbol.CreateTreeNode();
     
    629634    }
    630635
    631     private static ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide,
     636    private static ISymbolicExpressionTreeNode GreaterThan(ISymbolicExpressionTreeNode leftSide,
    632637      ISymbolicExpressionTreeNode rightSide) {
    633       if (IsConstant(leftSide) && IsConstant(rightSide)) {
    634         var lsConst = leftSide as ConstantTreeNode;
    635         var rsConst = rightSide as ConstantTreeNode;
    636         if (lsConst.Value > rsConst.Value) return MakeConstant(1.0);
    637         else return MakeConstant(-1.0);
     638      if (IsNumber(leftSide) && IsNumber(rightSide)) {
     639        var lsNode = leftSide as NumberTreeNode;
     640        var rsNode = rightSide as NumberTreeNode;
     641        if (lsNode.Value > rsNode.Value) return Number(1.0);
     642        else return Number(-1.0);
    638643      } else {
    639644        var gtNode = gtSymbol.CreateTreeNode();
     
    644649    }
    645650
    646     private static ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition,
     651    private static ISymbolicExpressionTreeNode IfThenElse(ISymbolicExpressionTreeNode condition,
    647652      ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) {
    648       if (IsConstant(condition)) {
    649         var constT = condition as ConstantTreeNode;
    650         if (constT.Value > 0.0) return trueBranch;
     653      if (IsConstantOrNumber(condition)) {
     654        var condNode = condition as INumericTreeNode;
     655        if (condNode.Value > 0.0) return trueBranch;
    651656        else return falseBranch;
    652657      } else {
     
    657662          var gtNode = gtSymbol.CreateTreeNode();
    658663          gtNode.AddSubtree(condition);
    659           gtNode.AddSubtree(MakeConstant(0.0));
     664          gtNode.AddSubtree(Number(0.0));
    660665          ifNode.AddSubtree(gtNode);
    661666        }
     
    666671    }
    667672
    668     private static ISymbolicExpressionTreeNode MakeSine(ISymbolicExpressionTreeNode node) {
    669       if (IsConstant(node)) {
    670         var constT = node as ConstantTreeNode;
    671         return MakeConstant(Math.Sin(constT.Value));
     673    private static ISymbolicExpressionTreeNode Sine(ISymbolicExpressionTreeNode node) {
     674      if (IsNumber(node)) {
     675        var numNode = node as NumberTreeNode;
     676        return Number(Math.Sin(numNode.Value));
    672677      } else if (IsFactor(node)) {
    673678        var factor = node as FactorVariableTreeNode;
    674         return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin));
     679        return Factor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin));
    675680      } else if (IsBinFactor(node)) {
    676681        var binFactor = node as BinaryFactorVariableTreeNode;
    677         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight));
     682        return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight));
    678683      } else {
    679684        var sineNode = sineSymbol.CreateTreeNode();
     
    683688    }
    684689
    685     private static ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) {
    686       if (IsConstant(node)) {
    687         var constT = node as ConstantTreeNode;
    688         return MakeConstant(Math.Tan(constT.Value));
     690    private static ISymbolicExpressionTreeNode Tangent(ISymbolicExpressionTreeNode node) {
     691      if (IsNumber(node)) {
     692        var numNode = node as NumberTreeNode;
     693        return Number(Math.Tan(numNode.Value));
    689694      } else if (IsFactor(node)) {
    690695        var factor = node as FactorVariableTreeNode;
    691         return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan));
     696        return Factor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan));
    692697      } else if (IsBinFactor(node)) {
    693698        var binFactor = node as BinaryFactorVariableTreeNode;
    694         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight));
     699        return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight));
    695700      } else {
    696701        var tanNode = tanSymbol.CreateTreeNode();
     
    700705    }
    701706
    702     private static ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) {
    703       if (IsConstant(node)) {
    704         var constT = node as ConstantTreeNode;
    705         return MakeConstant(Math.Cos(constT.Value));
     707    private static ISymbolicExpressionTreeNode Cosine(ISymbolicExpressionTreeNode node) {
     708      if (IsNumber(node)) {
     709        var numNode = node as NumberTreeNode;
     710        return Number(Math.Cos(numNode.Value));
    706711      } else if (IsFactor(node)) {
    707712        var factor = node as FactorVariableTreeNode;
    708         return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos));
     713        return Factor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos));
    709714      } else if (IsBinFactor(node)) {
    710715        var binFactor = node as BinaryFactorVariableTreeNode;
    711716        // cos(0) = 1 see similar case for Exp(binfactor)
    712         return MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight) - 1),
    713           MakeConstant(1.0));
     717        return Sum(BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight) - 1),
     718          Number(1.0));
    714719      } else {
    715720        var cosNode = cosineSymbol.CreateTreeNode();
     
    719724    }
    720725
    721     private static ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) {
    722       if (IsConstant(node)) {
    723         var constT = node as ConstantTreeNode;
    724         return MakeConstant(Math.Exp(constT.Value));
     726    private static ISymbolicExpressionTreeNode Exp(ISymbolicExpressionTreeNode node) {
     727      if (IsNumber(node)) {
     728        var numNode = node as NumberTreeNode;
     729        return Number(Math.Exp(numNode.Value));
    725730      } else if (IsFactor(node)) {
    726731        var factNode = node as FactorVariableTreeNode;
    727         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w)));
     732        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w)));
    728733      } else if (IsBinFactor(node)) {
    729734        // exp( binfactor w val=a) = if(val=a) exp(w) else exp(0) = binfactor( (exp(w) - 1) val a) + 1
    730735        var binFactor = node as BinaryFactorVariableTreeNode;
    731736        return
    732           MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight) - 1), MakeConstant(1.0));
     737          Sum(BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight) - 1), Number(1.0));
    733738      } else if (IsLog(node)) {
    734739        return node.GetSubtree(0);
    735740      } else if (IsAddition(node)) {
    736         return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));
     741        return node.Subtrees.Select(s => Exp(s)).Aggregate((s, t) => Product(s, t));
    737742      } else if (IsSubtraction(node)) {
    738         return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));
     743        return node.Subtrees.Select(s => Exp(s)).Aggregate((s, t) => Product(s, Negate(t)));
    739744      } else {
    740745        var expNode = expSymbol.CreateTreeNode();
     
    743748      }
    744749    }
    745     private static ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {
    746       if (IsConstant(node)) {
    747         var constT = node as ConstantTreeNode;
    748         return MakeConstant(Math.Log(constT.Value));
     750    private static ISymbolicExpressionTreeNode Log(ISymbolicExpressionTreeNode node) {
     751      if (IsNumber(node)) {
     752        var numNode = node as NumberTreeNode;
     753        return Number(Math.Log(numNode.Value));
    749754      } else if (IsFactor(node)) {
    750755        var factNode = node as FactorVariableTreeNode;
    751         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));
     756        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));
    752757      } else if (IsExp(node)) {
    753758        return node.GetSubtree(0);
    754759      } else if (IsSquareRoot(node)) {
    755         return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));
     760        return Fraction(Log(node.GetSubtree(0)), Number(2.0));
    756761      } else {
    757762        var logNode = logSymbol.CreateTreeNode();
     
    761766    }
    762767
    763     private static ISymbolicExpressionTreeNode MakeSquare(ISymbolicExpressionTreeNode node) {
    764       if (IsConstant(node)) {
    765         var constT = node as ConstantTreeNode;
    766         return MakeConstant(constT.Value * constT.Value);
     768    private static ISymbolicExpressionTreeNode Square(ISymbolicExpressionTreeNode node) {
     769      if (IsNumber(node)) {
     770        var numNode = node as NumberTreeNode;
     771        return Number(numNode.Value * numNode.Value);
    767772      } else if (IsFactor(node)) {
    768773        var factNode = node as FactorVariableTreeNode;
    769         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w));
     774        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w));
    770775      } else if (IsBinFactor(node)) {
    771776        var binFactor = node as BinaryFactorVariableTreeNode;
    772         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight);
     777        return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight);
    773778      } else if (IsSquareRoot(node)) {
    774779        return node.GetSubtree(0);
     
    777782        var mulNode = mulSymbol.CreateTreeNode();
    778783        foreach (var subtree in node.Subtrees) {
    779           mulNode.AddSubtree(MakeSquare(subtree));
     784          mulNode.AddSubtree(Square(subtree));
    780785        }
    781786        return mulNode;
    782787      } else if (IsAbsolute(node)) {
    783         return MakeSquare(node.GetSubtree(0)); // sqr(abs(x)) = sqr(x)
     788        return Square(node.GetSubtree(0)); // sqr(abs(x)) = sqr(x)
    784789      } else if (IsExp(node)) {
    785         return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(2.0))); // sqr(exp(x)) = exp(2x)
     790        return Exp(Product(node.GetSubtree(0), Number(2.0))); // sqr(exp(x)) = exp(2x)
    786791      } else if (IsSquare(node)) {
    787         return MakePower(node.GetSubtree(0), MakeConstant(4));
     792        return Power(node.GetSubtree(0), Number(4));
    788793      } else if (IsCube(node)) {
    789         return MakePower(node.GetSubtree(0), MakeConstant(6));
     794        return Power(node.GetSubtree(0), Number(6));
    790795      } else {
    791796        var sqrNode = sqrSymbol.CreateTreeNode();
     
    795800    }
    796801
    797     private static ISymbolicExpressionTreeNode MakeCube(ISymbolicExpressionTreeNode node) {
    798       if (IsConstant(node)) {
    799         var constT = node as ConstantTreeNode;
    800         return MakeConstant(constT.Value * constT.Value * constT.Value);
     802    private static ISymbolicExpressionTreeNode Cube(ISymbolicExpressionTreeNode node) {
     803      if (IsNumber(node)) {
     804        var numNode = node as NumberTreeNode;
     805        return Number(numNode.Value * numNode.Value * numNode.Value);
    801806      } else if (IsFactor(node)) {
    802807        var factNode = node as FactorVariableTreeNode;
    803         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w * w));
     808        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w * w));
    804809      } else if (IsBinFactor(node)) {
    805810        var binFactor = node as BinaryFactorVariableTreeNode;
    806         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight * binFactor.Weight);
     811        return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight * binFactor.Weight);
    807812      } else if (IsCubeRoot(node)) {
    808813        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
    809814      } else if (IsExp(node)) {
    810         return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(3)));
     815        return Exp(Product(node.GetSubtree(0), Number(3)));
    811816      } else if (IsSquare(node)) {
    812         return MakePower(node.GetSubtree(0), MakeConstant(6));
     817        return Power(node.GetSubtree(0), Number(6));
    813818      } else if (IsCube(node)) {
    814         return MakePower(node.GetSubtree(0), MakeConstant(9));
     819        return Power(node.GetSubtree(0), Number(9));
    815820      } else {
    816821        var cubeNode = cubeSymbol.CreateTreeNode();
     
    820825    }
    821826
    822     private static ISymbolicExpressionTreeNode MakeAbs(ISymbolicExpressionTreeNode node) {
    823       if (IsConstant(node)) {
    824         var constT = node as ConstantTreeNode;
    825         return MakeConstant(Math.Abs(constT.Value));
     827    private static ISymbolicExpressionTreeNode Abs(ISymbolicExpressionTreeNode node) {
     828      if (IsNumber(node)) {
     829        var numNode = node as NumberTreeNode;
     830        return Number(Math.Abs(numNode.Value));
    826831      } else if (IsFactor(node)) {
    827832        var factNode = node as FactorVariableTreeNode;
    828         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Abs(w)));
     833        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Abs(w)));
    829834      } else if (IsBinFactor(node)) {
    830835        var binFactor = node as BinaryFactorVariableTreeNode;
    831         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Abs(binFactor.Weight));
     836        return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Abs(binFactor.Weight));
    832837      } else if (IsSquare(node) || IsExp(node) || IsSquareRoot(node) || IsCubeRoot(node)) {
    833838        return node; // abs(sqr(x)) = sqr(x), abs(exp(x)) = exp(x) ...
     
    835840        var mul = mulSymbol.CreateTreeNode();
    836841        foreach (var st in node.Subtrees) {
    837           mul.AddSubtree(MakeAbs(st));
     842          mul.AddSubtree(Abs(st));
    838843        }
    839844        return mul;
     
    841846        var div = divSymbol.CreateTreeNode();
    842847        foreach (var st in node.Subtrees) {
    843           div.AddSubtree(MakeAbs(st));
     848          div.AddSubtree(Abs(st));
    844849        }
    845850        return div;
     
    852857
    853858    // constant folding only
    854     private static ISymbolicExpressionTreeNode MakeAnalyticalQuotient(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    855       if (IsConstant(b)) {
    856         var c = b as ConstantTreeNode;
    857         return MakeFraction(a, MakeConstant(Math.Sqrt(1.0 + c.Value * c.Value)));
     859    private static ISymbolicExpressionTreeNode AQ(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     860      if (IsNumber(b)) {
     861        var nNode = b as NumberTreeNode;
     862        return Fraction(a, Number(Math.Sqrt(1.0 + nNode.Value * nNode.Value)));
    858863      } else if (IsFactor(b)) {
    859864        var factNode = b as FactorVariableTreeNode;
    860         return MakeFraction(a, MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(1.0 + w * w))));
     865        return Fraction(a, Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(1.0 + w * w))));
    861866      } else if (IsBinFactor(b)) {
    862867        var binFactor = b as BinaryFactorVariableTreeNode;
    863         return MakeFraction(a, MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(1.0 + binFactor.Weight * binFactor.Weight)));
     868        return Fraction(a, BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(1.0 + binFactor.Weight * binFactor.Weight)));
    864869      } else {
    865870        var aqNode = aqSymbol.CreateTreeNode();
     
    870875    }
    871876
    872     private static ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) {
    873       if (IsConstant(node)) {
    874         var constT = node as ConstantTreeNode;
    875         return MakeConstant(Math.Sqrt(constT.Value));
     877    private static ISymbolicExpressionTreeNode SquareRoot(ISymbolicExpressionTreeNode node) {
     878      if (IsNumber(node)) {
     879        var numNode = node as NumberTreeNode;
     880        return Number(Math.Sqrt(numNode.Value));
    876881      } else if (IsFactor(node)) {
    877882        var factNode = node as FactorVariableTreeNode;
    878         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w)));
     883        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w)));
    879884      } else if (IsBinFactor(node)) {
    880885        var binFactor = node as BinaryFactorVariableTreeNode;
    881         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
     886        return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
    882887      } else if (IsSquare(node)) {
    883888        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
     
    889894    }
    890895
    891     private static ISymbolicExpressionTreeNode MakeCubeRoot(ISymbolicExpressionTreeNode node) {
    892       if (IsConstant(node)) {
    893         var constT = node as ConstantTreeNode;
    894         return MakeConstant(Math.Pow(constT.Value, 1.0 / 3.0));
     896    private static ISymbolicExpressionTreeNode CubeRoot(ISymbolicExpressionTreeNode node) {
     897      if (IsNumber(node)) {
     898        var numNode = node as NumberTreeNode;
     899        return Number(Math.Pow(numNode.Value, 1.0 / 3.0));
    895900      } else if (IsFactor(node)) {
    896901        var factNode = node as FactorVariableTreeNode;
    897         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, 1.0 / 3.0)));
     902        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, 1.0 / 3.0)));
    898903      } else if (IsBinFactor(node)) {
    899904        var binFactor = node as BinaryFactorVariableTreeNode;
    900         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(Math.Pow(binFactor.Weight, 1.0 / 3.0)));
     905        return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(Math.Pow(binFactor.Weight, 1.0 / 3.0)));
    901906      } else if (IsCube(node)) {
    902907        return node.GetSubtree(0);
     
    908913    }
    909914
    910     private static ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    911       if (IsConstant(a) && IsConstant(b)) {
    912         var constA = a as ConstantTreeNode;
    913         var constB = b as ConstantTreeNode;
    914         return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value)));
    915       } else if (IsFactor(a) && IsConstant(b)) {
     915    private static ISymbolicExpressionTreeNode Root(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     916      if (IsNumber(a) && IsNumber(b)) {
     917        var aNode = a as NumberTreeNode;
     918        var bNode = b as NumberTreeNode;
     919        return Number(Math.Pow(aNode.Value, 1.0 / Math.Round(bNode.Value)));
     920      } else if (IsFactor(a) && IsNumber(b)) {
    916921        var factNode = a as FactorVariableTreeNode;
    917         var constNode = b as ConstantTreeNode;
    918         return MakeFactor(factNode.Symbol, factNode.VariableName,
    919           factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(constNode.Value))));
    920       } else if (IsBinFactor(a) && IsConstant(b)) {
     922        var bNode = b as NumberTreeNode;
     923        return Factor(factNode.Symbol, factNode.VariableName,
     924          factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(bNode.Value))));
     925      } else if (IsBinFactor(a) && IsNumber(b)) {
    921926        var binFactor = a as BinaryFactorVariableTreeNode;
    922         var constNode = b as ConstantTreeNode;
    923         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(constNode.Value)));
    924       } else if (IsConstant(a) && IsFactor(b)) {
    925         var constNode = a as ConstantTreeNode;
     927        var bNode = b as NumberTreeNode;
     928        return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(bNode.Value)));
     929      } else if (IsNumber(a) && IsFactor(b)) {
     930        var aNode = a as NumberTreeNode;
    926931        var factNode = b as FactorVariableTreeNode;
    927         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, 1.0 / Math.Round(w))));
    928       } else if (IsConstant(a) && IsBinFactor(b)) {
    929         var constNode = a as ConstantTreeNode;
     932        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(aNode.Value, 1.0 / Math.Round(w))));
     933      } else if (IsNumber(a) && IsBinFactor(b)) {
     934        var aNode = a as NumberTreeNode;
    930935        var factNode = b as BinaryFactorVariableTreeNode;
    931         return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weight)));
     936        return BinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(aNode.Value, 1.0 / Math.Round(factNode.Weight)));
    932937      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    933938        var node0 = a as FactorVariableTreeNode;
    934939        var node1 = b as FactorVariableTreeNode;
    935         return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v))));
    936       } else if (IsConstant(b)) {
    937         var constB = b as ConstantTreeNode;
    938         var constBValue = Math.Round(constB.Value);
    939         if (constBValue == 1.0) {
     940        return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v))));
     941      } else if (IsNumber(b)) {
     942        var bNode = b as NumberTreeNode;
     943        var bVal = Math.Round(bNode.Value);
     944        if (bVal == 1.0) {
    940945          // root(a, 1) => a
    941946          return a;
    942         } else if (constBValue == 0.0) {
     947        } else if (bVal == 0.0) {
    943948          // root(a, 0) is not defined
    944           //return MakeConstant(1.0);
    945           return MakeConstant(double.NaN);
    946         } else if (constBValue == -1.0) {
     949          return Number(double.NaN);
     950        } else if (bVal == -1.0) {
    947951          // root(a, -1) => a^(-1/1) => 1/a
    948           return MakeFraction(MakeConstant(1.0), a);
    949         } else if (constBValue < 0) {
     952          return Fraction(Number(1.0), a);
     953        } else if (bVal < 0) {
    950954          // root(a, -b) => a^(-1/b) => (1/a)^(1/b) => root(1, b) / root(a, b) => 1 / root(a, b)
    951955          var rootNode = rootSymbol.CreateTreeNode();
    952956          rootNode.AddSubtree(a);
    953           rootNode.AddSubtree(MakeConstant(-1.0 * constBValue));
    954           return MakeFraction(MakeConstant(1.0), rootNode);
     957          rootNode.AddSubtree(Number(-1.0 * bVal));
     958          return Fraction(Number(1.0), rootNode);
    955959        } else {
    956960          var rootNode = rootSymbol.CreateTreeNode();
    957961          rootNode.AddSubtree(a);
    958           rootNode.AddSubtree(MakeConstant(constBValue));
     962          rootNode.AddSubtree(Number(bVal));
    959963          return rootNode;
    960964        }
     
    968972
    969973
    970     private static ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    971       if (IsConstant(a) && IsConstant(b)) {
    972         var constA = a as ConstantTreeNode;
    973         var constB = b as ConstantTreeNode;
    974         return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value)));
    975       } else if (IsFactor(a) && IsConstant(b)) {
     974    private static ISymbolicExpressionTreeNode Power(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     975      if (IsNumber(a) && IsNumber(b)) {
     976        var aNode = a as NumberTreeNode;
     977        var bNode = b as NumberTreeNode;
     978        return Number(Math.Pow(aNode.Value, Math.Round(bNode.Value)));
     979      } else if (IsFactor(a) && IsNumber(b)) {
    976980        var factNode = a as FactorVariableTreeNode;
    977         var constNode = b as ConstantTreeNode;
    978         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(constNode.Value))));
    979       } else if (IsBinFactor(a) && IsConstant(b)) {
     981        var bNode = b as NumberTreeNode;
     982        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(bNode.Value))));
     983      } else if (IsBinFactor(a) && IsNumber(b)) {
    980984        var binFactor = a as BinaryFactorVariableTreeNode;
    981         var constNode = b as ConstantTreeNode;
    982         return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(constNode.Value)));
    983       } else if (IsConstant(a) && IsFactor(b)) {
    984         var constNode = a as ConstantTreeNode;
     985        var bNode = b as NumberTreeNode;
     986        return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(bNode.Value)));
     987      } else if (IsNumber(a) && IsFactor(b)) {
     988        var aNode = a as NumberTreeNode;
    985989        var factNode = b as FactorVariableTreeNode;
    986         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, Math.Round(w))));
    987       } else if (IsConstant(a) && IsBinFactor(b)) {
    988         var constNode = a as ConstantTreeNode;
     990        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(aNode.Value, Math.Round(w))));
     991      } else if (IsNumber(a) && IsBinFactor(b)) {
     992        var aNode = a as NumberTreeNode;
    989993        var factNode = b as BinaryFactorVariableTreeNode;
    990         return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, Math.Round(factNode.Weight)));
     994        return BinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(aNode.Value, Math.Round(factNode.Weight)));
    991995      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    992996        var node0 = a as FactorVariableTreeNode;
    993997        var node1 = b as FactorVariableTreeNode;
    994         return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v))));
    995       } else if (IsConstant(b)) {
    996         var constB = b as ConstantTreeNode;
    997         double exponent = Math.Round(constB.Value);
     998        return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v))));
     999      } else if (IsNumber(b)) {
     1000        var bNode = b as NumberTreeNode;
     1001        double exponent = Math.Round(bNode.Value);
    9981002        if (exponent == 0.0) {
    9991003          // a^0 => 1
    1000           return MakeConstant(1.0);
     1004          return Number(1.0);
    10011005        } else if (exponent == 1.0) {
    10021006          // a^1 => a
     
    10041008        } else if (exponent == -1.0) {
    10051009          // a^-1 => 1/a
    1006           return MakeFraction(MakeConstant(1.0), a);
     1010          return Fraction(Number(1.0), a);
    10071011        } else if (exponent < 0) {
    10081012          // a^-b => (1/a)^b => 1/(a^b)
    10091013          var powNode = powSymbol.CreateTreeNode();
    10101014          powNode.AddSubtree(a);
    1011           powNode.AddSubtree(MakeConstant(-1.0 * exponent));
    1012           return MakeFraction(MakeConstant(1.0), powNode);
     1015          powNode.AddSubtree(Number(-1.0 * exponent));
     1016          return Fraction(Number(1.0), powNode);
    10131017        } else {
    10141018          var powNode = powSymbol.CreateTreeNode();
    10151019          powNode.AddSubtree(a);
    1016           powNode.AddSubtree(MakeConstant(exponent));
     1020          powNode.AddSubtree(Number(exponent));
    10171021          return powNode;
    10181022        }
     
    10261030
    10271031
    1028     // MakeFraction, MakeProduct and MakeSum take two already simplified trees and create a new simplified tree
    1029     private static ISymbolicExpressionTreeNode MakeFraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    1030       if (IsConstant(a) && IsConstant(b)) {
     1032    // Fraction, Product and Sum take two already simplified trees and create a new simplified tree
     1033    private static ISymbolicExpressionTreeNode Fraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     1034      if (IsNumber(a) && IsNumber(b)) {
    10311035        // fold constants
    1032         return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value);
    1033       } else if ((IsConstant(a) && ((ConstantTreeNode)a).Value != 1.0)) {
     1036        return Number(((NumberTreeNode)a).Value / ((NumberTreeNode)b).Value);
     1037      } else if (IsNumber(a) && ((NumberTreeNode)a).Value != 1.0) {
    10341038        // a / x => (a * 1/a) / (x * 1/a) => 1 / (x * 1/a)
    1035         return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
    1036       } else if (IsVariableBase(a) && IsConstant(b)) {
     1039        return Fraction(Number(1.0), Product(b, Invert(a)));
     1040      } else if (IsVariableBase(a) && IsNumber(b)) {
    10371041        // merge constant values into variable weights
    1038         var constB = ((ConstantTreeNode)b).Value;
    1039         ((VariableTreeNodeBase)a).Weight /= constB;
     1042        var bVal = ((NumberTreeNode)b).Value;
     1043        ((VariableTreeNodeBase)a).Weight /= bVal;
    10401044        return a;
    1041       } else if (IsFactor(a) && IsConstant(b)) {
     1045      } else if (IsFactor(a) && IsNumber(b)) {
    10421046        var factNode = a as FactorVariableTreeNode;
    1043         var constNode = b as ConstantTreeNode;
    1044         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / constNode.Value));
    1045       } else if (IsBinFactor(a) && IsConstant(b)) {
     1047        var bNode = b as NumberTreeNode;
     1048        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / bNode.Value));
     1049      } else if (IsBinFactor(a) && IsNumber(b)) {
    10461050        var factNode = a as BinaryFactorVariableTreeNode;
    1047         var constNode = b as ConstantTreeNode;
    1048         return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / constNode.Value);
     1051        var bNode = b as NumberTreeNode;
     1052        return BinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / bNode.Value);
    10491053      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    10501054        var node0 = a as FactorVariableTreeNode;
    10511055        var node1 = b as FactorVariableTreeNode;
    1052         return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v));
     1056        return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v));
    10531057      } else if (IsFactor(a) && IsBinFactor(b) && ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
    10541058        var node0 = a as FactorVariableTreeNode;
     
    10621066          if (wi == i) newWeighs[i] /= node1.Weight;
    10631067          else newWeighs[i] /= 0.0;
    1064         return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
     1068        return Factor(node0.Symbol, node0.VariableName, newWeighs);
    10651069      } else if (IsFactor(a)) {
    1066         return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
     1070        return Fraction(Number(1.0), Product(b, Invert(a)));
    10671071      } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameTypeAndVariable(a, b) && !IsBinFactor(b)) {
    10681072        // cancel variables (not allowed for bin factors because of division by zero)
    10691073        var aVar = a as VariableTreeNode;
    10701074        var bVar = b as VariableTreeNode;
    1071         return MakeConstant(aVar.Weight / bVar.Weight);
    1072       } else if (IsAddition(a) && IsConstant(b)) {
     1075        return Number(aVar.Weight / bVar.Weight);
     1076      } else if (IsAddition(a) && IsNumber(b)) {
    10731077        return a.Subtrees
    10741078          .Select(x => GetSimplifiedTree(x))
    1075           .Select(x => MakeFraction(x, GetSimplifiedTree(b)))
    1076           .Aggregate((c, d) => MakeSum(c, d));
    1077       } else if (IsMultiplication(a) && IsConstant(b)) {
    1078         return MakeProduct(a, Invert(b));
    1079       } else if (IsDivision(a) && IsConstant(b)) {
     1079          .Select(x => Fraction(x, GetSimplifiedTree(b)))
     1080          .Aggregate((c, d) => Sum(c, d));
     1081      } else if (IsMultiplication(a) && IsNumber(b)) {
     1082        return Product(a, Invert(b));
     1083      } else if (IsDivision(a) && IsNumber(b)) {
    10801084        // (a1 / a2) / c => (a1 / (a2 * c))
    1081         return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
     1085        return Fraction(a.GetSubtree(0), Product(a.GetSubtree(1), b));
    10821086      } else if (IsDivision(a) && IsDivision(b)) {
    10831087        // (a1 / a2) / (b1 / b2) =>
    1084         return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(1)), MakeProduct(a.GetSubtree(1), b.GetSubtree(0)));
     1088        return Fraction(Product(a.GetSubtree(0), b.GetSubtree(1)), Product(a.GetSubtree(1), b.GetSubtree(0)));
    10851089      } else if (IsDivision(a)) {
    10861090        // (a1 / a2) / b => (a1 / (a2 * b))
    1087         return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
     1091        return Fraction(a.GetSubtree(0), Product(a.GetSubtree(1), b));
    10881092      } else if (IsDivision(b)) {
    10891093        // a / (b1 / b2) => (a * b2) / b1
    1090         return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));
     1094        return Fraction(Product(a, b.GetSubtree(1)), b.GetSubtree(0));
    10911095      } else if (IsAnalyticalQuotient(a)) {
    1092         return MakeAnalyticalQuotient(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
     1096        return AQ(a.GetSubtree(0), Product(a.GetSubtree(1), b));
    10931097      } else {
    10941098        var div = divSymbol.CreateTreeNode();
     
    10991103    }
    11001104
    1101     private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    1102       if (IsConstant(a) && IsConstant(b)) {
     1105    private static ISymbolicExpressionTreeNode Sum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     1106      if (IsNumber(a) && IsNumber(b)) {
    11031107        // fold constants
    1104         ((ConstantTreeNode)a).Value += ((ConstantTreeNode)b).Value;
     1108        ((NumberTreeNode)a).Value += ((NumberTreeNode)b).Value;
    11051109        return a;
    1106       } else if (IsConstant(a)) {
     1110      } else if (IsNumber(a)) {
    11071111        // c + x => x + c
    11081112        // b is not constant => make sure constant is on the right
    1109         return MakeSum(b, a);
    1110       } else if (IsConstant(b) && ((ConstantTreeNode)b).Value == 0.0) {
     1113        return Sum(b, a);
     1114      } else if (IsNumber(b) && ((NumberTreeNode)b).Value == 0.0) {
    11111115        // x + 0 => x
    11121116        return a;
    1113       } else if (IsFactor(a) && IsConstant(b)) {
     1117      } else if (IsFactor(a) && IsNumber(b)) {
    11141118        var factNode = a as FactorVariableTreeNode;
    1115         var constNode = b as ConstantTreeNode;
    1116         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + constNode.Value));
     1119        var bNode = b as NumberTreeNode;
     1120        return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + bNode.Value));
    11171121      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    11181122        var node0 = a as FactorVariableTreeNode;
    11191123        var node1 = b as FactorVariableTreeNode;
    1120         return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v));
     1124        return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v));
    11211125      } else if (IsBinFactor(a) && IsFactor(b)) {
    1122         return MakeSum(b, a);
     1126        return Sum(b, a);
    11231127      } else if (IsFactor(a) && IsBinFactor(b) &&
    11241128        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
     
    11311135        node0.Weights.CopyTo(newWeighs, 0);
    11321136        newWeighs[wi] += node1.Weight;
    1133         return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
     1137        return Factor(node0.Symbol, node0.VariableName, newWeighs);
    11341138      } else if (IsAddition(a) && IsAddition(b)) {
    11351139        // merge additions
     
    11381142        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
    11391143        for (int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i));
    1140         if (IsConstant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) {
    1141           add.AddSubtree(MakeSum(a.Subtrees.Last(), b.Subtrees.Last()));
    1142         } else if (IsConstant(a.Subtrees.Last())) {
     1144        if (IsNumber(a.Subtrees.Last()) && IsNumber(b.Subtrees.Last())) {
     1145          add.AddSubtree(Sum(a.Subtrees.Last(), b.Subtrees.Last()));
     1146        } else if (IsNumber(a.Subtrees.Last())) {
    11431147          add.AddSubtree(b.Subtrees.Last());
    11441148          add.AddSubtree(a.Subtrees.Last());
     
    11541158        }
    11551159      } else if (IsAddition(b)) {
    1156         return MakeSum(b, a);
    1157       } else if (IsAddition(a) && IsConstant(b)) {
     1160        return Sum(b, a);
     1161      } else if (IsAddition(a) && IsNumber(b)) {
    11581162        // a is an addition and b is a constant => append b to a and make sure the constants are merged
    11591163        var add = addSymbol.CreateTreeNode();
    11601164        // add all sub trees except for the last
    11611165        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
    1162         if (IsConstant(a.Subtrees.Last()))
    1163           add.AddSubtree(MakeSum(a.Subtrees.Last(), b));
     1166        if (IsNumber(a.Subtrees.Last()))
     1167          add.AddSubtree(Sum(a.Subtrees.Last(), b));
    11641168        else {
    11651169          add.AddSubtree(a.Subtrees.Last());
     
    12011205                            group node by GroupId(node) into g
    12021206                            select g;
    1203       var constant = (from node in subtrees.OfType<ConstantTreeNode>()
    1204                       select node.Value).DefaultIfEmpty(0.0).Sum();
    1205       var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode));
     1207      var sumNumbers = (from node in subtrees.OfType<NumberTreeNode>()
     1208                        select node.Value).DefaultIfEmpty(0.0).Sum();
     1209      var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is NumberTreeNode));
    12061210
    12071211      foreach (var variableNodeGroup in groupedVarNodes) {
     
    12241228      foreach (var unchangedSubtree in unchangedSubtrees)
    12251229        sum.AddSubtree(unchangedSubtree);
    1226       if (constant != 0.0) {
    1227         sum.AddSubtree(MakeConstant(constant));
     1230      if (sumNumbers != 0.0) {
     1231        sum.AddSubtree(Number(sumNumbers));
    12281232      }
    12291233    }
     
    12311235    // nodes referencing variables can be grouped if they have
    12321236    private static string GroupId(IVariableTreeNode node) {
    1233       var binaryFactorNode = node as BinaryFactorVariableTreeNode;
    1234       var factorNode = node as FactorVariableTreeNode;
    1235       var variableNode = node as VariableTreeNode;
    1236       var laggedVarNode = node as LaggedVariableTreeNode;
    1237       if (variableNode != null) {
     1237      if (node is VariableTreeNode variableNode) {
    12381238        return "var " + variableNode.VariableName;
    1239       } else if (binaryFactorNode != null) {
     1239      } else if (node is BinaryFactorVariableTreeNode binaryFactorNode) {
    12401240        return "binfactor " + binaryFactorNode.VariableName + " " + binaryFactorNode.VariableValue;
    1241       } else if (factorNode != null) {
     1241      } else if (node is FactorVariableTreeNode factorNode) {
    12421242        return "factor " + factorNode.VariableName;
    1243       } else if (laggedVarNode != null) {
     1243      } else if (node is LaggedVariableTreeNode laggedVarNode) {
    12441244        return "lagged " + laggedVarNode.VariableName + " " + laggedVarNode.Lag;
    12451245      } else {
     
    12491249
    12501250
    1251     private static ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    1252       if (IsConstant(a) && IsConstant(b)) {
     1251    private static ISymbolicExpressionTreeNode Product(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     1252      if (IsNumber(a) && IsNumber(b)) {
    12531253        // fold constants
    1254         return MakeConstant(((ConstantTreeNode)a).Value * ((ConstantTreeNode)b).Value);
    1255       } else if (IsConstant(a)) {
     1254        return Number(((NumberTreeNode)a).Value * ((NumberTreeNode)b).Value);
     1255      } else if (IsNumber(a)) {
    12561256        // a * $ => $ * a
    1257         return MakeProduct(b, a);
     1257        return Product(b, a);
    12581258      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    12591259        var node0 = a as FactorVariableTreeNode;
    12601260        var node1 = b as FactorVariableTreeNode;
    1261         return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v));
     1261        return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v));
    12621262      } else if (IsBinFactor(a) && IsBinFactor(b) && AreSameTypeAndVariable(a, b)) {
    12631263        var node0 = a as BinaryFactorVariableTreeNode;
    12641264        var node1 = b as BinaryFactorVariableTreeNode;
    1265         return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight);
    1266       } else if (IsFactor(a) && IsConstant(b)) {
     1265        return BinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight);
     1266      } else if (IsFactor(a) && IsNumber(b)) {
    12671267        var node0 = a as FactorVariableTreeNode;
    1268         var node1 = b as ConstantTreeNode;
    1269         return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value));
    1270       } else if (IsBinFactor(a) && IsConstant(b)) {
     1268        var node1 = b as NumberTreeNode;
     1269        return Factor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value));
     1270      } else if (IsBinFactor(a) && IsNumber(b)) {
    12711271        var node0 = a as BinaryFactorVariableTreeNode;
    1272         var node1 = b as ConstantTreeNode;
    1273         return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value);
     1272        var node1 = b as NumberTreeNode;
     1273        return BinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value);
    12741274      } else if (IsBinFactor(a) && IsFactor(b)) {
    1275         return MakeProduct(b, a);
     1275        return Product(b, a);
    12761276      } else if (IsFactor(a) && IsBinFactor(b) &&
    12771277        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
     
    12811281        var wi = Array.IndexOf(varValues, node1.VariableValue);
    12821282        if (wi < 0) throw new ArgumentException();
    1283         return MakeBinFactor(node1.Symbol, node1.VariableName, node1.VariableValue, node1.Weight * node0.Weights[wi]);
    1284       } else if (IsConstant(b) && ((ConstantTreeNode)b).Value == 1.0) {
     1283        return BinFactor(node1.Symbol, node1.VariableName, node1.VariableValue, node1.Weight * node0.Weights[wi]);
     1284      } else if (IsNumber(b) && ((NumberTreeNode)b).Value == 1.0) {
    12851285        // $ * 1.0 => $
    12861286        return a;
    1287       } else if (IsConstant(b) && ((ConstantTreeNode)b).Value == 0.0) {
    1288         return MakeConstant(0);
    1289       } else if (IsConstant(b) && IsVariableBase(a)) {
     1287      } else if (IsNumber(b) && ((NumberTreeNode)b).Value == 0.0) {
     1288        return Number(0);
     1289      } else if (IsNumber(b) && IsVariableBase(a)) {
    12901290        // multiply constants into variables weights
    1291         ((VariableTreeNodeBase)a).Weight *= ((ConstantTreeNode)b).Value;
     1291        ((VariableTreeNodeBase)a).Weight *= ((NumberTreeNode)b).Value;
    12921292        return a;
    1293       } else if (IsConstant(b) && IsAddition(a) ||
     1293      } else if (IsNumber(b) && IsAddition(a) ||
    12941294          IsFactor(b) && IsAddition(a) ||
    12951295          IsBinFactor(b) && IsAddition(a)) {
    1296         // multiply constants into additions
    1297         return a.Subtrees.Select(x => MakeProduct(GetSimplifiedTree(x), GetSimplifiedTree(b))).Aggregate((c, d) => MakeSum(c, d));
     1296        // multiply numbers into additions
     1297        return a.Subtrees.Select(x => Product(GetSimplifiedTree(x), GetSimplifiedTree(b))).Aggregate((c, d) => Sum(c, d));
    12981298      } else if (IsDivision(a) && IsDivision(b)) {
    12991299        // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2)
    1300         return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1)));
     1300        return Fraction(Product(a.GetSubtree(0), b.GetSubtree(0)), Product(a.GetSubtree(1), b.GetSubtree(1)));
    13011301      } else if (IsDivision(a)) {
    13021302        // (a1 / a2) * b => (a1 * b) / a2
    1303         return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
     1303        return Fraction(Product(a.GetSubtree(0), b), a.GetSubtree(1));
    13041304      } else if (IsDivision(b)) {
    13051305        // a * (b1 / b2) => (b1 * a) / b2
    1306         return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1));
     1306        return Fraction(Product(b.GetSubtree(0), a), b.GetSubtree(1));
    13071307      } else if (IsMultiplication(a) && IsMultiplication(b)) {
    13081308        // merge multiplications (make sure constants are merged)
     
    13131313        return mul;
    13141314      } else if (IsMultiplication(b)) {
    1315         return MakeProduct(b, a);
     1315        return Product(b, a);
    13161316      } else if (IsMultiplication(a)) {
    13171317        // a is already an multiplication => append b
     
    13201320        return a;
    13211321      } else if (IsAbsolute(a) && IsAbsolute(b)) {
    1322         return MakeAbs(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)));
    1323       } else if (IsAbsolute(a) && IsConstant(b)) {
    1324         var constNode = b as ConstantTreeNode;
    1325         var posF = Math.Abs(constNode.Value);
    1326         if (constNode.Value > 0) {
    1327           return MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF)));
     1322        return Abs(Product(a.GetSubtree(0), b.GetSubtree(0)));
     1323      } else if (IsAbsolute(a) && IsNumber(b)) {
     1324        var bNode = b as NumberTreeNode;
     1325        var posF = Math.Abs(bNode.Value);
     1326        if (bNode.Value > 0) {
     1327          return Abs(Product(a.GetSubtree(0), Number(posF)));
    13281328        } else {
    13291329          var mul = mulSymbol.CreateTreeNode();
    1330           mul.AddSubtree(MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF))));
    1331           mul.AddSubtree(MakeConstant(-1.0));
     1330          mul.AddSubtree(Abs(Product(a.GetSubtree(0), Number(posF))));
     1331          mul.AddSubtree(Number(-1.0));
    13321332          return mul;
    13331333        }
    13341334      } else if (IsAnalyticalQuotient(a)) {
    1335         return MakeAnalyticalQuotient(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
     1335        return AQ(Product(a.GetSubtree(0), b), a.GetSubtree(1));
    13361336      } else {
    13371337        var mul = mulSymbol.CreateTreeNode();
     
    13551355
    13561356    private static ISymbolicExpressionTreeNode AddLagToDynamicNodes(ISymbolicExpressionTreeNode node, int lag) {
    1357       var laggedTreeNode = node as ILaggedTreeNode;
    1358       var variableNode = node as VariableTreeNode;
    1359       var variableConditionNode = node as VariableConditionTreeNode;
    1360       if (laggedTreeNode != null)
     1357      if (node is ILaggedTreeNode laggedTreeNode)
    13611358        laggedTreeNode.Lag += lag;
    1362       else if (variableNode != null) {
     1359      else if (node is VariableTreeNode variableNode) {
    13631360        var laggedVariableNode = (LaggedVariableTreeNode)laggedVariableSymbol.CreateTreeNode();
    13641361        laggedVariableNode.Lag = lag;
    13651362        laggedVariableNode.VariableName = variableNode.VariableName;
    13661363        return laggedVariableNode;
    1367       } else if (variableConditionNode != null) {
     1364      } else if (node is VariableConditionTreeNode) {
    13681365        throw new NotSupportedException("Removal of time lags around variable condition symbols is not allowed.");
    13691366      }
     
    13891386                            orderby g.Count()
    13901387                            select g;
    1391       var constantProduct = (from node in subtrees.OfType<VariableTreeNodeBase>()
    1392                              select node.Weight)
    1393         .Concat(from node in subtrees.OfType<ConstantTreeNode>()
    1394                 select node.Value)
    1395         .DefaultIfEmpty(1.0)
    1396         .Aggregate((c1, c2) => c1 * c2);
     1388      var numberProduct = (from node in subtrees.OfType<VariableTreeNodeBase>()
     1389                           select node.Weight)
     1390                          .Concat(from node in subtrees.OfType<NumberTreeNode>()
     1391                                  select node.Value)
     1392                          .DefaultIfEmpty(1.0)
     1393                          .Aggregate((c1, c2) => c1 * c2);
    13971394
    13981395      var unchangedSubtrees = from tree in subtrees
    1399                               where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is ConstantTreeNode)
     1396                              where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is NumberTreeNode)
    14001397                              select tree;
    14011398
     
    14221419          }
    14231420          for (int j = 0; j < representative.Weights.Length; j++) {
    1424             representative.Weights[j] *= constantProduct;
     1421            representative.Weights[j] *= numberProduct;
    14251422          }
    1426           constantProduct = 1.0;
     1423          numberProduct = 1.0;
    14271424          // if the product already contains a factor it is not necessary to multiply a constant below
    14281425          prod.AddSubtree(representative);
     
    14331430        prod.AddSubtree(unchangedSubtree);
    14341431
    1435       if (constantProduct != 1.0) {
    1436         prod.AddSubtree(MakeConstant(constantProduct));
     1432      if (numberProduct != 1.0) {
     1433        prod.AddSubtree(Number(numberProduct));
    14371434      }
    14381435    }
     
    14461443    /// <returns>-x</returns>
    14471444    private static ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) {
    1448       if (IsConstant(x)) {
    1449         ((ConstantTreeNode)x).Value *= -1;
     1445      if (IsNumber(x)) {
     1446        ((NumberTreeNode)x).Value *= -1;
    14501447      } else if (IsVariableBase(x)) {
    14511448        var variableTree = (VariableTreeNodeBase)x;
     
    14711468      } else {
    14721469        // any other function
    1473         return MakeProduct(x, MakeConstant(-1));
     1470        return Product(x, Number(-1));
    14741471      }
    14751472      return x;
     
    14831480    /// <returns></returns>
    14841481    private static ISymbolicExpressionTreeNode Invert(ISymbolicExpressionTreeNode x) {
    1485       if (IsConstant(x)) {
    1486         return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);
     1482      if (IsNumber(x)) {
     1483        return Number(1.0 / ((NumberTreeNode)x).Value);
    14871484      } else if (IsFactor(x)) {
    14881485        var factorNode = (FactorVariableTreeNode)x;
    1489         return MakeFactor(factorNode.Symbol, factorNode.VariableName, factorNode.Weights.Select(w => 1.0 / w));
     1486        return Factor(factorNode.Symbol, factorNode.VariableName, factorNode.Weights.Select(w => 1.0 / w));
    14901487      } else if (IsDivision(x)) {
    1491         return MakeFraction(x.GetSubtree(1), x.GetSubtree(0));
     1488        return Fraction(x.GetSubtree(1), x.GetSubtree(0));
    14921489      } else {
    14931490        // any other function
    1494         return MakeFraction(MakeConstant(1), x);
    1495       }
    1496     }
    1497 
    1498     private static ISymbolicExpressionTreeNode MakeConstant(double value) {
    1499       ConstantTreeNode constantTreeNode = (ConstantTreeNode)(constSymbol.CreateTreeNode());
    1500       constantTreeNode.Value = value;
    1501       return constantTreeNode;
    1502     }
    1503 
    1504     private static ISymbolicExpressionTreeNode MakeFactor(FactorVariable sy, string variableName, IEnumerable<double> weights) {
     1491        return Fraction(Number(1), x);
     1492      }
     1493    }
     1494
     1495    private static ISymbolicExpressionTreeNode Number(double value) {
     1496      var numberTreeNode = (NumberTreeNode)numberSymbol.CreateTreeNode();
     1497      numberTreeNode.Value = value;
     1498      return numberTreeNode;
     1499    }
     1500
     1501    private static ISymbolicExpressionTreeNode Factor(FactorVariable sy, string variableName, IEnumerable<double> weights) {
    15051502      var tree = (FactorVariableTreeNode)sy.CreateTreeNode();
    15061503      tree.VariableName = variableName;
     
    15081505      return tree;
    15091506    }
    1510     private static ISymbolicExpressionTreeNode MakeBinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) {
     1507    private static ISymbolicExpressionTreeNode BinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) {
    15111508      var tree = (BinaryFactorVariableTreeNode)sy.CreateTreeNode();
    15121509      tree.VariableName = variableName;
Note: See TracChangeset for help on using the changeset viewer.