Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
01/01/17 17:35:13 (7 years ago)
Author:
gkronber
Message:

#2650 worked on simplifier

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplifier.cs

    r14339 r14535  
    7171      IList<ISymbolicExpressionTreeNode> argumentTrees) {
    7272      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
    73       while (node.SubtreeCount > 0) node.RemoveSubtree(0);
    74       if (node.Symbol is InvokeFunction) {
     73      while(node.SubtreeCount > 0) node.RemoveSubtree(0);
     74      if(node.Symbol is InvokeFunction) {
    7575        var invokeSym = node.Symbol as InvokeFunction;
    7676        var defunNode = FindFunctionDefinition(root, invokeSym.FunctionName);
    7777        var macroExpandedArguments = new List<ISymbolicExpressionTreeNode>();
    78         foreach (var subtree in subtrees) {
     78        foreach(var subtree in subtrees) {
    7979          macroExpandedArguments.Add(MacroExpand(root, subtree, argumentTrees));
    8080        }
    8181        return MacroExpand(root, defunNode, macroExpandedArguments);
    82       } else if (node.Symbol is Argument) {
     82      } else if(node.Symbol is Argument) {
    8383        var argSym = node.Symbol as Argument;
    8484        // return the correct argument sub-tree (already macro-expanded)
     
    8686      } else {
    8787        // recursive application
    88         foreach (var subtree in subtrees) {
     88        foreach(var subtree in subtrees) {
    8989          node.AddSubtree(MacroExpand(root, subtree, argumentTrees));
    9090        }
     
    9494
    9595    private ISymbolicExpressionTreeNode FindFunctionDefinition(ISymbolicExpressionTreeNode root, string functionName) {
    96       foreach (var subtree in root.Subtrees.OfType<DefunTreeNode>()) {
    97         if (subtree.FunctionName == functionName) return subtree.GetSubtree(0);
     96      foreach(var subtree in root.Subtrees.OfType<DefunTreeNode>()) {
     97        if(subtree.FunctionName == functionName) return subtree.GetSubtree(0);
    9898      }
    9999
     
    209209    }
    210210
     211    private bool IsBinFactor(ISymbolicExpressionTreeNode node) {
     212      return node is BinaryFactorVariableTreeNode;
     213    }
     214
    211215    private bool IsConstant(ISymbolicExpressionTreeNode node) {
    212216      return node.Symbol is Constant;
     
    230234    /// <returns></returns>
    231235    public ISymbolicExpressionTreeNode GetSimplifiedTree(ISymbolicExpressionTreeNode original) {
    232       if (IsConstant(original) || IsVariableBase(original)) {
     236      if(IsConstant(original) || IsVariableBase(original)) {
    233237        return (ISymbolicExpressionTreeNode)original.Clone();
    234       } else if (IsAddition(original)) {
     238      } else if(IsAddition(original)) {
    235239        return SimplifyAddition(original);
    236       } else if (IsSubtraction(original)) {
     240      } else if(IsSubtraction(original)) {
    237241        return SimplifySubtraction(original);
    238       } else if (IsMultiplication(original)) {
     242      } else if(IsMultiplication(original)) {
    239243        return SimplifyMultiplication(original);
    240       } else if (IsDivision(original)) {
     244      } else if(IsDivision(original)) {
    241245        return SimplifyDivision(original);
    242       } else if (IsAverage(original)) {
     246      } else if(IsAverage(original)) {
    243247        return SimplifyAverage(original);
    244       } else if (IsLog(original)) {
     248      } else if(IsLog(original)) {
    245249        return SimplifyLog(original);
    246       } else if (IsExp(original)) {
     250      } else if(IsExp(original)) {
    247251        return SimplifyExp(original);
    248       } else if (IsSquare(original)) {
     252      } else if(IsSquare(original)) {
    249253        return SimplifySquare(original);
    250       } else if (IsSquareRoot(original)) {
     254      } else if(IsSquareRoot(original)) {
    251255        return SimplifySquareRoot(original);
    252       } else if (IsPower(original)) {
     256      } else if(IsPower(original)) {
    253257        return SimplifyPower(original);
    254       } else if (IsRoot(original)) {
     258      } else if(IsRoot(original)) {
    255259        return SimplifyRoot(original);
    256       } else if (IsSine(original)) {
     260      } else if(IsSine(original)) {
    257261        return SimplifySine(original);
    258       } else if (IsCosine(original)) {
     262      } else if(IsCosine(original)) {
    259263        return SimplifyCosine(original);
    260       } else if (IsTangent(original)) {
     264      } else if(IsTangent(original)) {
    261265        return SimplifyTangent(original);
    262       } else if (IsIfThenElse(original)) {
     266      } else if(IsIfThenElse(original)) {
    263267        return SimplifyIfThenElse(original);
    264       } else if (IsGreaterThan(original)) {
     268      } else if(IsGreaterThan(original)) {
    265269        return SimplifyGreaterThan(original);
    266       } else if (IsLessThan(original)) {
     270      } else if(IsLessThan(original)) {
    267271        return SimplifyLessThan(original);
    268       } else if (IsAnd(original)) {
     272      } else if(IsAnd(original)) {
    269273        return SimplifyAnd(original);
    270       } else if (IsOr(original)) {
     274      } else if(IsOr(original)) {
    271275        return SimplifyOr(original);
    272       } else if (IsNot(original)) {
     276      } else if(IsNot(original)) {
    273277        return SimplifyNot(original);
    274       } else if (IsTimeLag(original)) {
     278      } else if(IsTimeLag(original)) {
    275279        return SimplifyTimeLag(original);
    276       } else if (IsIntegral(original)) {
     280      } else if(IsIntegral(original)) {
    277281        return SimplifyIntegral(original);
    278282      } else {
     
    286290      // can't simplify this function but simplify all subtrees
    287291      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees);
    288       while (original.Subtrees.Count() > 0) original.RemoveSubtree(0);
     292      while(original.Subtrees.Count() > 0) original.RemoveSubtree(0);
    289293      var clone = (SymbolicExpressionTreeNode)original.Clone();
    290294      List<ISymbolicExpressionTreeNode> simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>();
    291       foreach (var subtree in subtrees) {
     295      foreach(var subtree in subtrees) {
    292296        simplifiedSubtrees.Add(GetSimplifiedTree(subtree));
    293297        original.AddSubtree(subtree);
    294298      }
    295       foreach (var simplifiedSubtree in simplifiedSubtrees) {
     299      foreach(var simplifiedSubtree in simplifiedSubtrees) {
    296300        clone.AddSubtree(simplifiedSubtree);
    297301      }
    298       if (simplifiedSubtrees.TrueForAll(t => IsConstant(t))) {
     302      if(simplifiedSubtrees.TrueForAll(t => IsConstant(t))) {
    299303        SimplifyConstantExpression(clone);
    300304      }
     
    308312
    309313    private ISymbolicExpressionTreeNode SimplifyAverage(ISymbolicExpressionTreeNode original) {
    310       if (original.Subtrees.Count() == 1) {
     314      if(original.Subtrees.Count() == 1) {
    311315        return GetSimplifiedTree(original.GetSubtree(0));
    312316      } else {
     
    321325
    322326    private ISymbolicExpressionTreeNode SimplifyDivision(ISymbolicExpressionTreeNode original) {
    323       if (original.Subtrees.Count() == 1) {
     327      if(original.Subtrees.Count() == 1) {
    324328        return Invert(GetSimplifiedTree(original.GetSubtree(0)));
    325329      } else {
     
    336340
    337341    private ISymbolicExpressionTreeNode SimplifyMultiplication(ISymbolicExpressionTreeNode original) {
    338       if (original.Subtrees.Count() == 1) {
     342      if(original.Subtrees.Count() == 1) {
    339343        return GetSimplifiedTree(original.GetSubtree(0));
    340344      } else {
     
    346350
    347351    private ISymbolicExpressionTreeNode SimplifySubtraction(ISymbolicExpressionTreeNode original) {
    348       if (original.Subtrees.Count() == 1) {
     352      if(original.Subtrees.Count() == 1) {
    349353        return Negate(GetSimplifiedTree(original.GetSubtree(0)));
    350354      } else {
     
    358362
    359363    private ISymbolicExpressionTreeNode SimplifyAddition(ISymbolicExpressionTreeNode original) {
    360       if (original.Subtrees.Count() == 1) {
     364      if(original.Subtrees.Count() == 1) {
    361365        return GetSimplifiedTree(original.GetSubtree(0));
    362366      } else {
     
    437441      var laggedTreeNode = original as ILaggedTreeNode;
    438442      var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0));
    439       if (!ContainsVariableCondition(simplifiedSubtree)) {
     443      if(!ContainsVariableCondition(simplifiedSubtree)) {
    440444        return AddLagToDynamicNodes(simplifiedSubtree, laggedTreeNode.Lag);
    441445      } else {
     
    447451      var laggedTreeNode = original as ILaggedTreeNode;
    448452      var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0));
    449       if (IsConstant(simplifiedSubtree)) {
     453      if(IsConstant(simplifiedSubtree)) {
    450454        return GetSimplifiedTree(MakeProduct(simplifiedSubtree, MakeConstant(-laggedTreeNode.Lag)));
    451455      } else {
     
    459463
    460464    private ISymbolicExpressionTreeNode MakeTimeLag(ISymbolicExpressionTreeNode subtree, int lag) {
    461       if (lag == 0) return subtree;
    462       if (IsConstant(subtree)) return subtree;
     465      if(lag == 0) return subtree;
     466      if(IsConstant(subtree)) return subtree;
    463467      var lagNode = (LaggedTreeNode)timeLagSymbol.CreateTreeNode();
    464468      lagNode.Lag = lag;
     
    468472
    469473    private ISymbolicExpressionTreeNode MakeIntegral(ISymbolicExpressionTreeNode subtree, int lag) {
    470       if (lag == 0) return subtree;
    471       else if (lag == -1 || lag == 1) {
     474      if(lag == 0) return subtree;
     475      else if(lag == -1 || lag == 1) {
    472476        return MakeSum(subtree, AddLagToDynamicNodes((ISymbolicExpressionTreeNode)subtree.Clone(), lag));
    473477      } else {
     
    480484
    481485    private ISymbolicExpressionTreeNode MakeNot(ISymbolicExpressionTreeNode t) {
    482       if (IsConstant(t)) {
     486      if(IsConstant(t)) {
    483487        var constNode = t as ConstantTreeNode;
    484         if (constNode.Value > 0) return MakeConstant(-1.0);
     488        if(constNode.Value > 0) return MakeConstant(-1.0);
    485489        else return MakeConstant(1.0);
    486       } else if (IsNot(t)) {
     490      } else if(IsNot(t)) {
    487491        return t.GetSubtree(0);
    488       } else if (!IsBoolean(t)) {
     492      } else if(!IsBoolean(t)) {
    489493        var gtNode = gtSymbol.CreateTreeNode();
    490494        gtNode.AddSubtree(t);
     
    501505
    502506    private ISymbolicExpressionTreeNode MakeOr(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    503       if (IsConstant(a) && IsConstant(b)) {
     507      if(IsConstant(a) && IsConstant(b)) {
    504508        var constA = a as ConstantTreeNode;
    505509        var constB = b as ConstantTreeNode;
    506         if (constA.Value > 0.0 || constB.Value > 0.0) {
     510        if(constA.Value > 0.0 || constB.Value > 0.0) {
    507511          return MakeConstant(1.0);
    508512        } else {
    509513          return MakeConstant(-1.0);
    510514        }
    511       } else if (IsConstant(a)) {
     515      } else if(IsConstant(a)) {
    512516        return MakeOr(b, a);
    513       } else if (IsConstant(b)) {
     517      } else if(IsConstant(b)) {
    514518        var constT = b as ConstantTreeNode;
    515         if (constT.Value > 0.0) {
     519        if(constT.Value > 0.0) {
    516520          // boolean expression is necessarily true
    517521          return MakeConstant(1.0);
     
    531535
    532536    private ISymbolicExpressionTreeNode MakeAnd(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    533       if (IsConstant(a) && IsConstant(b)) {
     537      if(IsConstant(a) && IsConstant(b)) {
    534538        var constA = a as ConstantTreeNode;
    535539        var constB = b as ConstantTreeNode;
    536         if (constA.Value > 0.0 && constB.Value > 0.0) {
     540        if(constA.Value > 0.0 && constB.Value > 0.0) {
    537541          return MakeConstant(1.0);
    538542        } else {
    539543          return MakeConstant(-1.0);
    540544        }
    541       } else if (IsConstant(a)) {
     545      } else if(IsConstant(a)) {
    542546        return MakeAnd(b, a);
    543       } else if (IsConstant(b)) {
     547      } else if(IsConstant(b)) {
    544548        var constB = b as ConstantTreeNode;
    545         if (constB.Value > 0.0) {
     549        if(constB.Value > 0.0) {
    546550          // the constant value has no effect on the result of the boolean condition so we can drop the constant term
    547551          var andNode = andSymbol.CreateTreeNode();
     
    562566    private ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide,
    563567      ISymbolicExpressionTreeNode rightSide) {
    564       if (IsConstant(leftSide) && IsConstant(rightSide)) {
     568      if(IsConstant(leftSide) && IsConstant(rightSide)) {
    565569        var lsConst = leftSide as ConstantTreeNode;
    566570        var rsConst = rightSide as ConstantTreeNode;
    567         if (lsConst.Value < rsConst.Value) return MakeConstant(1.0);
     571        if(lsConst.Value < rsConst.Value) return MakeConstant(1.0);
    568572        else return MakeConstant(-1.0);
    569573      } else {
     
    577581    private ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide,
    578582      ISymbolicExpressionTreeNode rightSide) {
    579       if (IsConstant(leftSide) && IsConstant(rightSide)) {
     583      if(IsConstant(leftSide) && IsConstant(rightSide)) {
    580584        var lsConst = leftSide as ConstantTreeNode;
    581585        var rsConst = rightSide as ConstantTreeNode;
    582         if (lsConst.Value > rsConst.Value) return MakeConstant(1.0);
     586        if(lsConst.Value > rsConst.Value) return MakeConstant(1.0);
    583587        else return MakeConstant(-1.0);
    584588      } else {
     
    592596    private ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition,
    593597      ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) {
    594       if (IsConstant(condition)) {
     598      if(IsConstant(condition)) {
    595599        var constT = condition as ConstantTreeNode;
    596         if (constT.Value > 0.0) return trueBranch;
     600        if(constT.Value > 0.0) return trueBranch;
    597601        else return falseBranch;
    598602      } else {
    599603        var ifNode = ifThenElseSymbol.CreateTreeNode();
    600         if (IsBoolean(condition)) {
     604        if(IsBoolean(condition)) {
    601605          ifNode.AddSubtree(condition);
    602606        } else {
     
    613617
    614618    private ISymbolicExpressionTreeNode MakeSine(ISymbolicExpressionTreeNode node) {
    615       if (IsConstant(node)) {
     619      if(IsConstant(node)) {
    616620        var constT = node as ConstantTreeNode;
    617621        return MakeConstant(Math.Sin(constT.Value));
     622      } else if(IsFactor(node)) {
     623        var factor = node as FactorVariableTreeNode;
     624        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin));
     625      } else if(IsBinFactor(node)) {
     626        var binFactor = node as BinaryFactorVariableTreeNode;
     627        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight));
    618628      } else {
    619629        var sineNode = sineSymbol.CreateTreeNode();
     
    624634
    625635    private ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) {
    626       if (IsConstant(node)) {
     636      if(IsConstant(node)) {
    627637        var constT = node as ConstantTreeNode;
    628638        return MakeConstant(Math.Tan(constT.Value));
     639      } else if(IsFactor(node)) {
     640        var factor = node as FactorVariableTreeNode;
     641        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan));
     642      } else if(IsBinFactor(node)) {
     643        var binFactor = node as BinaryFactorVariableTreeNode;
     644        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight));
    629645      } else {
    630646        var tanNode = tanSymbol.CreateTreeNode();
     
    635651
    636652    private ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) {
    637       if (IsConstant(node)) {
     653      if(IsConstant(node)) {
    638654        var constT = node as ConstantTreeNode;
    639655        return MakeConstant(Math.Cos(constT.Value));
     656      } else if(IsFactor(node)) {
     657        var factor = node as FactorVariableTreeNode;
     658        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos));
     659      } else if(IsBinFactor(node)) {
     660        var binFactor = node as BinaryFactorVariableTreeNode;
     661        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight));
    640662      } else {
    641663        var cosNode = cosineSymbol.CreateTreeNode();
     
    646668
    647669    private ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) {
    648       if (IsConstant(node)) {
     670      if(IsConstant(node)) {
    649671        var constT = node as ConstantTreeNode;
    650672        return MakeConstant(Math.Exp(constT.Value));
    651       } else if (IsFactor(node)) {
     673      } else if(IsFactor(node)) {
    652674        var factNode = node as FactorVariableTreeNode;
    653675        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w)));
    654       } else if (IsLog(node)) {
     676      } else if(IsBinFactor(node)) {
     677        var binFactor = node as BinaryFactorVariableTreeNode;
     678        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight));
     679      } else if(IsLog(node)) {
    655680        return node.GetSubtree(0);
    656       } else if (IsAddition(node)) {
     681      } else if(IsAddition(node)) {
    657682        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));
    658       } else if (IsSubtraction(node)) {
     683      } else if(IsSubtraction(node)) {
    659684        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));
    660685      } else {
     
    664689      }
    665690    }
     691    private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {
     692      if(IsConstant(node)) {
     693        var constT = node as ConstantTreeNode;
     694        return MakeConstant(Math.Log(constT.Value));
     695      } else if(IsFactor(node)) {
     696        var factNode = node as FactorVariableTreeNode;
     697        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));
     698      } else if(IsBinFactor(node)) {
     699        var binFactor = node as BinaryFactorVariableTreeNode;
     700        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Log(binFactor.Weight));
     701      } else if(IsExp(node)) {
     702        return node.GetSubtree(0);
     703      } else if(IsSquareRoot(node)) {
     704        return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));
     705      } else {
     706        var logNode = logSymbol.CreateTreeNode();
     707        logNode.AddSubtree(node);
     708        return logNode;
     709      }
     710    }
    666711
    667712    private ISymbolicExpressionTreeNode MakeSquare(ISymbolicExpressionTreeNode node) {
    668       if (IsConstant(node)) {
     713      if(IsConstant(node)) {
    669714        var constT = node as ConstantTreeNode;
    670715        return MakeConstant(constT.Value * constT.Value);
    671       } else if (IsFactor(node)) {
     716      } else if(IsFactor(node)) {
    672717        var factNode = node as FactorVariableTreeNode;
    673718        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w));
    674       } else if (IsSquareRoot(node)) {
     719      } else if(IsBinFactor(node)) {
     720        var binFactor = node as BinaryFactorVariableTreeNode;
     721        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight);
     722      } else if(IsSquareRoot(node)) {
    675723        return node.GetSubtree(0);
    676724      } else {
     
    682730
    683731    private ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) {
    684       if (IsConstant(node)) {
     732      if(IsConstant(node)) {
    685733        var constT = node as ConstantTreeNode;
    686734        return MakeConstant(Math.Sqrt(constT.Value));
    687       } else if (IsFactor(node)) {
     735      } else if(IsFactor(node)) {
    688736        var factNode = node as FactorVariableTreeNode;
    689737        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w)));
    690       } else if (IsSquare(node)) {
     738      } else if(IsBinFactor(node)) {
     739        var binFactor = node as BinaryFactorVariableTreeNode;
     740        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
     741      } else if(IsSquare(node)) {
    691742        return node.GetSubtree(0);
    692743      } else {
     
    697748    }
    698749
    699     private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {
    700       if (IsConstant(node)) {
    701         var constT = node as ConstantTreeNode;
    702         return MakeConstant(Math.Log(constT.Value));
    703       } else if (IsFactor(node)) {
    704         var factNode = node as FactorVariableTreeNode;
    705         return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));
    706       } else if (IsExp(node)) {
    707         return node.GetSubtree(0);
    708       } else if (IsSquareRoot(node)) {
    709         return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));
    710       } else {
    711         var logNode = logSymbol.CreateTreeNode();
    712         logNode.AddSubtree(node);
    713         return logNode;
    714       }
    715     }
    716 
    717750    private ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    718       if (IsConstant(a) && IsConstant(b)) {
     751      if(IsConstant(a) && IsConstant(b)) {
    719752        var constA = a as ConstantTreeNode;
    720753        var constB = b as ConstantTreeNode;
    721754        return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value)));
    722       } else if (IsFactor(a) && IsConstant(b)) {
     755      } else if(IsFactor(a) && IsConstant(b)) {
    723756        var factNode = a as FactorVariableTreeNode;
    724757        var constNode = b as ConstantTreeNode;
    725758        return MakeFactor(factNode.Symbol, factNode.VariableName,
    726759          factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(constNode.Value))));
    727       } else if (IsConstant(a) && IsFactor(b)) {
     760      } else if(IsBinFactor(a) && IsConstant(b)) {
     761        var binFactor = a as BinaryFactorVariableTreeNode;
     762        var constNode = b as ConstantTreeNode;
     763        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(constNode.Value)));
     764      } else if(IsConstant(a) && IsFactor(b)) {
    728765        var constNode = a as ConstantTreeNode;
    729766        var factNode = b as FactorVariableTreeNode;
    730767        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, 1.0 / Math.Round(w))));
    731       } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     768      } else if(IsConstant(a) && IsBinFactor(b)) {
     769        var constNode = a as ConstantTreeNode;
     770        var factNode = b as BinaryFactorVariableTreeNode;
     771        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weight)));
     772      } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    732773        var node0 = a as FactorVariableTreeNode;
    733774        var node1 = b as FactorVariableTreeNode;
    734775        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v))));
    735       } else if (IsConstant(b)) {
     776      } else if(IsConstant(b)) {
    736777        var constB = b as ConstantTreeNode;
    737778        var constBValue = Math.Round(constB.Value);
    738         if (constBValue.IsAlmost(1.0)) {
     779        if(constBValue.IsAlmost(1.0)) {
    739780          return a;
    740         } else if (constBValue.IsAlmost(0.0)) {
     781        } else if(constBValue.IsAlmost(0.0)) {
    741782          return MakeConstant(1.0);
    742         } else if (constBValue.IsAlmost(-1.0)) {
     783        } else if(constBValue.IsAlmost(-1.0)) {
    743784          return MakeFraction(MakeConstant(1.0), a);
    744         } else if (constBValue < 0) {
     785        } else if(constBValue < 0) {
    745786          var rootNode = rootSymbol.CreateTreeNode();
    746787          rootNode.AddSubtree(a);
     
    763804
    764805    private ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    765       if (IsConstant(a) && IsConstant(b)) {
     806      if(IsConstant(a) && IsConstant(b)) {
    766807        var constA = a as ConstantTreeNode;
    767808        var constB = b as ConstantTreeNode;
    768809        return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value)));
    769       } else if (IsFactor(a) && IsConstant(b)) {
     810      } else if(IsFactor(a) && IsConstant(b)) {
    770811        var factNode = a as FactorVariableTreeNode;
    771812        var constNode = b as ConstantTreeNode;
    772813        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(constNode.Value))));
    773       } else if (IsConstant(a) && IsFactor(b)) {
     814      } else if(IsBinFactor(a) && IsConstant(b)) {
     815        var binFactor = a as BinaryFactorVariableTreeNode;
     816        var constNode = b as ConstantTreeNode;
     817        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(constNode.Value)));
     818      } else if(IsConstant(a) && IsFactor(b)) {
    774819        var constNode = a as ConstantTreeNode;
    775820        var factNode = b as FactorVariableTreeNode;
    776821        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, Math.Round(w))));
    777       } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     822      } else if(IsConstant(a) && IsBinFactor(b)) {
     823        var constNode = a as ConstantTreeNode;
     824        var factNode = b as BinaryFactorVariableTreeNode;
     825        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, Math.Round(factNode.Weight)));
     826      } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    778827        var node0 = a as FactorVariableTreeNode;
    779828        var node1 = b as FactorVariableTreeNode;
    780829        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v))));
    781       } else if (IsConstant(b)) {
     830      } else if(IsConstant(b)) {
    782831        var constB = b as ConstantTreeNode;
    783832        double exponent = Math.Round(constB.Value);
    784         if (exponent.IsAlmost(0.0)) {
     833        if(exponent.IsAlmost(0.0)) {
    785834          return MakeConstant(1.0);
    786         } else if (exponent.IsAlmost(1.0)) {
     835        } else if(exponent.IsAlmost(1.0)) {
    787836          return a;
    788         } else if (exponent.IsAlmost(-1.0)) {
     837        } else if(exponent.IsAlmost(-1.0)) {
    789838          return MakeFraction(MakeConstant(1.0), a);
    790         } else if (exponent < 0) {
     839        } else if(exponent < 0) {
    791840          var powNode = powSymbol.CreateTreeNode();
    792841          powNode.AddSubtree(a);
     
    810859    // MakeFraction, MakeProduct and MakeSum take two already simplified trees and create a new simplified tree
    811860    private ISymbolicExpressionTreeNode MakeFraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    812       if (IsConstant(a) && IsConstant(b)) {
     861      if(IsConstant(a) && IsConstant(b)) {
    813862        // fold constants
    814863        return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value);
    815       } else if ((IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0))) {
     864      } else if((IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0))) {
    816865        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
    817       } else if (IsVariableBase(a) && IsConstant(b)) {
     866      } else if(IsVariableBase(a) && IsConstant(b)) {
    818867        // merge constant values into variable weights
    819868        var constB = ((ConstantTreeNode)b).Value;
    820869        ((VariableTreeNodeBase)a).Weight /= constB;
    821870        return a;
    822       } else if (IsFactor(a) && IsConstant(b)) {
     871      } else if(IsFactor(a) && IsConstant(b)) {
    823872        var factNode = a as FactorVariableTreeNode;
    824873        var constNode = b as ConstantTreeNode;
    825874        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / constNode.Value));
    826       } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     875      } else if(IsBinFactor(a) && IsConstant(b)) {
     876        var factNode = a as BinaryFactorVariableTreeNode;
     877        var constNode = b as ConstantTreeNode;
     878        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / constNode.Value);
     879      } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    827880        var node0 = a as FactorVariableTreeNode;
    828881        var node1 = b as FactorVariableTreeNode;
    829882        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v));
    830       } else if (IsFactor(a)) {
     883      } else if(IsFactor(a)) {
    831884        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
    832       } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameVariable(a, b)) {
    833         // cancel variables
     885      } else if(IsVariableBase(a) && IsVariableBase(b) && AreSameTypeAndVariable(a, b) && !IsBinFactor(b)) {
     886        // cancel variables (not allowed for bin factors because of division by zero)
    834887        var aVar = a as VariableTreeNode;
    835888        var bVar = b as VariableTreeNode;
    836889        return MakeConstant(aVar.Weight / bVar.Weight);
    837       } else if (IsAddition(a) && IsConstant(b)) {
     890      } else if(IsAddition(a) && IsConstant(b)) {
    838891        return a.Subtrees
    839892          .Select(x => GetSimplifiedTree(x))
    840893          .Select(x => MakeFraction(x, b))
    841894          .Aggregate((c, d) => MakeSum(c, d));
    842       } else if (IsMultiplication(a) && IsConstant(b)) {
     895      } else if(IsMultiplication(a) && IsConstant(b)) {
    843896        return MakeProduct(a, Invert(b));
    844       } else if (IsDivision(a) && IsConstant(b)) {
     897      } else if(IsDivision(a) && IsConstant(b)) {
    845898        // (a1 / a2) / c => (a1 / (a2 * c))
    846899        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
    847       } else if (IsDivision(a) && IsDivision(b)) {
     900      } else if(IsDivision(a) && IsDivision(b)) {
    848901        // (a1 / a2) / (b1 / b2) =>
    849902        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(1)), MakeProduct(a.GetSubtree(1), b.GetSubtree(0)));
    850       } else if (IsDivision(a)) {
     903      } else if(IsDivision(a)) {
    851904        // (a1 / a2) / b => (a1 / (a2 * b))
    852905        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
    853       } else if (IsDivision(b)) {
     906      } else if(IsDivision(b)) {
    854907        // a / (b1 / b2) => (a * b2) / b1
    855908        return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));
     
    863916
    864917    private ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    865       if (IsConstant(a) && IsConstant(b)) {
     918      if(IsConstant(a) && IsConstant(b)) {
    866919        // fold constants
    867920        ((ConstantTreeNode)a).Value += ((ConstantTreeNode)b).Value;
    868921        return a;
    869       } else if (IsConstant(a)) {
     922      } else if(IsConstant(a)) {
    870923        // c + x => x + c
    871924        // b is not constant => make sure constant is on the right
    872925        return MakeSum(b, a);
    873       } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) {
     926      } else if(IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) {
    874927        // x + 0 => x
    875928        return a;
    876       } else if (IsFactor(a) && IsConstant(b)) {
     929      } else if(IsFactor(a) && IsConstant(b)) {
    877930        var factNode = a as FactorVariableTreeNode;
    878931        var constNode = b as ConstantTreeNode;
    879932        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + constNode.Value));
    880       } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     933      } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    881934        var node0 = a as FactorVariableTreeNode;
    882935        var node1 = b as FactorVariableTreeNode;
    883936        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v));
    884       } else if (IsAddition(a) && IsAddition(b)) {
     937      } else if(IsAddition(a) && IsAddition(b)) {
    885938        // merge additions
    886939        var add = addSymbol.CreateTreeNode();
    887940        // add all sub trees except for the last
    888         for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
    889         for (int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i));
    890         if (IsConstant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) {
     941        for(int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
     942        for(int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i));
     943        if(IsConstant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) {
    891944          add.AddSubtree(MakeSum(a.Subtrees.Last(), b.Subtrees.Last()));
    892         } else if (IsConstant(a.Subtrees.Last())) {
     945        } else if(IsConstant(a.Subtrees.Last())) {
    893946          add.AddSubtree(b.Subtrees.Last());
    894947          add.AddSubtree(a.Subtrees.Last());
     
    898951        }
    899952        MergeVariablesInSum(add);
    900         if (add.Subtrees.Count() == 1) {
     953        if(add.Subtrees.Count() == 1) {
    901954          return add.GetSubtree(0);
    902955        } else {
    903956          return add;
    904957        }
    905       } else if (IsAddition(b)) {
     958      } else if(IsAddition(b)) {
    906959        return MakeSum(b, a);
    907       } else if (IsAddition(a) && IsConstant(b)) {
     960      } else if(IsAddition(a) && IsConstant(b)) {
    908961        // a is an addition and b is a constant => append b to a and make sure the constants are merged
    909962        var add = addSymbol.CreateTreeNode();
    910963        // add all sub trees except for the last
    911         for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
    912         if (IsConstant(a.Subtrees.Last()))
     964        for(int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
     965        if(IsConstant(a.Subtrees.Last()))
    913966          add.AddSubtree(MakeSum(a.Subtrees.Last(), b));
    914967        else {
     
    917970        }
    918971        return add;
    919       } else if (IsAddition(a)) {
     972      } else if(IsAddition(a)) {
    920973        // a is already an addition => append b
    921974        var add = addSymbol.CreateTreeNode();
    922975        add.AddSubtree(b);
    923         foreach (var subtree in a.Subtrees) {
     976        foreach(var subtree in a.Subtrees) {
    924977          add.AddSubtree(subtree);
    925978        }
    926979        MergeVariablesInSum(add);
    927         if (add.Subtrees.Count() == 1) {
     980        if(add.Subtrees.Count() == 1) {
    928981          return add.GetSubtree(0);
    929982        } else {
     
    935988        add.AddSubtree(b);
    936989        MergeVariablesInSum(add);
    937         if (add.Subtrees.Count() == 1) {
     990        if(add.Subtrees.Count() == 1) {
    938991          return add.GetSubtree(0);
    939992        } else {
     
    944997
    945998    // makes sure variable symbols in sums are combined
    946     // possible improvement: combine sums of products where the products only reference the same variable
    947999    private void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) {
    9481000      var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees);
    949       while (sum.Subtrees.Any()) sum.RemoveSubtree(0);
     1001      while(sum.Subtrees.Any()) sum.RemoveSubtree(0);
    9501002      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
    9511003                            where node.SubtreeCount == 0
    952                             // only consider terminal nodes
    953                             let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
    954                             let cat =
    955                               (node is BinaryFactorVariableTreeNode) ? ((BinaryFactorVariableTreeNode)node).VariableValue : string.Empty
    956                             group node by node.VariableName + cat + lag
    957         into g
     1004                            group node by GroupId(node) into g
    9581005                            select g;
    9591006      var constant = (from node in subtrees.OfType<ConstantTreeNode>()
     
    9611008      var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode));
    9621009
    963       foreach (var variableNodeGroup in groupedVarNodes) {
     1010      foreach(var variableNodeGroup in groupedVarNodes) {
    9641011        var firstNode = variableNodeGroup.First();
    965         if (firstNode is VariableTreeNodeBase) {
     1012        if(firstNode is VariableTreeNodeBase) {
    9661013          var representative = firstNode as VariableTreeNodeBase;
    9671014          var weightSum = variableNodeGroup.Cast<VariableTreeNodeBase>().Select(t => t.Weight).Sum();
    9681015          representative.Weight = weightSum;
    9691016          sum.AddSubtree(representative);
    970         } else if (firstNode is FactorVariableTreeNode) {
     1017        } else if(firstNode is FactorVariableTreeNode) {
    9711018          var representative = firstNode as FactorVariableTreeNode;
    972           foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
    973             for (int j = 0; j < representative.Weights.Length; j++) {
     1019          foreach(var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
     1020            for(int j = 0; j < representative.Weights.Length; j++) {
    9741021              representative.Weights[j] += node.Weights[j];
    9751022            }
    9761023          }
    977           for (int j = 0; j < representative.Weights.Length; j++) {
     1024          for(int j = 0; j < representative.Weights.Length; j++) {
    9781025            representative.Weights[j] += constant;
    9791026          }
     
    9811028        }
    9821029      }
    983       foreach (var unchangedSubtree in unchangedSubtrees)
     1030      foreach(var unchangedSubtree in unchangedSubtrees)
    9841031        sum.AddSubtree(unchangedSubtree);
    985       if (!constant.IsAlmost(0.0)) {
     1032      if(!constant.IsAlmost(0.0)) {
    9861033        sum.AddSubtree(MakeConstant(constant));
    9871034      }
    9881035    }
    9891036
     1037    // nodes referencing variables can be grouped if they have
     1038    private string GroupId(IVariableTreeNode node) {
     1039      var binaryFactorNode = node as BinaryFactorVariableTreeNode;
     1040      var factorNode = node as FactorVariableTreeNode;
     1041      var variableNode = node as VariableTreeNode;
     1042      var laggedVarNode = node as LaggedVariableTreeNode;
     1043      if(variableNode != null) {
     1044        return "var " + variableNode.VariableName;
     1045      } else if(binaryFactorNode != null) {
     1046        return "binfactor " + binaryFactorNode.VariableName + " " + binaryFactorNode.VariableValue;
     1047      } else if(factorNode != null) {
     1048        return "factor " + factorNode.VariableName;
     1049      } else if(laggedVarNode != null) {
     1050        return "lagged " + laggedVarNode.VariableName + " " + laggedVarNode.Lag;
     1051      } else {
     1052        throw new NotSupportedException();
     1053      }
     1054    }
     1055
    9901056
    9911057    private ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    992       if (IsConstant(a) && IsConstant(b)) {
     1058      if(IsConstant(a) && IsConstant(b)) {
    9931059        // fold constants
    9941060        ((ConstantTreeNode)a).Value *= ((ConstantTreeNode)b).Value;
    9951061        return a;
    996       } else if (IsConstant(a)) {
     1062      } else if(IsConstant(a)) {
    9971063        // a * $ => $ * a
    9981064        return MakeProduct(b, a);
    999       } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     1065      } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
    10001066        var node0 = a as FactorVariableTreeNode;
    10011067        var node1 = b as FactorVariableTreeNode;
    10021068        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v));
    1003       } else if (IsFactor(a) && IsConstant(b)) {
     1069      } else if(IsBinFactor(a) && IsBinFactor(b) && AreSameTypeAndVariable(a, b)) {
     1070        var node0 = a as BinaryFactorVariableTreeNode;
     1071        var node1 = b as BinaryFactorVariableTreeNode;
     1072        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight);
     1073      } else if(IsFactor(a) && IsConstant(b)) {
    10041074        var node0 = a as FactorVariableTreeNode;
    10051075        var node1 = b as ConstantTreeNode;
    10061076        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value));
    1007       } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) {
     1077      } else if(IsBinFactor(a) && IsConstant(b)) {
     1078        var node0 = a as BinaryFactorVariableTreeNode;
     1079        var node1 = b as ConstantTreeNode;
     1080        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value);
     1081      } else if(IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) {
    10081082        // $ * 1.0 => $
    10091083        return a;
    1010       } else if (IsConstant(b) && IsVariableBase(a)) {
     1084      } else if(IsConstant(b) && IsVariableBase(a)) {
    10111085        // multiply constants into variables weights
    10121086        ((VariableTreeNodeBase)a).Weight *= ((ConstantTreeNode)b).Value;
    10131087        return a;
    1014       } else if (IsConstant(b) && IsAddition(a) ||
     1088      } else if(IsConstant(b) && IsAddition(a) ||
    10151089          IsFactor(b) && IsAddition(a)) {
    10161090        // multiply constants into additions
    10171091        return a.Subtrees.Select(x => MakeProduct(x, b)).Aggregate((c, d) => MakeSum(c, d));
    1018       } else if (IsDivision(a) && IsDivision(b)) {
     1092      } else if(IsDivision(a) && IsDivision(b)) {
    10191093        // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2)
    10201094        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1)));
    1021       } else if (IsDivision(a)) {
     1095      } else if(IsDivision(a)) {
    10221096        // (a1 / a2) * b => (a1 * b) / a2
    10231097        return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
    1024       } else if (IsDivision(b)) {
     1098      } else if(IsDivision(b)) {
    10251099        // a * (b1 / b2) => (b1 * a) / b2
    10261100        return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1));
    1027       } else if (IsMultiplication(a) && IsMultiplication(b)) {
     1101      } else if(IsMultiplication(a) && IsMultiplication(b)) {
    10281102        // merge multiplications (make sure constants are merged)
    10291103        var mul = mulSymbol.CreateTreeNode();
    1030         for (int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i));
    1031         for (int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i));
     1104        for(int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i));
     1105        for(int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i));
    10321106        MergeVariablesAndConstantsInProduct(mul);
    10331107        return mul;
    1034       } else if (IsMultiplication(b)) {
     1108      } else if(IsMultiplication(b)) {
    10351109        return MakeProduct(b, a);
    1036       } else if (IsMultiplication(a)) {
     1110      } else if(IsMultiplication(a)) {
    10371111        // a is already an multiplication => append b
    10381112        a.AddSubtree(b);
     
    10531127
    10541128    private bool ContainsVariableCondition(ISymbolicExpressionTreeNode node) {
    1055       if (node.Symbol is VariableCondition) return true;
    1056       foreach (var subtree in node.Subtrees)
    1057         if (ContainsVariableCondition(subtree)) return true;
     1129      if(node.Symbol is VariableCondition) return true;
     1130      foreach(var subtree in node.Subtrees)
     1131        if(ContainsVariableCondition(subtree)) return true;
    10581132      return false;
    10591133    }
     
    10631137      var variableNode = node as VariableTreeNode;
    10641138      var variableConditionNode = node as VariableConditionTreeNode;
    1065       if (laggedTreeNode != null)
     1139      if(laggedTreeNode != null)
    10661140        laggedTreeNode.Lag += lag;
    1067       else if (variableNode != null) {
     1141      else if(variableNode != null) {
    10681142        var laggedVariableNode = (LaggedVariableTreeNode)laggedVariableSymbol.CreateTreeNode();
    10691143        laggedVariableNode.Lag = lag;
    10701144        laggedVariableNode.VariableName = variableNode.VariableName;
    10711145        return laggedVariableNode;
    1072       } else if (variableConditionNode != null) {
     1146      } else if(variableConditionNode != null) {
    10731147        throw new NotSupportedException("Removal of time lags around variable condition symbols is not allowed.");
    10741148      }
    10751149      var subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
    1076       while (node.SubtreeCount > 0) node.RemoveSubtree(0);
    1077       foreach (var subtree in subtrees) {
     1150      while(node.SubtreeCount > 0) node.RemoveSubtree(0);
     1151      foreach(var subtree in subtrees) {
    10781152        node.AddSubtree(AddLagToDynamicNodes(subtree, lag));
    10791153      }
     
    10811155    }
    10821156
    1083     private bool AreSameVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    1084       var aLaggedVar = a as LaggedVariableTreeNode;
    1085       var bLaggedVar = b as LaggedVariableTreeNode;
    1086       if (aLaggedVar != null && bLaggedVar != null) {
    1087         return aLaggedVar.VariableName == bLaggedVar.VariableName &&
    1088                aLaggedVar.Lag == bLaggedVar.Lag;
    1089       }
    1090       var aVar = a as VariableTreeNode;
    1091       var bVar = b as VariableTreeNode;
    1092       if (aVar != null && bVar != null) {
    1093         return aVar.VariableName == bVar.VariableName;
    1094       }
    1095       var aFactor = a as FactorVariableTreeNode;
    1096       var bFactor = b as FactorVariableTreeNode;
    1097       if (aFactor != null && bFactor != null) {
    1098         return aFactor.VariableName == bFactor.VariableName;
    1099       }
    1100       var aBinFactor = a as BinaryFactorVariableTreeNode;
    1101       var bBinFactor = b as BinaryFactorVariableTreeNode;
    1102       if (aBinFactor != null && bBinFactor != null) {
    1103         return aBinFactor.VariableName == bBinFactor.VariableName &&
    1104                aBinFactor.VariableValue == bBinFactor.VariableValue;
    1105       }
    1106       return false;
     1157    private bool AreSameTypeAndVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     1158      return GroupId((IVariableTreeNode)a) == GroupId((IVariableTreeNode)b);
    11071159    }
    11081160
     
    11101162    private void MergeVariablesAndConstantsInProduct(ISymbolicExpressionTreeNode prod) {
    11111163      var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees);
    1112       while (prod.Subtrees.Any()) prod.RemoveSubtree(0);
     1164      while(prod.Subtrees.Any()) prod.RemoveSubtree(0);
    11131165      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
    11141166                            where node.SubtreeCount == 0
    1115                             let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
    1116                             let cat =
    1117                               (node is BinaryFactorVariableTreeNode) ? ((BinaryFactorVariableTreeNode)node).VariableValue : string.Empty
    1118                             group node by node.VariableName + cat + lag
    1119         into g
     1167                            group node by GroupId(node) into g
    11201168                            orderby g.Count()
    11211169                            select g;
     
    11311179                              select tree;
    11321180
    1133       foreach (var variableNodeGroup in groupedVarNodes) {
     1181      foreach(var variableNodeGroup in groupedVarNodes) {
    11341182        var firstNode = variableNodeGroup.First();
    1135         if (firstNode is VariableTreeNodeBase) {
     1183        if(firstNode is VariableTreeNodeBase) {
    11361184          var representative = (VariableTreeNodeBase)firstNode;
    11371185          representative.Weight = 1.0;
    1138           if (variableNodeGroup.Count() > 1) {
     1186          if(variableNodeGroup.Count() > 1) {
    11391187            var poly = mulSymbol.CreateTreeNode();
    1140             for (int p = 0; p < variableNodeGroup.Count(); p++) {
     1188            for(int p = 0; p < variableNodeGroup.Count(); p++) {
    11411189              poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone());
    11421190            }
     
    11451193            prod.AddSubtree(representative);
    11461194          }
    1147         } else if (firstNode is FactorVariableTreeNode) {
     1195        } else if(firstNode is FactorVariableTreeNode) {
    11481196          var representative = (FactorVariableTreeNode)firstNode;
    1149           foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
    1150             for (int j = 0; j < representative.Weights.Length; j++) {
     1197          foreach(var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
     1198            for(int j = 0; j < representative.Weights.Length; j++) {
    11511199              representative.Weights[j] *= node.Weights[j];
    11521200            }
    11531201          }
    1154           for (int j = 0; j < representative.Weights.Length; j++) {
     1202          for(int j = 0; j < representative.Weights.Length; j++) {
    11551203            representative.Weights[j] *= constantProduct;
    11561204          }
     
    11611209      }
    11621210
    1163       foreach (var unchangedSubtree in unchangedSubtrees)
     1211      foreach(var unchangedSubtree in unchangedSubtrees)
    11641212        prod.AddSubtree(unchangedSubtree);
    11651213
    1166       if (!constantProduct.IsAlmost(1.0)) {
     1214      if(!constantProduct.IsAlmost(1.0)) {
    11671215        prod.AddSubtree(MakeConstant(constantProduct));
    11681216      }
     
    11771225    /// <returns>-x</returns>
    11781226    private ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) {
    1179       if (IsConstant(x)) {
     1227      if(IsConstant(x)) {
    11801228        ((ConstantTreeNode)x).Value *= -1;
    1181       } else if (IsVariableBase(x)) {
     1229      } else if(IsVariableBase(x)) {
    11821230        var variableTree = (VariableTreeNodeBase)x;
    11831231        variableTree.Weight *= -1.0;
    1184       } else if (IsFactor(x)) {
     1232      } else if(IsFactor(x)) {
    11851233        var factorNode = (FactorVariableTreeNode)x;
    1186         for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1;
    1187       } else if (IsAddition(x)) {
     1234        for(int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1;
     1235      } else if(IsBinFactor(x)) {
     1236        var factorNode = (BinaryFactorVariableTreeNode)x;
     1237        factorNode.Weight *= -1;
     1238      } else if(IsAddition(x)) {
    11881239        // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn)       
    11891240        var subtrees = new List<ISymbolicExpressionTreeNode>(x.Subtrees);
    1190         while (x.Subtrees.Any()) x.RemoveSubtree(0);
    1191         foreach (var subtree in subtrees) {
     1241        while(x.Subtrees.Any()) x.RemoveSubtree(0);
     1242        foreach(var subtree in subtrees) {
    11921243          x.AddSubtree(Negate(subtree));
    11931244        }
    1194       } else if (IsMultiplication(x) || IsDivision(x)) {
     1245      } else if(IsMultiplication(x) || IsDivision(x)) {
    11951246        // x0 * x1 * .. * xn * -1 => x0 * x1 * .. * -xn
    11961247        var lastSubTree = x.Subtrees.Last();
     
    12111262    /// <returns></returns>
    12121263    private ISymbolicExpressionTreeNode Invert(ISymbolicExpressionTreeNode x) {
    1213       if (IsConstant(x)) {
     1264      if(IsConstant(x)) {
    12141265        return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);
    1215       } else if (IsFactor(x)) {
     1266      } else if(IsFactor(x)) {
    12161267        var factorNode = (FactorVariableTreeNode)x;
    1217         for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] = 1.0 / factorNode.Weights[i];
     1268        for(int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] = 1.0 / factorNode.Weights[i];
    12181269        return factorNode;
    1219       } else if (IsDivision(x)) {
     1270      } else if(IsDivision(x)) {
    12201271        return MakeFraction(x.GetSubtree(1), x.GetSubtree(0));
    12211272      } else {
     
    12311282    }
    12321283
    1233     private ISymbolicExpressionTreeNode MakeVariable(double weight, string name) {
    1234       var tree = (VariableTreeNode)varSymbol.CreateTreeNode();
    1235       tree.Weight = weight;
    1236       tree.VariableName = name;
    1237       return tree;
    1238     }
    12391284    private ISymbolicExpressionTreeNode MakeFactor(FactorVariable sy, string variableName, IEnumerable<double> weights) {
    12401285      var tree = (FactorVariableTreeNode)sy.CreateTreeNode();
     
    12431288      return tree;
    12441289    }
     1290    private ISymbolicExpressionTreeNode MakeBinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) {
     1291      var tree = (BinaryFactorVariableTreeNode)sy.CreateTreeNode();
     1292      tree.VariableName = variableName;
     1293      tree.VariableValue = variableValue;
     1294      tree.Weight = weight;
     1295      return tree;
     1296    }
    12451297
    12461298
Note: See TracChangeset for help on using the changeset viewer.