מבוא מורחב - שיעור 101
Symbols
Manipulating lists and trees of symbols:symbolic differentiation
Lecture 10
מבוא מורחב - שיעור 102
Symbols
• We want to deal with data that is not just numeric.• For example:
(a b c d) ((rami 5743346) (dina 7584345))
• We have used symbols already as variable names.• With symbols, we can write application like
Symbolic differentiation Pattern searching in text An interpreter for scheme
מבוא מורחב - שיעור 103
The special form quote
• quote is a special form• (quote <argument>) return the argument
without evaluating it.• syntactic sugar:
‘ alpha is the same as (quote alpha)
‘(a b c) is the same as (quote (a b c))
מבוא מורחב - שיעור 104
Symbols are ordinary values
In particular we can form lists of symbols.
(list 1 2) ==> (1 2)
(list 'delta 'gamma) ==> (delta gamma)
symbolgamma
symboldelta
מבוא מורחב - שיעור 105
The special form quote
(quote a)a 'aa (define a 1) (define bcd 2) (list a bcd)(1 2) (list 'a 'bcd);; same as (list (quote a) (quote bcd)(a bcd) (list a 'bcd)(1 bcd) '(a bcd) ;; same as (quote (a bcd))(a bcd)
מבוא מורחב - שיעור 106
(define a 2) (define b 5)
(+ a b) ==>
'(+ a b) ==>
(+ 'a b) ==>
(list '+ a b) ==>
(list + 'a b) ==>
7
(+ a b)
error:+: expects type number…
(+ 2 5)
(#<primitive:+> a 5)
Examples using quote
מבוא מורחב - שיעור 107
Syntactic Sugar
Expression:
Rewrites to: evaluates to:
'2 (quote 2) 2
'() (quote ()) ()
'(a b)
(quote (a b))
(a b)
'(1 (b c)) (quote (1(b c))) (1 (b c))
מבוא מורחב - שיעור 108
The predicate symbol?symbol? : anytype -> boolean
Examples:(symbol? 'x)#t(symbol? x)Reference to undefined identifier: x(symbol? 3)#f(symbol? '3)#f(define b 2)(symbol? b)#f(define b 'a)(symbol? b)#t
מבוא מורחב - שיעור 109
The predicate eq?A primitive procedure that tests if the pointers representing the objects point to the same place.Based on two important facts:
• A symbol with a given name exists only once.
• Each application of cons creates a new pair, different from any other previously created.
Therefore
(eq? ‘a ‘a) #t
But
(eq? ‘(a b) ‘(a b)) #f
מבוא מורחב - שיעור 1010
x y
ba
z
eq? example
(define x ‘(a b))
(define y ‘(a b))
(define z y)
(eq? x y) (eq? y z) (eq? y ‘(a b))
#f#t
#f (a new list is created)
מבוא מורחב - שיעור 1011
The predicate equal?A primitive procedure that tests if the pointers
represent identical objects
1. For symbols, eq? and equal? are equivalent
2. If two pointers are eq?, they are surely equal?
3. Two pointers may be equal? but not eq?
• (equal? ‘(a b) ‘(a b)) #t
• (equal? ‘((a b) c) ‘((a b) c)) #t
• (equal? ‘((a d) c) ‘((a b) c)) #f
מבוא מורחב - שיעור 1012
Symbolic differentiation
(deriv <expr> <with-respect-to-var>) ==> <new-expr>
The expressions we deal with: x+y x+5 2x(x+5) + 2xy
deriv of (x+y) with respect to x = 1
deriv of (2x(x+5) + 2xy ) w.r.t x = 2(x+5) + 2x + 2y
For now we allow only addition and multiplication
מבוא מורחב - שיעור 1013
Step 1: Representing expressions.
Use list of symbols.
There are still few possible lists one can think of
For example, we can represent 2x+5 as'(2 * x + 5) or '(2 x + 5)
We shall use a list structure corresponding to the same prefix notation used by scheme in combinations.
'(+ (* 2 x) 5)
מבוא מורחב - שיעור 1014
Step 1: Legal Expressions- formal
Expr ::= SimpleExpr | CompoundExpr
SimpleExpr ::= number | symbol
CompoundExpr ::= ( OPERATOR Expr Expr )
OPERATOR ::= +|*
Using Backus-Naur-Form BNF, a formalism fordefining the syntax of programming languages.
מבוא מורחב - שיעור 1015
Example
(deriv <expr> <with-respect-to-var>) ==> <new-expr>
(deriv '(+ x 3) 'x) ==> 1
(deriv '(+ (* x y) 4) 'x) ==> y
(deriv '(* x x) 'x) ==> (+ x x)
(deriv 7 'x) ==> 0
(deriv 'x 'x) ==> 1
Want deriv to be such that
מבוא מורחב - שיעור 1016
Step 2: Abstraction: The underlying interface
Constructors: make-product make-sumPredicates: number? variable? sum-expr? product-expr?Selectors: addend augend multiplier multiplicand
מבוא מורחב - שיעור 1017
Step 3: Breaking the problem to smaller subproblems
• Base case: (corresponds to SimpleExpr) deriv number w.r.t. x = 0 deriv variable w.r.t. x = 1 if variable is the same as x
= 0 otherwise
• Recursive case: (corresponds to CompoundExpr)
(f+g)’ = f’ + g’ (f*g)’ = f * g’ + g * f’
מבוא מורחב - שיעור 1018
Step 4: An algorithm assuming an abstract interface.
(define deriv (lambda (expr var)
(cond
((number? expr) 0)
((variable? expr) (if (eq? expr var) 1 0))
((sum-expr? expr)
(make-sum (deriv (addend expr) var)
(deriv (augend expr) var)))
((product-expr? expr)
(make-sum
(make-product (multiplier expr)
(deriv (multiplicand expr) var))
(make-product (multiplicand expr)
(deriv (multiplier expr) var)))
(else (error "unknown expression" expr))))
מבוא מורחב - שיעור 1019
Step 5: The underlying interface – constructors and selectors.
And the selectors:
(define (addend expr) (cadr expr)) (define (augend expr) (caddr expr))
(define (multiplier expr) (cadr expr)) (define (multiplicand expr) (caddr expr))
We define the constructors:
(define (make-sum e1 e2) (list '+ e1 e2))
(define (make-product e1 e2) (list '* e1 e2))
מבוא מורחב - שיעור 1020
Step 5: The underlying interface – predicates.
(define (sum-expr? expr) (and (pair? expr)
(eq? (car expr) '+)))
(define (variable? expr) (symbol? expr))
(define (product-expr? expr) (and (pair? expr)
(eq? (car expr) '*)))
מבוא מורחב - שיעור 1021
(deriv '(* (+ x y) (+ x (* -1 y))) 'x) (+ (* (+ x (* -1 y)) (+ 1 0)) (* (+ x y) (+ 1 (+ (* y 0) (* -1 0)))))
Writing, Debugging, Testing…
(deriv 5 ‘x) 0(deriv ‘x ‘x) 1 (deriv ‘x ‘y) 0…
(deriv ‘(+ x y) ‘x) (+ 1 0)(deriv ‘(+ x y) ‘z) (+ 0 0)
(deriv '(* (+ x y) (- x y)) 'x) unknown expression (- x y)
מבוא מורחב - שיעור 1022
We would like to simplify expressions.
Instead of the expression (+ (* (+ x (* -1 y)) (+ 1 0)) (* (+ x y) (+ 1 (+ (* y 0) (* -1 0))))) [= (x-y)+ (x+y)]We would like to have 2x or actually (* 2 x)
What should we change?
How easy is it to make the change?
מבוא מורחב - שיעור 1023
We change make-sum and make-product
It’s easier to change a well-written code.
(define (make-sum a1 a2) (cond ((and (number? a1) (= a1 0)) a2) ((and (number? a2) (= a2 0)) a1) ((and (number? a1) (number? a2)) (+ a1 a2)) (else (list '+ a1 a2))))
(define (make-product a1 a2) (cond ((and (number? a1) (= a1 0)) 0) ((and (number? a2) (= a2 0)) 0) ((and (number? a1) (= a1 1)) a2) ((and (number? a2) (= a2 1)) a1) ((and (number? a1) (number? a2)) (* a1 a2)) (else (list '* a1 a2))))
מבוא מורחב - שיעור 1024
Testing again..
(deriv '(* (+ x y) (+ x (* -1 y))) 'x) (+ (+ x (* -1 y)) (+ x y))
This is an improvement.
There is still a long way to go….
מבוא מורחב - שיעור 1025
Allowing (- x y)(define deriv (lambda (expr var)
(cond
((number? expr) 0)
((variable? expr) (if (eq? expr var) 1 0))
((sum-expr? expr)
(make-sum (deriv (addend expr) var)
(deriv (augend expr) var)))
((minus-expr? expr)
(make-minus (deriv (addend expr) var)
(deriv (augend expr) var)))
((product-expr? expr)
. . . .
(else (error "unknown expression" expr))))
מבוא מורחב - שיעור 1026
Allowing (- x y)
(define (make-minus a1 a2) (cond ((and (number? a1) (number? a2)) (- a1 a2)) ((and (number? a2) (= a2 0)) a1) (else (list ‘- a1 a2))))
(define (minus-expr? expr) (and (pair? expr)
(eq? (car expr) ‘-)))
• We use the same selectors as in sum-expr. • Could do the same for product-expr• Is it a good idea?
מבוא מורחב - שיעור 1027
Allowing (- x y)
(deriv '(* (+ x y) (+ x (* -1 y))) 'x)
Now instead of:
We can write:
(deriv '(* (+ x y) (- x y)) 'x) (+ (+ x y) (- x y))
There’s still room for improvement!
מבוא מורחב - שיעור 1028
Allowing x^k, …. ,1/x, (ln x)
(define (ln-expr? expr) (and (pair? expr)
(eq? (car expr) 'ln)))
(define deriv (lambda (expr var)
(cond …
((minus-expr? expr)
…
((ln-expr? expr)
…
)..)
מבוא מורחב - שיעור 1029
Allowing (+ x y z … w) (* x y z … w)
How about the following change:
(define (addend expr) (cadr expr))
(define (augend expr)
(let ((first (car expr))
(second (cadr expr))
(rest (cddr expr)))
(cond ((> (length rest) 1) (cons first rest))
((= (length rest) 1) (car rest)))))Similarly for multiplier and multiplicand
מבוא מורחב - שיעור 1030
Testing..
> (deriv '(* x y z w x t y ) 't)(* x (* y (* z (* w (* x y)))))> (deriv '(* x y z w x t y) 'x)(+ (* y z w x t y) (* x (* y (* z (* w (* t y))))))
> (deriv '(+ x y z w a b c x y z e r t ) 'y)2> (deriv '(+ x y z w a b c x y z e r t ) 'f)0