private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha)
 {
     if (alpha.IsAlmost(0.0))
     {
         return(treeNode);
     }
     else
     {
         var addition   = new Addition();
         var node       = addition.CreateTreeNode();
         var alphaConst = MakeConstant(alpha);
         node.AddSubtree(treeNode);
         node.AddSubtree(alphaConst);
         return(node);
     }
 }
Пример #2
0
        public static ISymbolicExpressionTreeNode Derive(ISymbolicExpressionTreeNode branch, string variableName)
        {
            if (branch.Symbol is Constant)
            {
                return(CreateConstant(0.0));
            }
            if (branch.Symbol is Variable)
            {
                var varNode = branch as VariableTreeNode;
                if (varNode.VariableName == variableName)
                {
                    return(CreateConstant(varNode.Weight));
                }
                else
                {
                    return(CreateConstant(0.0));
                }
            }
            if (branch.Symbol is Addition)
            {
                var sum = addSy.CreateTreeNode();
                foreach (var subTree in branch.Subtrees)
                {
                    sum.AddSubtree(Derive(subTree, variableName));
                }
                return(sum);
            }
            if (branch.Symbol is Subtraction)
            {
                var sum = subSy.CreateTreeNode();
                foreach (var subTree in branch.Subtrees)
                {
                    sum.AddSubtree(Derive(subTree, variableName));
                }
                return(sum);
            }
            if (branch.Symbol is Multiplication)
            {
                // (f * g)' = f'*g + f*g'
                // for multiple factors: (f * g * h)' = ((f*g) * h)' = (f*g)' * h + (f*g) * h'

                if (branch.SubtreeCount >= 2)
                {
                    var f      = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                    var fprime = Derive(f, variableName);
                    for (int i = 1; i < branch.SubtreeCount; i++)
                    {
                        var g       = (ISymbolicExpressionTreeNode)branch.GetSubtree(i).Clone();
                        var fg      = Product((ISymbolicExpressionTreeNode)f.Clone(), (ISymbolicExpressionTreeNode)g.Clone());
                        var gPrime  = Derive(g, variableName);
                        var fgPrime = Sum(Product(fprime, g), Product(gPrime, f));
                        // prepare for next iteration
                        f      = fg;
                        fprime = fgPrime;
                    }
                    return(fprime);
                }
                else
                {
                    // multiplication with only one argument has no effect -> derive the argument
                    return(Derive(branch.GetSubtree(0), variableName));
                }
            }
            if (branch.Symbol is Division)
            {
                // (f/g)' = (f'g - g'f) / g²
                if (branch.SubtreeCount == 1)
                {
                    var g       = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                    var gPrime  = Product(CreateConstant(-1.0), Derive(g, variableName));
                    var sqrNode = new Square().CreateTreeNode();
                    sqrNode.AddSubtree(g);
                    return(Div(gPrime, sqrNode));
                }
                else
                {
                    // for two subtrees:
                    // (f/g)' = (f'g - fg')/g²

                    // if there are more than 2 subtrees
                    // div(x,y,z) is interpretered as (x/y)/z
                    // which is the same as x / (y*z)

                    // --> make a product of all but the first subtree and differentiate as for the 2-argument case above
                    var f      = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                    var g      = Product(branch.Subtrees.Skip(1).Select(n => (ISymbolicExpressionTreeNode)n.Clone()));
                    var fprime = Derive(f, variableName);
                    var gprime = Derive(g, variableName);
                    var gSqr   = Square(g);
                    return(Div(Subtract(Product(fprime, g), Product(f, gprime)), gSqr));
                }
            }
            if (branch.Symbol is Logarithm)
            {
                var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                return(Product(Div(CreateConstant(1.0), f), Derive(f, variableName)));
            }
            if (branch.Symbol is Exponential)
            {
                var f = (ISymbolicExpressionTreeNode)branch.Clone();
                return(Product(f, Derive(branch.GetSubtree(0), variableName)));
            }
            if (branch.Symbol is Square)
            {
                var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                return(Product(Product(CreateConstant(2.0), f), Derive(f, variableName)));
            }
            if (branch.Symbol is SquareRoot)
            {
                var f = (ISymbolicExpressionTreeNode)branch.Clone();
                var u = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                return(Product(Div(CreateConstant(1.0), Product(CreateConstant(2.0), f)), Derive(u, variableName)));
            }
            if (branch.Symbol is CubeRoot)
            {
                var f = (ISymbolicExpressionTreeNode)branch.Clone();
                var u = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                return(Product(Div(CreateConstant(1.0), Product(CreateConstant(3.0), Square(f))), Derive(u, variableName))); // 1/3 1/cbrt(f(x))^2 d/dx f(x)
            }
            if (branch.Symbol is Cube)
            {
                var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                return(Product(Product(CreateConstant(3.0), Square(f)), Derive(f, variableName)));
            }
            if (branch.Symbol is Absolute)
            {
                var f    = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                var absf = Abs((ISymbolicExpressionTreeNode)f.Clone());
                return(Product(Div(f, absf), Derive(f, variableName)));
            }
            if (branch.Symbol is AnalyticQuotient)
            {
                // aq(a(x), b(x)) = a(x) / sqrt(b(x)²+1)
                var a = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                var b = (ISymbolicExpressionTreeNode)branch.GetSubtree(1).Clone();

                var definition = Div(a, SquareRoot(Sum(Square(b), CreateConstant(1.0))));
                return(Derive(definition, variableName));
            }
            if (branch.Symbol is Sine)
            {
                var u   = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                var cos = (new Cosine()).CreateTreeNode();
                cos.AddSubtree(u);
                return(Product(cos, Derive(u, variableName)));
            }
            if (branch.Symbol is Cosine)
            {
                var u   = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                var sin = (new Sine()).CreateTreeNode();
                sin.AddSubtree(u);
                return(Product(CreateConstant(-1.0), Product(sin, Derive(u, variableName))));
            }
            if (branch.Symbol is Tangent)
            {
                // tan(x)' = 1 / cos²(x)
                var fxp = Derive(branch.GetSubtree(0), variableName);
                var u   = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
                return(Div(fxp, Square(Cosine(u))));
            }
            if (branch.Symbol is HyperbolicTangent)
            {
                // tanh(f(x))' = f(x)'sech²(f(x)) = f(x)'(1 - tanh²(f(x)))
                var fxp  = Derive(branch.GetSubtree(0), variableName);
                var tanh = (ISymbolicExpressionTreeNode)branch.Clone();
                return(Product(fxp, Subtract(CreateConstant(1.0), Square(tanh))));
            }
            throw new NotSupportedException(string.Format("Symbol {0} is not supported.", branch.Symbol));
        }
 private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
   if (alpha.IsAlmost(0.0)) {
     return treeNode;
   } else {
     var addition = new Addition();
     var node = addition.CreateTreeNode();
     var alphaConst = MakeConstant(alpha);
     node.AddSubtree(treeNode);
     node.AddSubtree(alphaConst);
     return node;
   }
 }