[Edu-sig] Example: parameterized functions w/ Python

Kirby Urner pdx4d@teleport.com
Thu, 27 Apr 2000 12:57:49 -0700


Earlier today I wrote:
> And we should acknowledge that "gray area" between "programming" 
> and simply writing out some algorithms.  Like, in a math context, 
> we maybe only need a very few lines of code to implement something.  
> You don't have to get into writing these large, gnarly programs 
> with hundreds of lines (you can, but you don't have to). [1]

To take a real world example, some of the post-K12 math 
teachers on MATHEDU are talking about parameterized functions, 
how these could be introduced earlier, meaning calc profs 
wouldn't have to cram them in at the last minute, in front 
of trying to wrap student minds around Stokes, Green, Gauss 
theorems at the end of a college vector calculus course (requires 
grad, div, curl -- learning curve already plenty steep).

Under http://mathforum.com/epigone/mathedu/lixthoofrah
Ralph Raimi writes:

   But back to calculators and software:  Is it really 
   possible within reasonable amounts of time to use 
   this technology to help in the understanding of 
   parametrizations, in time to get to Stokes and
   divergences?

And in http://mathforum.com/epigone/mathedu/planskolhand
Mark Bridger writes:

  Parametric "equations" can be introduced very early in a 
  student's mathematical instruction: probably at the same time 
  in algebra when graphing is introduced. Curves as trajectories 
  is not, you should pardon the phrase, "rocket science" (though 
  it is, sort of), but something that students can relate to 
  rather easily.

And indeed, he's right.  Plus here is where a computer, vs a 
simple graphing calculator, really shines, because we're wanting
to get "beyond flatland" and do curves in space, not pressed 
flat on the XY plane.[2]  Let's go find an example...

At http://iq.orst.edu/mathsg/vcalc/vec_fnc/vec_fnc.html we
find an example of a parameterized function.  The (x,y,z)
coordinates of a vector are each controlled by a separate
function:

    x(t) = 3 cos(t)  y(t) = 3 sin(t)  z(t) = 0.25(t)

The graph is shown, for 0 <= t <= 7 pi

How might we do this in Python?

First, t is the domain variable, and we want a lot of t-values 
from 0 to 7 pi, fairly close together.  We can build our 
variable 'domain' as a list, and then pass it in to some other 
function.  

Let's define some stuff in a fresh (empty) namespace (module), 
and invoke it from the IDLE interactive command line.

# Module para.py

def mkdomain(low, high, interval):
    i = low
    output = []          # the list
    while i <= high:     # increment until high reached
       output.append(i)  
       i = i + interval  # increment by interval
    return output

>>> import para, math

>>> domain = para.mkdomain(0,7*math.pi,0.1)

Then we can write the three functions, right at the command
line (nothing hard-coded in the saved module):

>>> def f(t):
      return 3 * math.cos(t)

>>> def g(t):
      return 3 * math.sin(t)

>>> def h(t):
      return 0.25 * t

The range is another list, with the function itself being 
defined by (domain, range) pairs i.e. myfunc = the set of 
tuples (t, Vector(f(t),g(t),h(t)) ).

OK, so let's return this function as a list of tuples:

# more from module para.py...

from coords import Vector  # coords.py is something I wrote

def mkfunction(f1,f2,f3,domain):
   outlist = []
   for t in domain:       # loop through domain values
      # build vector w/ passed functions, domain member
      rvalue  = Vector( (f1(t),f2(t),f3(t)) )
      # append (domain,range) tuple
      outlist.append((t,rvalue))
   return outlist

To obtain our function, simply write:

>>> myfunc = para.mkfunction(f,g,h,domain)

Notice how we're passing functions f,g and h by name 
-- along with the domain (a list of t-values) -- and 
how they execute internally on all members of the 
domain, to return (domain,range) pairs.

The Vector operator used above actually points to a 
Vector class, which includes methods for doing vector
operations (including dot and cross products).  In 
this prototypical curriculum, students have already 
seen the "vector" object demystified in the Vector 
class template.  It's a familiar object already.[3]

All that remains is to graph the function.  Again, I 
have some ready-made modules, none of which contain 
source code beyond the ability of high schoolers to
understand or even write themselves [4]:

>>> import functions
>>> import povray

>>> mygraph = povray.Povray("mygraph.pov")
>>> functions.xyzaxes(mygraph,5)   # draw XYZ axes +/- 5 long

# more from module para.py...

def graphit(myfunc, myfile):
   for i in range(len(myfunc)-1):  # indexed access to myfunc
       v1 = myfunc[i][1]    # vector of (t,vector) pair
       v2 = myfunc[i+1][1]  # vector from next pair
       myfile.edge(v1,v2)   # draw edge between the two

>>> graphit(myfunc,mygraph)

>>> mygraph.close()

And we're done.  Just have to render mygraph.pov in Povray,
maybe adjust camera distance to fit (again, this is old hat
to students using my Python + Povray approach to graphics).

Here's the graph [5]:
http://www.inetarena.com/~pdx4d/ocn/graphics/paramgraph.gif

Here's the module:
http://www.inetarena.com/~pdx4d/ocn/python/para.py

Kirby
Curriculum writer
Oregon Curriculum Network
http://www.inetarena.com/~pdx4d/ocn/

Notes:

[1] http://www.python.org/pipermail/edu-sig/2000-April/000330.html
[2] http://inetarena.com/~pdx4d/ocn/trends2000.html#bf
[3] http://www.inetarena.com/~pdx4d/ocn/numeracy1.html
[4] Ibid
[5] Note that the positive Z axis points away from the viewer
    (owing to camera position) -- still a standard XYZ coordinate 
    system though.