0

If I have an expression, such as x * x * x, stored in a data structure like: mult(var x, mult(var x, var x))

And I want to implement a function to recursively differentiate the equation (so to 3 * x * x or x*x + (x + x)*x etc, no simplification required), any suggestions how to being this?

edd91
  • 185
  • 8
  • I am not clear on what is the data structure you are using to store the expression. `mult(var x, mult(var x, var x))` looks more like a function to me than a data structure – Anand Undavia Mar 10 '17 at 05:57
  • *"such as"*: if you are looking to differentiate any expression, this question is too broad. If not, please be specific to what the question is about (powers of *x*? Any polynomial expression? divisions? ...), and your attempts and where you hit a problem. – trincot Mar 10 '17 at 06:11
  • 1
    This is a very nice problem to work through, but it's not trivial. A standard way to do it is "unification". The expressions are represented as syntax trees. Differentiation rules are represented as L->R pairs where L and R are syntax trees containing free variables. E.g. `d(A * B, x) --> d(A, x) * B + A * d(B, x)` where `A`, `B`, and `x` are free. Unification matches an input expression to a rule's left hand side. When it succeeds, it produces a "substitution" map taking variables to subtrees. Applying the map to the rule's right hand side gives a new expression. Stop when no rules match. – Gene Mar 10 '17 at 06:15

2 Answers2

2

You would find a matching differentiation rule and apply it. For example in this case we have the rule (where A and B stand for whole subexpressions)

diff(mult(A, B)) -> add(mult(diff(A),B), mult(A, diff(B)))

The left hand side of this rule matches the formula when we set

A = var x
B = mult(var x, var x)

So we can apply this rule to the formula and get

diff(mult(var x, mult(var x, var x))) ->
  add(mult(diff(var x),mult(var x, var x)), mult(var x, diff(mult(var x, var x))))

Now do the same recursively for the remaining diff operations.

The other other rule you will need here is:

diff(var x) -> 1
Henry
  • 42,982
  • 7
  • 68
  • 84
2

Just a note to point out that language can make difference. Lisp is particularly good for this problem.

(defun d (f x)
  (etypecase f
    (number 0)
    (symbol (if (eq f x) 1 0))
    (list (df (first f) (rest f) x))))

(defun df (op args x)
  (let ((a (first args))
        (b (second args)))
    (case op
      ((+ -) `(,op ,(d a x) ,(d b x)))
      (* `(+ (* ,a ,(d b x)) (* ,(d a x) ,b)))
      (/ `(/ (- (* ,(d a x) ,b) (* ,a ,(d b x))) (^ ,b 2)))
      (^ `(* (* ,b (^ ,a ,(1- b))) ,(d a x)))
      (sin `(* (cos ,a) ,(d a x)))
      (cos `(* (- (sin ,a)) ,(d a x))))))

Lisp likes prefix notation. This is equivalent to an abstract syntax tree for expressions. Binary operations look like (op lhs rhs). So to differentiate (3 sin(x^2))^2,

> (d '(^ (* (sin (^ x 2)) 3) 2) 'x)
(* (* 2 (^ (* (SIN (^ X 2)) 3) 1))
 (+ (* (SIN (^ X 2)) 0) (* (* (COS (^ X 2)) (* (* 2 (^ X 1)) 1)) 3)))

This is a correct answer, but clearly it's far from simple form. So the next step is to add an expression simplifier. With a very rudimentary one,

> (simplify (d '(^ (* (sin (^ x 2)) 3) 2) 'x))
(* (* 2 (* (SIN (^ X 2)) 3)) (* (* (COS (^ X 2)) (* 2 X)) 3))

With infix notation, this is 2(3 sin(x^2)) (3 cos(x^2) (2x)). Obviously more simplification is possible, but getting to "most simple" by any useful definition is a complicated topic.

Gene
  • 46,253
  • 4
  • 58
  • 96