exec, callback, and iterators -...

35
exec, callback, and iterators 1 The exec Function changing programs at run time constructing and defining the Simpson rule 2 Adding a Callback Function a function for Newton’s method a function of the user to process results 3 A Newton Iterator defining a counter class refactoring the Newton function into a class MCS 507 Lecture 10 Mathematical, Statistical and Scientific Software Jan Verschelde, 19 September 2012 Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 1 / 35

Transcript of exec, callback, and iterators -...

exec, callback, and iterators

1 The exec Functionchanging programs at run timeconstructing and defining the Simpson rule

2 Adding a Callback Functiona function for Newton’s methoda function of the user to process results

3 A Newton Iteratordefining a counter classrefactoring the Newton function into a class

MCS 507 Lecture 10Mathematical, Statistical and Scientific Software

Jan Verschelde, 19 September 2012

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 1 / 35

exec, callback, and iterators

1 The exec Functionchanging programs at run timeconstructing and defining the Simpson rule

2 Adding a Callback Functiona function for Newton’s methoda function of the user to process results

3 A Newton Iteratordefining a counter classrefactoring the Newton function into a class

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 2 / 35

executing Python code

The exec executes a string containing Python code.

>>> exec("x=3")

This cannot be done with eval.

We illustrate exec turning a formula into a function:

The code for the function definition is stored in a triple quotedstring, spanning multiple lines.

An %s marks the position to insert a formula.

The insertion is done by the % operator.

Calling exec on the code defines the function.

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 3 / 35

the script show_exec.py

from math import *

formula = raw_input(’Give a formula in x : ’)code = """def f(x):

return %s""" % formulaexec(code)x = input(’give a value for x : ’)y = f(x)print formula, "at x =", x , "is", y

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 4 / 35

running show_exec.py

At the command prompt $ we type

$ python show_exec.pyGive a formula in x : x**2 + 3give a value for x : 2x**2 + 3 at x = 2 is 7

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 5 / 35

exec, callback, and iterators

1 The exec Functionchanging programs at run timeconstructing and defining the Simpson rule

2 Adding a Callback Functiona function for Newton’s methoda function of the user to process results

3 A Newton Iteratordefining a counter classrefactoring the Newton function into a class

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 6 / 35

code from lecture 9

from sympy import *var(’a,b,wa,wm,wb’)rule = lambda f: wa*f(a) + wm*f((a+b)/2) \

+ wb*f(b)b0 = lambda x: 1; b1 = lambda x: xb2 = lambda x: x**2; var(’f,x’)e0 = rule(b0) - integrate(b0(x),(x,a,b))e1 = rule(b1) - integrate(b1(x),(x,a,b))e2 = rule(b2) - integrate(b2(x),(x,a,b))R = solve((e0,e1,e2),(wa,wm,wb))v = rule(f)s = Subs(v,(wa,wm,wb), \(R[wa],R[wm],R[wb])).doit()

formula = factor(s)

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 7 / 35

defining a function

We use exec to turn formulainto a function for the Simpson rule:

code = """def Simpson(f,A,B):

y = %sz = Subs(y,(a,b),(A,B)).doit()return z

""" % formulaexec(code)

Observe the difference between the symbolic variables a and b in theformula and the actual names of the formal parameters in Simpson.

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 8 / 35

testing the function

We integrate any quadric (using sympy):

print ’integrating c0+c1*x+c2*x**2 over [L,U]’var(’c0,c1,c2,L,U’)q = lambda x: c0 + c1*x + c2*x**2vr = simplify(Simpson(q,L,U))print ’approximation :’, vrer = integrate(q(x),(x,L,U))print ’ exact value :’, erprint ’ the error :’, vr - er

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 9 / 35

exec, callback, and iterators

1 The exec Functionchanging programs at run timeconstructing and defining the Simpson rule

2 Adding a Callback Functiona function for Newton’s methoda function of the user to process results

3 A Newton Iteratordefining a counter classrefactoring the Newton function into a class

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 10 / 35

Newton’s method

from sympy import *def Newton(f,df,x0,n=5,eps=1.0e-8):

"""Runs Newton’s method on f(x) = 0.INPUT PARAMETERS :

f a function in one variable,df derivative of the function f,x0 initial guess for the root,n maximum number of iterations,eps accurary requirement on |f(x)|

and on the update to x, |dx|.ON RETURN : the tuple (x,dx,y,fail), with:

x approximation for the root,dx magnitude of last correction,y residual |f(x)|,fail is true if accuracy not reached.

"""

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 11 / 35

the body of the function

