61A Lecture 6 - inst.eecs.berkeley.edu

61A Lecture 6
Friday, September 7
Lambda Expressions
An expression: this one
evaluates to a number
>>> ten = 10
>>> square = x * x
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"
>>> square(4)
16
Must be a single expression
Lambda expressions are rare in Python, but important in general
2
Lambda Expressions Versus Def Statements
square = lambda x: x * x
VS
def square(x):
return x * x
• Both create a function with the same arguments & behavior
• Both of those functions are associated with the environment
in which they are defined
• Both bind that function to the name "square"
• Only the def statement gives the function an intrinsic name
The Greek
letter lambda
3
Function Currying
def make_adder(n):
return lambda k: n + k
>>> make_adder(2)(3)
5
>>> add(2, 3)
5
There's a general
relationship between
these functions
Currying: Transforming a multi-argument function into a
single-argument, higher-order function.
Fun Fact: Currying was discovered by Moses Schönfinkel and
later re-discovered by Haskell Curry.
Schönfinkeling?
4
Newton's Method Background
Finds approximations to zeroes of differentiable functions
2.5
f(x) = x2 - 2
-5
-2.5
A "zero"
0
-2.5
2.5
5
x=1.414213562373095
Application: a method for (approximately) computing square
roots, using only basic arithmetic.
The positive zero of f(x) = x2 - a is
5
Newton's Method
Begin with a function f and
-f(x)/f'(x)
an initial guess x
-f(x)
(x, f(x))
1.
Compute the value of f at the guess: f(x)
2.
Compute the derivative of f at the guess: f'(x)
3.
Update guess to be:
)
6
Visualization of Newton's Method
(Demo)
http://en.wikipedia.org/wiki/File:NewtonIteration_Ani.gif
7
Using Newton's Method
How to find the square root of 2?
>>> f = lambda x: x*x - 2
>>> find_zero(f)
1.4142135623730951
f(x) = x2 - 2
How to find the log base 2 of 1024?
>>> g = lambda x: pow(2, x) - 1024
>>> find_zero(g)
10.0
g(x) = 2x - 1024
What number is one less than its square?
>>> h = lambda x: x*x - (x+1)
>>> find_zero(h)
1.618033988749895
h(x) = x2 - (x+1)
8
Special Case: Square Roots
How to compute square_root(a)
Idea: Iteratively refine a guess x about the square root of a
Update:
=
+
Babylonian Method
Implementation questions:
What guess should start the computation?
How do we know when we are finished?
9
Special Case: Cube Roots
How to compute cube_root(a)
Idea: Iteratively refine a guess x about the cube root of a
Update:
=
·
+
Implementation questions:
What guess should start the computation?
How do we know when we are finished?
10
"""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
x):
(2*x + a/(x * x))/3
def return
square_root_update(guess,
x): cube_root_update(guess,
return (x / (guess * guess) + 2 * guess)/3
return average(guess, x / guess)
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=10
def return
golden_test(guess):
improve guess with update until don
return guess * guess == guess """Iteratively
+ 1
def iter_improve(update, done, guess=1, max_updates=1000):
improvedone,
guessguess=1,
with
until done returns a true value.
guessupdate
−−
A number
def """Iteratively
iter_improve(update,
max_updates=1000):
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
update
−− AA number
function from guesses to guesses; updates the guess
guess −−
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)
return
guess
while not done(guess) and n < max_updates:
k
=
k
+
1
guess = update(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)
"""
Derivatives of Single-Argument Functions
3
= lim
2
1
-4
-3
-2
-1
0
1
2
3
4
5
x + h = 1.1
-1
x = 1
-2
-3
(Demo)
http://en.wikipedia.org/wiki/File:Graph_of_sliding_derivative_line.gif
12
Approximating Derivatives
(Demo)
13
"""
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
def
cube_root_newton(x):
Implementing
Newton's
Method
df = f(x + delta)
− 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):
find_root(lambda
y:
sin(y),
3)
df = f(x +andelta)
− function
f(x)
"""Return
update
for
f using Newton's method."""
3.141592653589793
return
df/delta
def
""" update(x):
approximated
return
x − f(x) Limit
/ 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():
return
x
− f(x)
"""Return a guess
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():
14
return iter_improve(newton_update(f), lambda x: f(x) == 0, guess)
interact()