Symbolic Differentiation
 an initial demonstration of symbolic computing
 representation of algebraic expressions as Lisp data objects
 algebraic expressions as an abstract data type (ADT)
recognizer, selector, constructor and converter functions
deriv
as a recursive program on the algebraic
expression domain
 representation can be summarized by a grammar (GRAIL)
Symbolic Differentiation: The Problem
Write a program which implements the following rules of mathematics:
dn/dx  =  0

dv/dx  =  1, if v = x, 0 otherwise

d(f)/dx  =   df/dx

d(f × g)/dx  = 
f × dg/dx + g × df/dx

d(f + g)/dx  =  df/dx + dg/dx

Here,
 n stands for
an arbitrary numeric constant.
 v stands for an arbitrary mathematical variable.
 f and g stand for arbitrary
algebraic expressions of any type.
Solution: A Recursive Program
deriv[E; V] =
[constantp[E] > makeconstant[0];
variablep[E] >
[eq[varname[E]; varname[V]] >
makeconstant[1];
otherwise > makeconstant[0]];
negationp[E] >
makenegation[deriv[operand[E]; V]];
productp[E] >
makesum
[makeproduct
[operand1[E];
deriv[operand2[E]; V]];
makeproduct
[operand2[E];
deriv[operand1[E]; V]]];
sump[E] >
makesum[deriv[operand1[E]; V];
deriv[operand2[E]; V]]]
Data Access Functions
The deriv
program is a straightforward
translation of differentation rules.
Data access functions (DAFs) refer to
symbolic representations of algebraic expressions.
 Recognizers
 distinguish alternative types of
algebraic expression:
constantp
,
variablep
, negationp
, etc.
 Converters
 convert between numeric or
string values and their symbolic representations as
algebraic expressions:
makeconstant
, varname
.
 Selectors
 select components of structured
algebraic expressions:
operand
, operand1
, operand2
.
 Constructors
 build structured algebraic expressions
from components:
makenegation
, makeproduct
, makesum
.
DAFs Hide the Representation
So far, no computer representation of algebraic
expressions has been specified!
An abstract solution.
 Readable: details of representation do not clutter
the algorithm.
 Languageindependent: easy to write in any language.
 Concreteness: need a representation for algebraic expressions.
 The DAFs comprise an abstract data type
for algebraic expressions.
Lisp lists: a quick and convenient way of representing
algebraic expressions.
Representation of Algebraic Expressions
How can we represent algebraic expressions as Lisp lists?
For example, consider 2×x+3×y
How about using:
(2 * x + 3 * y)
Problem: This does not group the appropriate components together
as single substructures (lists).
Instead:
((2 * x) + (3 * y))
A workable compromise.
Expression  Representation

numeric constants  numeric atoms

variables  symbolic atoms

f  ( F )

f × g  (F * G)

f+g  (F + G)

Here, F is the representation of f,
G the representation of g, and
N the representation of n (a numeric constant).
Expression  Representation

2  2

x  x 
3  3 
y  y 
2 × x  (2 * x) 
3 × y  (3 * y) 
2 × x+3 × y  ((2 * x) + (3 * y)) 

Now we need to implement the DAFs.
Implementation of DAFs: Constructors
Build the lists that represent structured formulas
(negations, products and sums).
First, some helper functions.
list2[e1; e2] =
cons[e1; cons[e2; ()]]
list3[e1; e2; e3] =
cons[e1; list2[e2; e3]]
A negation expression is a twoelement list whose first
element is the atom ``
''.
makenegation[expr] =
list2[""; expr]
Sums and products are threeelement lists with infix operators.
makesum[expr1; expr2] =
list3[expr1; "+"; expr2]
makeproduct[expr1; expr2] =
list3[expr1; "+*; expr2]
Implementation of DAFs: Selectors
Helper functions are useful for selecting list elements.
second[list] = first[rest[list]]
third[list] = second[rest[list]]
The component of a "negation" expression
its operand
.
operand[expr] = second[expr]
Sum and product expression there have two operands:
operand1[expr] = first[expr]
operand2[expr] = third[expr]
When we use the same selectors for two or more
different types of symbolic data, we say they
are overloaded.
Implementation of DAFs: Recognizers
Input assumption: recognizers are given a valid
representation of an algebraic expression.
Output: return T
iff the algebraic expression
is of the correct type.
constantp[expr] = numberp[expr]
variablep[expr] = symbolp[expr]
;;; Check for a 2element list,
;;; whose first element is the atom "".
negationp[expr] =
[listp[expr] >
[endp[rest[rest[expr]]] >
eq[first[expr]; ""];
otherwise > F];
otherwise > F]
Note: endp[rest[rest[expr]]]
asks the question: Is the list empty
after removing two elements?
\newpage
The job recognizing a threeelement
list with a particular operator
symbol can be factored out into
a single routine.
dyadicmathp[expr; infixsym] =
[listp[expr] >
[endp[rest[rest[expr]]] > F;
otherwise >
eq[second[expr]; infixsym]];
otherwise > F]
productp[expr] =
dyadicmathp[expr; "*"]
sump[expr] =
dyadicmathp[expr; "+"]
Implementation of DAFs: Convertors
In Small Lisp, convertor functions are trivial!
constval[constexpr] = constexpr
makeconstant[numatom] = numatom
varname[variable] = variable
makevariable[symatom] = symatom
These are identity functions! Why?
In Lisp, atoms serve two roles:
 as the ground elements of symbolic notations.
 as representations for numbers and strings.
In other languages, symbolic data will typically
be represented by pointer objects. Conversion
will be required.
Demo
1: cameron_sirius% smlisp
Small Lisp for Unix v1.10(gamma), (c) 19931994 Melissa O'Neill.
Type /help for help.
smlisp> /reset /gfs1/CMPT/384/src/deriv.cfg
All user definitions cleared.
Reading '/gfs1/CMPT/384/src/smlib/listfns.sl'... done.
Reading '/gfs1/CMPT/384/src/math/algexprs.adt'... done.
Reading '/gfs1/CMPT/384/src/math/deriv.sl'... done.
Evaluating... done.
smlisp> deriv[((2 * x) + (3 * y)); "x"]
(((2 * 1) + (x * 0)) + ((3 * 0) + (y * 0)))
smlisp> /quit
Bye.