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); } }
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; } }