def Newton(f,df,x0,n=5,eps=1.0e-8):" ... "x = x0; fail = Truefor i in xrange(n):

dx = -f(x)/df(x)x = x + dxy = abs(f(x))if ((abs(dx) <= eps) or (y <= eps)):

fail = Falsebreak

return (x,abs(dx),y,fail)

Observe the break: to exit the for loop when the accuracyrequirement is reached.

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 12 / 35

the main function

def main():"""Prompts the user for an expression in x,computes its derivative and calls Newton."""var(’x’)e = input(’Give an expression in x : ’)d = e.diff(x) # using sympyf = lambda v: Subs(e,(x),(v)).doit()df = lambda v: Subs(d,(x),(v)).doit()x0 = input(’Give an initial guess : ’)x0 = float(x0) # force float arithmeticprint Newton(f,df,x0)

main()

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 13 / 35

running newtonfun.py

At the command prompt $, we type

$ python newtonfun.pyGive an expression in x : exp(-x**2)*sin(x)Give an initial guess : 0.3(-4.08514573514360e-9, 0.00120525211528220, \

4.08514573514360e-9, False)$

What if we want intermediate output?

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 14 / 35

exec, callback, and iterators

1 The exec Functionchanging programs at run timeconstructing and defining the Simpson rule

2 Adding a Callback Functiona function for Newton’s methoda function of the user to process results

3 A Newton Iteratordefining a counter classrefactoring the Newton function into a class

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 15 / 35

a callback function

def print_steps(D):"""Prints the content of the dictionary Dand prompts the user to continue or not."""s = ""for k in D.keys():

s = s + " " + k + ’ = ’if ((k == ’dx’) or (k == ’res’)):

s = s + (’%.3e’ % D[k])else:

s = s + str(D[k])print sanswer = raw_input("continue ? (y/n) ")return (answer == ’y’)

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 16 / 35

using the callback

def Newton(f,df,x0,n=5,eps=1.0e-8,g=None):

Inside the for loop:

if g != None:D = {’step’: i+1, ’x’: x, ’dx’: dx, ’res’: y}proceed = g(D)if proceed != None:

if not proceed: break

In main: print Newton(f,df,x0,g=print_steps)

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 17 / 35

running newtoncallback.py

$ python newtoncallback.pyGive an expression in x : exp(-x**2)*sin(x)Give an initial guess : 0.3

x = -0.0798341284754188 step = 1 \dx = -3.798e-01 res = 7.924e-02

continue ? (y/n) yx = 0.00120524803013647 step = 2 \

dx = 8.104e-02 res = 1.205e-03continue ? (y/n) y

x = -4.08514573514360e-9 step = 3 \dx = -1.205e-03 res = 4.085e-09

continue ? (y/n) n(-4.08514573514360e-9, 0.00120525211528220, \

4.08514573514360e-9, False)

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 18 / 35

exec, callback, and iterators

1 The exec Functionchanging programs at run timeconstructing and defining the Simpson rule

2 Adding a Callback Functiona function for Newton’s methoda function of the user to process results

3 A Newton Iteratordefining a counter classrefactoring the Newton function into a class

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 19 / 35

a Counter class

class Counter():"""Our first class stores a counter."""def __init__(self,v=0):

"""Sets the counter to the value v."""self.count = v

def __str__(self):"""Returns the string representation."""return "counter is " + str(self.count)

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 20 / 35

use in Python session

If the class definition is saved in classcounter.py:

>>> from classcounter import *>>> c = Counter(3)>>> print ccounter is 3>>> str(c)’counter is 3’

Although we are not supposed to, we can manipulate the data attributeof an object of the class Counter directly:>>> c.count3>>> c.count = -4>>> ccounter is -4

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 21 / 35

class definition continued

If c is a Counter object, then typing c at the interactive prompt is thesame as print c.__repr__().

def __repr__(self):"""Defines the representation."""return self.__str__()

def next(self):"""Adds one to the counter."""self.count = self.count + 1

The next() method models an iterator.

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 22 / 35

a test function

def test():"""Performs a simple test."""c = Counter(3)print cc.next()print c

if __name__=="__main__": test()

Because of the last line, we run as

$ python classcounter.pycounter is 3counter is 4

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 23 / 35

exec, callback, and iterators

1 The exec Functionchanging programs at run timeconstructing and defining the Simpson rule

2 Adding a Callback Functiona function for Newton’s methoda function of the user to process results

3 A Newton Iteratordefining a counter classrefactoring the Newton function into a class

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 24 / 35

a Newton iterator

