Ignore:
Timestamp:
12/08/18 08:11:48 (12 months ago)
Author:
gkronber
Message:

#2915: merged all changes from branch to trunk

Location:
trunk
Files:
16 edited
4 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic

  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs

    r16206 r16356  
    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
     
    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();
     
    11551305        MergeVariablesAndConstantsInProduct(a);
    11561306        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));
    11571322      } else {
    11581323        var mul = mulSymbol.CreateTreeNode();
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs

    r15583 r16356  
    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      }
     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      }
    215229      if (node.Symbol is Logarithm) {
    216230        return AutoDiff.TermBuilder.Log(
     
    228242        return AutoDiff.TermBuilder.Power(
    229243          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);
    230252      }
    231253      if (node.Symbol is Sine) {
     
    301323          !(n.Symbol is Erf) &&
    302324          !(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)
    304330        select n).Any();
    305331      return !containsUnknownSymbol;
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs

    r15583 r16356  
    4848      var mul = new Multiplication();
    4949      var div = new Division();
     50      var aq = new AnalyticalQuotient();
    5051      var mean = new Average();
    5152      var sin = new Sine();
     
    5354      var tan = new Tangent();
    5455      var log = new Logarithm();
     56      var abs = new Absolute();
    5557      var pow = new Power();
    5658      pow.InitialFrequency = 0.0;
    5759      var square = new Square();
    5860      square.InitialFrequency = 0.0;
     61      var cube = new Cube();
     62      cube.InitialFrequency = 0.0;
    5963      var root = new Root();
    6064      root.InitialFrequency = 0.0;
    6165      var sqrt = new SquareRoot();
    6266      sqrt.InitialFrequency = 0.0;
     67      var cubeRoot = new CubeRoot();
     68      cubeRoot.InitialFrequency = 0.0;
    6369      var airyA = new AiryA();
    6470      airyA.InitialFrequency = 0.0;
     
    123129      autoregressiveVariable.Enabled = false;
    124130
    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,
    126132        airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral,
    127133        @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,
    129135        airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral
    130136      };
    131137
    132       var binaryFunctionSymbols = new List<Symbol>() { pow, root, gt, lt, variableCondition };
     138      var binaryFunctionSymbols = new List<Symbol>() { pow, root, gt, lt, aq, variableCondition };
    133139      var ternarySymbols = new List<Symbol>() { add, sub, mul, div, mean, and, or, xor };
    134140      var terminalSymbols = new List<Symbol>() { variableSymbol, binFactorVariable, factorVariable, constant, laggedVariable, autoregressiveVariable };
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs

    r15583 r16356  
    6969      var root = new Root();
    7070      var sqrt = new SquareRoot();
     71      var cube = new Cube();
     72      var cubeRoot = new CubeRoot();
    7173      var exp = new Exponential();
     74      var abs = new Absolute();
    7275
    7376      var airyA = new AiryA();
     
    8689      var psi = new Psi();
    8790      var sineIntegral = new SineIntegral();
     91      var analyticalQuotient = new AnalyticalQuotient();
    8892
    8993      var @if = new IfThenElse();
     
    114118      var trigonometricSymbols = new GroupSymbol(TrigonometricFunctionsName, new List<ISymbol>() { sin, cos, tan });
    115119      var exponentialAndLogarithmicSymbols = new GroupSymbol(ExponentialFunctionsName, new List<ISymbol> { exp, log });
    116       var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { airyA, 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});
    118122      var terminalSymbols = new GroupSymbol(TerminalsName, new List<ISymbol> { constant, variableSymbol, binFactorVariable, factorVariable });
    119123      var realValuedSymbols = new GroupSymbol(RealValuedSymbolsName, new List<ISymbol>() { arithmeticSymbols, trigonometricSymbols, exponentialAndLogarithmicSymbols, specialFunctions, terminalSymbols });
    120124
    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 });
    122126
    123127      var conditionSymbols = new GroupSymbol(ConditionsName, new List<ISymbol> { @if, variableCondition });
     
    140144      SetSubtreeCount(root, 2, 2);
    141145      SetSubtreeCount(square, 1, 1);
     146      SetSubtreeCount(cube, 1, 1);
    142147      SetSubtreeCount(sqrt, 1, 1);
     148      SetSubtreeCount(cubeRoot, 1, 1);
    143149      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
    145155      SetSubtreeCount(terminalSymbols, 0, 0);
    146156
     
    231241    public void ConfigureAsDefaultRegressionGrammar() {
    232242      Symbols.First(s => s is Average).Enabled = false;
     243      Symbols.First(s => s is Absolute).Enabled = false;
    233244      Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false;
    234245      Symbols.First(s => s.Name == PowerFunctionsName).Enabled = false;
     
    242253      Symbols.First(s => s is VariableCondition).Enabled = false;
    243254      Symbols.First(s => s is Xor).Enabled = false;
     255      Symbols.First(s => s is Absolute).Enabled = false;
    244256      Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false;
    245257      Symbols.First(s => s.Name == ExponentialFunctionsName).Enabled = false;
     
    251263    public void ConfigureAsDefaultTimeSeriesPrognosisGrammar() {
    252264      Symbols.First(s => s is Average).Enabled = false;
     265      Symbols.First(s => s is Absolute).Enabled = false;
    253266      Symbols.First(s => s.Name == TrigonometricFunctionsName).Enabled = false;
    254267      Symbols.First(s => s.Name == PowerFunctionsName).Enabled = false;
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj

    r16287 r16356  
    223223    <Compile Include="Symbols\BinaryFactorVariable.cs" />
    224224    <Compile Include="Symbols\BinaryFactorVariableTreeNode.cs" />
     225    <Compile Include="Symbols\AnalyticalQuotient.cs" />
     226    <Compile Include="Symbols\Cube.cs" />
    225227    <Compile Include="Symbols\FactorVariableTreeNode.cs" />
    226228    <Compile Include="Symbols\FactorVariable.cs" />
     229    <Compile Include="Symbols\Absolute.cs" />
     230    <Compile Include="Symbols\CubeRoot.cs" />
    227231    <Compile Include="Symbols\VariableBase.cs" />
    228232    <Compile Include="Symbols\VariableTreeNodeBase.cs" />
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs

    r15583 r16356  
    4242  /// Expr          = ['-' | '+'] Term { '+' Term | '-' Term }
    4343  /// 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
    4851  /// ArgList       = Expr { ',' Expr }
    4952  /// VarExpr       = varId OptFactorPart
     
    9598        { "*", new Multiplication()},
    9699        { "-", new Subtraction()},
     100        { "^", new Power() },
     101        { "ABS", new Absolute() },
    97102        { "EXP", new Exponential()},
    98103        { "LOG", new Logarithm()},
     
    101106        { "SQR", new Square() },
    102107        { "SQRT", new SquareRoot() },
     108        { "CUBE", new Cube() },
     109        { "CUBEROOT", new CubeRoot() },
    103110        { "SIN",new Sine()},
    104111        { "COS", new Cosine()},
     
    119126        { "DAWSON", new Dawson()},
    120127        { "EXPINT", new ExponentialIntegralEi()},
     128        { "AQ", new AnalyticalQuotient() },
    121129        { "MEAN", new Average()},
    122130        { "IF", new IfThenElse()},
     
    167175            && str[pos] != '*'
    168176            && str[pos] != '/'
     177            && str[pos] != '^'
    169178            && str[pos] != ')'
    170179            && str[pos] != ']'
     180            && str[pos] != '}'
    171181            && str[pos] != ',') {
    172182            sb.Append(str[pos]);
     
    227237          pos++;
    228238          yield return new Token { TokenType = TokenType.Operator, strVal = "*" };
     239        } else if (str[pos] == '^') {
     240          pos++;
     241          yield return new Token { TokenType = TokenType.Operator, strVal = "^" };
    229242        } else if (str[pos] == '(') {
    230243          pos++;
     
    239252          pos++;
    240253          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 = "}" };
    241260        } else if (str[pos] == '=') {
    242261          pos++;
     
    360379    }
    361380
    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
    366403    /// ArgList       = Expr { ',' Expr }
    367404    /// VarExpr       = varId OptFactorPart
     
    370407    /// varVal        =  ident | ' ident ' | " ident "
    371408    /// ident         =  '_' | letter { '_' | letter | digit }
    372     private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) {
     409    private ISymbolicExpressionTreeNode ParseSimpleFact(Queue<Token> tokens) {
    373410      var next = tokens.Peek();
    374411      if (next.TokenType == TokenType.LeftPar) {
    375         tokens.Dequeue();
     412        var initPar = tokens.Dequeue(); // match par type
    376413        var expr = ParseExpr(tokens);
    377414        var rPar = tokens.Dequeue();
    378415        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 }");
    380421        return expr;
    381422      } else if (next.TokenType == TokenType.Identifier) {
     
    424465          if (rPar.TokenType != TokenType.RightPar)
    425466            throw new ArgumentException("expected )");
     467
    426468
    427469          return funcNode;
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs

    r15583 r16356  
    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()},
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/BatchOperations.cs

    r16293 r16356  
    8989        a[i] = Math.Sqrt(b[i]);
    9090    }
     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    }
    91111  }
    92112}
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs

    r15583 r16356  
    4646    public const byte OR = 14;
    4747    public const byte NOT = 15;
    48     public const byte XOR = 45;
    4948
    5049
     
    8382    public const byte Erf = 43;
    8483    public const byte Bessel = 44;
     84    public const byte XOR = 45;
    8585    public const byte FactorVariable = 46;
    8686    public const byte BinaryFactorVariable = 47;
     87    public const byte Absolute = 48;
     88    public const byte AnalyticalQuotient = 49;
     89    public const byte Cube = 50;
     90    public const byte CubeRoot = 51;
    8791
    8892
     
    113117      { typeof(Power),OpCodes.Power},
    114118      { typeof(Root),OpCodes.Root},
    115       { typeof(TimeLag), OpCodes.TimeLag}, 
     119      { typeof(TimeLag), OpCodes.TimeLag},
    116120      { typeof(Integral), OpCodes.Integral},
    117121      { typeof(Derivative), OpCodes.Derivative},
     
    135139      { typeof(Bessel), OpCodes.Bessel},
    136140      { typeof(FactorVariable), OpCodes.FactorVariable },
    137       { typeof(BinaryFactorVariable), OpCodes.BinaryFactorVariable }
     141      { typeof(BinaryFactorVariable), OpCodes.BinaryFactorVariable },
     142      { typeof(Absolute), OpCodes.Absolute },
     143      { typeof(AnalyticalQuotient), OpCodes.AnalyticalQuotient },
     144      { typeof(Cube), OpCodes.Cube },
     145      { typeof(CubeRoot), OpCodes.CubeRoot }
    138146    };
    139147
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs

    r15583 r16356  
    4141
    4242    #region method info for the commonly called functions
     43    private static readonly MethodInfo Abs = typeof(Math).GetMethod("Abs", new[] { typeof(double) });
    4344    private static readonly MethodInfo Sin = typeof(Math).GetMethod("Sin", new[] { typeof(double) });
    4445    private static readonly MethodInfo Cos = typeof(Math).GetMethod("Cos", new[] { typeof(double) });
     
    207208            return Expression.Divide(result, Expression.Constant((double)node.SubtreeCount));
    208209          }
     210        case OpCodes.Absolute: {
     211            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     212            return Expression.Call(Abs, arg);
     213          }
    209214        case OpCodes.Cos: {
    210215            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     
    222227            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    223228            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));
    224233          }
    225234        case OpCodes.Power: {
     
    231240            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    232241            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));
    233246          }
    234247        case OpCodes.Root: {
     
    493506                Expression.Assign(result, Expression.Call(Bessel, arg))),
    494507              result);
     508          }
     509        case OpCodes.AnalyticalQuotient: {
     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))));
    495517          }
    496518        case OpCodes.IfThenElse: {
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs

    r16301 r16356  
    111111
    112112          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);
    114115              break;
    115116            }
     
    120121            }
    121122
     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
    122132          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);
    124135              break;
    125136            }
     
    147158          case OpCodes.Tan: {
    148159              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.AnalyticalQuotient: {
     169              Load(instr.buf, code[c].buf);
     170              AnalyticQuotient(instr.buf, code[c + 1].buf);
    149171              break;
    150172            }
     
    172194      var remainingRows = rows.Length % BATCHSIZE;
    173195      var roundedTotal = rows.Length - remainingRows;
     196
     197      // TODO: evaluated solutions are not counted
    174198
    175199      var result = new double[rows.Length];
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs

    r15583 r16356  
    5050    private static MethodInfo round = typeof(Math).GetMethod("Round", new Type[] { typeof(double) });
    5151    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) });
    5253
    5354    private static MethodInfo airyA = thisType.GetMethod("AiryA", new Type[] { typeof(double) });
     
    264265            return;
    265266          }
     267        case OpCodes.Absolute: {
     268            CompileInstructions(il, state, ds);
     269            il.Emit(System.Reflection.Emit.OpCodes.Call, abs);
     270            return;
     271          }
    266272        case OpCodes.Cos: {
    267273            CompileInstructions(il, state, ds);
     
    311317            return;
    312318          }
     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          }
    313325        case OpCodes.SquareRoot: {
    314326            CompileInstructions(il, state, ds);
     
    316328            return;
    317329          }
     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          }
    318336        case OpCodes.AiryA: {
    319337            CompileInstructions(il, state, ds);
     
    389407            CompileInstructions(il, state, ds);
    390408            il.Emit(System.Reflection.Emit.OpCodes.Call, sinIntegral);
     409            return;
     410          }
     411        case OpCodes.AnalyticalQuotient: {
     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);
    391421            return;
    392422          }
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs

    r15583 r16356  
    203203            return sum / currentInstr.nArguments;
    204204          }
     205        case OpCodes.Absolute: {
     206            return Math.Abs(Evaluate(dataset, ref row, state));
     207          }
    205208        case OpCodes.Cos: {
    206209            return Math.Cos(Evaluate(dataset, ref row, state));
     
    214217        case OpCodes.Square: {
    215218            return Math.Pow(Evaluate(dataset, ref row, state), 2);
     219          }
     220        case OpCodes.Cube: {
     221            return Math.Pow(Evaluate(dataset, ref row, state), 3);
    216222          }
    217223        case OpCodes.Power: {
     
    223229            return Math.Sqrt(Evaluate(dataset, ref row, state));
    224230          }
     231        case OpCodes.CubeRoot: {
     232            return Math.Pow(Evaluate(dataset, ref row, state), 1.0 / 3.0);
     233          }
    225234        case OpCodes.Root: {
    226235            double x = Evaluate(dataset, ref row, state);
     
    340349            if (double.IsNaN(x)) return double.NaN;
    341350            else return alglib.besseli0(x);
     351          }
     352
     353        case OpCodes.AnalyticalQuotient: {
     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);
    342357          }
    343358        case OpCodes.IfThenElse: {
  • trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs

    r15583 r16356  
    215215          if (instr.nArguments == 1) p = 1.0 / p;
    216216          instr.value = p;
     217        } else if (instr.opCode == OpCodes.AnalyticalQuotient) {
     218          var x1 = code[instr.childIndex].value;
     219          var x2 = code[instr.childIndex + 1].value;
     220          instr.value = x1 / Math.Sqrt(1 + x2 * x2);
    217221        } else if (instr.opCode == OpCodes.Average) {
    218222          double s = code[instr.childIndex].value;
     
    221225          }
    222226          instr.value = s / instr.nArguments;
     227        } else if (instr.opCode == OpCodes.Absolute) {
     228          instr.value = Math.Abs(code[instr.childIndex].value);
    223229        } else if (instr.opCode == OpCodes.Cos) {
    224230          instr.value = Math.Cos(code[instr.childIndex].value);
     
    229235        } else if (instr.opCode == OpCodes.Square) {
    230236          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);
    231239        } else if (instr.opCode == OpCodes.Power) {
    232240          double x = code[instr.childIndex].value;
     
    235243        } else if (instr.opCode == OpCodes.SquareRoot) {
    236244          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);
    237247        } else if (instr.opCode == OpCodes.Root) {
    238248          double x = code[instr.childIndex].value;
Note: See TracChangeset for help on using the changeset viewer.