Changeset 17072 for stable/HeuristicLab.Problems.DataAnalysis.Symbolic
- Timestamp:
- 07/04/19 16:07:49 (5 years ago)
- Location:
- stable
- Files:
-
- 17 edited
- 4 copied
Legend:
- Unmodified
- Added
- Removed
-
stable
- Property svn:mergeinfo changed
-
stable/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs
r17066 r17072 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(); … … 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(); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
r15584 r17072 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 AnalyticQuotient) { 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 AnalyticQuotient) && 328 !(n.Symbol is Cube) && 329 !(n.Symbol is CubeRoot) 304 330 select n).Any(); 305 331 return !containsUnknownSymbol; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs
r15584 r17072 62 62 if (node.SubtreeCount > 1) { 63 63 var token = GetToken(node.Symbol); 64 if (token == "+" || token == "-" || token == "OR" || token == "XOR") { 65 strBuilder.Append("("); 66 FormatRecursively(node.Subtrees.First(), strBuilder); 67 68 foreach (var subtree in node.Subtrees.Skip(1)) { 69 strBuilder.Append(" ").Append(token).Append(" "); 70 FormatRecursively(subtree, strBuilder); 71 } 72 strBuilder.Append(")"); 73 74 } else if (token == "*" || token == "/" || token == "AND") { 64 // operators 65 if (token == "+" || token == "-" || token == "OR" || token == "XOR" || 66 token == "*" || token == "/" || token == "AND" || 67 token == "^") { 75 68 strBuilder.Append("("); 76 69 FormatRecursively(node.Subtrees.First(), strBuilder); … … 184 177 185 178 private string GetToken(ISymbol symbol) { 186 var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol). SingleOrDefault();179 var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).FirstOrDefault(); 187 180 if (tok == null) 188 181 throw new ArgumentException(string.Format("Unknown symbol {0} found.", symbol.Name)); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs
r15584 r17072 48 48 var mul = new Multiplication(); 49 49 var div = new Division(); 50 var aq = new AnalyticQuotient(); 50 51 var mean = new Average(); 51 52 var sin = new Sine(); … … 53 54 var tan = new Tangent(); 54 55 var log = new Logarithm(); 56 var abs = new Absolute(); 55 57 var pow = new Power(); 56 58 pow.InitialFrequency = 0.0; 57 59 var square = new Square(); 58 60 square.InitialFrequency = 0.0; 61 var cube = new Cube(); 62 cube.InitialFrequency = 0.0; 59 63 var root = new Root(); 60 64 root.InitialFrequency = 0.0; 61 65 var sqrt = new SquareRoot(); 62 66 sqrt.InitialFrequency = 0.0; 67 var cubeRoot = new CubeRoot(); 68 cubeRoot.InitialFrequency = 0.0; 63 69 var airyA = new AiryA(); 64 70 airyA.InitialFrequency = 0.0; … … 123 129 autoregressiveVariable.Enabled = false; 124 130 125 var allSymbols = new List<Symbol>() { add, sub, mul, div, mean, sin, cos, tan, log, square, pow, sqrt, root, exp,131 var allSymbols = new List<Symbol>() { add, sub, mul, div, aq, mean, abs, sin, cos, tan, log, square, cube, pow, sqrt, cubeRoot, root, exp, 126 132 airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral, 127 133 @if, gt, lt, and, or, not,xor, timeLag, integral, derivative, constant, variableSymbol, binFactorVariable, factorVariable, laggedVariable,autoregressiveVariable, variableCondition }; 128 var unaryFunctionSymbols = new List<Symbol>() { square, sqrt, sin, cos, tan, log, exp, not, timeLag, integral, derivative,134 var unaryFunctionSymbols = new List<Symbol>() { abs, square, sqrt, cube, cubeRoot, sin, cos, tan, log, exp, not, timeLag, integral, derivative, 129 135 airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral 130 136 }; 131 137 132 var binaryFunctionSymbols = new List<Symbol>() { pow, root, gt, lt, variableCondition };138 var binaryFunctionSymbols = new List<Symbol>() { pow, root, gt, lt, aq, variableCondition }; 133 139 var ternarySymbols = new List<Symbol>() { add, sub, mul, div, mean, and, or, xor }; 134 140 var terminalSymbols = new List<Symbol>() { variableSymbol, binFactorVariable, factorVariable, constant, laggedVariable, autoregressiveVariable }; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs
r15584 r17072 69 69 var root = new Root(); 70 70 var sqrt = new SquareRoot(); 71 var cube = new Cube(); 72 var cubeRoot = new CubeRoot(); 71 73 var exp = new Exponential(); 74 var abs = new Absolute(); 72 75 73 76 var airyA = new AiryA(); … … 86 89 var psi = new Psi(); 87 90 var sineIntegral = new SineIntegral(); 91 var analyticalQuotient = new AnalyticQuotient(); 88 92 89 93 var @if = new IfThenElse(); … … 114 118 var trigonometricSymbols = new GroupSymbol(TrigonometricFunctionsName, new List<ISymbol>() { sin, cos, tan }); 115 119 var exponentialAndLogarithmicSymbols = new GroupSymbol(ExponentialFunctionsName, new List<ISymbol> { exp, log }); 116 var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { a iryA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi,117 fresnelCosineIntegral,fresnelSineIntegral,gamma,hypCosineIntegral,hypSineIntegral,norm, psi, sineIntegral });120 var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { abs, airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, 121 fresnelCosineIntegral,fresnelSineIntegral,gamma,hypCosineIntegral,hypSineIntegral,norm, psi, sineIntegral, analyticalQuotient}); 118 122 var terminalSymbols = new GroupSymbol(TerminalsName, new List<ISymbol> { constant, variableSymbol, binFactorVariable, factorVariable }); 119 123 var realValuedSymbols = new GroupSymbol(RealValuedSymbolsName, new List<ISymbol>() { arithmeticSymbols, trigonometricSymbols, exponentialAndLogarithmicSymbols, specialFunctions, terminalSymbols }); 120 124 121 var powerSymbols = new GroupSymbol(PowerFunctionsName, new List<ISymbol> { square, pow, sqrt, root });125 var powerSymbols = new GroupSymbol(PowerFunctionsName, new List<ISymbol> { square, pow, sqrt, root, cube, cubeRoot }); 122 126 123 127 var conditionSymbols = new GroupSymbol(ConditionsName, new List<ISymbol> { @if, variableCondition }); … … 140 144 SetSubtreeCount(root, 2, 2); 141 145 SetSubtreeCount(square, 1, 1); 146 SetSubtreeCount(cube, 1, 1); 142 147 SetSubtreeCount(sqrt, 1, 1); 148 SetSubtreeCount(cubeRoot, 1, 1); 143 149 SetSubtreeCount(exponentialAndLogarithmicSymbols, 1, 1); 144 SetSubtreeCount(specialFunctions, 1, 1); 150 foreach(var sy in specialFunctions.Symbols.Except(new[] { analyticalQuotient})) { 151 SetSubtreeCount(sy, 1, 1); 152 } 153 SetSubtreeCount(analyticalQuotient, 2, 2); 154 145 155 SetSubtreeCount(terminalSymbols, 0, 0); 146 156 … … 231 241 public void ConfigureAsDefaultRegressionGrammar() { 232 242 Symbols.First(s => s is Average).Enabled = false; 243 Symbols.First(s => s is Absolute).Enabled = false; 233 244 Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false; 234 245 Symbols.First(s => s.Name == PowerFunctionsName).Enabled = false; … … 242 253 Symbols.First(s => s is VariableCondition).Enabled = false; 243 254 Symbols.First(s => s is Xor).Enabled = false; 255 Symbols.First(s => s is Absolute).Enabled = false; 244 256 Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false; 245 257 Symbols.First(s => s.Name == ExponentialFunctionsName).Enabled = false; … … 251 263 public void ConfigureAsDefaultTimeSeriesPrognosisGrammar() { 252 264 Symbols.First(s => s is Average).Enabled = false; 265 Symbols.First(s => s is Absolute).Enabled = false; 253 266 Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false; 254 267 Symbols.First(s => s.Name == PowerFunctionsName).Enabled = false; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
r17071 r17072 209 209 <Compile Include="SymbolicDataAnalysisSolutionImpactValuesCalculator.cs" /> 210 210 <Compile Include="Symbols\Addition.cs" /> 211 <Compile Include="Symbols\AnalyticQuotient.cs" /> 211 212 <Compile Include="Symbols\And.cs" /> 212 213 <Compile Include="Symbols\AutoregressiveVariable.cs" /> … … 219 220 <Compile Include="Symbols\BinaryFactorVariable.cs" /> 220 221 <Compile Include="Symbols\BinaryFactorVariableTreeNode.cs" /> 222 <Compile Include="Symbols\Cube.cs" /> 221 223 <Compile Include="Symbols\FactorVariableTreeNode.cs" /> 222 224 <Compile Include="Symbols\FactorVariable.cs" /> 225 <Compile Include="Symbols\Absolute.cs" /> 226 <Compile Include="Symbols\CubeRoot.cs" /> 223 227 <Compile Include="Symbols\VariableBase.cs" /> 224 228 <Compile Include="Symbols\VariableTreeNodeBase.cs" /> -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
r15584 r17072 42 42 /// Expr = ['-' | '+'] Term { '+' Term | '-' Term } 43 43 /// Term = Fact { '*' Fact | '/' Fact } 44 /// Fact = '(' Expr ')' 45 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 46 /// | funcId '(' ArgList ')' 47 /// | VarExpr | number 44 /// Fact = SimpleFact [ '^' SimpleFact ] 45 /// SimpleFact = '(' Expr ')' 46 /// | '{' Expr '}' 47 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ') 48 /// | funcId '(' ArgList ')' 49 /// | VarExpr 50 /// | number 48 51 /// ArgList = Expr { ',' Expr } 49 52 /// VarExpr = varId OptFactorPart … … 95 98 { "*", new Multiplication()}, 96 99 { "-", new Subtraction()}, 100 { "^", new Power() }, 101 { "ABS", new Absolute() }, 97 102 { "EXP", new Exponential()}, 98 103 { "LOG", new Logarithm()}, 99 { "POW", new Power() },104 { "POW", new Power() }, 100 105 { "ROOT", new Root()}, 101 106 { "SQR", new Square() }, 102 107 { "SQRT", new SquareRoot() }, 108 { "CUBE", new Cube() }, 109 { "CUBEROOT", new CubeRoot() }, 103 110 { "SIN",new Sine()}, 104 111 { "COS", new Cosine()}, … … 119 126 { "DAWSON", new Dawson()}, 120 127 { "EXPINT", new ExponentialIntegralEi()}, 128 { "AQ", new AnalyticQuotient() }, 121 129 { "MEAN", new Average()}, 122 130 { "IF", new IfThenElse()}, … … 167 175 && str[pos] != '*' 168 176 && str[pos] != '/' 177 && str[pos] != '^' 169 178 && str[pos] != ')' 170 179 && str[pos] != ']' 180 && str[pos] != '}' 171 181 && str[pos] != ',') { 172 182 sb.Append(str[pos]); … … 227 237 pos++; 228 238 yield return new Token { TokenType = TokenType.Operator, strVal = "*" }; 239 } else if (str[pos] == '^') { 240 pos++; 241 yield return new Token { TokenType = TokenType.Operator, strVal = "^" }; 229 242 } else if (str[pos] == '(') { 230 243 pos++; … … 239 252 pos++; 240 253 yield return new Token { TokenType = TokenType.RightBracket, strVal = "]" }; 254 } else if (str[pos] == '{') { 255 pos++; 256 yield return new Token { TokenType = TokenType.LeftPar, strVal = "{" }; 257 } else if (str[pos] == '}') { 258 pos++; 259 yield return new Token { TokenType = TokenType.RightPar, strVal = "}" }; 241 260 } else if (str[pos] == '=') { 242 261 pos++; … … 360 379 } 361 380 362 /// Fact = '(' Expr ')' 363 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 364 /// | funcId '(' ArgList ')' 365 /// | VarExpr | number 381 // Fact = SimpleFact ['^' SimpleFact] 382 private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) { 383 var expr = ParseSimpleFact(tokens); 384 var next = tokens.Peek(); 385 if (next.TokenType == TokenType.Operator && next.strVal == "^") { 386 tokens.Dequeue(); // skip; 387 388 var p = GetSymbol("^").CreateTreeNode(); 389 p.AddSubtree(expr); 390 p.AddSubtree(ParseSimpleFact(tokens)); 391 expr = p; 392 } 393 return expr; 394 } 395 396 397 /// SimpleFact = '(' Expr ')' 398 /// | '{' Expr '}' 399 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 400 /// | funcId '(' ArgList ') 401 /// | VarExpr 402 /// | number 366 403 /// ArgList = Expr { ',' Expr } 367 404 /// VarExpr = varId OptFactorPart … … 370 407 /// varVal = ident | ' ident ' | " ident " 371 408 /// ident = '_' | letter { '_' | letter | digit } 372 private ISymbolicExpressionTreeNode Parse Fact(Queue<Token> tokens) {409 private ISymbolicExpressionTreeNode ParseSimpleFact(Queue<Token> tokens) { 373 410 var next = tokens.Peek(); 374 411 if (next.TokenType == TokenType.LeftPar) { 375 tokens.Dequeue();412 var initPar = tokens.Dequeue(); // match par type 376 413 var expr = ParseExpr(tokens); 377 414 var rPar = tokens.Dequeue(); 378 415 if (rPar.TokenType != TokenType.RightPar) 379 throw new ArgumentException("expected )"); 416 throw new ArgumentException("expected closing parenthesis"); 417 if (initPar.strVal == "(" && rPar.strVal == "}") 418 throw new ArgumentException("expected closing )"); 419 if (initPar.strVal == "{" && rPar.strVal == ")") 420 throw new ArgumentException("expected closing }"); 380 421 return expr; 381 422 } else if (next.TokenType == TokenType.Identifier) { … … 424 465 if (rPar.TokenType != TokenType.RightPar) 425 466 throw new ArgumentException("expected )"); 467 426 468 427 469 return funcNode; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs
r15584 r17072 41 41 {"*", new Multiplication()}, 42 42 {"-", new Subtraction()}, 43 {"ABS", new Absolute() }, 43 44 {"EXP", new Exponential()}, 44 45 {"LOG", new Logarithm()}, … … 47 48 {"SQR", new Square()}, 48 49 {"SQRT", new SquareRoot()}, 50 {"CUBE", new Cube()}, 51 {"CUBEROOT", new CubeRoot()}, 49 52 {"SIN",new Sine()}, 50 53 {"COS", new Cosine()}, … … 65 68 {"DAWSON", new Dawson()}, 66 69 {"EXPINT", new ExponentialIntegralEi()}, 70 {"AQ", new AnalyticQuotient() }, 67 71 {"MEAN", new Average()}, 68 72 {"IF", new IfThenElse()}, -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/BatchOperations.cs
r17071 r17072 89 89 a[i] = Math.Sqrt(b[i]); 90 90 } 91 92 public static void Cube(double[] a, double[] b) { 93 for (int i = 0; i < BATCHSIZE; ++i) 94 a[i] = Math.Pow(b[i], 3d); 95 } 96 97 public static void CubeRoot(double[] a, double[] b) { 98 for (int i = 0; i < BATCHSIZE; ++i) 99 a[i] = Math.Pow(b[i], 1d / 3d); 100 } 101 102 public static void Absolute(double[] a, double[] b) { 103 for (int i = 0; i < BATCHSIZE; ++i) 104 a[i] = Math.Abs(b[i]); 105 } 106 107 public static void AnalyticQuotient(double[] a, double[] b) { 108 for (int i = 0; i < BATCHSIZE; ++i) 109 a[i] = a[i] / Math.Sqrt(1d + b[i] * b[i]); 110 } 91 111 } 92 112 } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
r15584 r17072 46 46 public const byte OR = 14; 47 47 public const byte NOT = 15; 48 public const byte XOR = 45;49 48 50 49 … … 83 82 public const byte Erf = 43; 84 83 public const byte Bessel = 44; 84 public const byte XOR = 45; 85 85 public const byte FactorVariable = 46; 86 86 public const byte BinaryFactorVariable = 47; 87 public const byte Absolute = 48; 88 public const byte AnalyticQuotient = 49; 89 public const byte Cube = 50; 90 public const byte CubeRoot = 51; 87 91 88 92 … … 113 117 { typeof(Power),OpCodes.Power}, 114 118 { typeof(Root),OpCodes.Root}, 115 { typeof(TimeLag), OpCodes.TimeLag}, 119 { typeof(TimeLag), OpCodes.TimeLag}, 116 120 { typeof(Integral), OpCodes.Integral}, 117 121 { typeof(Derivative), OpCodes.Derivative}, … … 135 139 { typeof(Bessel), OpCodes.Bessel}, 136 140 { typeof(FactorVariable), OpCodes.FactorVariable }, 137 { typeof(BinaryFactorVariable), OpCodes.BinaryFactorVariable } 141 { typeof(BinaryFactorVariable), OpCodes.BinaryFactorVariable }, 142 { typeof(Absolute), OpCodes.Absolute }, 143 { typeof(AnalyticQuotient), OpCodes.AnalyticQuotient }, 144 { typeof(Cube), OpCodes.Cube }, 145 { typeof(CubeRoot), OpCodes.CubeRoot } 138 146 }; 139 147 -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs
r15584 r17072 41 41 42 42 #region method info for the commonly called functions 43 private static readonly MethodInfo Abs = typeof(Math).GetMethod("Abs", new[] { typeof(double) }); 43 44 private static readonly MethodInfo Sin = typeof(Math).GetMethod("Sin", new[] { typeof(double) }); 44 45 private static readonly MethodInfo Cos = typeof(Math).GetMethod("Cos", new[] { typeof(double) }); … … 207 208 return Expression.Divide(result, Expression.Constant((double)node.SubtreeCount)); 208 209 } 210 case OpCodes.Absolute: { 211 var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns); 212 return Expression.Call(Abs, arg); 213 } 209 214 case OpCodes.Cos: { 210 215 var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns); … … 222 227 var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns); 223 228 return Expression.Power(arg, Expression.Constant(2.0)); 229 } 230 case OpCodes.Cube: { 231 var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns); 232 return Expression.Power(arg, Expression.Constant(3.0)); 224 233 } 225 234 case OpCodes.Power: { … … 231 240 var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns); 232 241 return Expression.Call(Sqrt, arg); 242 } 243 case OpCodes.CubeRoot: { 244 var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns); 245 return Expression.Power(arg, Expression.Constant(1.0 / 3.0)); 233 246 } 234 247 case OpCodes.Root: { … … 493 506 Expression.Assign(result, Expression.Call(Bessel, arg))), 494 507 result); 508 } 509 case OpCodes.AnalyticQuotient: { 510 var x1 = MakeExpr(node.GetSubtree(0), variableIndices, row, columns); 511 var x2 = MakeExpr(node.GetSubtree(1), variableIndices, row, columns); 512 return Expression.Divide(x1, 513 Expression.Call(Sqrt, 514 Expression.Add( 515 Expression.Constant(1.0), 516 Expression.Multiply(x2, x2)))); 495 517 } 496 518 case OpCodes.IfThenElse: { -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs
r17071 r17072 111 111 112 112 case OpCodes.Root: { 113 Root(instr.buf, code[c].buf); 113 Load(instr.buf, code[c].buf); 114 Root(instr.buf, code[c + 1].buf); 114 115 break; 115 116 } … … 120 121 } 121 122 123 case OpCodes.Cube: { 124 Cube(instr.buf, code[c].buf); 125 break; 126 } 127 case OpCodes.CubeRoot: { 128 CubeRoot(instr.buf, code[c].buf); 129 break; 130 } 131 122 132 case OpCodes.Power: { 123 Pow(instr.buf, code[c].buf); 133 Load(instr.buf, code[c].buf); 134 Pow(instr.buf, code[c + 1].buf); 124 135 break; 125 136 } … … 147 158 case OpCodes.Tan: { 148 159 Tan(instr.buf, code[c].buf); 160 break; 161 } 162 163 case OpCodes.Absolute: { 164 Absolute(instr.buf, code[c].buf); 165 break; 166 } 167 168 case OpCodes.AnalyticQuotient: { 169 Load(instr.buf, code[c].buf); 170 AnalyticQuotient(instr.buf, code[c + 1].buf); 149 171 break; 150 172 } … … 172 194 var remainingRows = rows.Length % BATCHSIZE; 173 195 var roundedTotal = rows.Length - remainingRows; 196 197 // TODO: evaluated solutions are not counted 174 198 175 199 var result = new double[rows.Length]; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
r15584 r17072 50 50 private static MethodInfo round = typeof(Math).GetMethod("Round", new Type[] { typeof(double) }); 51 51 private static MethodInfo sqrt = typeof(Math).GetMethod("Sqrt", new Type[] { typeof(double) }); 52 private static MethodInfo abs = typeof(Math).GetMethod("Abs", new Type[] { typeof(double) }); 52 53 53 54 private static MethodInfo airyA = thisType.GetMethod("AiryA", new Type[] { typeof(double) }); … … 264 265 return; 265 266 } 267 case OpCodes.Absolute: { 268 CompileInstructions(il, state, ds); 269 il.Emit(System.Reflection.Emit.OpCodes.Call, abs); 270 return; 271 } 266 272 case OpCodes.Cos: { 267 273 CompileInstructions(il, state, ds); … … 311 317 return; 312 318 } 319 case OpCodes.Cube: { 320 CompileInstructions(il, state, ds); 321 il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 3.0); 322 il.Emit(System.Reflection.Emit.OpCodes.Call, power); 323 return; 324 } 313 325 case OpCodes.SquareRoot: { 314 326 CompileInstructions(il, state, ds); … … 316 328 return; 317 329 } 330 case OpCodes.CubeRoot: { 331 CompileInstructions(il, state, ds); 332 il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0 / 3.0); 333 il.Emit(System.Reflection.Emit.OpCodes.Call, power); 334 return; 335 } 318 336 case OpCodes.AiryA: { 319 337 CompileInstructions(il, state, ds); … … 389 407 CompileInstructions(il, state, ds); 390 408 il.Emit(System.Reflection.Emit.OpCodes.Call, sinIntegral); 409 return; 410 } 411 case OpCodes.AnalyticQuotient: { 412 CompileInstructions(il, state, ds); // x1 413 CompileInstructions(il, state, ds); // x2 414 415 il.Emit(System.Reflection.Emit.OpCodes.Dup); 416 il.Emit(System.Reflection.Emit.OpCodes.Mul); // x2*x2 417 il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); 418 il.Emit(System.Reflection.Emit.OpCodes.Mul); // 1+x2*x2 419 il.Emit(System.Reflection.Emit.OpCodes.Call, sqrt); 420 il.Emit(System.Reflection.Emit.OpCodes.Div); 391 421 return; 392 422 } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
r15584 r17072 203 203 return sum / currentInstr.nArguments; 204 204 } 205 case OpCodes.Absolute: { 206 return Math.Abs(Evaluate(dataset, ref row, state)); 207 } 205 208 case OpCodes.Cos: { 206 209 return Math.Cos(Evaluate(dataset, ref row, state)); … … 214 217 case OpCodes.Square: { 215 218 return Math.Pow(Evaluate(dataset, ref row, state), 2); 219 } 220 case OpCodes.Cube: { 221 return Math.Pow(Evaluate(dataset, ref row, state), 3); 216 222 } 217 223 case OpCodes.Power: { … … 223 229 return Math.Sqrt(Evaluate(dataset, ref row, state)); 224 230 } 231 case OpCodes.CubeRoot: { 232 return Math.Pow(Evaluate(dataset, ref row, state), 1.0 / 3.0); 233 } 225 234 case OpCodes.Root: { 226 235 double x = Evaluate(dataset, ref row, state); … … 340 349 if (double.IsNaN(x)) return double.NaN; 341 350 else return alglib.besseli0(x); 351 } 352 353 case OpCodes.AnalyticQuotient: { 354 var x1 = Evaluate(dataset, ref row, state); 355 var x2 = Evaluate(dataset, ref row, state); 356 return x1 / Math.Pow(1 + x2 * x2, 0.5); 342 357 } 343 358 case OpCodes.IfThenElse: { -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
r15584 r17072 215 215 if (instr.nArguments == 1) p = 1.0 / p; 216 216 instr.value = p; 217 } else if (instr.opCode == OpCodes.AnalyticQuotient) { 218 var x1 = code[instr.childIndex].value; 219 var x2 = code[instr.childIndex + 1].value; 220 instr.value = x1 / Math.Sqrt(1 + x2 * x2); 217 221 } else if (instr.opCode == OpCodes.Average) { 218 222 double s = code[instr.childIndex].value; … … 221 225 } 222 226 instr.value = s / instr.nArguments; 227 } else if (instr.opCode == OpCodes.Absolute) { 228 instr.value = Math.Abs(code[instr.childIndex].value); 223 229 } else if (instr.opCode == OpCodes.Cos) { 224 230 instr.value = Math.Cos(code[instr.childIndex].value); … … 229 235 } else if (instr.opCode == OpCodes.Square) { 230 236 instr.value = Math.Pow(code[instr.childIndex].value, 2); 237 } else if (instr.opCode == OpCodes.Cube) { 238 instr.value = Math.Pow(code[instr.childIndex].value, 3); 231 239 } else if (instr.opCode == OpCodes.Power) { 232 240 double x = code[instr.childIndex].value; … … 235 243 } else if (instr.opCode == OpCodes.SquareRoot) { 236 244 instr.value = Math.Sqrt(code[instr.childIndex].value); 245 } else if (instr.opCode == OpCodes.CubeRoot) { 246 instr.value = Math.Pow(code[instr.childIndex].value, 1.0 / 3.0); 237 247 } else if (instr.opCode == OpCodes.Root) { 238 248 double x = code[instr.childIndex].value; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AnalyticQuotient.cs
r16362 r17072 28 28 [Item("Analytic Quotient", "The analytic quotient function aq(a,b) = a / sqrt(b²+1) can be used as an " + 29 29 "alternative to protected division. See H. Drieberg and P. Rocket, The Use of an Analytic Quotient Operator" + 30 " in Genetic Programming. IEEE Transactions on Evolutionary Computation, Vol. 17, No. 1, February 2013, pp 146 -- 152")]30 " in Genetic Programming. IEEE Transactions on Evolutionary Computation, Vol. 17, No. 1, February 2013, pp. 146 -- 152")] 31 31 public sealed class AnalyticQuotient : Symbol { 32 32 private const int minimumArity = 2; … … 48 48 public AnalyticQuotient() : base("AnalyticQuotient", "The analytic quotient function aq(a,b) = a / sqrt(b²+1) can be used as an " + 49 49 "alternative to protected division. See H. Drieberg and P. Rocket, The Use of an Analytic Quotient Operator" + 50 " in Genetic Programming. IEEE Transactions on Evolutionary Computation, Vol. 17, No. 1, February 2013, pp 146 -- 152") { }50 " in Genetic Programming. IEEE Transactions on Evolutionary Computation, Vol. 17, No. 1, February 2013, pp. 146 -- 152") { } 51 51 } 52 52 }
Note: See TracChangeset
for help on using the changeset viewer.