Simpson’s Rule is a more accurate method of numerical integration than the method illustrated above. Using Simpson’s Rule, the integral of a function f between a and b is approximated as
where
I’m going to regroup the terms for ease of computation into those multiplied by 1, 2 and 4. I’ll re-use the sum function that’s in the chapter.
(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))
(define (cube x) (* x x x))
;; This will assume that n is even, which is fine for the tasks we
;; have been given of 100 and 1000. I'm not going to bother doing
;; e.g. Simpson's 3/8 rule.
(define (int-simpson f a b n)
(define h (/ (- b a) n))
(define (add-2h x) (+ x h h))
(* (+ (f a)
(* 2 (sum f (add-2h a) add-2h (- b h)))
(* 4 (sum f (+ a h) add-2h b))
(f b))
(/ h 3)))
(display (int-simpson cube 0 1.0 100)) (newline)
(display (int-simpson cube 0 1.0 1000)) (newline)
;; 0.25000000000000044
;; 0.25000000000000083For the same number of steps this gives a little more accuracy on the input values we have.
Now do it iteratively.
(define (sum term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (+ result (term a)))))
(iter a 0))Reasonably straight forward one here.
Did this for Zach ahead of time, will copy the question in later.
- Defining product
(define (product f a g b)
(if (> a b)
1
(* (f a)
(product f (g a) g b))))- Need to still rewrite it as tail recursive but for approximating π we can use Wallis’ formula as shown
(define (approx n)
(define (f n)
(* (/ (* 2 n)
(- (* 2 n) 1))
(/ (* 2 n)
(+ (* 2 n) 1))))
(product f 1.0 inc n))Doing it iteratively.
(define (product term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (* (term a) result))))
(iter a 1))Show that sum and product (Exercise 1.31) are both special cases of a still more general notion called accumulate that combines a collection of terms, using some general accumulation function:
(accumulate combiner null-value term a next b)Accumulate takes as arguments the same term and range specifications as sum and product, together with a combiner procedure (of two arguments) that specifies how the current term is to be combined with the accumulation of the preceding terms and a null-value that specifies what base value to use when the terms run out. Write accumulate and show how sum and product can both be defined as simple calls to accumulate.
If your accumulate procedure generates a recursive process, write one that generates an iterative process. If it generates an iterative process, write one that generates a recursive process.
Using the bits developed in the previous exercise:
(define (accumulate combiner null-value term a next b)
(if (> a b)
null-value
(combiner (term a)
(accumulate combiner null-value term (next a) next b))))
(define (accumulate-iter combiner null-value term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (combiner result (term a)))))
(iter a null-value))Then
(define (sum term a next b)
(accumulate + 0 term a next b))
(define (sum-iter term a next b)
(accumulate-iter + 0 term a next b))
(define (product term a next b)
(accumulate * 1 term a next b))
(define (product-iter term a next b)
(accumulate-iter * 1 term a next b))You can obtain an even more general version of accumulate (Exercise 1.32) by introducing the notion of a filter on the terms to be combined. That is, combine only those terms derived from values in the range that satisfy a specified condition. The resulting filtered-accumulate abstraction takes the same arguments as accumulate, together with an additional predicate of one argument that specifies the filter. Write filtered-accumulate as a procedure. Show how to express the following using filtered-accumulate:
- the sum of the squares of the prime numbers in the interval a to b (assuming that you have a prime? predicate already written)
- the product of all the positive integers less than n that are relatively prime to n (i.e., all positive integers i<n such that GCD(i,n)=1).
;; filtered accumulate
(define (filtered-accumulate predicate? combiner null-value term a next b)
(if (> a b)
null-value
(combiner
(if (predicate? a) (term a) null-value)
(filtered-accumulate predicate? combiner null-value term (next a) next b))))
;; sum of squares of primes in an interval
(define (inc n) (+ n 1))
(define (sum-of-squares-prime a b)
(filtered-accumulate prime? + 0 square a inc b))
;; product of all positive integers less than n that are relatively prime to n
;; define the predicate to check for being relatively prime
(define (relative-prime? i n)
(= (gcd i n) 1))
(define (id x) x)
;; predicate in filtered-accumulate only has one argument so we need some faffery
;; to get access to the namespace to get n
(define (product-of-relative-prime n)
(define (relative-prime? i)
(= (gcd i n) 1))
(filtered-accumulate relative-prime? * 1 identity 1 inc (- n 1)))Suppose we define the procedure
(define (f g) (g 2))Then we have
(f square)
;; 4
(f (lambda (z) (* z (+ z 1))))
;; 6What happens if we (perversely) ask the interpreter to evaluate the combination (f f)? Explain.
The evaluation steps will be
(f f)
(f 2)
(2 2)And will fail, since 2 is not an function.
Show that the golden ratio φ is a fixed point of the transformation
The fixed point for
Which we can reformulate as
Now do it programatticaly.
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2))
tolerance))
(define (try guess)
(let ((next (f guess)))
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
(display (fixed-point (lambda (x) (+ 1 (/ 1 x))) 1.0))
;; 1.6180327868852458Modify fixed-point so that it prints the sequence of approximations it generates, using the newline and display primitives shown in Exercise 1.22. Then find a solution to
Rewriting the above fixed-point definition to do what we need
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2))
tolerance))
(define (try guess)
(display guess) (newline)
(let ((next (f guess)))
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
;; undamped
(display (fixed-point (lambda (x) (/ (log 1000) (log x))) 2))
;; 2
;; 9.965784284662087
;; 3.004472209841214
;; 6.279195757507157
;; 3.759850702401539
;; 5.215843784925895
;; 4.182207192401397
;; 4.8277650983445906
;; 4.387593384662677
;; 4.671250085763899
;; 4.481403616895052
;; 4.6053657460929
;; 4.5230849678718865
;; 4.577114682047341
;; 4.541382480151454
;; 4.564903245230833
;; 4.549372679303342
;; 4.559606491913287
;; 4.552853875788271
;; 4.557305529748263
;; 4.554369064436181
;; 4.556305311532999
;; 4.555028263573554
;; 4.555870396702851
;; 4.555315001192079
;; 4.5556812635433275
;; 4.555439715736846
;; 4.555599009998291
;; 4.555493957531389
;; 4.555563237292884
;; 4.555517548417651
;; 4.555547679306398
;; 4.555527808516254
;; 4.555540912917957
;; 4.555532270803653
;; damped
(display (fixed-point (lambda (x) (average x (/ (log 1000) (log x)))) 2))
;; 2
;; 5.9828921423310435
;; 4.922168721308343
;; 4.628224318195455
;; 4.568346513136242
;; 4.5577305909237005
;; 4.555909809045131
;; 4.555599411610624
;; 4.5555465521473675
;; 4.555537551999825Damping causes it to take a lot fewer steps to converge in this case.
I’m not writing that one out. Hot damn.
(define (cont-frac-recur n d k)
(define (recur i)
(if (= k i)
(/ (n i) (d i))
(/ (n i) (+ (d i) (recur (+ 1 i))))))
(recur 1))Estimating
| k | result |
|---|---|
| 4 | 0.6000000000000001 |
| 5 | 0.625 |
| 6 | 0.6153846153846154 |
| 7 | 0.6190476190476191 |
| 8 | 0.6176470588235294 |
| 9 | 0.6181818181818182 |
| 10 | 0.6179775280898876 |
| 11 | 0.6180555555555556 |
| 12 | 0.6180257510729613 |
Calculating
Start at the lowest fraction and work up:
(define (cont-frac-iter n d k)
(define (iter i result)
(if (= 0 i)
result
(iter (sub i) (/ (n i) (+ result (d i))))))
(iter (sub k) (/ (n k) (d k))))