dos_compilers/Ashwood-Smith PC-LISP v3/DIFF.L
2024-07-04 18:51:32 -07:00

108 lines
3.6 KiB
Common Lisp

; 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 <exp>), (* <exp> 0), (^ <exp> 1), (+ <exp> 0)
; and replaces them with the appropriate things <exp>,0,<exp> and <exp>
; 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")