; DIFF.L FOR PC-LISP V2.13 ; ~~~~~~~~~~~~~~~~~~~~~~~~ ; This module is kind of fun, it takes an expression in a prefix lisp ; like form and will compute the derivative of the expression with respect ; to the indicated variable. After symbolic differentiation is done some ; folding is done to remove redundant stuff from the expression. Eg we get ; rid of things multiplied by zero, and fold things with 0 added to them, ; or things raised to the power 1. This reduces the output complexity ; significantly. ; ; Peter Ashwood-Smith ; September 1986. ; ; D(e,X) - ; Will compute the symbolic derivative of expression e with respect ; to varible X. We take the expression in standard lisp prefix form and will ; use the following rules of differentiation. ; ; D(x) = 1 ; D(a) = 0 ; D(ln u) = D(u)/u ; D(u+v) = D(u)+D(v) ; D(u-v) = D(u)-D(v) ; D(u*v) = D(u)*v + u*D(v) ; D(u/v) = D(u)*v + (u*D(v))/v^2 ; D(v^u) = (v^u)*(u*D(v)/v + D(u)*ln(v)) ; (defun D(e X &aux u v) (cond ((equal e X) 1) ((atom e) 0) (t (setq u (cadr e) v (caddr e)) (caseq (car e) (ln `(/ ,(D u X) ,u)) (+ `(+ ,(D u X) ,(D v X))) (- `(- ,(D u X) ,(D v X))) (* `(+ (* ,(D u X) ,v) (* ,(D v X) ,u))) (/ `(- (/ ,(D u X) ,v) (/ (* ,u ,(D v X)) (^ ,v 2)))) (^ `(* ,e (+ (/ (* ,v ,(D u X)) ,u) (* ,(D v X) (ln ,u))))) (t (princ "ERROR") (exit)] ; ; Fold(e) - ; Will traverse the expression 'e' and construct a new expression. ; It checks for things like (* 1 ), (* 0), (^ 1), (+ 0) ; and replaces them with the appropriate things ,0, and ; respectively. These simple algabraic modifications greatly reduce the output ; complexity but do not do a complete job by any means. We use the macros ; ?times, ?plus and ?power to do the dirty work for us. We set displace-macros ; to t to cause PC-LISP to substitute the code into the body of Fold thus ; making it much faster. ; (setq displace-macros t) (defmacro ?times(v e) `(and (eq (car ,e) '*) (member ,v ,e] (defmacro ?plus(v e) `(and (eq (car ,e) '+) (member ,v ,e] (defmacro ?power(v e) `(and (eq (car ,e) '^) (eq (caddr ,e) ,v] (defun Fold(e) (cond ((atom e) e) (t (setq e (cons (Fold (car e)) (Fold (cdr e)))) (cond ((?times 0 e) 0) ((?times 1 e) (cond ((eq (cadr e) 1) (caddr e)) (t (cadr e)))) ((?power 1 e) (cadr e)) ((?plus 0 e) (cond ((eq (cadr e) 0) (caddr e)) (t (cadr e)))) (t e] (defun Differentiate(e x) (Fold (D e x)] ; ----------------- end if differentiate module ------------------ (princ "\t\tSYMBOLIC DIFFERENCIATION\n\n") (princ "Following is the Input Expression Y\n") (setq y '(* x (ln (+ x a)))) (pp-form y) (princ "\nComputing 1st Derivitive of Y with respect to x, Y'\n") (setq Dy (Differentiate y 'x)) (pp-form Dy) (princ "\nComputing 2nd Derivitive of Y with respect to x, Y''\n") (setq DDy (Differentiate Dy 'x)) (pp-form DDy) (princ "\nComputing 3rd Derivitive of Y with respect to x, Y'''\n") (setq DDDy (Differentiate DDy 'x)) (pp-form DDDy) (princ "\nComputing 4th Derivitive of Y with respect to x, Y''''\n") (setq DDDDy (Differentiate DDDy 'x)) (pp-form DDDDy) (princ "\nComputing 5th Derivitive of Y with respect to x, Y'''''\n") (setq DDDDDy (Differentiate DDDDy 'x)) (pp-form DDDDDy) (princ "\n\nDone (finally)\n")