Computer Algebra Interfaces

DDA implements a few parts of computer algebra system (CAS), especially with it’s Abstract Syntax tree. Since we don’t want to reinvent the wheel, we interface with common computer algebra systems. There are at least two popular for the Python ecosystem available:

  • SymPy, bundled within the SciPy package, can be easily used as a pure python library.

  • Sagemath, which is more of a monolithic software. The symbolic foundation of sage is provided by Ginac and Pynac, respectively. Many open source computer algebra systems are bundled with sage, such as Maxima and Octave. Furthermore, interfaces to many others such as Maple, Mupad or Mathematica are part of sage.

So far, we had quick success with adopting SymPy (see next section).

SymPy module API reference

This module provides interplay with the SymPy package. SymPy is a lightweight pure-python computer algebra system which is bundled with SciPy. An adapter to/from SymPy allows to use powerful Computer Algebra basic functions such as expression simplification.

We use this currently to provide a lean latex representation for the cumbersome DDA expressions.


Import a state from a set of equations from SymPy.

This function expects a python list of sympy equations where there is a single sympy symbol on one hand and an expression on the other hand (see examples below).

The mapping basically follows the SymPy key invariant: “Every well-formed SymPy expression must either have empty args or satisfy expr == expr.func(*expr.args)”.

Therefore we basically map a sympy expression (expr.func, expr.args) to the DDA (head, tail) notation. While the heads are easy to map (for instance, sympy.Mul equals dda.mult), special attention must be given to the tails, for instance SymPys Mul(a,b,c) translates to DDAs mult(mult(a,b),c) (in DDA we always assume commutative real-valued variables). Also in DDA there is neg(x) or div(x,y) which is represented in SymPy as Mul(Integer(-1), x) and Mul(Symbol('x'), Pow(Symbol('y'), Integer(-1))), respectively.

dda.sympy.to_sympy(state, symbol_mapper=<function <lambda>>, round_n=15)[source]

Export a state to a set of equations for SymPy. Returns a list of sympy.Eq objects. Of course it requires Sympy installed/available.


The heart of this function is a mapping from ast.Symbol terms (functions) to Sympy functions, for instance by mapping Symbol("int")(...) to -sympy.Integral(sympy.Add(...), t).

Thanks to the ease of the computing elements, this mapping does not require pattern matching but can be performed on a basic level. However, not all terms are yet supported.

The argument symbol_mapper allows to apply another mapping on the DDA Symbol heads. By default, it is the identity function.

With Sympy, you can do all funny things, such as:

>>> from dda import *
>>> x,int,neg=symbols("x,int,neg")
>>> state = State({'x': int(neg(x), 0.2, 1)})
>>> to_sympy(state)
[Eq(x, -Integral(1.2 - x, t))]
dda.sympy.to_latex(state, chunk_n=None)[source]

Export to latex, using sympy.

This mostly differs from sympy.latex for large equation systems where we use the align latex environment instead of a single equation. For the above example:

>>> import sympy, dda
>>> x,int,neg=dda.symbols("x,int,neg")
>>> state = dda.State({'x': int(neg(x), 0.2, 1)})
>>> print(sympy.latex(to_sympy(state)))  
\left[ x = - \int \left(1.2 - x\right)\, dt\right]
>>> print(to_latex(state))               
x &= - \int \left(1.2 - x\right)\, dt