320 likes | 351 Views
Symbols Manipulating lists and trees of symbols: symbolic differentiation. Lecture 10. 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.
E N D
SymbolsManipulating lists and trees of symbols:symbolic differentiation Lecture 10 מבוא מורחב - שיעור 10
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 מבוא מורחב - שיעור 10
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)) מבוא מורחב - שיעור 10
symboldelta symbolgamma Symbols are ordinary values In particular we can form lists of symbols. (list 1 2) ==> (1 2) (list 'delta 'gamma) ==> (delta gamma) מבוא מורחב - שיעור 10
The special form quote • (quote a) a • 'a a • (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) מבוא מורחב - שיעור 10
Examples using quote • (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) מבוא מורחב - שיעור 10
Syntactic Sugar מבוא מורחב - שיעור 10
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 מבוא מורחב - שיעור 10
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 מבוא מורחב - שיעור 10
z x y a b 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) מבוא מורחב - שיעור 10
The predicate equal? A primitive procedure that tests if the pointers represent identical objects • For symbols, eq? and equal? are equivalent • If two pointers are eq?, they are surely equal? • 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 מבוא מורחב - שיעור 10
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 מבוא מורחב - שיעור 10
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) מבוא מורחב - שיעור 10
Step 1: Legal Expressions- formal Using Backus-Naur-Form BNF, a formalism for defining the syntax of programming languages. Expr ::= SimpleExpr | CompoundExpr SimpleExpr ::= number | symbol CompoundExpr ::= ( OPERATORExprExpr ) OPERATOR ::= +|* מבוא מורחב - שיעור 10
Example (deriv <expr> <with-respect-to-var>) ==> <new-expr> Want deriv to be such that • (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 מבוא מורחב - שיעור 10
Step 2: Abstraction: The underlying interface Constructors: make-product make-sum Predicates: number? variable? sum-expr? product-expr? Selectors: addend augend multiplier multiplicand מבוא מורחב - שיעור 10
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’ מבוא מורחב - שיעור 10
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)))) מבוא מורחב - שיעור 10
Step 5: The underlying interface – constructors and selectors. We define the constructors: (define (make-sum e1 e2) (list '+ e1 e2)) (define (make-product e1 e2) (list '* e1 e2)) And the selectors: (define (addend expr) (cadr expr)) (define (augend expr) (caddr expr)) (define (multiplier expr) (cadr expr)) (define (multiplicand expr) (caddr expr)) מבוא מורחב - שיעור 10
Step 5: The underlying interface – predicates. (define (sum-expr? expr) (and (pair? expr) (eq? (car expr) '+))) (define (product-expr? expr) (and (pair? expr) (eq? (car expr) '*))) (define (variable? expr) (symbol? expr)) מבוא מורחב - שיעור 10
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) (deriv '(* (+ x y) (+ x (* -1 y))) 'x) (+ (* (+ x (* -1 y)) (+ 1 0)) (* (+ x y) (+ 1 (+ (* y 0) (* -1 0))))) מבוא מורחב - שיעור 10
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? מבוא מורחב - שיעור 10
We change make-sum and make-product (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)))) It’s easier to change a well-written code. מבוא מורחב - שיעור 10
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…. מבוא מורחב - שיעור 10
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)))) מבוא מורחב - שיעור 10
Allowing (- x y) • We use the same selectors as in sum-expr. • Could do the same for product-expr • Is it a good idea? (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) ‘-))) מבוא מורחב - שיעור 10
Allowing (- x y) Now instead of: (deriv '(* (+ x y) (+ x (* -1 y))) 'x) We can write: (deriv '(* (+ x y) (- x y)) 'x) (+ (+ x y) (- x y)) There’s still room for improvement! מבוא מורחב - שיעור 10
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) … )..) מבוא מורחב - שיעור 10
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 multiplierandmultiplicand מבוא מורחב - שיעור 10
Testing.. > (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 > (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)))))) מבוא מורחב - שיעור 10
Guidelines • Carefully think about • The problem • Type of data • The algorithm. • Identify • Constructors • Selectors • Other operations • Use data abstractions. • Respect abstraction barriers. • Avoid nested if expressions, complicated procedures and always use good names. מבוא מורחב - שיעור 10