Calculating Derivatives?

David C. Ullrich ullrich at math.okstate.edu
Mon Mar 27 15:14:33 EST 2000


carbon wrote:

> Is there any python source that relates to calculating derivatives?
> I'd like to try writing software that does this (for polynomials), but
> I don't know where to start.  any resources or help would be greatly
> appreciated.  thanks.

    A person can actually trick Python into calculating derivatives
for very general sorts of functions. You make a class Function;
you give it magic methods so the sum of two functions is a Sum
instance (where Sum is a certain subclass of Function). You tell
it what the derivatives of the functions at the bottom are, you
make certain that Sum knows that the derivative of a sum is the
sum of the derivatives, Product knows the product rule,
Composition knows the chain rule, etc. Far from the most
efficient way if you're just interested in polynomials, but it's
very general - I've been using the gizmo for all sorts of things.
(Once you get carried away with this you have a class
Polynomial(Function) that deals with polynomials more
efficiently - then you have sines of polynomials and polynomials
of sines, etc.)

    An outline follows (possibly including typos, was sort
of extracted from a much more elaborate module).
The module contains more than one class. But it's not
an unruly proliferation, we need one subclass for each
operator:

class Function:
 def __init__(self, f):
  self._eval = f
 def __call__(self, x):
  if not callable(x):
   return self._eval(x)
  else:
   return Composition(self, x)
 def __add__(self, other):
  return Sum(self, other)
 def __mul__(self, other):
  return Product(self, other)
 def __neg__(self):
  return Negative(self)
 def _ddx(self):
  return None
  #the empty function looks like a typo

class Composition(Function):
 def __init__(self, outer, inner):
  self.outer=outer
  self.inner=inner
 def _eval(self,x):
  return self.outer(self.inner(x))
 def _ddx(self):
  return (ddx(self.outer)(self.inner))*ddx(self.inner)

class Sum(Function):
 def __init__(self, left, right):
  self.left= left
  self.right=right
 def _eval(self, x):
  return self.left(x) + self.right(x)
 def _ddx(self):
  return ddx(self.left) + ddx(self.right)

class Product(Function):
 def __init__(self, left, right):
  self.left=left
  self.right=right
 def _eval(self, x):
  return self.left(x)*self.right(x)
 def _ddx(self):
  return self.left*ddx(self.right) + \
         ddx(self.left)*self.right

class Negative(Function):
 def __init__(self, other):
  self.inner=other
 def _eval(self, x):
  return - (self.inner(x))
 def _ddx(self):
  return - ddx(self.inner)

def ddx(F):
 return F._ddx()


X = Function(lambda t: t)
X._ddx = lambda: Function(lambda t: 1)
import math
Sin = Function(math.sin)
Cos = Function(math.cos)
Sin._ddx = lambda: Cos
Cos._ddx = lambda: -Sin

def test():

 F=Sin
 print '%s = %s' % (ddx(F)(0), 1)

 F=X*X+X
 print '%s = %s' % (ddx(F)(1), 3)

 print '%s = %s' % (ddx(Sin(X*X))(0), 0)

if __name__ == '__main__':
 test()

    Didn't realize Netscape was going to convert
tabs to single spaces, no time to fix it right now,
sorry.

DU




More information about the Python-list mailing list