MC logo

Symbolic Calculus


CS 231 Lecture Examples

<< Download >>
;
; This is a small example of symbolic differentiation adapted from the Scheme
; version in _Programming_Lanugages_,_Concepts_and_Constructs_, First
; Edition, by Ravi Sethi. 
;
; We will represent the expressions as lisp lists using the usual lisp
; prefix syntax.  For instance, (+ x 2) will mean x + 2.  And, (d '(+ x 2))
; will yield 2.  Note that (+) is legal and means 0, and (*) is legal and
; means 1.
;

; ** Basic parts. **
; In this section we present some simple functions to identify the basic
; parts.
(defun is-constant (x) (numberp x))
(defun is-variable (x) (symbolp x))
(defun is-sum (x) (and (listp x) (equal (car x) '+)))
(defun is-product (x) (and (listp x) (equal (car x) '*)))
; The functions numberp, symbolp and listp, are built-in predicates 
; identifying, respectively, numbers, symbols, and lists.

; ** Main derivative function **
; This function takes the derivative of an expression.  It actually just
; decides what sort of expression it is and farms the work out to
; specialized functions based on the type of expression.
(defun d (x E)
    (cond
        ((is-constant E) (diff-constant x E))
        ((is-variable E) (diff-variable x E))
        ((is-sum E) (diff-sum x E))
        ((is-product E) (diff-product x E))
        (t (error "d: Cannot parse " E))
    )
)
; The (error) function enters a break loop.

; ** Trivial derivatives. **
; The derivative of a constant is 0, the derivative of a variable with
; respect to itself is 1, with respect to any other variable is 0.
(defun diff-constant (x E) 0)
(defun diff-variable (x E) (if (equal x E) 1 0) )

; ** Derivation of sums **
; For anyone who recalls calculus, the derivative of a sum is the sum of
; the derivatives of the terms.  We use mapcar to go through the list
; and take all the derivatives.
(defun diff-sum (x E)
    (cons '+                            ; Result is a sum.
        (mapcar                         ; Apply to each term.
            (lambda (term) (d x term))  ; Take the derivative of the term.
            (cdr E)                     ; Extract the terms (discard old +)
        )
    )
)

; ** Derivation of a product **
; This is done in two steps.  The function diff-product takes care of the
; simple cases where there are zero or one factor: (*) or (* subE).  The
; more complex cases it passes off to diff-product-args.  This is actually
; done to simplify diff-product-args so that it can be written knowing
; there are at least two factors.
(defun diff-product (x E)
    (let*
        (
            (arg-list (cdr E))              ; Just the args, ma'am
            (num-args (length arg-list))    ; And how may there are.
        )
        (cond
            ((= num-args 0) 0)              ; (*) is 1, deriv is 0.
            ((= num-args 1)                 ; (* M), deriv is deriv of M.
                (d x (car arg-list))
            )
            (t (diff-product-args x arg-list)) ; Real work here.
        )
    )
)

; Here is where the real work of the product differentiation is done.  It
; receives a list of factors (the leading * having been removed).
; It computes using the chain rule, which says the derivative of UV is
; U times the derivative of V plus V times the derivative of U.  That
; is: d(UV) = UdV + VdU.  Note that if the product has multiple factors,
; U will be the first one, and V will be the product of all the remaining ones.
(defun diff-product-args (x arg-list)
    (let*
        (
            (U (car arg-list))              ; U is the head of the list.
            (dU (d x U))
            (V (cons '* (cdr arg-list)))    ; V is all the rest, so keep *.
            (dV (d x V))
            (UdV (list '* U dV))
            (VdU (list '* V dU))
        )
        (list '+ UdV VdU)
    )
)
; The list function simply returns the list of its arguments.

<<
>>