sicp-solutions/ex-1.45.scm

81 lines
2.7 KiB
Scheme

#lang sicp
; here, I will prove an upper bound on the number of average
; dampings needed for a given n while calculating nth-root
; in other words, you might need fewer damps than what i prove
; but you definitely have enough damps with this method.
; with n, we need the transform y -> x/y^(n-1)
; one thing which will guarrantee convergence is that the
; derivative of the transform is 0 < d < 1 AFTER the point of
; convergence we're looking for, for example
; derivative of this transform is for SQUARE ROOT is:
; transf: y -> x/y
; deriv: -(x/y^2), which for y>=sqrt(x) will give us a number:
; -1 <= N <= 0, so we can't guarrantee divergence.
; when we average damp, the deriv becomes:
; ( -(x/y^2) + 1 ) / 2, now it lands between 0 and 1.
; for cube root, transform is y->x/y^2, deriv is:
; -2(x/y^3), this lands in the range -2 < d < 0
; if we damp it once, we get the range -0.5 < d < 0.5, so we
; need to damp again to get the range 0.25 < d < 0.75
; in general for calculating the nth-root, we need the
; transform y -> x/y^(n-1), which will have the derivative:
; -(n-1)(x/y^n), the derivative will for y>(nth-root x)
; fall in the range -(n-1) < d < 0.
; Note that when we average damp the function, this range
; becomes -((n-1+1)/2) = -n/2 < d < 0.5, then
; ((-n/2)+1) / 2 < d < 0.75
; when we play around we see that for n-1 = 1, we only need
; one damp, for n-1 = 2 or 3 we need two damps
; for n-1 = 4 or 5 or 6 or 7, we need three, in general
; for n >= 2, we need ceil(log2(n)), average damps
; again, note, we might actually need fewer damps, this is
; just and upper-bound, however, luckily, we can never
; over-damp with this function when coming from the right
; because the upper bound for the derivative values will
; always be 0.5,0.75,0.875,.... < 1.
; so with enought damping we can always get a range of derivs
; in 0 < d < 1.
(define (log2 x)
(/ (log x) (log 2)))
(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))
(define (identity x) x)
(define (compose f g)
(lambda (x) (f (g x))))
(define (repeated f n)
(if (= n 0)
identity
(compose f (repeated f (- n 1)))))
(define (average a b)
(/ (+ a b) 2))
(define (average-damp f)
(lambda (x) (average x (f x))))
; returns a procedure
(define (nth-root n)
(let* ((damp-number (ceiling (log2 n)))
(damps (repeated average-damp damp-number)))
(lambda (x)
(fixed-point (damps (lambda (y)
(/ x (expt y (- n 1)))))
(exact->inexact x)))))