Changeset 16239


Ignore:
Timestamp:
10/18/18 16:07:20 (3 years ago)
Author:
gkronber
Message:

#2915 added support for abs(x), cube(x), cuberoot(x), and aq(x) to:

  • formatters,
  • infix parser
  • constant opt (autodiff)
  • simplifier (incomplete)
Location:
branches/2915-AbsoluteSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4
Files:
5 edited

Legend:

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

    r15583 r16239  
    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 AnalyticalQuotient aqSymbol = new AnalyticalQuotient();
     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 AnalyticalQuotient;
    169189    }
    170190
     
    261281      } else if (IsSquareRoot(original)) {
    262282        return SimplifySquareRoot(original);
     283      } else if (IsCube(original)) {
     284        return SimplifyCube(original);
     285      } else if (IsCubeRoot(original)) {
     286        return SimplifyCubeRoot(original);
    263287      } else if (IsPower(original)) {
    264288        return SimplifyPower(original);
     
    271295      } else if (IsTangent(original)) {
    272296        return SimplifyTangent(original);
     297      } else if (IsAnalyticalQuotient(original)) {
     298        return SimplifyAnalyticalQuotient(original);
    273299      } else if (IsIfThenElse(original)) {
    274300        return SimplifyIfThenElse(original);
     
    380406    }
    381407
     408    private static ISymbolicExpressionTreeNode SimplifyAbsolute(ISymbolicExpressionTreeNode original) {
     409      return MakeAbs(GetSimplifiedTree(original.GetSubtree(0)));
     410    }
     411
    382412    private static ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) {
    383413      return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
     
    432462      return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
    433463    }
     464    private static ISymbolicExpressionTreeNode SimplifyCube(ISymbolicExpressionTreeNode original) {
     465      return MakeCube(GetSimplifiedTree(original.GetSubtree(0)));
     466    }
     467
     468    private static ISymbolicExpressionTreeNode SimplifyCubeRoot(ISymbolicExpressionTreeNode original) {
     469      return MakeCubeRoot(GetSimplifiedTree(original.GetSubtree(0)));
     470    }
    434471
    435472    private static ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) {
     
    443480    private static ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) {
    444481      return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
     482    }
     483
     484    private static ISymbolicExpressionTreeNode SimplifyAnalyticalQuotient(ISymbolicExpressionTreeNode original) {
     485      return MakeAnalyticalQuotient(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    445486    }
    446487
     
    737778    }
    738779
     780    private static ISymbolicExpressionTreeNode MakeCube(ISymbolicExpressionTreeNode node) {
     781      if (IsConstant(node)) {
     782        var constT = node as ConstantTreeNode;
     783        return MakeConstant(constT.Value * constT.Value * constT.Value);
     784      } else if (IsFactor(node)) {
     785        var factNode = node as FactorVariableTreeNode;
     786        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w * w));
     787      } else if (IsBinFactor(node)) {
     788        var binFactor = node as BinaryFactorVariableTreeNode;
     789        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight * binFactor.Weight);
     790      } else if (IsCubeRoot(node)) {
     791        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
     792      } else {
     793        var cubeNode = cubeSymbol.CreateTreeNode();
     794        cubeNode.AddSubtree(node);
     795        return cubeNode;
     796      }
     797    }
     798
     799    private static ISymbolicExpressionTreeNode MakeAbs(ISymbolicExpressionTreeNode node) {
     800      if (IsConstant(node)) {
     801        var constT = node as ConstantTreeNode;
     802        return MakeConstant(Math.Abs(constT.Value));
     803      } else if (IsFactor(node)) {
     804        var factNode = node as FactorVariableTreeNode;
     805        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Abs(w)));
     806      } else if (IsBinFactor(node)) {
     807        var binFactor = node as BinaryFactorVariableTreeNode;
     808        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Abs(binFactor.Weight));
     809      } else {
     810        var absNode = absSymbol.CreateTreeNode();
     811        absNode.AddSubtree(node);
     812        return absNode;
     813      }
     814    }
     815
     816    // 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)));
     827      } else {
     828        var aqNode = aqSymbol.CreateTreeNode();
     829        aqNode.AddSubtree(x1);
     830        aqNode.AddSubtree(x2);
     831        return aqNode;
     832      }
     833    }
     834
    739835    private static ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) {
    740836      if (IsConstant(node)) {
     
    748844        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
    749845      } else if (IsSquare(node)) {
    750         return node.GetSubtree(0);
     846        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
    751847      } else {
    752848        var sqrtNode = sqrtSymbol.CreateTreeNode();
    753849        sqrtNode.AddSubtree(node);
    754850        return sqrtNode;
     851      }
     852    }
     853
     854    private static ISymbolicExpressionTreeNode MakeCubeRoot(ISymbolicExpressionTreeNode node) {
     855      if (IsConstant(node)) {
     856        var constT = node as ConstantTreeNode;
     857        return MakeConstant(Math.Pow(constT.Value, 1.0 / 3.0));
     858      } else if (IsFactor(node)) {
     859        var factNode = node as FactorVariableTreeNode;
     860        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, 1.0 / 3.0)));
     861      } else if (IsBinFactor(node)) {
     862        var binFactor = node as BinaryFactorVariableTreeNode;
     863        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(Math.Pow(binFactor.Weight, 1.0 / 3.0)));
     864      } else if (IsCube(node)) {
     865        return node.GetSubtree(0);
     866      } else {
     867        var cubeRootNode = cubeRootSymbol.CreateTreeNode();
     868        cubeRootNode.AddSubtree(node);
     869        return cubeRootNode;
    755870      }
    756871    }
  • branches/2915-AbsoluteSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs

    r16236 r16239  
    8585      diff: x => -(Math.Exp(-(x * x)) * Math.Sqrt(Math.Exp(x * x)) * x) / Math.Sqrt(2 * Math.PI));
    8686
     87    private static readonly Func<Term, UnaryFunc> abs = UnaryFunc.Factory(
     88      eval: Math.Abs,
     89      diff: x => Math.Sign(x)
     90      );
     91
    8792    #endregion
    8893
     
    213218        else return terms.Aggregate((a, b) => new AutoDiff.Product(a, 1.0 / b));
    214219      }
    215       if(node.Symbol is AnalyticalQuotient) {
     220      if (node.Symbol is Absolute) {
     221        var x1 = ConvertToAutoDiff(node.GetSubtree(0));
     222        return abs(x1);
     223      }
     224      if (node.Symbol is AnalyticalQuotient) {
    216225        var x1 = ConvertToAutoDiff(node.GetSubtree(0));
    217226        var x2 = ConvertToAutoDiff(node.GetSubtree(1));
     
    233242        return AutoDiff.TermBuilder.Power(
    234243          ConvertToAutoDiff(node.GetSubtree(0)), 0.5);
     244      }
     245      if (node.Symbol is Cube) {
     246        return AutoDiff.TermBuilder.Power(
     247          ConvertToAutoDiff(node.GetSubtree(0)), 3.0);
     248      }
     249      if (node.Symbol is CubeRoot) {
     250        return AutoDiff.TermBuilder.Power(
     251          ConvertToAutoDiff(node.GetSubtree(0)), 1.0/3.0);
    235252      }
    236253      if (node.Symbol is Sine) {
     
    306323          !(n.Symbol is Erf) &&
    307324          !(n.Symbol is Norm) &&
    308           !(n.Symbol is StartSymbol)
     325          !(n.Symbol is StartSymbol) &&
     326          !(n.Symbol is Absolute) &&
     327          !(n.Symbol is AnalyticalQuotient) &&
     328          !(n.Symbol is Cube) &&
     329          !(n.Symbol is CubeRoot)
    309330        select n).Any();
    310331      return !containsUnknownSymbol;
  • branches/2915-AbsoluteSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs

    r15944 r16239  
    102102        { "SQR", new Square() },
    103103        { "SQRT", new SquareRoot() },
     104        { "CUBE", new Cube() },
     105        { "CUBEROOT", new CubeRoot() },
    104106        { "SIN",new Sine()},
    105107        { "COS", new Cosine()},
     
    120122        { "DAWSON", new Dawson()},
    121123        { "EXPINT", new ExponentialIntegralEi()},
     124        { "AQ", new AnalyticalQuotient() },
    122125        { "MEAN", new Average()},
    123126        { "IF", new IfThenElse()},
  • branches/2915-AbsoluteSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs

    r15583 r16239  
    4141        {"*", new Multiplication()},
    4242        {"-", new Subtraction()},
     43        {"ABS", new Absolute() },
    4344        {"EXP", new Exponential()},
    4445        {"LOG", new Logarithm()},
     
    4748        {"SQR", new Square()},
    4849        {"SQRT", new SquareRoot()},
     50        {"CUBE", new Cube()},
     51        {"CUBEROOT", new CubeRoot()},
    4952        {"SIN",new Sine()},
    5053        {"COS", new Cosine()},
     
    6568        {"DAWSON", new Dawson()},
    6669        {"EXPINT", new ExponentialIntegralEi()},
     70        {"AQ", new AnalyticalQuotient() },
    6771        {"MEAN", new Average()},
    6872        {"IF", new IfThenElse()},
  • branches/2915-AbsoluteSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs

    r16238 r16239  
    233233        } else if (instr.opCode == OpCodes.Tan) {
    234234          instr.value = Math.Tan(code[instr.childIndex].value);
    235         } else if(instr.opCode == OpCodes.Square) {
     235        } else if (instr.opCode == OpCodes.Square) {
    236236          instr.value = Math.Pow(code[instr.childIndex].value, 2);
    237         } else if(instr.opCode == OpCodes.Cube) {
     237        } else if (instr.opCode == OpCodes.Cube) {
    238238          instr.value = Math.Pow(code[instr.childIndex].value, 3);
    239239        } else if (instr.opCode == OpCodes.Power) {
     
    241241          double y = Math.Round(code[instr.childIndex + 1].value);
    242242          instr.value = Math.Pow(x, y);
    243         } else if(instr.opCode == OpCodes.SquareRoot) {
     243        } else if (instr.opCode == OpCodes.SquareRoot) {
    244244          instr.value = Math.Sqrt(code[instr.childIndex].value);
    245         } else if(instr.opCode == OpCodes.CubeRoot) {
     245        } else if (instr.opCode == OpCodes.CubeRoot) {
    246246          instr.value = Math.Pow(code[instr.childIndex].value, 1.0 / 3.0);
    247247        } else if (instr.opCode == OpCodes.Root) {
Note: See TracChangeset for help on using the changeset viewer.