Ignore:
Timestamp:
12/06/18 18:59:09 (12 months ago)
Author:
gkronber
Message:

#2915: added a unit test cases for simplification of new symbols and extended the tree simplifier accordingly.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2915-AbsoluteSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs

    r16240 r16344  
    263263      if (IsConstant(original) || IsVariableBase(original)) {
    264264        return (ISymbolicExpressionTreeNode)original.Clone();
     265      } else if (IsAbsolute(original)) {
     266        return SimplifyAbsolute(original);
    265267      } else if (IsAddition(original)) {
    266268        return SimplifyAddition(original);
     
    771773      } else if (IsSquareRoot(node)) {
    772774        return node.GetSubtree(0);
     775      } else if (IsMultiplication(node)) {
     776        // sqr( x * y ) = sqr(x) * sqr(y)
     777        var mulNode = mulSymbol.CreateTreeNode();
     778        foreach (var subtree in node.Subtrees) {
     779          mulNode.AddSubtree(MakeSquare(subtree));
     780        }
     781        return mulNode;
     782      } else if (IsAbsolute(node)) {
     783        return MakeSquare(node.GetSubtree(0)); // sqr(abs(x)) = sqr(x)
     784      } else if (IsExp(node)) {
     785        return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(2.0))); // sqr(exp(x)) = exp(2x)
     786      } else if (IsCube(node)) {
     787        return MakePower(node.GetSubtree(0), MakeConstant(6));
    773788      } else {
    774789        var sqrNode = sqrSymbol.CreateTreeNode();
     
    790805      } else if (IsCubeRoot(node)) {
    791806        return node.GetSubtree(0); // NOTE: not really accurate because cuberoot(x) with negative x is evaluated to NaN and after this simplification we evaluate as x
     807      } else if (IsExp(node)) {
     808        return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(3)));
     809      } else if (IsSquare(node)) {
     810        return MakePower(node.GetSubtree(0), MakeConstant(6));
    792811      } else {
    793812        var cubeNode = cubeSymbol.CreateTreeNode();
     
    807826        var binFactor = node as BinaryFactorVariableTreeNode;
    808827        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Abs(binFactor.Weight));
     828      } else if (IsSquare(node) || IsExp(node) || IsSquareRoot(node) || IsCubeRoot(node)) {
     829        return node; // abs(sqr(x)) = sqr(x), abs(exp(x)) = exp(x) ...
     830      } else if (IsMultiplication(node)) {
     831        var mul = mulSymbol.CreateTreeNode();
     832        foreach (var st in node.Subtrees) {
     833          mul.AddSubtree(MakeAbs(st));
     834        }
     835        return mul;
     836      } else if (IsDivision(node)) {
     837        var div = divSymbol.CreateTreeNode();
     838        foreach (var st in node.Subtrees) {
     839          div.AddSubtree(MakeAbs(st));
     840        }
     841        return div;
    809842      } else {
    810843        var absNode = absSymbol.CreateTreeNode();
     
    815848
    816849    // constant folding only
    817     private static ISymbolicExpressionTreeNode MakeAnalyticalQuotient(ISymbolicExpressionTreeNode x1, ISymbolicExpressionTreeNode x2) {
    818       if (IsConstant(x2)) {
    819         var c = x2 as ConstantTreeNode;
    820         return MakeFraction(x1, MakeConstant(Math.Sqrt(1.0 + c.Value*c.Value)));
    821       } else if (IsFactor(x2)) {
    822         var factNode = x2 as FactorVariableTreeNode;
    823         return MakeFraction(x1, MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(1.0 + w * w))));
    824       } else if (IsBinFactor(x2)) {
    825         var binFactor = x2 as BinaryFactorVariableTreeNode;
    826         return MakeFraction(x1, MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(1.0 + binFactor.Weight * binFactor.Weight)));
     850    private static ISymbolicExpressionTreeNode MakeAnalyticalQuotient(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
     851      if (IsConstant(b)) {
     852        var c = b as ConstantTreeNode;
     853        return MakeFraction(a, MakeConstant(Math.Sqrt(1.0 + c.Value * c.Value)));
     854      } else if (IsFactor(b)) {
     855        var factNode = b as FactorVariableTreeNode;
     856        return MakeFraction(a, MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(1.0 + w * w))));
     857      } else if (IsBinFactor(b)) {
     858        var binFactor = b as BinaryFactorVariableTreeNode;
     859        return MakeFraction(a, MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(1.0 + binFactor.Weight * binFactor.Weight)));
    827860      } else {
    828861        var aqNode = aqSymbol.CreateTreeNode();
    829         aqNode.AddSubtree(x1);
    830         aqNode.AddSubtree(x2);
     862        aqNode.AddSubtree(a);
     863        aqNode.AddSubtree(b);
    831864        return aqNode;
    832865      }
     
    10421075        // a / (b1 / b2) => (a * b2) / b1
    10431076        return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));
     1077      } else if (IsAnalyticalQuotient(a)) {
     1078        return MakeAnalyticalQuotient(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
    10441079      } else {
    10451080        var div = divSymbol.CreateTreeNode();
     
    12701305        MergeVariablesAndConstantsInProduct(a);
    12711306        return a;
     1307      } else if (IsAbsolute(a) && IsAbsolute(b)) {
     1308        return MakeAbs(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)));
     1309      } else if (IsAbsolute(a) && IsConstant(b)) {
     1310        var constNode = b as ConstantTreeNode;
     1311        var posF = Math.Abs(constNode.Value);
     1312        if (constNode.Value > 0) {
     1313          return MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF)));
     1314        } else {
     1315          var mul = mulSymbol.CreateTreeNode();
     1316          mul.AddSubtree(MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF))));
     1317          mul.AddSubtree(MakeConstant(-1.0));
     1318          return mul;
     1319        }
     1320      } else if (IsAnalyticalQuotient(a)) {
     1321        return MakeAnalyticalQuotient(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
    12721322      } else {
    12731323        var mul = mulSymbol.CreateTreeNode();
Note: See TracChangeset for help on using the changeset viewer.