CS 227 Lecture -*- Outline -*- Remember to talk about all let/letrec's in the programs. Show how to use (load "ch5.ss") to get polynomials * Symbolic Manipulation of Polynomials this section is a good example, both of the use of let and letrec, and of data abstraction. (remember the ratls?) It is also a good example of symbol processing in Scheme -- several large systems are built in LISP -- systems like Mathematica. This will also help us study machine arithmetic. ** Polynomials (review of math for terminology) --------------------- POLYNOMIALS 41 2 -25.2 x + 3.4 x + 2.3 x - 5.3 --------------------- *** Terms (parts of polynomial) or monomials ------------------ TERM VALUES 41 -25.2 x as printed by print-poly: -25.2 x^{41} 41 -25.2 x is a term (monomial) -25.2 is a coefficient (a real) 41 is the degree (natural number) ------------------ Terms of same degree can be added ------------------ OPERATIONS ON TERMS addition of terms of like degree: 3.1 x^2 + 2.2 x^2 ========= ------------------ and can multiply by a real ------------------ scalar multiplication: 3 7.0 * (-4 x ) = ------------------ Write these symbolically, use k for degree a_k and b_k for coefficients c for a real number Can multiply 2 terms (even if degrees differ) (a_j x^j)(b_k x^k) = (a_j b_k) (x^{j+k}) ------------------ multiplication by another term: -2.1 x^{41} * 3.0 x^2 ================= ------------------ have them do this. *** Polynomial values When add 2 terms of different degree, do not get a new term -- have to just symbolically record that they are added ------------------ POLYNOMIAL VALUES -2.1 x^{41} + 3.0 x^2 ======================= -2.1 x^{41} + 3.0 x^2 ------------------ Do this symbolically. Note that the plus is just a notation. Point out degree, leading term, leading coefficient. ------------------ Def: a polynomial value is either coef or coef x^{degree} + rp where degree is a natural, coef is a real number, and rp is a polynomial value. ------------------ *** polynomial objects ------------------ POLYNOMIAL OBJECTS Def: a polynomial object (type poly) is either the-zero-poly or (poly-cons degree coef rp) where degree is a natural, coef is a real, and rp is a polynomial object. ------------------- *** basic procedures ------------------- BASIC PROCEDURES the-zero-poly: poly poly-cons: (-> (natural real poly) poly) ; REQUIRES: poly's degree < the natural ; unless the poly is 0 x^0 degree: (-> (poly) integer) leading-coef: (-> (poly) real) rest-of-poly: (-> (poly) poly) ------------------ Note that the arguments of poly-cons are "backwards" Note that you get these by loading "ch5.ss" *** examples Build some polynomials with these on-line, or on the board Show how result of poly-cons is used by observers *** equations -------------- EQUATIONS FOR POLYNOMIALS assuming (degree p) < d (poly-cons (degree p) (leading-coef p) (rest-of-poly p)) = (degree the-zero-poly) = (degree (poly-cons d c p)) = (leading-coef the-zero-poly) = (leading-coef (poly-cons d c p)) = (rest-of-poly the-zero-poly) = (rest-of-poly (poly-cons d c p)) = ------------- Better to leave some of these blank. These are key to recursion on polys (remember data driven recursion?) Show what happens if violate restriction on poly-cons. ** Algebra of polynomials This is another layer of operations, like we did for rationals we'll use these to build addition, etc. NOT part of the basic operations *** Convenience Ops. Write these out on the board, or have them write... What would be the base case for polys? Test for zero (5.6) --------------- (zero-poly? the-zero-poly) ==> #t (zero-poly? (poly-cons 7 4. the-zero-poly)) ==> #f ;; Program 5.6 (define zero-poly? ; TYPE: (-> (poly) boolean) (lambda (poly) (and (zero? (degree poly)) (zero? (leading-coef poly))))) ;; What's wrong with the following? (define zero-poly? ; TYPE: (-> (poly) boolean) (lambda (poly) (and (zero? (car poly)) (zero? (cadr poly))))) --------------- have them answer in groups. make-term (5.7). Note args "backwards" as in poly-cons -------------- (print-poly (make-term 7 5.1)) =prints=> 5.1 x^7 ;; Program 5.7 (define make-term ; TYPE: (-> (natural real) poly) (lambda (deg coef) ; ENSURES: the result is coef*x^{deg} (poly-cons deg coef the-zero-poly))) YOU DO THESE (print-poly (monomial 5.1 7)) =prints=> 5.1 x^7 --------------------- have them do this in groups ;elegant solution... (define monomial ; TYPE: (-> (real natural) poly) (lambda (coef deg) (make-term deg coef))) leading-term (5.8) --------------- (print-poly (leading-term (poly-cons 7 5.1 (poly-cons 6 -3.2 the-zero-poly)))) =prints=> 5.1 x^7 ---------------- have them do this in groups ;; Program 5.8 (define leading-term ; TYPE: (-> (poly) poly) (lambda (poly) (make-term (degree poly) (leading-coef poly)))) and play with these. ** Programs for adding and multiplying polynomials Start with addition ------------------ ADDITION OF POLYNOMIALS -4 x^7 + 3.2 x^2 + 4.0 x + 5.3 x^5 + 7.1 x + 3.4 ========================================== (print-poly (p+ (poly-cons 7 -4 (poly-cons 2 3.2 (poly-cons 1 4.0 the-zero-poly))) (poly-cons 5 5.3 (poly-cons 1 7.1 (poly-cons 0 3.4 the-zero-poly))) )) =prints=> -4 x^7 + 5.3 x^5 + 3.2 x^2 + 11.1 x + 3.4 ------------------ *** Addition develop p+ using the following steps What is the type? poly, poly --> poly So we guess this is simultaneous (flat) recursion over polynomials base: If either argument is zero, can return the other, induction: want to do something with leading terms and the rest of each 2 cases: Degrees of each is same (poly-cons (degree poly1) ; = (degree poly2) (+ (leading-coef poly1) (leading-coef poly2)) (p+ (rest-of-poly poly1) (rest-of-poly poly2))) If degrees differ, then because of restrictions on poly-cons, have to figure out which is bigger. (if (> (degree poly1) (degree poly2)) (poly-cons (degree poly1) (leading-coef poly1) (p+ (rest-of-poly poly1) poly2))) But note the verbose and redundant computation of (degree poly1), better to use let. Show Figure 5.9 ------------------ (define p+ ; TYPE: (-> (poly poly) poly) (lambda (poly1 poly2) (cond ((zero-poly? poly1) poly2) ((zero-poly? poly2) poly1) (else (let ((n1 (degree poly1)) (n2 (degree poly2)) (a1 (leading-coef poly1)) (a2 (leading-coef poly2)) (rest1 (rest-of-poly poly1)) (rest2 (rest-of-poly poly2))) (cond ((> n1 n2) (poly-cons n1 a1 (p+ rest1 poly2))) ((< n1 n2) (poly-cons n2 a2 (p+ poly1 rest2))) (else (poly-cons n1 (+ a1 a2) (p+ rest1 rest2))) )))))) ------------------ *** Multiplication could do the same kind of thing for multiplication. ------------------ MULTIPLICATION 3 x^5 + 2 x^3 + 4 x + 3 * 4 x^2 + 3 x + 2 ========================================== 6 x^5 + 4 x^3 + 8 x + 6 + 9 x^6 + 6 x^4 + 12 x^2 + 9 x +12 x^7 + 8 x^5 + 16 x^3 + 12 x^2 ========================================== 12 x^7 + 9 x^6 + 14 x^5 + 6 x^4 + 20 x^3 + 24 x^2 + 17 x + 6 (print-poly (p* (poly-cons 5 3 (poly-cons 3 2 (poly-cons 1 4 (poly-cons 0 3 the-zero-poly)))) (poly-cons 2 4 (poly-cons 1 3 (poly-cons 0 2 the-zero-poly))))) =prints=> 12 x^7 + 9 x^6 + 14 x^5 + 6 x^4 + 20 x^3 + 24 x^2 + 17 x + 6y ------------------ This gives us a plan Multiply each term of one and add But have to do this recursively So want to multiply leading-term of one with the second, then add that to the product of the rest of one by the second. Call procedure t* that multiplies a term (or monomial) by a polynomial. Have to do this recursively also, by recursion on polys! defining t* and p* as separate defines ------------------- (define p* ; TYPE: (-> (poly poly) poly) (lambda (poly1 poly2) (if (zero-poly? poly1) the-zero-poly (p+ (t* (leading-term poly1) poly2) (p* poly1 (rest-of-poly p1)))))) (define t* ; TYPE: (-> (term poly) poly) (lambda (trm poly) ; ENSURES: result is the product of ; trm and poly (if (zero-poly? poly) the-zero-poly (poly-cons (+ (degree trm) (degree poly)) (* (leading-coef trm) (leading-coef poly)) (t* trm (rest-of-poly poly)))))) ------------------- Q: can you avoid passing any arguments in p* and t*? How? Q: can you avoid making t* a global name? How? What order is needed for the let/letrecs in the p* define? Explain literate programming stuff below --------------- <
>=
(define p* ;; program 5.10
(letrec (< >)
(p*-helper poly1)))))
< >=
(p*-helper ; TYPE: (-> (poly) poly)
(lambda (p1)
(if (zero-poly? p1)
the-zero-poly
(p+ (t* (leading-term p1) poly2)
(p*-helper (rest-of-poly p1))))
))
<