Problem: Adding a callback function to a Newton functionwe can see intermediate results and even stop the iteration,but the callback function remains subordinate to the mainfunction that performs the Newton iterations.

The class NewtonIterator defines an object that storesthe state of all variables in a Newton iteration.

Applying the next() method to an object of the classNewtonIterator executes one Newton step.

Control of the execution is reverted to the consumer.

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 25 / 35

using newtoniterator

>>> from newtoniterator import *>>> f = lambda x: x**2 - 2.0>>> df = lambda x: 2.0*x>>> nf = NewtonIterator(f,df,2.0)>>> print nfstep 0 : x = 2.0000000000000000e+00, \

|dx| = 1.000e+00, |f(x)| = 2.000e+00>>> nf.next()>>> print nfstep 1 : x = 1.5000000000000000e+00, \

|dx| = 5.000e-01, |f(x)| = 2.500e-01

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 26 / 35

storing the state

class NewtonIterator():"""A Newton iterator applies the Newton operatorto find a solution to the equation f(x) = 0."""def __init__(self,f,df,x0,n=5,eps=1.0e-8):

"""Initializes the state of the iterator."""self.step = 0self.f = fself.df = dfself.x = float(x0)self.max = nself.eps = epsself.dx = 1.0self.res = abs(f(x0))

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 27 / 35

printing the state

def __str__(self):"""Returns the string representationof the data attributes."""s = "step %d : " % self.steps = s + ("x = %.16e" % self.x)s = s + (", |dx| = %.3e" % self.dx)s = s + (", |f(x)| = %.3e" % self.res)return s

def __repr__(self): return self.__str__()

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 28 / 35

a Newton step

def next(self):"""Does one Newton step."""self.step = self.step + 1if (self.step > self.max):

raise StopIteration("only %d \steps allowed" % self.max)

else:z = self.xself.dx = -self.f(z)/self.df(z)self.x = z + self.dxself.dx = abs(self.dx)self.res = abs(self.f(self.x))

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 29 / 35

raising an exception

If we have reached the maximum number of steps:

>>> nf.next()Traceback (most recent call last):

File "<stdin>", line 1, in <module>File "newtoniterator.py", line 63, in nextraise StopIteration("only %d steps allowed" % self.max)

StopIteration: only 5 steps allowed

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 30 / 35

the stop test

def accurate(self):"""Returns True if the accuracy requirementsare satisfied. Returns False otherwise."""return ((self.dx <= self.eps) or

(self.res <= self.eps))

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 31 / 35

the test function

def test():"""Approximates the square root of 2."""f = lambda x: x**2 - 2.0df = lambda x: 2.0*xnf = NewtonIterator(f,df,2.0)print nffor i in xrange(5):

nf.next()print nfif nf.accurate(): break

if __name__=="__main__": test()

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 32 / 35

running newtoniterator.py

$ python newtoniterator.pystep 0 : x = 2.0000000000000000e+00, \|dx| = 1.000e+00, |f(x)| = 2.000e+00

step 1 : x = 1.5000000000000000e+00, \|dx| = 5.000e-01, |f(x)| = 2.500e-01

step 2 : x = 1.4166666666666667e+00, \|dx| = 8.333e-02, |f(x)| = 6.944e-03

step 3 : x = 1.4142156862745099e+00, \|dx| = 2.451e-03, |f(x)| = 6.007e-06

step 4 : x = 1.4142135623746899e+00, \|dx| = 2.124e-06, |f(x)| = 4.511e-12

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 33 / 35

Summary + Exercises

Refactoring code defined by a loop as an iterator via a class gives theuser more flexibility.

Exercises:1 Replace the break and the enclosing for loop in the functionNewton of the script newtonfun.py by an equivalent whileloop.

2 Write a script that prompts the user for n, the number of iterationsin a for loop that calls scipy.integrate.simps in its body.With each new call the number of function evaluations inscipy.integrate.simps doubles. Put the loop in a functionwhich takes n as an input parameter.Add a callback function to this function.

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 34 / 35

more exercises

3 Make an iterator for the composite Simpson rule, usingscipy.integrate.simps. In each step of the iterator, the totalnumber of function evaluations doubles.

4 Write code for your own composite Simpson rule to be used in aniterator fashion. Organize the computations so that all previousfunction evaluations are recycled.

The second homework is due on Friday 21 September, at 10AM:solve exercises 1 and 3 of Lecture 4; exercises 4 and 5 of Lecture 5;exercises 1, 2 and 5 of Lecture 6; exercises 1, 2, and 4 of Lecture 7.

Scientific Software (MCS 507) exec, callback, and iterators 19 Sep 2012 35 / 35