CS 22

Clab 7: Invariants, Divide and Conquer; Functions as first-class objects


At some point, I'll say a few words about invariants, Divide and Conquer, and Functions as first-class objects. When I am not talking work on the following stuff.

Down at the bottom, there is a solution to the exercise subst requested in Clab6.

Review the material in text on pp. 62-65 on lambda and let http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.2 . From r5rs in on-line help in drscheme, read about lambda and let (the binding construct meaning -- shun the sinful iteration material) Make sure you understand the examples illustrated and how the values were obtained. Ask questions if you have them.

Now enter the search procedure given on page 67.

(define (search f neg-point pos-point) (let ((midpoint (average neg-point pos-point))) (if (close-enough? neg-point pos-point) midpoint (let ((test-value (f midpoint))) (cond ((positive? test-value) (search f neg-point midpoint)) ((negative? test-value) (search f midpoint pos-point)) (else midpoint)))))) (define (close-enough? x y) (< (abs (- x y)) 0.001)) (define average (lambda (x y) (/ (+ x y) 2))) (define cube (lambda (x) (* x x x))) Make sure you understand what it is doing. You will need to define average and close-enough? if you have not done so already. The function cube that we have used before has a root at 0. Test search by evaluating: (search cube -1 2.0). This is an example of a divide and conquer algorithm. Divide and conquer is a general algorithm design technique. Using this technique, one tries to find a way to divide a problem in half (approximately) and then solve just half a problem (or even two halves sometimes, hoping that solving two halves will be easier than solving one whole). Turn trace on search and average and evaluate (search cube -1 2.0) again. Make sure you see how the algorithm is dividing the region where the root may be in half each pass through. The number of thousandths (.001s) between -1 and 2 is 3000 so you can se that the complexity of this algorithm is logarithmic in the size of the interval divided by the accuracy desired.

x^2-4 is a function with root at 2. Without naming this function, we can express it as (lambda (x) (- (square x) 4)). Try search on this function by evaluating: (search (lambda (x) (- (square x) 4)) 0 3.0). Check that you got the root.

1-x is the equation of the straight line that passes through the the points (0, 1) and (3, -2). We can express it as (lambda (x) (- 1 x)). Find the root of 1 -x by evaluating: (search (lambda (x) (- 1 x)) 0 3.0). You should have gotten an answer. BUT--Don't bet your life on the answer you got. What is the right answer? Did you get the right answer? Why not? What do you have to do to get the right answer? Now read page 67 again and then page 68.

Now carefully review the material on pages 73-75. http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.4

Define deriv as in the text . Note that deriv is a procedure that takes one argument, a function, and returns a function that is an approximation to the derivative of the first argument. deriv expects to be executed in an environment where dx is defined to be a small positive real number (e.g. 0.00001). You should have the functions square and cube defined from before. If not, define them now. Define dx to be 0.001. Now evaluate

(define Dsquare (deriv square)) Dsquare is a function that is an approximation to the derivative of x^2. That is Dsquare is a function that should be very close to the function 2x. Try evaluating Dsquare on some values and check that it does behave like an approximation to the function 2x. Now evaluate (define g (deriv cube)) g should be an approximation to the function 3x^2 which is the derivative of x^3. Check it on a few values.

The composition of 2 functions f and g, sometimes written fg is defined by fg(x) = f(g(x)). That is first apply g to x, then apply f to the result. For example if f(x) = x^3 and g(x) = 1 + x, then fg(x) = (1 + x)^3. We want to define a procedure that takes two functions as arguments and returns the composition of those two argument functions. Here is a start:

;;;given the 2 functions f and g, compose returns the composition fg (define (compose f g) (...you fill in this part) ;;; for convenience we will define the function 1+ which increments ;;; its argument by one. (define 1+ (lambda (x) (+ 1 x))) For example: > (1+ 7) 8 After you have successfully defined compose, you should be able to evaluate: (define h (compose cube 1+)) If you did it right h should be the function h(x) = (1 + x)^3.

Try it and check h for a few values. Try some other compositions.

Ask any questions you may have.


Solution to subst from clab06. There are other correct solutions.

;; subst returns a list with all occurrences of old ;; replaced with new in list l: (define subst (lambda (new old l) (cond ((null? l) '()) ((equal? (car l) old) (cons new (subst new old (cdr l)))) (else (cons (car l) (subst new old (cdr l)))))))