PySymbolic design proposal

by Pearu Peterson <pearu@cens.ioc.ee>

$Revision: 1.4 $

$Date: 2000/10/24 15:20:06 $

This document is OBSOLUTE. Read PySymbolic Users Guide instead.

Contents

Introduction

PySymbolic - Doing Symbolics in Python - is a Python package for symbolic mathematical calculation. One of the design features of PySymbolic is that mathematical notations can be represented using Python native syntax. Although Python was not meant to manipulate its objects symbolically, its clear and rich language design makes it possible to extend Python to the world of symbolic calculations of mathematics. However, it is clear that Pythons fixed set of operators will limit PySymbolics ability to provide the level of completeness of mathematical notations as it is in programs like Mathematica, Maple, etc. But this rather pessimistic opinion of mine may turn to be wrong (I certainly hope so!). It is also clear that in short term PySymbolic cannot compete with available symbolic manipulation tools except in its low cost (0 cents) and its availability in Python programs (this was my main point for starting this project).

A very important factor for this project to be successful, is the support from Python community. I hope that there will be enough interested users and contributors to reach the critical mass and to get Python to crunch symbols (TM).

Getting started

To use PySymbolic, you must import Symbolic module:

>>> from Symbolic import *

Module Symbolic provides class Symbolic and various functions such as simplify, diff, etc. To manipulate objects symbolically, you must define them as Symbolic instances. For example,

>>> x = Symbolic("x")

This Symbolic instance x can be used to generate new and more complex Symbolic objects by just performing operations with it. For example,

>>> y = 5*x*x + 4*x/3
>>> y
Symbolic("(5 * x) * x + (4 * x) / 3")

In general, the constructor Symbolic(<obj>) converts arbitrary Python object to a Symbolic instance. Typically, a Symbolic object is created from a string. For example,

>>> z = Symbolic("(3*y-2)*(2*x-x/2)")
>>> print z
(3 * x - 2) * (2 * x - x / 2)

Note that a Symbolic object may contain arbitrary (but valid) Python statements. For example,

>>> c = Symbolic('if x==2:\n\ty=3\nelse:\n\tz=1\n')
>>> print c
if x == 2: 
    y = 3
else: 
    z = 1

An application for the full support of Python language syntax may be symbolic differentiation of functions defined in Python, for example. However, in the following I will concentrate more on simple Python statements that make more sense for symbolic mathematical calculations. No need to mention that Python environment itself provides a rich variety of tools for programming tasks.

As already seen above, you can perform various operations with Symbolic objects. In expressions typical operations are addition, subtraction, multiplication, division, raising to a power, etc. For example,

>>> 1*x/y+2*z+0
Symbolic("(x / ((5 * x) * x + (4 * x) / 3) + 2 * ((3 * y - 2) * (2 * x - x / 2)))")

While constructing the new Symbolic object for 1*x/y+2*z+0, only most obvious simplifications are carried out. To get a deeper simplification level, use simplify(<obj>) function. For example,

>>> f = simplify(1*x/y+2*z+0)
Symbolic("-6 * x + x / (4 * x / 3 + 5 * x**2) + 9 * x * y")

(Clearly, there is room for improvement, but that's the current behavior of vers. 0.14.)

Warning: Note that 3/4*x is 0 because integer division. You must use 3*x/4.

In PySymbolic you can differentiate expressions using diff(<expr>,<var>) function. For example,

>>> print simplify(diff(x**3/3-x**2+5*x,x))
5 - 2 * x + x**2

Developers guide

In this section the internals of PySymbolic package are described. I hope it will help possible contributors to get better understanding of the code. Current implementation of PySymbolic is certainly in alpha stage and it may change considerably in future.

Overview of PySymbolic

In PySymbolic one can distinguish three closely related tasks:

  1. Creating Symbolic objects;
  2. Performing operations with Symbolic objects;
  3. Applying extension functions.

New Symbolic objects are created either directly with the constructor Symbolic(<string>) or as a result of operations with already defined Symbolic objects. In the former case, Python code in <string> is parsed and the result (ast-list, see below) is saved into its attribute ast. All manipulations with Symbolic objects are actually manipulations with their ast-lists. The so-called extension functions are functions that actually do relevant manipulations with Symbolic objects, e.g. simplify, differentiate, integrate, etc.

Parsing Python strings

Parsing of a Python string containing arbitrary Python code means constructing a lisp-like list - I will call it ast-list. An ast-list is a recursive list of lists where 1st element (I will call it ast-list key) is always a string and it defines how to interpret the following elements which can be either ast-lists or a single string. For example, Python string a+b is parsed to an ast-list ['arith_expr',['NAME','a'],['PLUS','+'],['NAME','b']].

Relevant functions are

Complete specification of ast-lists is determined by Python grammar. Python grammar is defined in the file Grammar/Grammar located in the Python source tree.

PySymbolic parsing part (symparser.py) can be considered being complete. For better performance, it should eventually implemented in C.

Manipulating ast-lists

To perform symbolic operations in the level of ast-lists, use the following functions:

To create elementary ast-lists, use functions

and the dictionary

The following test functions on ast-lists are available:

Some auxiliary functions that can be useful:

Operations with Symbolic objects

Symbolic object has the following methods:

In addition, Symbolic has the following extension methods:

Extensions

Currently there are only two extensions that are partially implemented: simplification and differentiation. I am not completely happy with the current simplification procedures as its many tasks should actually be implemented elsewhere, e.g. in functions like expand, collect, etc.

Differentiation module, however, needs no rewrite, just extension and bug fixes.

For better performance all extension functions should be eventually implemented in ast-list level, or better yet, in C.

Current experience shows that extension functions are, in general, recursive.

Differentiation

Differentiation routines locate in file differentiator.py and it provides a function:

astdifferentiate(a,v)
It returns an ast-list containing derivative of a in respect to v. (a,v are ast-lists, of course.) It behaves as follows (let's denote diff=astdifferentiate):

Simplification

Simple is always a very relative concept and so there should be several simplification functions that simplify expressions in different ways, often in very controversial ways. For example, in some cases it is useful to expand powers so that lots of terms will cancel, in other cases, however, it gives little effect, expressions may become even more complicated.

On the other hand, simplification functions should try to make expressions as simple as possible without users intervention. It probably requires different strategies in different parts of an expression. It is not clear to me, how to make this in the most optimal way. Should it try all possible combinations at all recurrence levels and then tries to find the most compact combination? What is the measure for simplicity? How to optimize this? Caching?

Ok, to tackle these problems, some basic simplification functions are required. I would propose the following functions:

Wish list for extensions

For completeness, PySymbolic should contain the following extensions (in random order):

Many of these disciplines are not simple and working with them requires special algorithms with different complexity levels. Some of them can be implemented directly in Python, and for some of them interfaces to freely available C libraries should be created.

Anyway, if you feel that you wish to contribute in any of these disciplines, please, let us know. This is to avoid parallel contributions.

Thanks, Pearu

Links

The following libraries should be considered interfaced to Python in order to use them in PySymbolic:

Other attempts to do symbolics in Python: