61A-006-Newton_6pp.pdf

Lambda Expressions
An expression: this one
evaluates to a number
>>> ten = 10
>>> square = x * x
61A Lecture 6
Also an expression:
evaluates to a function
>>> square = lambda x: x * x
Notice: no "return"
A function
with formal parameter x
and body "return x * x"
Friday, September 9
>>> square(4)
16
Must be a single expression
Lambda expressions are rare in Python, but important in general
2
Lambda Expressions Versus Def Statements
def make_adder(n):
return lambda k: n + k
def square(x):
return x * x
VS
square = lambda x: x * x
Function Currying
>>> make_adder(2)(3)
5
>>> add(2, 3)
5
• Both create a function with the same arguments & body
• Both of those functions are associated with the environment
in which they are defined
There's a general
relationship between
these functions
• Both bind that function to the name "square"
• Only the def statement gives the function an intrinsic name
<lambda>(x):
Currying: Transforming a multi-argument function into a
single-argument, higher-order function.
square(x):
return x * x
Fun Fact: Currying was discovered by Moses Schönfinkel and
later re-discovered by Haskell Curry.
return x * x
Schönfinkeling?
3
Newton's Method Background
4
Newton's Method
Begin with a function f and
Finds approximations to zeroes of differentiable functions
-f(x)/f'(x)
an initial guess x
2.5
-f(x)
y =
-5
x2
- 2
-2.5
A "zero"
0
2.5
5
(x, f(x))
x=1.414213562373095
-2.5
Application: a method for (approximately) computing square
roots, using only basic arithmetic.
The positive zero of y = x2 - a is
√
D
5
1.
Compute the value of f at guess: f(x)
2.
Compute the derivative of f at guess: f'(x)
3.
Update guess x to be:
[−
I[)
I
[
6
Visualization of Newton's Method
Using Newton's Method
How to find the square root of 2?
>>> f = lambda x: x*x - 2
>>> find_root(f, 1)
f(x)=x2 - 2
How to find the log base 2 of 1024?
(Demo)
>>> g = lambda x: pow(2, x) - 1024
>>> find_root(g, 1)
What number is one less than its square?
>>> h = lambda x: x*x - (x+1)
>>> find_root(h, 1)
http://en.wikipedia.org/wiki/File:NewtonIteration_Ani.gif
7
8
Special Case: Square Roots
Special Case: Square Roots
How to compute square_root(a)
How to compute cube_root(a)
Idea: Iteratively refine a guess x about the square root of a
Idea: Iteratively refine a guess x about the cube root of a
Update:
6_newton.py
[=
[+
D
[
"""Iterative improvement.""" newton.py
Page 1
Babylonian Method
from ucb import main, interact"""Iterative improvement."""
newton.py
Page 1
#
Direct implementations
from ucb import main, interact
Implementation
questions:
"""Iterative
improvement."""
def
square_root(a):
def average(x, y):
"""Return the square root of a.
(x + y)/2
What
guess
should
startreturn
the computation?
from ucb
import
main,
interact
>>> square_root(9)
def square_root(x):
def 3.0
average(x, y):
the square root of x.
return
(x +wey)/2
How do
know when we """Return
are finished?
"""
x = 1
>>> square_root(9)
def while
square_root(x):
x * x != a:
3.0
"""Return
the square root of x.
x = square_root_update(x,
a)
"""
9
return x
guess = 1
>>> square_root(9)
while not guess * guess == x:
3.0
def square_root_update(x,
a):
guess = square_root_update(guess, x)
"""
return
average(x, a/x)
return guess
guess = 1
while not guess
def average(x,
y): * guess == x:
def cube_root(x):
guess
square_root_update(guess,
x)
return
(x += y)/2
"""Return the cube root of x.
return guess
def cube_root(a):
def """Return
cube_root(x):
the cube root of a. >>> cube_root(27)
"""Return the cube root of x. 3.0
"""
>>> cube_root(27)
guess = 1
>>> cube_root(27)
3.0
while not guess * guess * guess == x:
3.0
"""
guess = cube_root_update(guess, x)
"""
x
= 1
return guess
guess pow(x,
= 1
while
3) != a:
while
not
guess * guess * guess
x =
cube_root_update(x,
a) == x:
def square_root_update(guess,
x):
return
x = cube_root_update(guess,
guess
x)
return average(guess, x / guess)
return guess
def cube_root_update(x, a):
(Demo)
def
(2*x + a/(x * x))/3
def return
square_root_update(guess,
x): cube_root_update(guess, x):
return (x / (guess * guess) + 2 * guess)/3
return average(guess, x / guess)
Iterative Improvement
[=
Update:
·[+
D
[
Page 1
Implementation questions:
What guess should start the computation?
How do we know when we are finished?
10
Iterative Improvement
def golden_update(guess):
#
Iterative
improvement
def
cube_root_update(guess,
x):
1/guess + 1
return (x / (guess * guess) + return
2 * guess)/3
def golden_update(x):
def golden_test(guess):
1/x + 1
def return
golden_update(guess):
return guess * guess == guess + 1
return 1/guess + 1
def golden_test(x):
x * x == x + 1
def iter_improve(update, done, guess=1, max_updates=1000):
def return
golden_test(guess):
improve guess with update until done returns a update:
true value.
return guess * guess == guess """Iteratively
+ 1
def iter_improve(update, done, guess=1, max_updates=1000):
done:
"""Iteratively
improve
guess
with
update
until
done returns a true value.
guess
éé
A
number
def iter_improve(update, done, guess=1, max_updates=1000):
guess:
1
update
éé A until
function
guesses
to guesses
"""Iteratively improve guess with
update
donefrom
returns
a true
value.
guess éé An initial guess
done éé A function from guesses to boolean values
iter_improve
update
éé
A
function
from
guesses
to
guesses;
updates
the
guess
guess éé A number
done
éé éé
A function
from
guesses
boolean
values; tests if guess
is good
>>>toiter_improve(golden_update,
golden_test)
update
A function
from
guesses
to
guesses
1.618033988749895
done éé A function from guesses
to boolean values
>>> iter_improve(golden_update,
"""golden_test)
1.618033988749895
n =golden_test)
0
>>> iter_improve(golden_update,
"""
while not done(guess) and n < max_updates:
1.618033988749895
k
= 0
guess = update(guess)
"""
while
not
done(guess)
and
k
<
max_updates:
n = n + 1
n = 0
guess
update(guess)
guess
while
not =done(guess)
and n < return
max_updates:
k
= k += 1update(guess)
guess
return guess
def square_root_improve(x):
n = n + 1
"""Return the square root of x.
return guess
def square_root_improve(a):
"""Return the square root of a.
11
>>> square_root_improve(9)
def square_root_improve(x):
3.0
"""Return
the square root of x.
>>>
square_root_improve(9)
"""
3.0
def update(guess):
>>> square_root_improve(9)
"""
return square_root_update(guess, x)
3.0 update(guess):
def
def done(guess):
""" return square_root_update(guess,
a) guess * guess == x
return
def done(guess):
update(guess):
def
done)
return guess
square_root_update(guess,
x)
return
* guess == a return iter_improve(update,
def
done(guess):
return iter_improve(update, done)
golden_update:
golden_update
golden_test:
golden_test
iter_improve:
iter_improve
1
2.0
1.5
1.6666666666666665
guess: 1
1.6
golden_test
guess:
1.625
1.6153846153846154
1.619047619047619
1.6176470588235294
1.6181818181818182
12
Square Roots by Iterative Improvement
Square Roots by Iterative Improvement
square_root:
square_root:
(Demo)
square_root
(Demo)
square_root
iter_improve:
iter_improve:
iter_improve
...
a: 256
update:
done: ...
...
a: 256
update:
done: ...
update(guess):
square_root
iter_improve
square_root
return ...
guess:1
square_root(256)
guess: 1
update:
...
update(guess):
return ...
iter_improve
update
def update(guess):
...
...
return iter_improve(...)
square_root(256)
...
return iter_improve(...)
square_root(256)
13
Derivatives of Single-Argument Functions
square_root(256)
14
Approximating Derivatives
3
I
[ = lim
K →
I[KI[
K
2
1
-4
-3
-2
-1
0
newton.py
1
2
3
4
5
x + h = 1.1
Page 2
(Demo)
-1
3.0
"""
x = 1
def update(guess):
return cube_root_update(guess,
x)
-2
def done(guess):
return guess * guess * guess == x
return iter_improve(update, done)
-3
newton.py
def
square_root_newton(x):
"""Return the square root of(Demo)
x.
3.0
""" square_root_newton(9)
>>>
http://en.wikipedia.org/wiki/File:Graph_of_sliding_derivative_line.gif
def update(guess):
newton.py
3.0
15
""" return cube_root_update(guess, x)
def
3.0 done(guess):
return
find_root(lambda y: y * y é x)
""" return guess * guess * guess == x
def update(guess):
return
iter_improve(update, done)
def cube_root_newton(x):
returnthe
cube_root_update(guess,
x)
"""Return
cube root of x.
def done(guess):
def square_root_newton(x):
return
guess
*
guess
*
guess
==
x
"""Return
the
square
root
of
x.
>>> cube_root_newton(27)
return iter_improve(update, done)
3.0
>>>
square_root_newton(9)
"""
def 3.0
square_root_newton(x):
return
find_root(lambda y: y * y * y é x)
"""Return the square root of x.
"""
return find_root(lambda
y: y * y é x)
def approx_derivative(f,
x, delta=1eé5):
>>> square_root_newton(9)
"""Return
an approximation to the derivative of f at x."""
3.0= f(x + delta)
def
cube_root_newton(x):
Implementing
Newton's
Method
df
é f(x)
"""
"""Return
the cube root of x.
return
df/delta
return find_root(lambda y: y * y é x)
>>>
cube_root_newton(27)
def newton_update(f):
def 3.0
cube_root_newton(x):
"""Return
an update function for f using Newton's method."""
"""Return
the cube root of x.
"""
def
update(x):
return
find_root(lambda
y: y * y * y é x) x)
return
x é f(x) / approx_derivative(f,
>>>
cube_root_newton(27)
return update
3.0
def approx_derivative(f,
x, delta=1eé5):
Could to
be the
replaced
with of f at x."""
"""
"""Return
an guess=1):
approximation
derivative
def find_root(f,
return
y: exact
yof* the
y derivative
* function
y é x)
df
= f(xfind_root(lambda
+adelta)
é f(x)
"""Return
guess of
a the
zero
f, near guess.
return df/delta
def approx_derivative(f, x, delta=1eé5):
>>>
from
math
import
sin
"""Return an approximation to the derivative of f at x."""
def >>>
newton_update(f):
y: sin(y), 3)
df =find_root(lambda
f(x +andelta)
f(x)
"""Return
updateé function
for f using Newton's method."""
3.141592653589793
return df/delta
def
""" update(x):
Limit
approximated
return
x
é
f(x)
/
approx_derivative(f,
x)x: f(x) == 0, guess)
return
iter_improve(newton_update(f), lambda
def return
newton_update(f):
by a small value
update
"""Return an update function for f using Newton's method."""
@maindef update(x):
def
guess=1):
def find_root(f,
run():
returna xguess
é f(x)
"""Return
of /a approx_derivative(f,
zero of the function x)
f, near guess.
interact()
return update
>>> from math import sin
Definition of a
def >>>
find_root(f,
guess=1):
find_root(lambda
y: sin(y), 3)
function
"""Return a guess of a zero of the function
f, nearzero
guess.
3.141592653589793
"""
>>> from
math import sin
return
iter_improve(newton_update(f),
lambda x: f(x) == 0, guess)
>>> find_root(lambda y: sin(y), 3)
@main3.141592653589793
"""
def run():
17
return iter_improve(newton_update(f), lambda x: f(x) == 0, guess)
interact()
@main
def run():
interact()
Page 2
Page 2
16