## 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] =
[constant-p[E] --> make-constant;
variable-p[E] -->
[eq[var-name[E]; var-name[V]] -->
make-constant;
otherwise --> make-constant];
negation-p[E] -->
make-negation[deriv[operand[E]; V]];
product-p[E] -->
make-sum
[make-product
[operand1[E];
deriv[operand2[E]; V]];
make-product
[operand2[E];
deriv[operand1[E]; V]]];
sum-p[E] -->
make-sum[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: `constant-p`, `variable-p`, `negation-p`, etc.
Converters
convert between numeric or string values and their symbolic representations as algebraic expressions: `make-constant`, `var-name`.
Selectors
select components of structured algebraic expressions: `operand`, `operand1`, `operand2`.
Constructors
build structured algebraic expressions from components: `make-negation`, `make-product`, `make-sum`.

## 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.
• Language-independent: 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 two-element list whose first element is the atom ```-`''.
```make-negation[expr] =
list2["-"; expr]
```
Sums and products are three-element lists with infix operators.
```make-sum[expr1; expr2] =
list3[expr1; "+"; expr2]
make-product[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.
```constant-p[expr] = numberp[expr]

variable-p[expr] = symbolp[expr]
```
```;;;  Check for a 2-element list,
;;;  whose first element is the atom "-".
negation-p[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 three-element list with a particular operator symbol can be factored out into a single routine.
```dyadic-math-p[expr; infix-sym] =
[listp[expr] -->
[endp[rest[rest[expr]]] --> F;
otherwise -->
eq[second[expr]; infix-sym]];
otherwise --> F]

product-p[expr] =

sum-p[expr] =
```

## Implementation of DAFs: Convertors

In Small Lisp, convertor functions are trivial!
```const-val[const-expr] = const-expr

make-constant[num-atom] = num-atom

var-name[variable] = variable

make-variable[sym-atom] = sym-atom
```
These are identity functions! Why? In Lisp, atoms serve two roles:
1. as the ground elements of symbolic notations.
2. 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) 1993-1994 Melissa O'Neill.
Type /help for help.
smlisp> /reset /gfs1/CMPT/384/src/deriv.cfg
All user definitions cleared.