Example: Finding Fixed Points
Example: Finding Fixed Points
For some functions f we can locate the xed points by starting with an initial estimate and then by applying f in a repetitive way.
x, f(x), f(f(x)), f(f(f(x))), ...
until the value does not vary anymore (or the change is suciently small).
Programmatic Solution
This leads to the following function for nding a xed point:
val tolerance = 0.0001 def isCloseEnough(x: Double, y: Double) = abs((x - y) / x) / x < tolerance def fixedPoint(f: Double => Double)(firstGuess: Double) = { def iterate(guess: Double): Double = { val next = f(guess) if (isCloseEnough(guess, next)) next else iterate(next) } iterate(firstGuess) }
First Attempt
This suggests to calculate sqrt(x) by iteration towards a xed point:
def sqrt(x: Double) = fixedPoint(y => x / y)(1.0)
Unfortunately, this does not converge. Lets add a println instruction to the function fixedPoint so we can follow the current value of guess:
Average Damping
One way to control such oscillations is to prevent the estimation from varying too much. This is done by averaging successive values of the original sequence:
def sqrt(x: Double) = fixedPoint(y => (y + x / y) / 2)(1.0)
This produces
1.5 1.4166666666666665 1.4142156862745097 1.4142135623746899 1.4142135623746899
In fact, if we expand the xed point function fixedPoint we nd a similar square root function to what we developed last week.
Exercise:
Write a square root function using fixedPoint and averageDamp.
Summary
We saw last week that the functions are essential abstractions because they allow us to introduce general methods to perform computations as explicit and named elements in our programming language. This week, weve seen that these abstractions can be combined with higher-order functions to create new abstractions. As a programmer, one must look for opportunities to abstract and reuse. The highest level of abstraction is not always the best, but it is important to know the techniques of abstraction, so as to use them when appropriate.