[Edu-sig] More calculus in Python
Kirby Urner
urnerk at qwest.net
Mon Dec 27 23:35:00 CET 2004
This is part of an exchange with math profs over on math-teach*, but I think
is of relevance here, given all the Python. KU
* http://www.mathforum.com/epigone/math-teach/ghyrturcrerl
==============
>On Dec 26, 2004, at 4:01 PM, Kirby Urner wrote:
>
>> To recapitulate how we'll do some of the early calculus stuff using
>> Python, the advantage of top-level functions is you can pass them as
>> arguments to other functions. This mirrors the behavior of the
>> derivative operator, which Spivak likes to symbolize as D.
>> D(f) -> g, means you take a function, f, operate on it (D), and
>> spit back another function, g.
>
>Kirby,
>
>You may want to check out so-called "automatic differentiation". The
>underlying idea is this: We overload the symbols of ordinary algebra,
>thus extending algebra to the collection of ordered pairs (u, u'), where
>u is a function and u' its derivative:
>
>(u, u') + (v, v') := (u + v, u' + v');
>
>(u, u') * (v, v') := (u * v, u' * v + u * v'),
>
>etc.
>
>We embed the reals in this system: the real number a --> (a, 0).
>
>The identity function (which we abusively write as "x") is embedded as x
>--> (x, 1).
>
>Of course, this can all be hidden from the user if we wish.
>
>Let's suppose that we have told our computer how to extend addition and
>multiplication as above, and that we've given it the image of the
>identity function too.
>
>Note what happens. When the machine uses these definitions to calculate
>the squaring function, we get
>
>(x, 1) * (x, 1) = (x * x, 1 * x + x * 1) = (x^2, 2 x).
>
>This happens for other things as well, so we don't need to give most of
>the formal embeddings. With what we've already done, we're ready to do
>polynomial calculus now. With a few more rules [sin x --> (sin x,
>cosx), the quotient rule
>
>(u, u')/(v, v') = (u/v, (u' * v - u * v')/v^2),
>
>etc.] we can do all of elementary calculus.
>
Thanks Lou.
A first take in Python: write a Pair class to store (u, du) and define the
basic four operations, as you've defined them; write a Function class to
define the same four ops with respect to generic functions. Even ordinary
numbers will be considered functions which "return their own value."
class Pair:
"""
A generic pair (f, f'), both Functions (below), and
rules for the four basic ops w/r to Pairs
"""
def __init__(self, u, du):
self.u = u
self.du = du
def __add__(self, other):
return Pair(self.u + other.u, self.du + other.du)
def __sub__(self, other):
return Pair(self.u - other.u, self.du - other.du)
def __mul__(self, other):
return Pair(self.u * other.u, \
self.du * other.u + self.u * other.du)
def __div__(self, other):
return Pair(self.u/other.u, \
(self.du * other.u - self.u * other.du)/other.u**2)
class Function:
"""
A generic wrapper for uni-variable functions, allowing them to
be composed using the four operations
"""
def __init__(self, f):
self.f = lambda x: f(x)
def __add__(self, other):
return Function(lambda x: self.f(x) + other.f(x))
def __sub__(self,other):
return Function(lambda x: self.f(x) - other.f(x))
def __mul__(self,other):
return Function(lambda x: self.f(x) * other.f(x))
def __div__(self,other):
return Function(lambda x: self.f(x) / other.f(x))
def __call__(self,x):
"""call wrapped function with argument x, return result"""
return self.f(x)
Now we define the identity function, and unity, per your language game.
>>> def ident(x): return x
>>> id = Function(ident) # Function-wrapped identity function
>>> def one(x): return 1
>>> unity = Function(one) # Function-wrapped one
Now we define a Pair (ident, unity) corresponding to your (x, 1).
>>> p1 = Pair(id, unity)
Multiplying p1 * p1 should return a new pair such that newpair.u is a
parabolic or 2nd powering function, and newpair.du is the derivative
thereof.
>>> newp = p1 * p1
>>> [newp.u(i) for i in range(-5,6)]
[25, 16, 9, 4, 1, 0, 1, 4, 9, 16, 25]
>>> [newp.du(i) for i in range(-5,6)]
[-10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10]
So far so good. Thanks for this brain teaser and opportunity to show off
functional programming in Python.
Kirby
More information about the Edu-sig
mailing list