Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
02/11/20 13:36:02 (4 years ago)
Author:
bburlacu
Message:

#1772: Merge trunk changes and fix all errors and compilation warnings.

Location:
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic

  • branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs

    r16130 r17434  
    22
    33/* HeuristicLab
    4  * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     4 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    55 *
    66 * This file is part of HeuristicLab.
     
    3737    private static readonly Division divSymbol = new Division();
    3838    private static readonly Constant constSymbol = new Constant();
     39    private static readonly Absolute absSymbol = new Absolute();
    3940    private static readonly Logarithm logSymbol = new Logarithm();
    4041    private static readonly Exponential expSymbol = new Exponential();
     
    4243    private static readonly Square sqrSymbol = new Square();
    4344    private static readonly SquareRoot sqrtSymbol = new SquareRoot();
     45    private static readonly AnalyticQuotient aqSymbol = new AnalyticQuotient();
     46    private static readonly Cube cubeSymbol = new Cube();
     47    private static readonly CubeRoot cubeRootSymbol = new CubeRoot();
    4448    private static readonly Power powSymbol = new Power();
    4549    private static readonly Sine sineSymbol = new Sine();
     
    131135    }
    132136
     137    private static bool IsAbsolute(ISymbolicExpressionTreeNode node) {
     138      return node.Symbol is Absolute;
     139    }
     140
    133141    // exponential
    134142    private static bool IsLog(ISymbolicExpressionTreeNode node) {
     
    152160    }
    153161
     162    private static bool IsCube(ISymbolicExpressionTreeNode node) {
     163      return node.Symbol is Cube;
     164    }
     165
     166    private static bool IsCubeRoot(ISymbolicExpressionTreeNode node) {
     167      return node.Symbol is CubeRoot;
     168    }
     169
    154170    private static bool IsPower(ISymbolicExpressionTreeNode node) {
    155171      return node.Symbol is Power;
     
    167183    private static bool IsTangent(ISymbolicExpressionTreeNode node) {
    168184      return node.Symbol is Tangent;
     185    }
     186
     187    private static bool IsAnalyticalQuotient(ISymbolicExpressionTreeNode node) {
     188      return node.Symbol is AnalyticQuotient;
    169189    }
    170190
     
    243263      if (IsConstant(original) || IsVariableBase(original)) {
    244264        return (ISymbolicExpressionTreeNode)original.Clone();
     265      } else if (IsAbsolute(original)) {
     266        return SimplifyAbsolute(original);
    245267      } else if (IsAddition(original)) {
    246268        return SimplifyAddition(original);
     
    261283      } else if (IsSquareRoot(original)) {
    262284        return SimplifySquareRoot(original);
     285      } else if (IsCube(original)) {
     286        return SimplifyCube(original);
     287      } else if (IsCubeRoot(original)) {
     288        return SimplifyCubeRoot(original);
    263289      } else if (IsPower(original)) {
    264290        return SimplifyPower(original);
     
    271297      } else if (IsTangent(original)) {
    272298        return SimplifyTangent(original);
     299      } else if (IsAnalyticalQuotient(original)) {
     300        return SimplifyAnalyticalQuotient(original);
    273301      } else if (IsIfThenElse(original)) {
    274302        return SimplifyIfThenElse(original);
     
    380408    }
    381409
     410    private static ISymbolicExpressionTreeNode SimplifyAbsolute(ISymbolicExpressionTreeNode original) {
     411      return MakeAbs(GetSimplifiedTree(original.GetSubtree(0)));
     412    }
     413
    382414    private static ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) {
    383415      return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
     
    432464      return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
    433465    }
     466    private static ISymbolicExpressionTreeNode SimplifyCube(ISymbolicExpressionTreeNode original) {
     467      return MakeCube(GetSimplifiedTree(original.GetSubtree(0)));
     468    }
     469
     470    private static ISymbolicExpressionTreeNode SimplifyCubeRoot(ISymbolicExpressionTreeNode original) {
     471      return MakeCubeRoot(GetSimplifiedTree(original.GetSubtree(0)));
     472    }
    434473
    435474    private static ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) {
     
    443482    private static ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) {
    444483      return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
     484    }
     485
     486    private static ISymbolicExpressionTreeNode SimplifyAnalyticalQuotient(ISymbolicExpressionTreeNode original) {
     487      return MakeAnalyticalQuotient(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    445488    }
    446489
     
    730773      } else if (IsSquareRoot(node)) {
    731774        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));
    732788      } else {
    733789        var sqrNode = sqrSymbol.CreateTreeNode();
    734790        sqrNode.AddSubtree(node);
    735791        return sqrNode;
     792      }
     793    }
     794
     795    private static ISymbolicExpressionTreeNode MakeCube(ISymbolicExpressionTreeNode node) {
     796      if (IsConstant(node)) {
     797        var constT = node as ConstantTreeNode;
     798        return MakeConstant(constT.Value * constT.Value * constT.Value);
     799      } else if (IsFactor(node)) {
     800        var factNode = node as FactorVariableTreeNode;
     801        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w * w));
     802      } else if (IsBinFactor(node)) {
     803        var binFactor = node as BinaryFactorVariableTreeNode;
     804        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight * binFactor.Weight);
     805      } else if (IsCubeRoot(node)) {
     806        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));
     811      } else {
     812        var cubeNode = cubeSymbol.CreateTreeNode();
     813        cubeNode.AddSubtree(node);
     814        return cubeNode;
     815      }
     816    }
     817
     818    private static ISymbolicExpressionTreeNode MakeAbs(ISymbolicExpressionTreeNode node) {
     819      if (IsConstant(node)) {
     820        var constT = node as ConstantTreeNode;
     821        return MakeConstant(Math.Abs(constT.Value));
     822      } else if (IsFactor(node)) {
     823        var factNode = node as FactorVariableTreeNode;
     824        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Abs(w)));
     825      } else if (IsBinFactor(node)) {
     826        var binFactor = node as BinaryFactorVariableTreeNode;
     827        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;
     842      } else {
     843        var absNode = absSymbol.CreateTreeNode();
     844        absNode.AddSubtree(node);
     845        return absNode;
     846      }
     847    }
     848
     849    // constant folding only
     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)));
     860      } else {
     861        var aqNode = aqSymbol.CreateTreeNode();
     862        aqNode.AddSubtree(a);
     863        aqNode.AddSubtree(b);
     864        return aqNode;
    736865      }
    737866    }
     
    748877        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
    749878      } else if (IsSquare(node)) {
    750         return node.GetSubtree(0);
     879        return node.GetSubtree(0); // NOTE: not really accurate because sqrt(x) with negative x is evaluated to NaN and after this simplification we evaluate as x
    751880      } else {
    752881        var sqrtNode = sqrtSymbol.CreateTreeNode();
    753882        sqrtNode.AddSubtree(node);
    754883        return sqrtNode;
     884      }
     885    }
     886
     887    private static ISymbolicExpressionTreeNode MakeCubeRoot(ISymbolicExpressionTreeNode node) {
     888      if (IsConstant(node)) {
     889        var constT = node as ConstantTreeNode;
     890        return MakeConstant(Math.Pow(constT.Value, 1.0 / 3.0));
     891      } else if (IsFactor(node)) {
     892        var factNode = node as FactorVariableTreeNode;
     893        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, 1.0 / 3.0)));
     894      } else if (IsBinFactor(node)) {
     895        var binFactor = node as BinaryFactorVariableTreeNode;
     896        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(Math.Pow(binFactor.Weight, 1.0 / 3.0)));
     897      } else if (IsCube(node)) {
     898        return node.GetSubtree(0);
     899      } else {
     900        var cubeRootNode = cubeRootSymbol.CreateTreeNode();
     901        cubeRootNode.AddSubtree(node);
     902        return cubeRootNode;
    755903      }
    756904    }
     
    9271075        // a / (b1 / b2) => (a * b2) / b1
    9281076        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));
    9291079      } else {
    9301080        var div = divSymbol.CreateTreeNode();
     
    11211271        // $ * 1.0 => $
    11221272        return a;
     1273      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) {
     1274        return MakeConstant(0);
    11231275      } else if (IsConstant(b) && IsVariableBase(a)) {
    11241276        // multiply constants into variables weights
     
    11531305        MergeVariablesAndConstantsInProduct(a);
    11541306        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));
    11551322      } else {
    11561323        var mul = mulSymbol.CreateTreeNode();
Note: See TracChangeset for help on using the changeset viewer.