SEP 1: Calculus in SAGE

This is SAGE Enhancement Proposal (SEP) number 1.

Authors

Alex Clemesha, David Joyner, Bobby Moretti, William Stein,

(This is a summary of emails from William Stein, Bobby Moretti, Joel Mohler, Alex Clemesha, Robert Bradshaw, David Joyner, David Harvey, Tom Boothby.)

Preamble

A system for manipulating analytic functions in SAGE.

Abstract

A Python class structure is needed to provide SAGE with the ability to perform calculus computations. Simple, intuitive syntax that does not break core Python semantics is a top priority. Basic calculus functions such as polynomials, trig functions, exponential functions, special functions, etc. should be manipulatable in SAGE using standard arithmetic and calculus operations.

Public domain

Construction of calculus functions

To construct a calculus function, consider the assignment

sage: f = expr

where expr is an symbolic expression, i.e., an element of the set of basic calculus functions closed under the operations +,-,*,/,^, composition, differentiation, and integration. The objects that generate this set (under the given operations) shall be called primitive functions. The set of primitive functions shall consist of basic analytic functions such as sine, cosine, polynomials, and exponentials. These functions shall be global instances of specific subclasses of the Function class, invoked via the Python __call__() method. When you call a Function it returns a symbolic expression.

There will be a class Function and a class SymbolicExpression.

The output of __call___() on an Function is a SymbolicExpression or a Function (in case of composition).

A proposed class hierarchy

   PrimitiveFunction
   SymbolicExpression
      SymbolicVariable
      Constant
      SymbolicBinaryOperation

Operations on functions

Invoking other systems

In keeping with SAGE's philosophy of not reinventing the wheel, difficult operations may be defered to other systems (MAXIMA!) to which SAGE has an interface. The result of such computations should always be parsed and transformed into a valid SAGE expression. The result should not be a text string. Whenever possible, it should optionally be possible to compute using several systems, so one can compare results. Some operations that will be deferred to other systems in many cases:

Basic operations

The operations on basic functions shall include addition, subtraction, multiplication, division, and exponentiation. These will be implemented by overloading the associated Python operator. In addition to these arithmetic operations, functions may be created by composition, differentiation, and integration of Function objects.

Composition shall be invoked when one object of type Function is called as the argument of another function. Differentiation may be implemented in SAGE or passed on to another system (the most likely choice being Maxima), in either case resulting in a simplified expression. The simplification step must return a Function object, i.e., an symbolic expression, and would likely be implemented in Maxima. The simplification can be undone by performing the expand operation, which is defined below. Integration shall be computed entirely within a separate system (again, most likely Maxima) and a simplified result shall be passed back to SAGE in the same manner as described above for differentiation.

Other operations shall include algebraic simplification and various types of expansion are implemented using a separate system as is isolation of one variable.

Implementation of basic operations

As discussed above, binary operation shall be implemented by overloading the relevant Python operators. Unary operations shall be member methods of the Function class. For example:

sage: f = x * sin(3*x^2 + y) + cos(y)
sage: f.derivative(y)
2*x*cos(3*x^2 + 2*y) - sin(y)

Substitution

Substitution shall be another key operation on functions. By substitution, we mean the mathematical operation of replacing a variable (or set of variables) with either a fixed value, or with another symbolic expression. In this sense, the operation of substitution represents two mathematical concepts: evaluation of a function at a given element of its domain set, and algebraic substitution.

Algorithm

This operation shall be implemented as a member method of the Function class known as substitute. (It is *key* that people find the substitute operation quickly). This method shall be implemented as a recursive algorithm. If the Function is built out of some operation, then the algorithm calls itself on each of the operands. The algorithm terminates when the Function object in question is either a primitive variable or a constant. If the termination happens to be on a variable, the variable is substituted with the replacement expression.

Implementation

The substitute method shall be called in one of the following ways: Let f be an symbolic expression.

f(x=2, w=z^2)

sage: f.subsitute({x: 2, y: z^2})

sage: f.substitute(x=2, y=z^2)

sage: f.function(*args)

This method shall return a callable without named parameters version of f, which otherwise works in the same way. Output is result of subs. this just another formal function, but with a call method. Also, function((vars...),expr) makes an evaluatable function.

For example:

g = sin(x)*cos(x+y+3)
f = g.function(x,y)

g = f(x=x,y=7); g
///
sin(x)*cos(x+10)

g(x=10)
///
sin(10)*cos(20)

f(x=5,y=7)
///
sin(5)*cos(15)

We could possibly add the following type of function as well:

or dummy = sin(x*) * cos(x+y+3) f = dummy.function(x,y) Also, with my proposal one could also already type f = function( (x,y),  sin(x)*cos(x+y+3) ) Here this would be implemented via:

def function( vars, expr):
    return expr.function(*vars)

Preparsing for defining a callable symbolic expression

f(x,y) = sin(x+y) * x + cos(y^2)*z

contour_plot(f, (-1,2), (-1,2))

This would get converted by the preparser to:

f = (sin(x+y) * x + cos(y^2 + z^3)).function(x,y)

f.integral(z)
///
sin(x+y) * x*z + cos(y^2)*(z^2/2)

plot(f(2,5), (z, 0, 5))
plot(f(y=5), (x, 0, 3), (z, 0, 5))

Mathematica:

Plot[f[2,5,z], {z, 0, 5}]

Another important niceness:

h = x^3 + y^2 + sin(z)

h is a symbolic expression.

This gets preparsed to:

z = h.function(x,y)

or even

h(x,y) = h

h(5,6) 
///
5^3 + y

Motivation

For SAGE to have wide-spread acceptance in calculus, ease-of-use is critical. The current situation, illustrated with lambda functions, ElementaryFunctions, or built-in Python functions is inadequate.

Rationale

Though Maple and Mathematica have functionality with regard to calculus computations which SAGE is currently lacking, something better is needed. The syntax is still frustrating and unnatural for many new users, even for these sophisticated CAS's. Many find these systems very counterintuitive to do basic calculus. Part of the problem is the difference between mathematical functions and computer language functions. This SEP asserts that SAGE can do better and can provide a simpler system.

Backwards compatibility - This will be a new class and will provide new functionality which will not interfere with previous implementations.

References

CalculusSEP (last edited 2008-11-14 13:42:01 by localhost)