- Timestamp:
- 12/08/18 08:11:48 (6 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/2915-AbsoluteSymbol (added) merged: 15943-15944,16236-16240,16304,16306,16332,16344-16352,16355 /branches/2937_SymReg_AnalyticalQuotient (added) merged: 16083
- Property svn:mergeinfo changed
-
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs
r16206 r16356 37 37 private static readonly Division divSymbol = new Division(); 38 38 private static readonly Constant constSymbol = new Constant(); 39 private static readonly Absolute absSymbol = new Absolute(); 39 40 private static readonly Logarithm logSymbol = new Logarithm(); 40 41 private static readonly Exponential expSymbol = new Exponential(); … … 42 43 private static readonly Square sqrSymbol = new Square(); 43 44 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(); 44 48 private static readonly Power powSymbol = new Power(); 45 49 private static readonly Sine sineSymbol = new Sine(); … … 131 135 } 132 136 137 private static bool IsAbsolute(ISymbolicExpressionTreeNode node) { 138 return node.Symbol is Absolute; 139 } 140 133 141 // exponential 134 142 private static bool IsLog(ISymbolicExpressionTreeNode node) { … … 152 160 } 153 161 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 154 170 private static bool IsPower(ISymbolicExpressionTreeNode node) { 155 171 return node.Symbol is Power; … … 167 183 private static bool IsTangent(ISymbolicExpressionTreeNode node) { 168 184 return node.Symbol is Tangent; 185 } 186 187 private static bool IsAnalyticalQuotient(ISymbolicExpressionTreeNode node) { 188 return node.Symbol is AnalyticalQuotient; 169 189 } 170 190 … … 243 263 if (IsConstant(original) || IsVariableBase(original)) { 244 264 return (ISymbolicExpressionTreeNode)original.Clone(); 265 } else if (IsAbsolute(original)) { 266 return SimplifyAbsolute(original); 245 267 } else if (IsAddition(original)) { 246 268 return SimplifyAddition(original); … … 261 283 } else if (IsSquareRoot(original)) { 262 284 return SimplifySquareRoot(original); 285 } else if (IsCube(original)) { 286 return SimplifyCube(original); 287 } else if (IsCubeRoot(original)) { 288 return SimplifyCubeRoot(original); 263 289 } else if (IsPower(original)) { 264 290 return SimplifyPower(original); … … 271 297 } else if (IsTangent(original)) { 272 298 return SimplifyTangent(original); 299 } else if (IsAnalyticalQuotient(original)) { 300 return SimplifyAnalyticalQuotient(original); 273 301 } else if (IsIfThenElse(original)) { 274 302 return SimplifyIfThenElse(original); … … 380 408 } 381 409 410 private static ISymbolicExpressionTreeNode SimplifyAbsolute(ISymbolicExpressionTreeNode original) { 411 return MakeAbs(GetSimplifiedTree(original.GetSubtree(0))); 412 } 413 382 414 private static ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) { 383 415 return MakeNot(GetSimplifiedTree(original.GetSubtree(0))); … … 432 464 return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0))); 433 465 } 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 } 434 473 435 474 private static ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) { … … 443 482 private static ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) { 444 483 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))); 445 488 } 446 489 … … 730 773 } else if (IsSquareRoot(node)) { 731 774 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)); 732 788 } else { 733 789 var sqrNode = sqrSymbol.CreateTreeNode(); 734 790 sqrNode.AddSubtree(node); 735 791 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; 736 865 } 737 866 } … … 748 877 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight)); 749 878 } 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 751 880 } else { 752 881 var sqrtNode = sqrtSymbol.CreateTreeNode(); 753 882 sqrtNode.AddSubtree(node); 754 883 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; 755 903 } 756 904 } … … 927 1075 // a / (b1 / b2) => (a * b2) / b1 928 1076 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)); 929 1079 } else { 930 1080 var div = divSymbol.CreateTreeNode(); … … 1155 1305 MergeVariablesAndConstantsInProduct(a); 1156 1306 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)); 1157 1322 } else { 1158 1323 var mul = mulSymbol.CreateTreeNode(); -
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
r15583 r16356 85 85 diff: x => -(Math.Exp(-(x * x)) * Math.Sqrt(Math.Exp(x * x)) * x) / Math.Sqrt(2 * Math.PI)); 86 86 87 private static readonly Func<Term, UnaryFunc> abs = UnaryFunc.Factory( 88 eval: Math.Abs, 89 diff: x => Math.Sign(x) 90 ); 91 87 92 #endregion 88 93 … … 213 218 else return terms.Aggregate((a, b) => new AutoDiff.Product(a, 1.0 / b)); 214 219 } 220 if (node.Symbol is Absolute) { 221 var x1 = ConvertToAutoDiff(node.GetSubtree(0)); 222 return abs(x1); 223 } 224 if (node.Symbol is AnalyticalQuotient) { 225 var x1 = ConvertToAutoDiff(node.GetSubtree(0)); 226 var x2 = ConvertToAutoDiff(node.GetSubtree(1)); 227 return x1 / (TermBuilder.Power(1 + x2 * x2, 0.5)); 228 } 215 229 if (node.Symbol is Logarithm) { 216 230 return AutoDiff.TermBuilder.Log( … … 228 242 return AutoDiff.TermBuilder.Power( 229 243 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); 230 252 } 231 253 if (node.Symbol is Sine) { … … 301 323 !(n.Symbol is Erf) && 302 324 !(n.Symbol is Norm) && 303 !(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) 304 330 select n).Any(); 305 331 return !containsUnknownSymbol;
Note: See TracChangeset
for help on using the changeset viewer.