Changeset 17102


Ignore:
Timestamp:
07/08/19 00:03:06 (2 weeks ago)
Author:
mkommend
Message:

#2948: Merged 16358, 16494, 16543, 16737 into stable.

Location:
stable
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs

    r17097 r17102  
    4848    private static readonly Cosine cosSy = new Cosine();
    4949    private static readonly Square sqrSy = new Square();
     50    private static readonly Absolute absSy = new Absolute();
     51    private static readonly SquareRoot sqrtSy = new SquareRoot();
    5052
    5153    public static ISymbolicExpressionTreeNode Derive(ISymbolicExpressionTreeNode branch, string variableName) {
     
    8183        if (branch.SubtreeCount >= 2) {
    8284          var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
    83           var g = (ISymbolicExpressionTreeNode)branch.GetSubtree(1).Clone();
    8485          var fprime = Derive(f, variableName);
    85           var gprime = Derive(g, variableName);
    86           var fgPrime = Sum(Product(f, gprime), Product(fprime, g));
    87           for (int i = 2; i < branch.SubtreeCount; i++) {
     86          for (int i = 1; i < branch.SubtreeCount; i++) {
     87            var g = (ISymbolicExpressionTreeNode)branch.GetSubtree(i).Clone();
    8888            var fg = Product((ISymbolicExpressionTreeNode)f.Clone(), (ISymbolicExpressionTreeNode)g.Clone());
    89             var h = (ISymbolicExpressionTreeNode)branch.GetSubtree(i).Clone();
    90             var hPrime = Derive(h, variableName);
    91             fgPrime = Sum(Product(fgPrime, h), Product(fg, hPrime));
     89            var gPrime = Derive(g, variableName);
     90            var fgPrime = Sum(Product(fprime, g), Product(gPrime, f));
     91            // prepare for next iteration
     92            f = fg;
     93            fprime = fgPrime;
    9294          }
    93           return fgPrime;
     95          return fprime;
    9496        } else
    9597          // multiplication with only one argument has no effect -> derive the argument
     
    138140        return Product(Div(CreateConstant(1.0), Product(CreateConstant(2.0), f)), Derive(u, variableName));
    139141      }
     142      if (branch.Symbol is CubeRoot) {
     143        var f = (ISymbolicExpressionTreeNode)branch.Clone();
     144        var u = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
     145        return Product(Div(CreateConstant(1.0), Product(CreateConstant(3.0), Square(f))), Derive(u, variableName));
     146      }
     147      if (branch.Symbol is Cube) {
     148        var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
     149        return Product(Product(CreateConstant(3.0), Square(f)), Derive(f, variableName));
     150      }
     151      if (branch.Symbol is Absolute) {
     152        var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
     153        var absf = Abs((ISymbolicExpressionTreeNode)f.Clone());
     154        return Product(Div(f, absf), Derive(f, variableName));
     155      }
     156      if (branch.Symbol is AnalyticQuotient) {
     157        // aq(a(x), b(x)) = a(x) / sqrt(b(x)²+1)
     158        var a = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
     159        var b = (ISymbolicExpressionTreeNode)branch.GetSubtree(1).Clone();
     160
     161        var definition = Div(a, SquareRoot(Sum(Square(b), CreateConstant(1.0))));
     162        return Derive(definition, variableName);
     163      }
    140164      if (branch.Symbol is Sine) {
    141165        var u = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
     
    195219      return cos;
    196220    }
     221    private static ISymbolicExpressionTreeNode Abs(ISymbolicExpressionTreeNode f) {
     222      var abs = absSy.CreateTreeNode();
     223      abs.AddSubtree(f);
     224      return abs;
     225    }
    197226    private static ISymbolicExpressionTreeNode Square(ISymbolicExpressionTreeNode f) {
    198227      var sqr = sqrSy.CreateTreeNode();
    199228      sqr.AddSubtree(f);
    200229      return sqr;
     230    }
     231    private static ISymbolicExpressionTreeNode SquareRoot(ISymbolicExpressionTreeNode f) {
     232      var sqrt = sqrtSy.CreateTreeNode();
     233      sqrt.AddSubtree(f);
     234      return sqrt;
    201235    }
    202236
     
    221255          !(n.Symbol is Square) &&
    222256          !(n.Symbol is SquareRoot) &&
     257          !(n.Symbol is Cube) &&
     258          !(n.Symbol is CubeRoot) &&
     259          !(n.Symbol is Absolute) &&
     260          !(n.Symbol is AnalyticQuotient) &&
    223261          !(n.Symbol is Sine) &&
    224262          !(n.Symbol is Cosine) &&
  • stable/HeuristicLab.Tests

  • stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/DeriveTest.cs

    r17097 r17102  
    6060      Assert.AreEqual("(1 / (SQR(COS((3*'x'))) * 0.333333333333333))", Derive("tan(3*x)", "x")); // diff(tan(f(x)), x) = 1.0 / cos²(f(x)), simplifier puts constant factor into the denominator
    6161
     62      Assert.AreEqual("((9*'x') / ABS((3*'x')))", Derive("abs(3*x)", "x"));
     63      Assert.AreEqual("(SQR('x') * 3)", Derive("cube(x)", "x"));
     64      Assert.AreEqual("(1 / (SQR(CUBEROOT('x')) * 3))", Derive("cuberoot(x)", "x"));
     65
     66      Assert.AreEqual("0", Derive("(a+b)/(x+SQR(x))", "y")); // df(a,b,x) / dy = 0
     67
     68
     69      Assert.AreEqual("('a' * 'b' * 'c')", Derive("a*b*c*d", "d"));
     70      Assert.AreEqual("('a' / ('b' * 'c' * SQR('d') * (-1)))", Derive("a/b/c/d", "d"));
     71
    6272      {
    6373        // special case: Inv(x) using only one argument to the division symbol
     
    113123        var t = new SymbolicExpressionTree(root);
    114124
    115         Assert.AreEqual("(('y' * 'z' * 60) / SQR(('y' * 'z' * 20)))", // actually 3 / (4y  5z) but simplifier is not smart enough to cancel numerator and denominator
    116                                                                       // 60 y z / y² z² 20² == 6 / y z 40 == 3 / y z 20
     125        Assert.AreEqual("(('y' * 'z' * 60) / (SQR('y') * SQR('z') * 400))", // actually 3 / (4y  5z) but simplifier is not smart enough to cancel numerator and denominator
     126                                                                            // 60 y z / y² z² 20² == 6 / y z 40 == 3 / y z 20
    117127          formatter.Format(DerivativeCalculator.Derive(t, "x")));
    118         Assert.AreEqual("(('x' * 'z' * (-60)) / SQR(('y' * 'z' * 20)))", // actually 3x * -(4 5 z) / (4y 5z)² = -3x / (20 y² z)
    119                                                                          // -3 4 5 x z / 4² y² 5² z² = -60 x z / 20² z² y² ==    -60 x z / y² z² 20²
     128        Assert.AreEqual("(('x' * 'z' * (-60)) / (SQR('y') * SQR('z') * 400))", // actually 3x * -(4 5 z) / (4y 5z)² = -3x / (20 y² z)
     129                                                                               // -3 4 5 x z / 4² y² 5² z² = -60 x z / 20² z² y² ==    -60 x z / y² z² 20²
    120130          formatter.Format(DerivativeCalculator.Derive(t, "y")));
    121         Assert.AreEqual("(('x' * 'y' * (-60)) / SQR(('y' * 'z' * 20)))",
     131        Assert.AreEqual("(('x' * 'y' * (-60)) / (SQR('y') * SQR('z') * 400))",
    122132          formatter.Format(DerivativeCalculator.Derive(t, "z")));
    123133      }
Note: See TracChangeset for help on using the changeset viewer.