Changeset 17434 for branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters
- Timestamp:
- 02/11/20 13:36:02 (5 years ago)
- Location:
- branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic
- Files:
-
- 4 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs
r16130 r17434 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-2018Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 38 38 double @const = 0) { 39 39 40 if (factorCoefficients.Length == 0 && coefficients.Length == 0) throw new ArgumentException(); 40 if (factorCoefficients.Length == 0 && coefficients.Length == 0 && @const==0) throw new ArgumentException(); 41 42 // Combine both trees 43 ISymbolicExpressionTreeNode add = (new Addition()).CreateTreeNode(); 41 44 42 45 // Create tree for double variables 43 ISymbolicExpressionTree tree = null;44 46 if (coefficients.Length > 0) { 45 tree = CreateTree(variableNames, new int[variableNames.Length], coefficients, @const); 46 if (factorCoefficients.Length == 0) return tree; 47 var varTree = CreateTree(variableNames, new int[variableNames.Length], coefficients); 48 foreach (var varNode in varTree.IterateNodesPrefix().OfType<VariableTreeNode>()) 49 add.AddSubtree(varNode); 47 50 } 48 51 49 52 // Create tree for string variables 50 ISymbolicExpressionTree factorTree = null;51 53 if (factorCoefficients.Length > 0) { 52 factorTree = CreateTree(factors, factorCoefficients, @const); 53 if (tree == null) return factorTree; 54 var factorTree = CreateTree(factors, factorCoefficients); 55 foreach (var binFactorNode in factorTree.IterateNodesPrefix().OfType<BinaryFactorVariableTreeNode>()) 56 add.AddSubtree(binFactorNode); 54 57 } 55 58 56 // Combine both trees 57 ISymbolicExpressionTreeNode add = tree.Root.GetSubtree(0).GetSubtree(0); 58 foreach (var binFactorNode in factorTree.IterateNodesPrefix().OfType<BinaryFactorVariableTreeNode>()) 59 add.InsertSubtree(add.SubtreeCount - 1, binFactorNode); 59 if (@const!=0.0) { 60 ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode(); 61 cNode.Value = @const; 62 add.AddSubtree(cNode); 63 } 64 65 ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode()); 66 ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode(); 67 tree.Root.AddSubtree(startNode); 68 startNode.AddSubtree(add); 60 69 return tree; 61 62 throw new ArgumentException();63 70 } 64 71 -
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs
r16130 r17434 2 2 3 3 /* HeuristicLab 4 * Copyright (C) 2002-2018Heuristic and Evolutionary Algorithms Laboratory (HEAL)4 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 5 5 * 6 6 * This file is part of HeuristicLab. … … 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 AnalyticQuotient aqSymbol = new AnalyticQuotient(); 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 AnalyticQuotient; 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(); … … 1121 1271 // $ * 1.0 => $ 1122 1272 return a; 1273 } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) { 1274 return MakeConstant(0); 1123 1275 } else if (IsConstant(b) && IsVariableBase(a)) { 1124 1276 // multiply constants into variables weights … … 1153 1305 MergeVariablesAndConstantsInProduct(a); 1154 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)); 1155 1322 } else { 1156 1323 var mul = mulSymbol.CreateTreeNode(); -
branches/1772_HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
r16130 r17434 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-2018Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 76 76 eval: Math.Tan, 77 77 diff: x => 1 + Math.Tan(x) * Math.Tan(x)); 78 78 private static readonly Func<Term, UnaryFunc> tanh = UnaryFunc.Factory( 79 eval: Math.Tanh, 80 diff: x => 1 - Math.Tanh(x) * Math.Tanh(x)); 79 81 private static readonly Func<Term, UnaryFunc> erf = UnaryFunc.Factory( 80 82 eval: alglib.errorfunction, … … 84 86 eval: alglib.normaldistribution, 85 87 diff: x => -(Math.Exp(-(x * x)) * Math.Sqrt(Math.Exp(x * x)) * x) / Math.Sqrt(2 * Math.PI)); 88 89 private static readonly Func<Term, UnaryFunc> abs = UnaryFunc.Factory( 90 eval: Math.Abs, 91 diff: x => Math.Sign(x) 92 ); 93 94 private static readonly Func<Term, UnaryFunc> cbrt = UnaryFunc.Factory( 95 eval: x => x < 0 ? -Math.Pow(-x, 1.0 / 3) : Math.Pow(x, 1.0 / 3), 96 diff: x => { var cbrt_x = x < 0 ? -Math.Pow(-x, 1.0 / 3) : Math.Pow(x, 1.0 / 3); return 1.0 / (3 * cbrt_x * cbrt_x); } 97 ); 98 99 86 100 87 101 #endregion … … 213 227 else return terms.Aggregate((a, b) => new AutoDiff.Product(a, 1.0 / b)); 214 228 } 229 if (node.Symbol is Absolute) { 230 var x1 = ConvertToAutoDiff(node.GetSubtree(0)); 231 return abs(x1); 232 } 233 if (node.Symbol is AnalyticQuotient) { 234 var x1 = ConvertToAutoDiff(node.GetSubtree(0)); 235 var x2 = ConvertToAutoDiff(node.GetSubtree(1)); 236 return x1 / (TermBuilder.Power(1 + x2 * x2, 0.5)); 237 } 215 238 if (node.Symbol is Logarithm) { 216 239 return AutoDiff.TermBuilder.Log( … … 229 252 ConvertToAutoDiff(node.GetSubtree(0)), 0.5); 230 253 } 254 if (node.Symbol is Cube) { 255 return AutoDiff.TermBuilder.Power( 256 ConvertToAutoDiff(node.GetSubtree(0)), 3.0); 257 } 258 if (node.Symbol is CubeRoot) { 259 return cbrt(ConvertToAutoDiff(node.GetSubtree(0))); 260 } 231 261 if (node.Symbol is Sine) { 232 262 return sin( … … 239 269 if (node.Symbol is Tangent) { 240 270 return tan( 271 ConvertToAutoDiff(node.GetSubtree(0))); 272 } 273 if (node.Symbol is HyperbolicTangent) { 274 return tanh( 241 275 ConvertToAutoDiff(node.GetSubtree(0))); 242 276 } … … 299 333 !(n.Symbol is Cosine) && 300 334 !(n.Symbol is Tangent) && 335 !(n.Symbol is HyperbolicTangent) && 301 336 !(n.Symbol is Erf) && 302 337 !(n.Symbol is Norm) && 303 !(n.Symbol is StartSymbol) 338 !(n.Symbol is StartSymbol) && 339 !(n.Symbol is Absolute) && 340 !(n.Symbol is AnalyticQuotient) && 341 !(n.Symbol is Cube) && 342 !(n.Symbol is CubeRoot) 304 343 select n).Any(); 305 344 return !containsUnknownSymbol;
Note: See TracChangeset
for help on using the changeset viewer.