Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
03/17/11 14:07:47 (13 years ago)
Author:
mkommend
Message:

#1418: Corrected problem interfaces & unified naming of subtrees.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplifier.cs

    r5574 r5733  
    5555      var clone = (ISymbolicExpressionTreeNode)originalTree.Root.Clone();
    5656      // macro expand (initially no argument trees)
    57       var macroExpandedTree = MacroExpand(clone, clone.GetSubTree(0), new List<ISymbolicExpressionTreeNode>());
     57      var macroExpandedTree = MacroExpand(clone, clone.GetSubtree(0), new List<ISymbolicExpressionTreeNode>());
    5858      ISymbolicExpressionTreeNode rootNode = (new ProgramRootSymbol()).CreateTreeNode();
    59       rootNode.AddSubTree(GetSimplifiedTree(macroExpandedTree));
     59      rootNode.AddSubtree(GetSimplifiedTree(macroExpandedTree));
    6060      return new SymbolicExpressionTree(rootNode);
    6161    }
     
    6363    // the argumentTrees list contains already expanded trees used as arguments for invocations
    6464    private ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node, IList<ISymbolicExpressionTreeNode> argumentTrees) {
    65       List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.SubTrees);
    66       while (node.SubTrees.Count() > 0) node.RemoveSubTree(0);
     65      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
     66      while (node.SubtreesCount > 0) node.RemoveSubtree(0);
    6767      if (node.Symbol is InvokeFunction) {
    6868        var invokeSym = node.Symbol as InvokeFunction;
     
    8080        // recursive application
    8181        foreach (var subtree in subtrees) {
    82           node.AddSubTree(MacroExpand(root, subtree, argumentTrees));
     82          node.AddSubtree(MacroExpand(root, subtree, argumentTrees));
    8383        }
    8484        return node;
     
    8787
    8888    private ISymbolicExpressionTreeNode FindFunctionDefinition(ISymbolicExpressionTreeNode root, string functionName) {
    89       foreach (var subtree in root.SubTrees.OfType<DefunTreeNode>()) {
    90         if (subtree.FunctionName == functionName) return subtree.GetSubTree(0);
     89      foreach (var subtree in root.Subtrees.OfType<DefunTreeNode>()) {
     90        if (subtree.FunctionName == functionName) return subtree.GetSubtree(0);
    9191      }
    9292
     
    232232    private ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) {
    233233      // can't simplify this function but simplify all subtrees
    234       List<ISymbolicExpressionTreeNode> subTrees = new List<ISymbolicExpressionTreeNode>(original.SubTrees);
    235       while (original.SubTrees.Count() > 0) original.RemoveSubTree(0);
     234      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees);
     235      while (original.Subtrees.Count() > 0) original.RemoveSubtree(0);
    236236      var clone = (SymbolicExpressionTreeNode)original.Clone();
    237       List<ISymbolicExpressionTreeNode> simplifiedSubTrees = new List<ISymbolicExpressionTreeNode>();
    238       foreach (var subTree in subTrees) {
    239         simplifiedSubTrees.Add(GetSimplifiedTree(subTree));
    240         original.AddSubTree(subTree);
    241       }
    242       foreach (var simplifiedSubtree in simplifiedSubTrees) {
    243         clone.AddSubTree(simplifiedSubtree);
    244       }
    245       if (simplifiedSubTrees.TrueForAll(t => IsConstant(t))) {
     237      List<ISymbolicExpressionTreeNode> simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>();
     238      foreach (var subtree in subtrees) {
     239        simplifiedSubtrees.Add(GetSimplifiedTree(subtree));
     240        original.AddSubtree(subtree);
     241      }
     242      foreach (var simplifiedSubtree in simplifiedSubtrees) {
     243        clone.AddSubtree(simplifiedSubtree);
     244      }
     245      if (simplifiedSubtrees.TrueForAll(t => IsConstant(t))) {
    246246        SimplifyConstantExpression(clone);
    247247      }
     
    255255
    256256    private ISymbolicExpressionTreeNode SimplifyAverage(ISymbolicExpressionTreeNode original) {
    257       if (original.SubTrees.Count() == 1) {
    258         return GetSimplifiedTree(original.GetSubTree(0));
     257      if (original.Subtrees.Count() == 1) {
     258        return GetSimplifiedTree(original.GetSubtree(0));
    259259      } else {
    260260        // simplify expressions x0..xn
    261261        // make sum(x0..xn) / n
    262         Trace.Assert(original.SubTrees.Count() > 1);
    263         var sum = original.SubTrees
     262        Trace.Assert(original.Subtrees.Count() > 1);
     263        var sum = original.Subtrees
    264264          .Select(x => GetSimplifiedTree(x))
    265265          .Aggregate((a, b) => MakeSum(a, b));
    266         return MakeFraction(sum, MakeConstant(original.SubTrees.Count()));
     266        return MakeFraction(sum, MakeConstant(original.Subtrees.Count()));
    267267      }
    268268    }
    269269
    270270    private ISymbolicExpressionTreeNode SimplifyDivision(ISymbolicExpressionTreeNode original) {
    271       if (original.SubTrees.Count() == 1) {
    272         return Invert(GetSimplifiedTree(original.GetSubTree(0)));
     271      if (original.Subtrees.Count() == 1) {
     272        return Invert(GetSimplifiedTree(original.GetSubtree(0)));
    273273      } else {
    274274        // simplify expressions x0..xn
    275275        // make multiplication (x0 * 1/(x1 * x1 * .. * xn))
    276         Trace.Assert(original.SubTrees.Count() > 1);
    277         var simplifiedTrees = original.SubTrees.Select(x => GetSimplifiedTree(x));
     276        Trace.Assert(original.Subtrees.Count() > 1);
     277        var simplifiedTrees = original.Subtrees.Select(x => GetSimplifiedTree(x));
    278278        return
    279279          MakeProduct(simplifiedTrees.First(), Invert(simplifiedTrees.Skip(1).Aggregate((a, b) => MakeProduct(a, b))));
     
    282282
    283283    private ISymbolicExpressionTreeNode SimplifyMultiplication(ISymbolicExpressionTreeNode original) {
    284       if (original.SubTrees.Count() == 1) {
    285         return GetSimplifiedTree(original.GetSubTree(0));
    286       } else {
    287         Trace.Assert(original.SubTrees.Count() > 1);
    288         return original.SubTrees
     284      if (original.Subtrees.Count() == 1) {
     285        return GetSimplifiedTree(original.GetSubtree(0));
     286      } else {
     287        Trace.Assert(original.Subtrees.Count() > 1);
     288        return original.Subtrees
    289289          .Select(x => GetSimplifiedTree(x))
    290290          .Aggregate((a, b) => MakeProduct(a, b));
     
    293293
    294294    private ISymbolicExpressionTreeNode SimplifySubtraction(ISymbolicExpressionTreeNode original) {
    295       if (original.SubTrees.Count() == 1) {
    296         return Negate(GetSimplifiedTree(original.GetSubTree(0)));
     295      if (original.Subtrees.Count() == 1) {
     296        return Negate(GetSimplifiedTree(original.GetSubtree(0)));
    297297      } else {
    298298        // simplify expressions x0..xn
    299299        // make addition (x0,-x1..-xn)
    300         Trace.Assert(original.SubTrees.Count() > 1);
    301         var simplifiedTrees = original.SubTrees.Select(x => GetSimplifiedTree(x));
     300        Trace.Assert(original.Subtrees.Count() > 1);
     301        var simplifiedTrees = original.Subtrees.Select(x => GetSimplifiedTree(x));
    302302        return simplifiedTrees.Take(1)
    303303          .Concat(simplifiedTrees.Skip(1).Select(x => Negate(x)))
     
    307307
    308308    private ISymbolicExpressionTreeNode SimplifyAddition(ISymbolicExpressionTreeNode original) {
    309       if (original.SubTrees.Count() == 1) {
    310         return GetSimplifiedTree(original.GetSubTree(0));
     309      if (original.Subtrees.Count() == 1) {
     310        return GetSimplifiedTree(original.GetSubtree(0));
    311311      } else {
    312312        // simplify expression x0..xn
    313313        // make addition (x0..xn)
    314         Trace.Assert(original.SubTrees.Count() > 1);
    315         return original.SubTrees
     314        Trace.Assert(original.Subtrees.Count() > 1);
     315        return original.Subtrees
    316316          .Select(x => GetSimplifiedTree(x))
    317317          .Aggregate((a, b) => MakeSum(a, b));
     
    320320
    321321    private ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) {
    322       return MakeNot(GetSimplifiedTree(original.GetSubTree(0)));
     322      return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
    323323    }
    324324    private ISymbolicExpressionTreeNode SimplifyOr(ISymbolicExpressionTreeNode original) {
    325       return original.SubTrees
     325      return original.Subtrees
    326326        .Select(x => GetSimplifiedTree(x))
    327327        .Aggregate((a, b) => MakeOr(a, b));
    328328    }
    329329    private ISymbolicExpressionTreeNode SimplifyAnd(ISymbolicExpressionTreeNode original) {
    330       return original.SubTrees
     330      return original.Subtrees
    331331        .Select(x => GetSimplifiedTree(x))
    332332        .Aggregate((a, b) => MakeAnd(a, b));
    333333    }
    334334    private ISymbolicExpressionTreeNode SimplifyLessThan(ISymbolicExpressionTreeNode original) {
    335       return MakeLessThan(GetSimplifiedTree(original.GetSubTree(0)), GetSimplifiedTree(original.GetSubTree(1)));
     335      return MakeLessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    336336    }
    337337    private ISymbolicExpressionTreeNode SimplifyGreaterThan(ISymbolicExpressionTreeNode original) {
    338       return MakeGreaterThan(GetSimplifiedTree(original.GetSubTree(0)), GetSimplifiedTree(original.GetSubTree(1)));
     338      return MakeGreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    339339    }
    340340    private ISymbolicExpressionTreeNode SimplifyIfThenElse(ISymbolicExpressionTreeNode original) {
    341       return MakeIfThenElse(GetSimplifiedTree(original.GetSubTree(0)), GetSimplifiedTree(original.GetSubTree(1)), GetSimplifiedTree(original.GetSubTree(2)));
     341      return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)), GetSimplifiedTree(original.GetSubtree(2)));
    342342    }
    343343    private ISymbolicExpressionTreeNode SimplifyTangent(ISymbolicExpressionTreeNode original) {
    344       return MakeTangent(GetSimplifiedTree(original.GetSubTree(0)));
     344      return MakeTangent(GetSimplifiedTree(original.GetSubtree(0)));
    345345    }
    346346    private ISymbolicExpressionTreeNode SimplifyCosine(ISymbolicExpressionTreeNode original) {
    347       return MakeCosine(GetSimplifiedTree(original.GetSubTree(0)));
     347      return MakeCosine(GetSimplifiedTree(original.GetSubtree(0)));
    348348    }
    349349    private ISymbolicExpressionTreeNode SimplifySine(ISymbolicExpressionTreeNode original) {
    350       return MakeSine(GetSimplifiedTree(original.GetSubTree(0)));
     350      return MakeSine(GetSimplifiedTree(original.GetSubtree(0)));
    351351    }
    352352    private ISymbolicExpressionTreeNode SimplifyExp(ISymbolicExpressionTreeNode original) {
    353       return MakeExp(GetSimplifiedTree(original.GetSubTree(0)));
     353      return MakeExp(GetSimplifiedTree(original.GetSubtree(0)));
    354354    }
    355355
    356356    private ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) {
    357       return MakeLog(GetSimplifiedTree(original.GetSubTree(0)));
     357      return MakeLog(GetSimplifiedTree(original.GetSubtree(0)));
    358358    }
    359359    private ISymbolicExpressionTreeNode SimplifyRoot(ISymbolicExpressionTreeNode original) {
    360       return MakeRoot(GetSimplifiedTree(original.GetSubTree(0)), GetSimplifiedTree(original.GetSubTree(1)));
     360      return MakeRoot(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    361361    }
    362362
    363363    private ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) {
    364       return MakePower(GetSimplifiedTree(original.GetSubTree(0)), GetSimplifiedTree(original.GetSubTree(1)));
     364      return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    365365    }
    366366    #endregion
     
    373373        else return MakeConstant(1.0);
    374374      } else if (IsNot(t)) {
    375         return t.GetSubTree(0);
     375        return t.GetSubtree(0);
    376376      } else if (!IsBoolean(t)) {
    377377        var gtNode = gtSymbol.CreateTreeNode();
    378         gtNode.AddSubTree(t); gtNode.AddSubTree(MakeConstant(0.0));
     378        gtNode.AddSubtree(t); gtNode.AddSubtree(MakeConstant(0.0));
    379379        var notNode = notSymbol.CreateTreeNode();
    380         notNode.AddSubTree(gtNode);
     380        notNode.AddSubtree(gtNode);
    381381        return notNode;
    382382      } else {
    383383        var notNode = notSymbol.CreateTreeNode();
    384         notNode.AddSubTree(t);
     384        notNode.AddSubtree(t);
    385385        return notNode;
    386386      }
     
    406406          // the constant value has no effect on the result of the boolean condition so we can drop the constant term
    407407          var orNode = orSymbol.CreateTreeNode();
    408           orNode.AddSubTree(a);
     408          orNode.AddSubtree(a);
    409409          return orNode;
    410410        }
    411411      } else {
    412412        var orNode = orSymbol.CreateTreeNode();
    413         orNode.AddSubTree(a);
    414         orNode.AddSubTree(b);
     413        orNode.AddSubtree(a);
     414        orNode.AddSubtree(b);
    415415        return orNode;
    416416      }
     
    432432          // the constant value has no effect on the result of the boolean condition so we can drop the constant term
    433433          var andNode = andSymbol.CreateTreeNode();
    434           andNode.AddSubTree(a);
     434          andNode.AddSubtree(a);
    435435          return andNode;
    436436        } else {
     
    440440      } else {
    441441        var andNode = andSymbol.CreateTreeNode();
    442         andNode.AddSubTree(a);
    443         andNode.AddSubTree(b);
     442        andNode.AddSubtree(a);
     443        andNode.AddSubtree(b);
    444444        return andNode;
    445445      }
     
    453453      } else {
    454454        var ltNode = ltSymbol.CreateTreeNode();
    455         ltNode.AddSubTree(leftSide);
    456         ltNode.AddSubTree(rightSide);
     455        ltNode.AddSubtree(leftSide);
     456        ltNode.AddSubtree(rightSide);
    457457        return ltNode;
    458458      }
     
    466466      } else {
    467467        var gtNode = gtSymbol.CreateTreeNode();
    468         gtNode.AddSubTree(leftSide);
    469         gtNode.AddSubTree(rightSide);
     468        gtNode.AddSubtree(leftSide);
     469        gtNode.AddSubtree(rightSide);
    470470        return gtNode;
    471471      }
     
    479479        var ifNode = ifThenElseSymbol.CreateTreeNode();
    480480        if (IsBoolean(condition)) {
    481           ifNode.AddSubTree(condition);
     481          ifNode.AddSubtree(condition);
    482482        } else {
    483483          var gtNode = gtSymbol.CreateTreeNode();
    484           gtNode.AddSubTree(condition); gtNode.AddSubTree(MakeConstant(0.0));
    485           ifNode.AddSubTree(gtNode);
    486         }
    487         ifNode.AddSubTree(trueBranch);
    488         ifNode.AddSubTree(falseBranch);
     484          gtNode.AddSubtree(condition); gtNode.AddSubtree(MakeConstant(0.0));
     485          ifNode.AddSubtree(gtNode);
     486        }
     487        ifNode.AddSubtree(trueBranch);
     488        ifNode.AddSubtree(falseBranch);
    489489        return ifNode;
    490490      }
     
    497497      } else {
    498498        var sineNode = sineSymbol.CreateTreeNode();
    499         sineNode.AddSubTree(node);
     499        sineNode.AddSubtree(node);
    500500        return sineNode;
    501501      }
     
    507507      } else {
    508508        var tanNode = tanSymbol.CreateTreeNode();
    509         tanNode.AddSubTree(node);
     509        tanNode.AddSubtree(node);
    510510        return tanNode;
    511511      }
     
    517517      } else {
    518518        var cosNode = cosineSymbol.CreateTreeNode();
    519         cosNode.AddSubTree(node);
     519        cosNode.AddSubtree(node);
    520520        return cosNode;
    521521      }
     
    526526        return MakeConstant(Math.Exp(constT.Value));
    527527      } else if (IsLog(node)) {
    528         return node.GetSubTree(0);
     528        return node.GetSubtree(0);
    529529      } else if (IsAddition(node)) {
    530         return node.SubTrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));
     530        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));
    531531      } else if (IsSubtraction(node)) {
    532         return node.SubTrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));
     532        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));
    533533      } else {
    534534        var expNode = expSymbol.CreateTreeNode();
    535         expNode.AddSubTree(node);
     535        expNode.AddSubtree(node);
    536536        return expNode;
    537537      }
     
    542542        return MakeConstant(Math.Log(constT.Value));
    543543      } else if (IsExp(node)) {
    544         return node.GetSubTree(0);
     544        return node.GetSubtree(0);
    545545      } else if (IsMultiplication(node)) {
    546         return node.SubTrees.Select(s => MakeLog(s)).Aggregate((x, y) => MakeSum(x, y));
     546        return node.Subtrees.Select(s => MakeLog(s)).Aggregate((x, y) => MakeSum(x, y));
    547547      } else if (IsDivision(node)) {
    548548        var subtractionNode = subSymbol.CreateTreeNode();
    549         foreach (var subTree in node.SubTrees) {
    550           subtractionNode.AddSubTree(MakeLog(subTree));
     549        foreach (var subtree in node.Subtrees) {
     550          subtractionNode.AddSubtree(MakeLog(subtree));
    551551        }
    552552        return subtractionNode;
    553553      } else {
    554554        var logNode = logSymbol.CreateTreeNode();
    555         logNode.AddSubTree(node);
     555        logNode.AddSubtree(node);
    556556        return logNode;
    557557      }
     
    573573        } else if (constBValue < 0) {
    574574          var rootNode = rootSymbol.CreateTreeNode();
    575           rootNode.AddSubTree(a);
    576           rootNode.AddSubTree(MakeConstant(-1.0 * constBValue));
     575          rootNode.AddSubtree(a);
     576          rootNode.AddSubtree(MakeConstant(-1.0 * constBValue));
    577577          return MakeFraction(MakeConstant(1.0), rootNode);
    578578        } else {
    579579          var rootNode = rootSymbol.CreateTreeNode();
    580           rootNode.AddSubTree(a);
    581           rootNode.AddSubTree(MakeConstant(constBValue));
     580          rootNode.AddSubtree(a);
     581          rootNode.AddSubtree(MakeConstant(constBValue));
    582582          return rootNode;
    583583        }
    584584      } else {
    585585        var rootNode = rootSymbol.CreateTreeNode();
    586         rootNode.AddSubTree(a);
    587         rootNode.AddSubTree(b);
     586        rootNode.AddSubtree(a);
     587        rootNode.AddSubtree(b);
    588588        return rootNode;
    589589      }
     
    605605        } else if (exponent < 0) {
    606606          var powNode = powSymbol.CreateTreeNode();
    607           powNode.AddSubTree(a);
    608           powNode.AddSubTree(MakeConstant(-1.0 * exponent));
     607          powNode.AddSubtree(a);
     608          powNode.AddSubtree(MakeConstant(-1.0 * exponent));
    609609          return MakeFraction(MakeConstant(1.0), powNode);
    610610        } else {
    611611          var powNode = powSymbol.CreateTreeNode();
    612           powNode.AddSubTree(a);
    613           powNode.AddSubTree(MakeConstant(exponent));
     612          powNode.AddSubtree(a);
     613          powNode.AddSubtree(MakeConstant(exponent));
    614614          return powNode;
    615615        }
    616616      } else {
    617617        var powNode = powSymbol.CreateTreeNode();
    618         powNode.AddSubTree(a);
    619         powNode.AddSubTree(b);
     618        powNode.AddSubtree(a);
     619        powNode.AddSubtree(b);
    620620        return powNode;
    621621      }
     
    641641        return MakeConstant(aVar.Weight / bVar.Weight);
    642642      } else if (IsAddition(a) && IsConstant(b)) {
    643         return a.SubTrees
     643        return a.Subtrees
    644644          .Select(x => GetSimplifiedTree(x))
    645645         .Select(x => MakeFraction(x, b))
     
    649649      } else if (IsDivision(a) && IsConstant(b)) {
    650650        // (a1 / a2) / c => (a1 / (a2 * c))
    651         Trace.Assert(a.SubTrees.Count() == 2);
    652         return MakeFraction(a.GetSubTree(0), MakeProduct(a.GetSubTree(1), b));
     651        Trace.Assert(a.Subtrees.Count() == 2);
     652        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
    653653      } else if (IsDivision(a) && IsDivision(b)) {
    654654        // (a1 / a2) / (b1 / b2) =>
    655         Trace.Assert(a.SubTrees.Count() == 2);
    656         Trace.Assert(b.SubTrees.Count() == 2);
    657         return MakeFraction(MakeProduct(a.GetSubTree(0), b.GetSubTree(1)), MakeProduct(a.GetSubTree(1), b.GetSubTree(0)));
     655        Trace.Assert(a.Subtrees.Count() == 2);
     656        Trace.Assert(b.Subtrees.Count() == 2);
     657        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(1)), MakeProduct(a.GetSubtree(1), b.GetSubtree(0)));
    658658      } else if (IsDivision(a)) {
    659659        // (a1 / a2) / b => (a1 / (a2 * b))
    660         Trace.Assert(a.SubTrees.Count() == 2);
    661         return MakeFraction(a.GetSubTree(0), MakeProduct(a.GetSubTree(1), b));
     660        Trace.Assert(a.Subtrees.Count() == 2);
     661        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
    662662      } else if (IsDivision(b)) {
    663663        // a / (b1 / b2) => (a * b2) / b1
    664         Trace.Assert(b.SubTrees.Count() == 2);
    665         return MakeFraction(MakeProduct(a, b.GetSubTree(1)), b.GetSubTree(0));
     664        Trace.Assert(b.Subtrees.Count() == 2);
     665        return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));
    666666      } else {
    667667        var div = divSymbol.CreateTreeNode();
    668         div.AddSubTree(a);
    669         div.AddSubTree(b);
     668        div.AddSubtree(a);
     669        div.AddSubtree(b);
    670670        return div;
    671671      }
     
    688688        var add = addSymbol.CreateTreeNode();
    689689        // add all sub trees except for the last
    690         for (int i = 0; i < a.SubTrees.Count() - 1; i++) add.AddSubTree(a.GetSubTree(i));
    691         for (int i = 0; i < b.SubTrees.Count() - 1; i++) add.AddSubTree(b.GetSubTree(i));
    692         if (IsConstant(a.SubTrees.Last()) && IsConstant(b.SubTrees.Last())) {
    693           add.AddSubTree(MakeSum(a.SubTrees.Last(), b.SubTrees.Last()));
    694         } else if (IsConstant(a.SubTrees.Last())) {
    695           add.AddSubTree(b.SubTrees.Last());
    696           add.AddSubTree(a.SubTrees.Last());
    697         } else {
    698           add.AddSubTree(a.SubTrees.Last());
    699           add.AddSubTree(b.SubTrees.Last());
     690        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
     691        for (int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i));
     692        if (IsConstant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) {
     693          add.AddSubtree(MakeSum(a.Subtrees.Last(), b.Subtrees.Last()));
     694        } else if (IsConstant(a.Subtrees.Last())) {
     695          add.AddSubtree(b.Subtrees.Last());
     696          add.AddSubtree(a.Subtrees.Last());
     697        } else {
     698          add.AddSubtree(a.Subtrees.Last());
     699          add.AddSubtree(b.Subtrees.Last());
    700700        }
    701701        MergeVariablesInSum(add);
    702         if (add.SubTrees.Count() == 1) {
    703           return add.GetSubTree(0);
     702        if (add.Subtrees.Count() == 1) {
     703          return add.GetSubtree(0);
    704704        } else {
    705705          return add;
     
    711711        var add = addSymbol.CreateTreeNode();
    712712        // add all sub trees except for the last
    713         for (int i = 0; i < a.SubTrees.Count() - 1; i++) add.AddSubTree(a.GetSubTree(i));
    714         if (IsConstant(a.SubTrees.Last()))
    715           add.AddSubTree(MakeSum(a.SubTrees.Last(), b));
     713        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
     714        if (IsConstant(a.Subtrees.Last()))
     715          add.AddSubtree(MakeSum(a.Subtrees.Last(), b));
    716716        else {
    717           add.AddSubTree(a.SubTrees.Last());
    718           add.AddSubTree(b);
     717          add.AddSubtree(a.Subtrees.Last());
     718          add.AddSubtree(b);
    719719        }
    720720        return add;
     
    722722        // a is already an addition => append b
    723723        var add = addSymbol.CreateTreeNode();
    724         add.AddSubTree(b);
    725         foreach (var subTree in a.SubTrees) {
    726           add.AddSubTree(subTree);
     724        add.AddSubtree(b);
     725        foreach (var subtree in a.Subtrees) {
     726          add.AddSubtree(subtree);
    727727        }
    728728        MergeVariablesInSum(add);
    729         if (add.SubTrees.Count() == 1) {
    730           return add.GetSubTree(0);
     729        if (add.Subtrees.Count() == 1) {
     730          return add.GetSubtree(0);
    731731        } else {
    732732          return add;
     
    734734      } else {
    735735        var add = addSymbol.CreateTreeNode();
    736         add.AddSubTree(a);
    737         add.AddSubTree(b);
     736        add.AddSubtree(a);
     737        add.AddSubtree(b);
    738738        MergeVariablesInSum(add);
    739         if (add.SubTrees.Count() == 1) {
    740           return add.GetSubTree(0);
     739        if (add.Subtrees.Count() == 1) {
     740          return add.GetSubtree(0);
    741741        } else {
    742742          return add;
     
    748748    // possible improvement: combine sums of products where the products only reference the same variable
    749749    private void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) {
    750       var subtrees = new List<ISymbolicExpressionTreeNode>(sum.SubTrees);
    751       while (sum.SubTrees.Count() > 0) sum.RemoveSubTree(0);
     750      var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees);
     751      while (sum.Subtrees.Count() > 0) sum.RemoveSubtree(0);
    752752      var groupedVarNodes = from node in subtrees.OfType<VariableTreeNode>()
    753753                            let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
    754754                            group node by node.VariableName + lag into g
    755755                            select g;
    756       var unchangedSubTrees = subtrees.Where(t => !(t is VariableTreeNode));
     756      var unchangedSubtrees = subtrees.Where(t => !(t is VariableTreeNode));
    757757
    758758      foreach (var variableNodeGroup in groupedVarNodes) {
     
    760760        var representative = variableNodeGroup.First();
    761761        representative.Weight = weightSum;
    762         sum.AddSubTree(representative);
    763       }
    764       foreach (var unchangedSubtree in unchangedSubTrees)
    765         sum.AddSubTree(unchangedSubtree);
     762        sum.AddSubtree(representative);
     763      }
     764      foreach (var unchangedSubtree in unchangedSubtrees)
     765        sum.AddSubtree(unchangedSubtree);
    766766    }
    767767
     
    784784      } else if (IsConstant(b) && IsAddition(a)) {
    785785        // multiply constants into additions
    786         return a.SubTrees.Select(x => MakeProduct(x, b)).Aggregate((c, d) => MakeSum(c, d));
     786        return a.Subtrees.Select(x => MakeProduct(x, b)).Aggregate((c, d) => MakeSum(c, d));
    787787      } else if (IsDivision(a) && IsDivision(b)) {
    788788        // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2)
    789         Trace.Assert(a.SubTrees.Count() == 2);
    790         Trace.Assert(b.SubTrees.Count() == 2);
    791         return MakeFraction(MakeProduct(a.GetSubTree(0), b.GetSubTree(0)), MakeProduct(a.GetSubTree(1), b.GetSubTree(1)));
     789        Trace.Assert(a.Subtrees.Count() == 2);
     790        Trace.Assert(b.Subtrees.Count() == 2);
     791        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1)));
    792792      } else if (IsDivision(a)) {
    793793        // (a1 / a2) * b => (a1 * b) / a2
    794         Trace.Assert(a.SubTrees.Count() == 2);
    795         return MakeFraction(MakeProduct(a.GetSubTree(0), b), a.GetSubTree(1));
     794        Trace.Assert(a.Subtrees.Count() == 2);
     795        return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
    796796      } else if (IsDivision(b)) {
    797797        // a * (b1 / b2) => (b1 * a) / b2
    798         Trace.Assert(b.SubTrees.Count() == 2);
    799         return MakeFraction(MakeProduct(b.GetSubTree(0), a), b.GetSubTree(1));
     798        Trace.Assert(b.Subtrees.Count() == 2);
     799        return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1));
    800800      } else if (IsMultiplication(a) && IsMultiplication(b)) {
    801801        // merge multiplications (make sure constants are merged)
    802802        var mul = mulSymbol.CreateTreeNode();
    803         for (int i = 0; i < a.SubTrees.Count(); i++) mul.AddSubTree(a.GetSubTree(i));
    804         for (int i = 0; i < b.SubTrees.Count(); i++) mul.AddSubTree(b.GetSubTree(i));
     803        for (int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i));
     804        for (int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i));
    805805        MergeVariablesAndConstantsInProduct(mul);
    806806        return mul;
     
    809809      } else if (IsMultiplication(a)) {
    810810        // a is already an multiplication => append b
    811         a.AddSubTree(b);
     811        a.AddSubtree(b);
    812812        MergeVariablesAndConstantsInProduct(a);
    813813        return a;
    814814      } else {
    815815        var mul = mulSymbol.CreateTreeNode();
    816         mul.AddSubTree(a);
    817         mul.AddSubTree(b);
     816        mul.AddSubtree(a);
     817        mul.AddSubtree(b);
    818818        MergeVariablesAndConstantsInProduct(mul);
    819819        return mul;
     
    842842    // helper to combine the constant factors in products and to combine variables (powers of 2, 3...)
    843843    private void MergeVariablesAndConstantsInProduct(ISymbolicExpressionTreeNode prod) {
    844       var subtrees = new List<ISymbolicExpressionTreeNode>(prod.SubTrees);
    845       while (prod.SubTrees.Count() > 0) prod.RemoveSubTree(0);
     844      var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees);
     845      while (prod.Subtrees.Count() > 0) prod.RemoveSubtree(0);
    846846      var groupedVarNodes = from node in subtrees.OfType<VariableTreeNode>()
    847847                            let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
     
    856856                            .Aggregate((c1, c2) => c1 * c2);
    857857
    858       var unchangedSubTrees = from tree in subtrees
     858      var unchangedSubtrees = from tree in subtrees
    859859                              where !(tree is VariableTreeNode)
    860860                              where !(tree is ConstantTreeNode)
     
    867867          var poly = mulSymbol.CreateTreeNode();
    868868          for (int p = 0; p < variableNodeGroup.Count(); p++) {
    869             poly.AddSubTree((ISymbolicExpressionTreeNode)representative.Clone());
     869            poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone());
    870870          }
    871           prod.AddSubTree(poly);
    872         } else {
    873           prod.AddSubTree(representative);
    874         }
    875       }
    876 
    877       foreach (var unchangedSubtree in unchangedSubTrees)
    878         prod.AddSubTree(unchangedSubtree);
     871          prod.AddSubtree(poly);
     872        } else {
     873          prod.AddSubtree(representative);
     874        }
     875      }
     876
     877      foreach (var unchangedSubtree in unchangedSubtrees)
     878        prod.AddSubtree(unchangedSubtree);
    879879
    880880      if (!constantProduct.IsAlmost(1.0)) {
    881         prod.AddSubTree(MakeConstant(constantProduct));
     881        prod.AddSubtree(MakeConstant(constantProduct));
    882882      }
    883883    }
     
    898898      } else if (IsAddition(x)) {
    899899        // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn)       
    900         List<ISymbolicExpressionTreeNode> subTrees = new List<ISymbolicExpressionTreeNode>(x.SubTrees);
    901         while (x.SubTrees.Count() > 0) x.RemoveSubTree(0);
    902         foreach (var subTree in subTrees) {
    903           x.AddSubTree(Negate(subTree));
     900        List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(x.Subtrees);
     901        while (x.Subtrees.Count() > 0) x.RemoveSubtree(0);
     902        foreach (var subtree in subtrees) {
     903          x.AddSubtree(Negate(subtree));
    904904        }
    905905      } else if (IsMultiplication(x) || IsDivision(x)) {
    906906        // x0 * x1 * .. * xn * -1 => x0 * x1 * .. * -xn
    907         x.RemoveSubTree(x.SubTrees.Count() - 1);
    908         x.AddSubTree(Negate(x.SubTrees.Last())); // last is maybe a constant, prefer to negate the constant
     907        x.RemoveSubtree(x.Subtrees.Count() - 1);
     908        x.AddSubtree(Negate(x.Subtrees.Last())); // last is maybe a constant, prefer to negate the constant
    909909      } else {
    910910        // any other function
     
    924924        return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);
    925925      } else if (IsDivision(x)) {
    926         Trace.Assert(x.SubTrees.Count() == 2);
    927         return MakeFraction(x.GetSubTree(1), x.GetSubTree(0));
     926        Trace.Assert(x.Subtrees.Count() == 2);
     927        return MakeFraction(x.GetSubtree(1), x.GetSubtree(0));
    928928      } else {
    929929        // any other function
Note: See TracChangeset for help on using the changeset viewer.