Sympy Docs PDF 0.7.6
Sympy Docs PDF 0.7.6
Release 0.7.6
SymPy Development Team
November 20, 2014
CONTENTS
1 Installation
1.1 Source . . . . .
1.2 Git . . . . . . . .
1.3 Anaconda . . .
1.4 Other Methods
1.5 Run SymPy . .
1.6 Questions . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
2
2
2
3
2 SymPy Tutorial
2.1 Preliminaries . . . . . . . . . . . . . .
2.2 Introduction . . . . . . . . . . . . . . .
2.3 Gotchas . . . . . . . . . . . . . . . . .
2.4 Basic Operations . . . . . . . . . . . .
2.5 Printing . . . . . . . . . . . . . . . . .
2.6 Simplication . . . . . . . . . . . . . .
2.7 Calculus . . . . . . . . . . . . . . . . .
2.8 Solvers . . . . . . . . . . . . . . . . . .
2.9 Matrices . . . . . . . . . . . . . . . . .
2.10 Advanced Expression Manipulation .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
7
10
15
18
23
37
43
46
52
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
61
61
61
62
65
70
73
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
75
75
75
77
84
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
85
85
187
276
303
.
.
.
.
.
.
.
.
.
.
.
.
5.5
5.6
5.7
5.8
5.9
5.10
5.11
5.12
5.13
5.14
5.15
5.16
5.17
5.18
5.19
5.20
5.21
5.22
5.23
5.24
5.25
5.26
5.27
5.28
5.29
5.30
5.31
5.32
5.33
5.34
5.35
5.36
5.37
5.38
5.39
Concrete Mathematics . . . . . . . . . . . . . . . . .
Numerical evaluation . . . . . . . . . . . . . . . . . .
Numeric Computation . . . . . . . . . . . . . . . . . .
Functions Module . . . . . . . . . . . . . . . . . . . .
Geometric Algebra Module . . . . . . . . . . . . . . .
Geometry Module . . . . . . . . . . . . . . . . . . . .
Symbolic Integrals . . . . . . . . . . . . . . . . . . . .
Numeric Integrals . . . . . . . . . . . . . . . . . . . .
Logic Module . . . . . . . . . . . . . . . . . . . . . . .
Matrices . . . . . . . . . . . . . . . . . . . . . . . . . .
Welcome to mpmaths documentation! . . . . . . . .
Polynomials Manipulation Module . . . . . . . . . .
Printing System . . . . . . . . . . . . . . . . . . . . . .
Plotting Module . . . . . . . . . . . . . . . . . . . . . .
Pyglet Plotting Module . . . . . . . . . . . . . . . . .
Assumptions module . . . . . . . . . . . . . . . . . . .
Term rewriting . . . . . . . . . . . . . . . . . . . . . .
Series Expansions . . . . . . . . . . . . . . . . . . . .
Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Simplify . . . . . . . . . . . . . . . . . . . . . . . . . .
Details on the Hypergeometric Function Expansion
Stats . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
PDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Solvers . . . . . . . . . . . . . . . . . . . . . . . . . . .
Diophantine . . . . . . . . . . . . . . . . . . . . . . . .
Inequality Solvers . . . . . . . . . . . . . . . . . . . .
Tensor Module . . . . . . . . . . . . . . . . . . . . . .
Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . .
Parsing input . . . . . . . . . . . . . . . . . . . . . . .
Calculus . . . . . . . . . . . . . . . . . . . . . . . . . .
Physics Module . . . . . . . . . . . . . . . . . . . . . .
Category Theory Module . . . . . . . . . . . . . . . .
Dierential Geometry Module . . . . . . . . . . . . .
Contributions to docs . . . . . . . . . . . . . . . . . .
Python
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
Module .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1861
. 1861
. 1861
. 1862
. 1864
. 1864
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
319
331
337
340
450
489
583
619
625
635
713
1046
1248
1270
1283
1287
1302
1304
1312
1327
1350
1361
1397
1460
1468
1483
1505
1508
1532
1588
1592
1597
1829
1846
1860
7 Wiki
1869
7.1 FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1869
8 SymPy Papers
1871
9 Planet SymPy
1873
10 SymPy logos
1875
1877
1879
ii
13 About
1881
13.1 SymPy Development Team . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1881
13.2 Financial and Infrastructure Support . . . . . . . . . . . . . . . . . . . . . . . . . . 1891
13.3 License . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1892
14 SymPy Special Topics
1893
14.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1893
14.2 Finite Dierence Approximations to Derivatives . . . . . . . . . . . . . . . . . . . . 1893
Bibliography
1899
1919
Index
1923
iii
iv
CHAPTER
ONE
INSTALLATION
The SymPy CAS can be installed on virtually any computer with Python 2.6 or above. SymPy
does not require any special Python modules: let us know if you have any problems with
SymPy on a standard Python install. The current recommended method of installation is
directly from the source les. Alternatively, executables are available for Windows, and some
Linux distributions have SymPy packages available.
SymPy ocially supports Python 2.6, 2.7, 3.2, 3.3, 3.4, and PyPy.
1.1 Source
SymPy currently recommends that users install directly from the source les. You will rst
have to download the source les via the archive. Download the latest release (tar.gz) from
the downloads site and open it with your operating systems standard decompression utility.
After the download is complete, you should have a folder called sympy. From your favorite
command line terminal, change directory into that folder and execute the following:
$ python setup.py install
Alternatively, if you dont want to install the package onto your computer, you may run SymPy
with the isympy console (which automatically imports SymPy packages and denes common
symbols) by executing within the sympy folder:
$ ./bin/isympy
You may now run SymPy statements directly within the Python shell:
>>>
>>>
>>>
>>>
>>>
>>>
x
1.2 Git
If you are a developer or like to get the latest updates as they come, be sure to install from
git. To download the repository, execute the following from the command line:
Then, execute either the setup.py or the bin/isympy scripts as demonstrated above.
To update to the latest version, go into your repository and execute:
$ git pull origin master
If you want to install SymPy, but still want to use the git version, you can run from your
repository:
$ setupegg.py develop
This will cause the installed version to always point to the version in the git directory.
1.3 Anaconda
Although SymPy does not have any hard dependencies, many nice features are only enabled
when certain libraries are installed. For example, without Matplotlib, only simple text-based
plotting is enabled. With the IPython notebook or qtconsole, you can get nicer LATEX printing
by running init printing(). An easy way to get all these libraries in addition to SymPy is to
install Anaconda, which is a free Python distribution from Continuum Analytics that includes
SymPy, Matplotlib, IPython, NumPy, and many more useful packages for scientic computing.
From here, execute some simple SymPy statements like the ones below:
>>> x = Symbol(x)
>>> limit(sin(x)/x, x, 0)
1
>>> integrate(1/x, x)
log(x)
For a starter guide on using SymPy eectively, refer to the SymPy Tutorial (page 5).
Chapter 1. Installation
1.6 Questions
If you have a question about installation or SymPy in general, feel free to visit our chat on
Gitter. In addition, our mailing list is an excellent source of community support.
If you think theres a bug or you would like to request a feature, please open an issue ticket.
1.6. Questions
Chapter 1. Installation
CHAPTER
TWO
SYMPY TUTORIAL
2.1 Preliminaries
This tutorial assumes that the reader already knows the basics of the Python programming
language. If you do not, the ocial Python tutorial is excellent.
This tutorial assumes a decent mathematical background. Most examples require knowledge
lower than a calculus level, and some require knowledge at a calculus level. Some of the
advanced features require more than this. If you come across a section that uses some mathematical function you are not familiar with, you can probably skip over it, or replace it with a
similar one that you are more familiar with. Or look up the function on Wikipedia and learn
something new. Some important mathematical concepts that are not common knowledge will
be introduced as necessary.
2.1.1 Installation
Quick Tip
You do not need to install SymPy to try it.
You can use the online shell at
http://live.sympy.org, or the shell at the bottom right of this documentation page.
You will need to install SymPy rst. See the installation guide (page 1).
Alternately, you can just use the SymPy Live Sphinx extension to run the code blocks in the
browser. For example, click on the green Run code block in SymPy Live button below
>>> from sympy import *
>>> x = symbols(x)
>>> a = Integral(cos(x)*exp(x), x)
>>> Eq(a, a.doit())
Integral(exp(x)*cos(x), x) == exp(x)*sin(x)/2 + exp(x)*cos(x)/2
The SymPy Live shell in the bottom corner will pop up and evaluate the code block. You can
also click any individual line to evaluate it one at a time.
The SymPy Live shell is a fully interactive Python shell. You can type any expression in the
input box to evaluate it. Feel free to use it throughout the tutorial to experiment.
To show or hide the SymPy Live shell at any time, just click the green button on the bottom
right of the screen.
By default, the SymPy Live shell uses LATEX for output. If you want the output to look more like
the output in the documentation, change the output format to Str or Unicode in the settings.
If you wish to modify an example before evaluating it, change the evaluation mode to copy
in the SymPy Live settings. This will cause clicking on an example to copy the example to
the SymPy Live shell, but not evaluate it, allowing you to change it before execution. You can
also use the up/down arrow keys on your keyboard in the input box to move through the shell
history.
The SymPy Live shell is also available at http://live.sympy.org, with extra features, like a
mobile phone enhanced version and saved history.
2.1.2 Exercises
This tutorial was the basis for a tutorial given at the 2013 SciPy conference in Austin, TX.
The website for that tutorial is here. It has links to videos, materials, and IPython notebook
exercises. The IPython notebook exercises in particular are recommended to anyone going
through this tutorial.
Feedback on this tutorial, or on SymPy in general is always welcome. Just write to our mailing
list.
2.2 Introduction
2.2.1 What is Symbolic Computation?
Symbolic computation deals with the computation of mathematical objects symbolically. This
means that the mathematical objects are represented exactly, not approximately, and mathematical expressions with unevaluated variables are left in symbolic form.
Lets take an example. Say we wanted to use the built-in Python functions to compute square
roots. We might do something like this
>>> import math
>>> math.sqrt(9)
3.0
9 is a perfect square, so we got the exact answer, 3. But suppose we computed the square
root of a number that isnt a perfect square
>>> math.sqrt(8)
2.82842712475
Here we got an approximate result. 2.82842712475 is not the exact square root of 8 (indeed,
the actual square root of 8 cannot be represented by a nite decimal, since it is an irrational
number). If all we cared about was the decimal form of the square root of 8, we would be
done.
Furthermoreand this is where we start to see the real power of symbolic computationsymbolic results can be symbolically simplied.
>>> sympy.sqrt(8)
2*sqrt(2)
2.2. Introduction
>>> expr
x + 2*y
Note that we wrote x + 2*y just as we would if x and y were ordinary Python variables. But
in this case, instead of evaluating to something, the expression remains as just x + 2*y. Now
let us play around with it:
>>> expr + 1
x + 2*y + 1
>>> expr - x
2*y
Notice something in the above example. When we typed expr - x, we did not get x + 2*y x, but rather just 2*y. The x and the -x automatically canceled one another. This is similar to
how sqrt(8) automatically turned into 2*sqrt(2) above. This isnt always the case in SymPy,
however:
>>> x*expr
x*(x + 2*y)
Here, we might have expected x(x + 2y) to transform into x2 + 2xy, but instead we see that the
expression was left alone.
This
is a common theme in SymPy. Aside from obvious simplications like x x = 0 and 8 = 2 2, most simplications are not performed automatically. This
is because we might prefer the factored form x(x + 2y), or we might prefer the expanded form
x2 + 2xy. Both forms are useful in dierent circumstances. In SymPy, there are functions to
go from one form to the other
>>> from sympy import expand, factor
>>> expanded_expr = expand(x*expr)
>>> expanded_expr
x**2 + 2*x*y
>>> factor(expanded_expr)
x*(x + 2*y)
This will make all further examples pretty print with unicode characters.
>>> init_printing(use_unicode=True)
Compute
Find limx0
sin (x)
x .
>>> limit(sin(x)/x, x, 0)
1
Solve x2 2 = 0.
>>> solve(x**2 - 2, x)
___
___
-\ 2 , \ 2
t t
y(t) = C2e
+ C1 + -e
____
____
3
\ 17
\ 17
3
- + ------: 1, - ------ + -: 1
2
2
2
2
Rewrite the Bessel function J (z) in terms of the spherical Bessel function j (z).
>>> besselj(nu, z).rewrite(jn)
___
___
\ 2 \ z jn( - 1/2, z)
-------------------------___
\
2.2. Introduction
2.3 Gotchas
To begin, we should make something about SymPy clear. SymPy is nothing more than a Python
library, like NumPy, Django, or even modules in the Python standard library sys or re. What
this means is that SymPy does not add anything to the Python language. Limitations that are
inherent in the Python language are also inherent in SymPy. It also means that SymPy tries
to use Python idioms whenever possible, making programming with SymPy easy for those
already familiar with programming with Python. As a simple example, SymPy uses Python
syntax to build expressions. Implicit multiplication (like 3x or 3 x) is not allowed in Python,
and thus not allowed in SymPy. To multiply 3 and x, you must type 3*x with the *.
2.3.1 Symbols
One consequence of this fact is that SymPy can be used in any environment where Python is
available. We just import it, like we would any other library:
>>> from sympy import *
10
This imports all the functions and classes from SymPy into our interactive Python session.
Now, suppose we start to do a computation.
>>> x + 1
Traceback (most
...
NameError: name
Traceback (most
...
NameError: name
Oops! What happened here? We tried to use the variable x, but it tells us that x is not dened.
In Python, variables have no meaning until they are dened. SymPy is no dierent. Unlike
many symbolic manipulation systems you may have used, in SymPy, variables are not dened
automatically. To dene variables, we must use symbols.
>>> x = symbols(x)
>>> x + 1
x + 1
symbols takes a string of variable names separated by spaces or commas, and creates Symbols out of them. We can then assign these to variable names. Later, we will investigate some
convenient ways we can work around this issue. For now, let us just dene the most common
variable names, x, y, and z, for use through the rest of this section
>>> x, y, z = symbols(x y z)
As a nal note, we note that the name of a Symbol and the name of the variable it is assigned
to need not have anything to do with one another.
>>> a, b = symbols(b a)
>>> a
b
>>> b
a
Here we have done the very confusing thing of assigning a Symbol with the name a to the
variable b, and a Symbol of the name b to the variable a. Now the Python variable named a
points to the SymPy Symbol named b, and visa versa. How confusing. We could have also
done something like
>>> crazy = symbols(unrelated)
>>> crazy + 1
unrelated + 1
This also shows that Symbols can have names longer than one character if we want.
Usually, the best practice is to assign Symbols to Python variables of the same name, although
there are exceptions: Symbol names can contain characters that are not allowed in Python
variable names, or may just want to avoid typing long names by assigning Symbols with long
names to single letter Python variables.
To avoid confusion, throughout this tutorial, Symbol names and Python variable names will
always coincide. Furthermore, the word Symbol will refer to a SymPy Symbol and the word
variable will refer to a Python variable.
Finally, let us be sure we understand the dierence between SymPy Symbols and Python
variables. Consider the following:
2.3. Gotchas
11
x = symbols(x)
expr = x + 1
x = 2
print(expr)
What do you think the output of this code will be? If you thought 3, youre wrong. Lets see
what really happens
>>>
>>>
>>>
>>>
x +
x = symbols(x)
expr = x + 1
x = 2
print(expr)
1
Changing x to 2 had no eect on expr. This is because x = 2 changes the Python variable
x to 2, but has no eect on the SymPy Symbol x, which was what we used in creating expr.
When we created expr, the Python variable x was a Symbol. After we created, it, we changed
the Python variable x to 2. But expr remains the same. This behavior is not unique to SymPy.
All Python programs work this way: if a variable is changed, expressions that were already
created with that variable do not change automatically. For example
>>> x = abc
>>> expr = x + def
>>> expr
abcdef
>>> x = ABC
>>> expr
abcdef
Quick Tip
To change the value of a Symbol in an expression, use subs
>>> x = symbols(x)
>>> expr = x + 1
>>> expr.subs(x, 2)
3
In this example, if we want to know what expr is with the new value of x, we need to reevaluate
the code that created expr, namely, expr = x + 1. This can be complicated if several lines
created expr. One advantage of using a symbolic computation system like SymPy is that we
can build a symbolic representation for expr, and then substitute x with values. The correct
way to do this in SymPy is to use subs, which will be discussed in more detail later.
>>> x = symbols(x)
>>> expr = x + 1
>>> expr.subs(x, 2)
3
12
You may think, however, that ==, which is used for equality testing in Python, is used for
SymPy as equality. This is not quite correct either. Let us see what happens when we use ==.
>>> x + 1 == 4
False
There is one additional caveat about == as well. Suppose we want to know if (x+1)2 = x2 +2x+1.
We might try something like this:
>>> (x + 1)**2 == x**2 + 2*x + 1
False
We got False again. However, (x + 1)2 does equal x2 + 2x + 1. What is going on here? Did we
nd a bug in SymPy, or is it just not powerful enough to recognize this basic algebraic fact?
Recall from above that == represents exact structural equality testing. Exact here means
that two expressions will compare equal with == only if they are exactly equal structurally.
Here, (x + 1)2 and x2 + 2x + 1 are not the same symbolically. One is the power of an addition of
two terms, and the other is the addition of three terms.
It turns out that when using SymPy as a library, having == test for exact symbolic equality is
far more useful than having it represent symbolic equality, or having it test for mathematical
equality. However, as a new user, you will probably care more about the latter two. We have
already seen an alternative to representing equalities symbolically, Eq. To test if two things
are equal, it is best to recall the basic fact that if a = b, then a b = 0. Thus, the best way to
check if a = b is to take a b and simplify it, and see if it goes to 0. We will learn later (page 23)
that the function to do this is called simplify. This method is not infalliblein fact, it can
be theoretically proven that it is impossible to determine if two symbolic expressions are
identically equal in generalbut for most common expressions, it works quite well.
>>>
>>>
>>>
0
>>>
>>>
4*x
a = (x + 1)**2
b = x**2 + 2*x + 1
simplify(a - b)
c = x**2 - 2*x + 1
simplify(a - c)
There is also a method called equals that tests if two expressions are equal by evaluating
them numerically at random points.
>>> a = cos(x)**2 - sin(x)**2
>>> b = cos(2*x)
>>> a.equals(b)
True
13
Finally, a small technical discussion on how SymPy works is in order. When you type something like x + 1, the SymPy Symbol x is added to the Python int 1. Pythons operator rules
then allow SymPy to tell Python that SymPy objects know how to be added to Python ints, and
so 1 is automatically converted to the SymPy Integer object.
This sort of operator magic happens automatically behind the scenes, and you rarely need to
even know that it is happening. However, there is one exception. Whenever you combine a
SymPy object and a SymPy object, or a SymPy object and a Python object, you get a SymPy
object, but whenever you combine two Python objects, SymPy never comes into play, and so
you get a Python object.
>>> type(Integer(1) + 1)
<class sympy.core.numbers.Integer>
>>> type(1 + 1)
<... int>
This is usually not a big deal. Python ints work much the same as SymPy Integers, but there
is one important exception: division. In SymPy, the division of two Integers gives a Rational:
>>> Integer(1)/Integer(3)
1/3
>>> type(Integer(1)/Integer(3))
<class sympy.core.numbers.Rational>
But in Python / represents either integer division or oating point division, depending on
whether you are in Python 2 or Python 3, and depending on whether or not you have run from
future import division:
>>> from __future__ import division
>>> 1/2
0.5
This problem also comes up whenever we have a larger symbolic expression with int/int in
it. For example:
>>> x + 1/2
x + 0.5
This happens because Python rst evaluates 1/2 into 0.5, and then that is cast into a SymPy
type when it is added to x. Again, we can get around this by explicitly creating a Rational:
>>> x + Rational(1, 2)
x + 1/2
There are several tips on avoiding this situation in the Gotchas and Pitfalls (page 61) document.
14
2.4.1 Substitution
One of the most common things you might want to do with a mathematical expression is
substitution. Substitution replaces all instances of something in an expression with something
else. It is done using the subs method. For example
>>> expr = cos(x) + 1
>>> expr.subs(x, y)
cos(y) + 1
2. Replacing a subexpression with another subexpression. There are two reasons we might
want to do this. The rst is if we are trying to build an expression that has some symmexx
try, such as xx . To build this, we might start with x**y, and replace y with x**y. We
would then get x**(x**y). If we replaced y in this new expression with x**x, we would
get x**(x**(x**x)), the desired expression.
>>> expr = x**y
>>> expr
x**y
>>> expr = expr.subs(y, x**y)
>>> expr
x**(x**y)
>>> expr = expr.subs(y, x**x)
>>> expr
x**(x**(x**x))
The second is if we want to perform a very controlled simplication, or perhaps a simplication that SymPy is otherwise unable to do. For example, say we have sin(2x)+cos(2x),
and we want to replace sin(2x) with 2 sin(x) cos(x). As we will learn later, the function
expand trig does this. However, this function will also expand cos(2x), which we may
not want. While there are ways to perform such precise simplication, and we will learn
some of them in the advanced expression manipulation (page 52) section, an easy way
is to just replace sin(2x) with 2 sin(x) cos(x).
15
There are two important things to note about subs. First, it returns a new expression. SymPy
objects are immutable. That means that subs does not modify it in-place. For example
>>> expr = cos(x)
>>> expr.subs(x, 0)
1
>>> expr
cos(x)
>>> x
x
Quick Tip
SymPy expressions are immutable. No function will change them in-place.
Here, we see that performing expr.subs(x, 0) leaves expr unchanged. In fact, since SymPy
expressions are immutable, no function will change them in-place. All functions will return
new expressions.
To perform multiple substitutions at once, pass a list of (old, new) pairs to subs.
>>> expr = x**3 + 4*x*y - z
>>> expr.subs([(x, 2), (y, 4), (z, 0)])
40
It is often useful to combine this with a list comprehension to do a large set of similar replacements all at once. For example, say we had x4 4x3 + 4x2 2x + 3 and we wanted to replace
all instances of x that have an even power with y, to get y 4 4x3 + 4y 2 2x + 3.
>>> expr = x**4 - 4*x**3 + 4*x**2 - 2*x + 3
>>> replacements = [(x**i, y**i) for i in range(5) if i % 2 == 0]
>>> expr.subs(replacements)
-4*x**3 - 2*x + y**4 + 4*y**2 + 3
16
2.4.3 evalf
To evaluate a numerical expression into a oating point number, use evalf.
>>> expr = sqrt(8)
>>> expr.evalf()
2.82842712474619
SymPy can evaluate oating point expressions to arbitrary precision. By default, 15 digits of
precision are used, but you can pass any number as the argument to evalf. Lets compute
the rst 100 digits of .
>>> pi.evalf(100)
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
To numerically evaluate an expression with a Symbol at a point, we might use subs followed
by evalf, but it is more ecient and numerically stable to pass the substitution to evalf
using the subs ag, which takes a dictionary of Symbol: point pairs.
>>> expr = cos(2*x)
>>> expr.evalf(subs={x: 2.4})
0.0874989834394464
Sometimes there are roundo errors smaller than the desired precision that remain after an
expression is evaluated. Such numbers can be removed at the users discretion by setting the
chop ag to True.
>>> one = cos(1)**2 + sin(1)**2
>>> (one - 1).evalf()
-0.e-124
>>> (one - 1).evalf(chop=True)
0
2.4.4 lambdify
subs and evalf are good if you want to do simple evaluation, but if you intend to evaluate
an expression at many points, there are more ecient ways. For example, if you wanted to
evaluate an expression at a thousand points, using SymPy would be far slower than it needs
to be, especially if you only care about machine precision. Instead, you should use libraries
like NumPy and SciPy.
The easiest way to convert a SymPy expression to an expression that can be numerically
evaluated is to use the lambdify function. lambdify acts like a lambda function, except it
converts the SymPy names to the names of the given numerical library, usually NumPy. For
example
>>> import numpy
>>> a = numpy.arange(10)
>>> expr = sin(x)
>>> f = lambdify(x, expr, numpy)
>>> f(a)
[ 0.
0.84147098 0.90929743
-0.2794155
0.6569866
0.98935825
0.14112001 -0.7568025
0.41211849]
-0.95892427
You can use other libraries than NumPy. For example, to use the standard library math module, use math.
17
To use lambdify with numerical libraries that it does not know about, pass a dictionary of
sympy name:numerical function pairs. For example
>>> def mysin(x):
...
...
My sine. Not only accurate for small x.
...
...
return x
>>> f = lambdify(x, expr, {sin:mysin})
>>> f(0.1)
0.1
2.5 Printing
As we have already seen, SymPy can pretty print its output using Unicode characters. This
is a short introduction to the most common printing options available in SymPy.
2.5.1 Printers
There are several printers available in SymPy. The most common ones are
str
repr
ASCII pretty printer
Unicode pretty printer
LaTeX
MathML
Dot
In addition to these, there are also printers that can output SymPy objects to code, such as
C, Fortran, Javascript, Theano, and Python. These are not discussed in this tutorial.
Quick Tip
You an also change the printer used in SymPy Live. Just change the Output Format in
the settings.
18
If you plan to work in an interactive calculator-type session, the init session() function will
automatically import everything in SymPy, create some common Symbols, setup plotting, and
run init printing().
>>> from sympy import init_session
>>> init_session()
Python console for SymPy 0.7.3 (Python 2.7.5-64-bit) (ground types: gmpy)
These commands were executed:
>>> from future import division
>>> from sympy import *
>>> x, y, z, t = symbols(x y z t)
>>> k, m, n = symbols(k m n, integer=True)
>>> f, g, h = symbols(f g h, cls=Function)
>>> init printing() # doctest: +SKIP
Documentation can be found at http://www.sympy.org
>>>
If LATEX is not installed, but Matplotlib is installed, it will use the Matplotlib rendering
engine. If Matplotlib is not installed, it uses the Unicode pretty printer.
In the IPython notebook, it will use MathJax to render LATEX.
2.5. Printing
19
In an IPython console session, or a regular Python session, it will use the Unicode pretty
printer if the terminal supports Unicode.
In a terminal that does not support Unicode, the ASCII pretty printer is used.
20
To explicitly not use LATEX, pass use latex=False to init printing() or init session(). To
explicitly not use Unicode, pass use unicode=False.
repr
The repr form of an expression is designed to show the exact form of an expression. It will
be discussed more in the Advanced Expression Manipulation (page 52) section. To get it, use
2.5. Printing
21
srepr() 1 .
>>> srepr(Integral(sqrt(1/x), x))
Integral(Pow(Pow(Symbol(x), Integer(-1)), Rational(1, 2)), Tuple(Symbol(x)))
The repr form is mostly useful for understanding how an expression is built internally.
ASCII Pretty Printer
The ASCII pretty printer is accessed from pprint(). If the terminal does not support Unicode,
the ASCII printer is used by default. Otherwise, you must pass use unicode=False.
>>> pprint(Integral(sqrt(1/x), x), use_unicode=False)
/
|
|
___
|
/ 1
|
/ - dx
| \/
x
|
/
pprint() prints the output to the screen. If you want the string form, use pretty().
>>> pretty(Integral(sqrt(1/x), x), use_unicode=False)
/
\n |
\n |
___
\n |
/ 1
\n |
>>> print(pretty(Integral(sqrt(1/x), x), use_unicode=False))
/
|
|
___
|
/ 1
|
/ - dx
| \/
x
|
/
dx\n | \\/
___
- dx
\
x
1 SymPy does not use the Python builtin repr() function for repr printing, because in Python str(list) calls
repr() on the elements of the list, and some SymPy functions return lists (such as solve()). Since srepr() is so
verbose, it is unlikely that anyone would want it called by default on the output of solve().
22
\n |
LATEX
To get the LATEX form of an expression, use latex().
>>> print(latex(Integral(sqrt(1/x), x)))
\int \sqrt{\frac{1}{x}}\, dx
The latex() function has many options to change the formatting of dierent things. See its
documentation (page 1260) for more details.
MathML
There is also a printer to MathML, called print mathml().
sympy.printing.mathml.
print mathml() prints the output. If you want the string, use the function mathml().
Dot
The dotprint() function in sympy.printing.dot prints output to dot format, which can be
rendered with Graphviz. See the Advanced Expression Manipulation (page 52) section for
some examples of the output of this printer.
2.6 Simplication
To make this document easier to read, we are going to enable pretty printing.
>>> from sympy import *
>>> x, y, z = symbols(x y z)
>>> init_printing(use_unicode=True)
2.6.1 simplify
Now lets jump in and do some interesting mathematics. One of the most useful features of
a symbolic manipulation system is the ability to simplify mathematical expressions. SymPy
2.6. Simplication
23
has dozens of functions to perform various kinds of simplication. There is also one general
function called simplify() that attempts to apply all of these functions in an intelligent way
to arrive at the simplest form of an expression. Here are some examples
>>> simplify(sin(x)**2 + cos(x)**2)
1
>>> simplify((x**3 + x**2 - x - 1)/(x**2 + 2*x + 1))
x - 1
>>> simplify(gamma(x)/gamma(x - 2))
(x - 2)(x - 1)
Here, gamma(x) is (x), the gamma function. We see that simplify() is capable of handling
a large class of expressions.
But simplify() has a pitfall. It just applies all the major simplication operations in SymPy,
and uses heuristics to determine the simplest result. But simplest is not a well-dened
term. For example, say we wanted to simplify x2 + 2x + 1 into (x + 1)2 :
>>> simplify(x**2 + 2*x + 1)
2
x + 2x + 1
We did not get what we want. There is a function to perform this simplication, called factor(), which will be discussed below.
Another pitfall to simplify() is that it can be unnecessarily slow, since it tries many kinds
of simplications before picking the best one. If you already know exactly what kind of simplication you are after, it is better to apply the specic simplication function(s) that apply
those simplications.
Applying specic simplication functions instead of simplify() also has the advantage that
specic functions have certain guarantees about the form of their output. These will be discussed with each function below. For example, factor(), when called on a polynomial with
rational coecients, is guaranteed to factor the polynomial into irreducible factors. simplify() has no guarantees. It is entirely heuristical, and, as we saw above, it may even miss
a possible type of simplication that SymPy is capable of doing.
simplify() is best when used interactively, when you just want to whittle down an expression to a simpler form. You may then choose to apply specic functions once you see what
simplify() returns, to get a more precise result. It is also useful when you have no idea what
form an expression will take, and you need a catchall function to simplify it.
24
Given a polynomial, expand() will put it into a canonical form of a sum of monomials.
expand() may not sound like a simplication function. After all, by its very name, it makes
expressions bigger, not smaller. Usually this is the case, but often an expression will become
smaller upon calling expand() on it due to cancellation.
>>> expand((x + 1)*(x - 2) - (x - 1)*x)
-2
factor
factor() takes a polynomial and factors it into irreducible factors over the rational numbers.
For example:
>>> factor(x**3 - x**2 + x - 1)
2
(x - 1)x + 1
>>> factor(x**2*z + 4*x*y*z + 4*y**2*z)
2
z(x + 2y)
For polynomials, factor() is the opposite of expand(). factor() uses a complete multivariate factorization algorithm over the rational numbers, which means that each of the factors
returned by factor() is guaranteed to be irreducible.
If you are interested in the factors themselves, factor list returns a more structured output.
>>> factor_list(x**2*z + 4*x*y*z + 4*y**2*z)
(1, [(z, 1), (x + 2y, 2)])
Note that the input to factor and expand need not be polynomials in the strict sense. They
will intelligently factor or expand any kind of expression (though note that the factors may
not be irreducible if the input is no longer a polynomial over the rationals).
>>> expand((cos(x) + sin(x))**2)
2
2
sin (x) + 2sin(x)cos(x) + cos (x)
>>> factor(cos(x)**2 + 2*cos(x)*sin(x) + sin(x)**2)
2
(sin(x) + cos(x))
collect
collect() collects common powers of a term in an expression. For example
>>> expr = x*y + x
>>> expr
3
2
2
x - x z + 2x +
>>> collected_expr
>>> collected_expr
3
2
x + x (-z + 2) +
xy + x - 3
= collect(expr, x)
x(y + 1) - 3
2.6. Simplication
25
>>> collected_expr.coeff(x, 2)
-z + 2
cancel
cancel() will take any rational function and put it into the standard canonical form, pq , where
p and q are expanded polynomials with no common factors, and the leading coecients of p
and q do not have denominators (i.e., are integers).
>>> cancel((x**2 + 2*x + 1)/(x**2 + x))
x + 1
----x
>>> expr = 1/x + (3*x/2 - 2)/(x - 4)
>>> expr
3x
--- - 2
2
1
------- + x - 4
x
>>> cancel(expr)
2
3x - 2x - 8
-------------2
2x - 8x
>>> expr = (x*y**2 - 2*x*y*z + x*z**2 + y**2 - 2*y*z + z**2)/(x**2 - 1)
>>> expr
2
2
2
2
xy - 2xyz + xz + y - 2yz + z
--------------------------------------2
x - 1
>>> cancel(expr)
2
2
y - 2yz + z
--------------x - 1
Note that since factor() will completely factorize both the numerator and the denominator
of an expression, it can also be used to do the same thing:
>>> factor(expr)
2
(y - z)
-------x - 1
However, if you are only interested in making sure that the expression is in canceled form,
cancel() is more ecient than factor().
apart
apart() performs a partial fraction decomposition on a rational function.
26
trigsimp
To simplify expressions using trigonometric identities, use trigsimp().
>>> trigsimp(sin(x)**2 + cos(x)**2)
1
>>> trigsimp(sin(x)**4 - 2*cos(x)**2*sin(x)**2 + cos(x)**4)
cos(4x)
1
-------- + 2
2
>>> trigsimp(sin(x)*tan(x)/sec(x))
2
sin (x)
Much like simplify(), trigsimp() applies various trigonometric identities to the input expression, and then uses a heuristic to return the best one.
2.6. Simplication
27
expand trig
To expand trigonometric functions, that is, apply the sum or double angle identities, use
expand trig().
>>> expand_trig(sin(x + y))
sin(x)cos(y) + sin(y)cos(x)
>>> expand_trig(tan(2*x))
2tan(x)
------------2
- tan (x) + 1
Because expand trig() tends to make trigonometric expressions larger, and trigsimp()
tends to make them smaller, these identities can be applied in reverse using trigsimp()
>>> trigsimp(sin(x)*cos(y) + sin(y)*cos(x))
sin(x + y)
2.6.4 Powers
Before we introduce the power simplication functions, a mathematical discussion on the
identities held by powers is in order. There are three kinds of identities satised by exponents
1. xa xb = xa+b
2. xa y a = (xy)a
3. (xa )b = xab
Identity 1 is always true.
Identity 2 is not always true. For example, if x = y = 1 and a = 12 , then xa y a = 1 1 =
ab
21/2
1
1 = 1 and x = (1)
= (1) = 1. However, identity 3 is true when b is an integer (again,
it may also hold in other cases
as well). Two common consequences of the failure of identity
2
3 are that x 6= x and that x1 6= 1x .
To summarize
Identity
1. xa xb = xa+b
2. xa y a = (xy)a
3. (xa )b = xab
Counterexample
when
conditions
are not met
None
(1)1/2 (1)1/2 6= (1
1)1/2
(
(1)2
)1/2
6= (1)21/2
Important consequences
None
x y 6=
xy in general
x2 6= x and x1 6= 1x
in general
This is important to remember, because by default, SymPy will not perform simplications if
they are not true in general.
28
In order to make SymPy perform simplications involving identities that are only true under
certain assumptions, we need to put assumptions on our Symbols. We will undertake a full
discussion of the assumptions system later, but for now, all we need to know are the following.
By default, SymPy Symbols are assumed to be complex (elements of C). That is, a simplication will not be applied to an expression with a given Symbol unless it holds for all
complex numbers.
Symbols can be given dierent assumptions by passing the assumption to symbols().
For the rest of this section, we will be assuming that x and y are positive, and that a and
b are real. We will leave z, t, and c as arbitrary complex Symbols to demonstrate what
happens in that case.
>>> x, y = symbols(x y, positive=True)
>>> a, b = symbols(a b, real=True)
>>> z, t, c = symbols(z t c)
Note: In SymPy, sqrt(x) is just a shortcut to x**Rational(1, 2). They are exactly the
same object.
>>> sqrt(x) == x**Rational(1, 2)
True
powsimp
powsimp() applies identities 1 and 2 from above, from left to right.
>>> powsimp(x**a*x**b)
a + b
x
>>> powsimp(x**a*y**a)
a
(xy)
If you know that you want to apply this simplication, but you dont want to mess with assumptions, you can pass the force=True ag. This will force the simplication to take place,
regardless of assumptions.
>>> powsimp(t**c*z**c, force=True)
c
(tz)
Note that in some instances, in particular, when the exponents are integers or rational numbers, and identity 2 holds, it will be applied automatically
>>> (z*t)**2
2 2
t z
>>> sqrt(x*y)
___
___
\ x \ y
2.6. Simplication
29
This means that it will be impossible to undo this identity with powsimp(), because even if
powsimp() were to put the bases together, they would be automatically split apart again.
>>> powsimp(z**2*t**2)
2 2
t z
>>> powsimp(sqrt(x)*sqrt(y))
___
___
\ x \ y
And as with powsimp(), you can force the expansion to happen without ddling with assumptions by using force=True.
>>> expand_power_base((z*t)**c, force=True)
c c
t z
As with identity 2, identity 1 is applied automatically if the power is a number, and hence
cannot be undone with expand power exp().
>>> x**2*x**3
5
x
>>> expand_power_exp(x**5)
5
x
powdenest
powdenest() applies identity 3, from left to right.
>>> powdenest((x**a)**b)
ab
x
As before, the identity is not applied if it is not true under the given assumptions.
30
>>> powdenest((z**a)**b)
b
a
z
Logarithms have similar issues as powers. There are two main identities
1. log (xy) = log (x) + log (y)
2. log (xn ) = n log (x)
Neither identity is true for arbitrary complex x and y, due to the branch cut in the complex
plane for the complex logarithm. However, sucient conditions for the identities to hold are
if x and y are positive and n is real.
>>> x, y = symbols(x y, positive=True)
>>> n = symbols(n, real=True)
2.6. Simplication
31
>>> expand_log(log(z*t))
log(tz)
As with powsimp() and powdenest(), expand log() has a force option that can be used to
ignore assumptions.
>>> expand_log(log(z**2))
2
logz
>>> expand_log(log(z**2), force=True)
2log(z)
logcombine
To apply identities 1 and 2 from right to left, use logcombine().
>>> logcombine(log(x) + log(y))
log(xy)
>>> logcombine(n*log(x))
n
logx
>>> logcombine(n*log(z))
nlog(z)
logcombine() also has a force option that can be used to ignore assumptions.
>>> logcombine(n*log(z), force=True)
n
logz
The factorial function is factorial. factorial(n) represents n! = 1 2 (n 1) n. n! represents the number of permutations of n distinct items.
>>> factorial(n)
n!
( )
The binomial coecient function is binomial. binomial(n, k) represents nk , the number
of ways to choose k items from a set of n distinct items. It is also often written as nCk, and is
pronounced n choose k.
32
>>> binomial(n, k)
n
k
The factorial
function is closely related to the gamma function, gamma. gamma(z) represents
(z) = 0 tz1 et dt, which for positive integer z is the same as (z 1)!.
>>> gamma(z)
(z)
rewrite
A common way to deal with special functions is to rewrite them in terms of one another. This
works for any function in SymPy, not just special functions. To rewrite an expression in terms
of a function, use expr.rewrite(function). For example,
>>> tan(x).rewrite(sin)
2
2sin (x)
--------sin(2x)
>>> factorial(x).rewrite(gamma)
(x + 1)
For some tips on applying more targeted rewriting, see the Advanced Expression Manipulation (page 52) section.
expand func
To expand special functions in terms of some identities, use expand func(). For example
>>> expand_func(gamma(x + 3))
x(x + 1)(x + 2)(x)
hyperexpand
To rewrite hyper in terms of more standard functions, use hyperexpand().
>>> hyperexpand(hyper([1, 1], [2], z))
-log(-z + 1)
------------z
2.6. Simplication
33
hyperexpand() also works on the more general Meijer G-function (see its documentation
(page 428) for more information).
>>> expr = meijerg([[1],[1]], [[1],[]], -z)
>>> expr
-1, 1 1 1 |
| -z
-2, 1 1
|
>>> hyperexpand(expr)
1
z
e
combsimp
To simplify combinatorial expressions, use combsimp().
>>> combsimp(factorial(n)/factorial(n - 3))
n(n - 2)(n - 1)
>>> combsimp(binomial(n+1, k+1)/binomial(n, k))
n + 1
----k + 1
-------sin(x)
a0 +
a1 +
a2 +
1
..
.+
1
an
where a0 , . . . , an are integers, and a1 , . . . , an are positive. A continued fraction can also be innite, but innite objects are more dicult to represent in computers, so we will only examine
the nite case here.
A continued fraction of the above form is often represented as a list [a0 ; a1 , . . . , an ]. Lets write
a simple function that converts such a list to its continued fraction form. The easiest way
to construct a continued fraction from a list is to work backwards. Note that despite the
apparent symmetry of the denition, the rst element, a0 , must usually be handled dierently
from the rest.
34
We use Integer(0) in list to frac so that the result will always be a SymPy object, even if
we only pass in Python ints.
>>> list_to_frac([1, 2, 3, 4])
43
-30
Every nite continued fraction is a rational number, but we are interested in symbolics here,
so lets create a symbolic continued fraction. The symbols() function that we have been using
has a shortcut to create numbered symbols. symbols(a0:5) will create the symbols a0, a1,
..., a5.
>>> syms = symbols(a0:5)
>>> syms
(a, a1, a2, a, a)
>>> a0, a1, a2, a3, a4 = syms
>>> frac = list_to_frac(syms)
>>> frac
1
a + ----------------1
a1 + -----------1
a2 + ------1
a + -a
This form is useful for understanding continued fractions, but lets put it into standard rational
function form using cancel().
>>> frac = cancel(frac)
>>> frac
aa1a2aa + aa1a2 + aa1a + aaa + a + a2aa + a2 + a
------------------------------------------------------------------------a1a2aa + a1a2 + a1a + aa + 1
Now suppose we were given frac in the above canceled form. In fact, we might be given the
fraction in any form, but we can always put it into the above canonical form with cancel().
Suppose that we knew that it could be rewritten as a continued fraction. How could we do
this with SymPy? A continued fraction is recursively c + f1 , where c is an integer and f is
a (smaller) continued fraction. If we could write the expression in this form, we could pull
out each c recursively and add it to a list. We could then get a continued fraction with our
list to frac() function.
2.6. Simplication
35
The key observation here is that we can convert an expression to the form c + f1 by doing a
partial fraction decomposition with respect to c. This is because f does not contain c. This
means we need to use the apart() function. We use apart() to pull the term out, then
subtract it from the expression, and take the reciprocal to get the f part.
>>> l = []
>>> frac = apart(frac, a0)
>>> frac
a2aa + a2 + a
a + --------------------------------------a1a2aa + a1a2 + a1a + aa + 1
>>> l.append(a0)
>>> frac = 1/(frac - a0)
>>> frac
a1a2aa + a1a2 + a1a + aa + 1
--------------------------------------a2aa + a2 + a
36
Quick Tip
You can execute multiple lines at once in SymPy Live. Typing Shift-Enter instead of
Enter will enter a newline instead of executing.
Of course, this exercise seems pointless, because we already know that our frac is
list to frac([a0, a1, a2, a3, a4]). So try the following exercise. Take a list of symbols
and randomize them, and create the canceled continued fraction, and see if you can reproduce
the original list. For example
>>>
>>>
>>>
>>>
>>>
import random
l = list(symbols(a0:5))
random.shuffle(l)
orig_frac = frac = cancel(list_to_frac(l))
del l
Click on Run code block in SymPy Live on the denition of list to frac) above, and then
on the above example, and try to reproduce l from frac. I have deleted l at the end to
remove the temptation for peeking (you can check your answer at the end by calling cancel(list to frac(l)) on the list that you generate at the end, and comparing it to orig frac.
See if you can think of a way to gure out what symbol to pass to apart() at each stage (hint:
1
think of what happens to a0 in the formula a0 + a1 +
when it is canceled).
2.7 Calculus
This section covers how to do basic calculus tasks such as derivatives, integrals, limits, and
series expansions in SymPy. If you are not familiar with the math of any part of this section,
you may safely skip it.
>>> from sympy import *
>>> x, y, z = symbols(x y z)
>>> init_printing(use_unicode=True)
2.7.1 Derivatives
To take derivatives, use the diff function.
>>> diff(cos(x), x)
-sin(x)
>>> diff(exp(x**2), x)
2
x
2xe
diff can take multiple derivatives at once. To take multiple derivatives, pass the variable as
many times as you wish to dierentiate, or pass a number after the variable. For example,
both of the following nd the third derivative of x4 .
>>> diff(x**4, x, x, x)
24x
>>> diff(x**4, x, 3)
24x
2.7. Calculus
37
You can also take derivatives with respect to many variables at once. Just pass each derivative
in order, using the same syntax as for single variable derivatives. For example, each of the
7
following will compute xy 2 z4 exyz .
>>> expr = exp(x*y*z)
>>> diff(expr, x, y, y, z, z,
3 2 3 3 3
2 2 2
x y x y z + 14x y z
>>> diff(expr, x, y, 2, z, 4)
3 2 3 3 3
2 2 2
x y x y z + 14x y z
>>> diff(expr, x, y, y, z, 4)
3 2 3 3 3
2 2 2
x y x y z + 14x y z
z, z)
xyz
+ 52xyz + 48e
xyz
+ 52xyz + 48e
xyz
+ 52xyz + 48e
diff can also be called as a method. The two ways of calling diff are exactly the same, and
are provided only for convenience.
>>> expr.diff(x, y, y, z, 4)
3 2 3 3 3
2 2 2
xyz
x y x y z + 14x y z + 52xyz + 48e
To create an unevaluated derivative, use the Derivative class. It has the same syntax as
diff.
>>> deriv = Derivative(expr, x, y, y, z, 4)
>>> deriv
7
xyz
----------e
4
2
z y x
These unevaluated objects are useful for delaying the evaluation of the derivative, or for printing purposes. They are also used when SymPy does not know how to compute the derivative
of an expression (for example, if it contains an undened function, which are described in the
Solving Dierential Equations (page 45) section).
2.7.2 Integrals
To compute an integral, use the integrate function. There are two kinds of integrals, denite
and indenite. To compute an indenite integral, that is, an antiderivative, or primitive, just
pass the variable after the expression.
>>> integrate(cos(x), x)
sin(x)
Note that SymPy does not include the constant of integration. If you want it, you can add
one yourself, or rephrase your problem as a dierential equation and use dsolve to solve it,
which does add the constant (see Solving Dierential Equations (page 45)).
38
Quick Tip
in SymPy is oo (thats the lowercase letter oh twice). This is because oo looks like
, and is easy to type.
To compute a denite integral, pass the argument (integration variable, lower limit,
upper limit). For example, to compute
ex dx,
0
we would do
>>> integrate(exp(-x), (x, 0, oo))
1
As with indenite integrals, you can pass multiple limit tuples to perform a multiple integral.
For example, to compute
2
2
ex y dx dy,
do
>>> integrate(exp(-x**2 - y**2), (x, -oo, oo), (y, -oo, oo))
x
x dx
As with Derivative, you can create an unevaluated integral using Integral. To later evaluate
this integral, call doit.
>>> expr = Integral(log(x)**2, x)
>>> expr
2
log (x) dx
>>> expr.doit()
2
xlog (x) - 2xlog(x) + 2x
integrate uses powerful algorithms that are always improving to compute both denite and
indenite integrals, including heuristic pattern matching type algorithms, a partial implementation of the Risch algorithm, and an algorithm using Meijer G-functions that is useful
for computing integrals in terms of special functions, especially denite integrals. Here is a
sampling of some of the power of integrate.
2.7. Calculus
39
4
2 x
2
x
x x
x + x e - x - 2xe - 2x - e e
---------------------------------------- dx
2
2 x
(x - 1) (x + 1) e + 1
>>> integ.doit()
x
x
e
loge + 1 + -----2
x - 1
>>> integ = Integral(sin(x**2), x)
>>> integ
2
sinx dx
>>> integ.doit()
___
___
___
\ 2 x
3\ 2 \ fresnels-------(3/4)
___
\
-------------------------------------8(7/4)
>>> integ = Integral(x**y*exp(-x), (x, 0, oo))
>>> integ
y -x
x e
dx
0
>>> integ.doit()
(y + 1)
for -re(y) < 1
y -x
x e
dx
otherwise
This last example returned a Piecewise expression because the integral does not converge
unless <(y) > 1.
40
2.7.3 Limits
SymPy can compute symbolic limits with the limit function. The syntax to compute
lim f (x)
xx0
is limit(f(x), x, x0).
>>> limit(sin(x)/x, x, 0)
1
limit should be used instead of subs whenever the point of evaluation is a singularity. Even
though SymPy has objects to represent , using them for evaluation is not reliable because
they do not keep track of things like rate of growth. Also, things like and
return nan
(not-a-number). For example
>>> expr = x**2/exp(x)
>>> expr.subs(x, oo)
nan
>>> limit(expr, x, oo)
0
Like Derivative and Integral, limit has an unevaluated counterpart, Limit. To evaluate
it, use doit.
>>> expr = Limit((cos(x) - 1)/x, x, 0)
>>> expr
cos(x) - 1
lim ---------x-0
x
>>> expr.doit()
0
To evaluate a limit at one side only, pass + or - as a third argument to limit. For example,
to compute
lim
x0+
1
,
x
do
>>> limit(1/x, x, 0, +)
As opposed to
>>> limit(1/x, x, 0, -)
-
2.7. Calculus
41
x
4
1 + x + -- + Ox
2
( )
The O x4 term at the end represents the Landau order term at x = 0 (not to be confused with
big O notation used in computer science, which generally represents the Landau order term
at x = ). It means that all x terms with power greater than or equal to x4 are omitted. Order
terms can be created and manipulated outside of series. They automatically absorb higher
order terms.
>>> x + x**3 + x**6 + O(x**4)
3
4
x + x + Ox
>>> x*O(1)
O(x)
If you do not want the order term, use the removeO method.
>>> expr.series(x, 0, 4).removeO()
2
x
-- + x + 1
2
here the rst order derivative was approximated around x using a minimum number of points
(2 for 1st order derivative) evaluated equidistantly using a step-size of 1. We can use arbitrary
steps (possibly containing symbolic expressions):
>>> f = Function(f)
>>> d2fdx2 = f(x).diff(x, 2)
>>> h = Symbol(h)
>>> as_finite_diff(d2fdx2, [-3*h,-h,2*h])
f(-3h)
f(-h)
2f(2h)
------- - ----- + --------
42
2
5h
2
3h
2
15h
If you are just interested in evaluating the weights, you can do so manually:
>>> finite_diff_weights(2, [-3, -1, 2], 0)[-1][-1]
[1/5, -1/3, 2/15]
note that we only need the last element in the last sublist returned from nite di weights.
The reason for this is that nite di weights also generates weights for lower derivatives and
using fewer points (see the documentation of finite diff weights for more details).
if using finite diff weights directly looks complicated and the as finite diff function
operating on Derivative instances is not exible enough, you can use apply finite diff
which takes order, x list, y list and x0 as parameters:
>>> x_list = [-3, 1, 2]
>>> y_list = symbols(a b c)
>>> apply_finite_diff(1, x_list, y_list, 0)
3a
b
2c
- --- - - + --20
4
5
2.8 Solvers
>>> from sympy import *
>>> x, y, z = symbols(x y z)
>>> init_printing(use_unicode=True)
However, there is an even easier way. In SymPy, any expression is not in an Eq is automatically
assumed to equal 0 by the solving functions. Since a = b if and only if a b = 0, this means
that instead of using x == y, you can just use x - y. For example
>>> solve(Eq(x**2, 1), x)
[-1, 1]
>>> solve(Eq(x**2 - 1, 0), x)
[-1, 1]
>>> solve(x**2 - 1, x)
[-1, 1]
This is particularly useful if the equation you wish to solve is already equal to 0. Instead of
typing solve(Eq(expr, 0), x), you can just use solve(expr, x).
2.8. Solvers
43
Note: If solve returns [] or raises NotImplementedError, it doesnt mean that the equation
has no solutions. It just means that it couldnt nd any. Often this means that the solutions
cannot be represented symbolically. For example, the equation x = cos(x) has a solution, but
it cannot be represented symbolically using standard functions.
>>> solve(x - cos(x), x)
Traceback (most recent call last):
...
NotImplementedError: multiple generators [x, exp(I*x)]
No algorithms are implemented to solve equation exp(I*x)
Traceback (most recent call last):
...
NotImplementedError: multiple generators [x, exp(I*x)]
In fact, solve makes no guarantees whatsoever about the completeness of the solutions it
nds. Much of solve is heuristics, which may nd some solutions to an equation or system
of equations, but not all of them.
solve can also solve systems of equations. Pass a list of equations and a list of variables to
solve for.
>>>
{x:
>>>
\ 2 + 3, \ 2 + 3, \ 2 + 3, - \ 2 + 3
Note: The type of the output of solve when solving systems of equations varies depending
on the type of the input. If you want a consistent interface, pass dict=True.
>>> solve([x - y + 2, x + y - 3], [x, y], dict=True)
[{x: 1/2, y: 5/2}]
>>> solve([x*y - 7, x + y - 6], [x, y], dict=True)
___
___
___
___
x: - \ 2 + 3, y: \ 2 + 3, x: \ 2 + 3, y: - \ 2 + 3
solve reports each solution only once. To get the solutions of a polynomial including multiplicity use roots.
44
>>>
[0,
>>>
{0:
The output {0: 1, 3: 2} of roots means that 0 is a root of multiplicity 1 and 3 is a root of
multiplicity 2.
f and g are now undened functions. We can call f(x), and it will represent an unknown
function.
>>> f(x)
f(x)
To solve the ODE, pass it and the function to solve for to dsolve.
>>> dsolve(diffeq, f(x))
x
cos(x)
f(x) = (C1 + C2x)e + -----2
dsolve returns an instance of Eq. This is because in general, solutions to dierential equations cannot be solved explicitly for the function.
>>> dsolve(f(x).diff(x)*(1 - sin(f(x))), f(x))
f(x) + cos(f(x)) = C1
The arbitrary constants in the solutions from dsolve are symbols of the form C1, C2, C3, and
so on.
2.8. Solvers
45
2.9 Matrices
>>> from sympy import *
>>> init_printing(use_unicode=True)
To make a matrix in SymPy, use the Matrix object. A matrix is constructed by providing a list
of row vectors that make up the matrix. For example, to construct the matrix
1 1
3 4
0 2
use
>>>
1
To make it easy to make column vectors, a list of elements is considered to be a column vector.
>>> Matrix([1, 2, 3])
1
2
3
Matrices are manipulated just like any other object in SymPy or Python.
>>> M = Matrix([[1, 2, 3], [3, 2, 1]])
>>> N = Matrix([0, 1, 1])
>>> M*N
5
3
One important thing to note about SymPy matrices is that, unlike every other object in SymPy,
they are mutable. This means that they can be modied in place, as we will see below. The
downside to this is that Matrix cannot be used in places that require immutability, such as
inside other SymPy expressions or as keys to dictionaries. If you need an immutable version
of Matrix, use ImmutableMatrix.
-2 0 4
46
>>> M.shape
(2, 3)
0
>>>
>>>
[2
M.col_del(0)
M
3
4
M.row_del(1)
M
3]
To insert rows or columns, use row insert or col insert. These operations do not operate
in place.
>>>
[2
>>>
>>>
2
0
>>>
>>>
1
-2
M
3]
M = M.row_insert(1, Matrix([[0, 4]]))
M
3
4
M = M.col_insert(0, Matrix([1, -2]))
M
2 3
0 4
Unless explicitly stated, the methods mentioned below do not operate in place. In general,
a method that does not operate in place will return a new Matrix and a method that does
operate in place will return None.
2.9. Matrices
47
-2 10
>>> M*N
0 24
0 15
>>> 3*M
3
9
-6 9
>>> M**2
-5 12
-8 3
>>> M**-1
1/3 -1/3
2/9 1/9
>>> N**-1
Traceback (most recent call last):
...
ValueError: Matrix det == 0; not invertible.
Traceback (most recent call last):
...
ValueError: Matrix det == 0; not invertible.
4
>>>
1
5 6
M.T
4
0
>>>
1
48
eye(3)
0 0
1 0
0 1
eye(4)
0 0 0
To create a matrix of all zeros, use zeros. zeros(n, m) creates an n m matrix of 0s.
>>> zeros(2, 3)
0 0 0
0 0 0
ones(3, 2)
1
To create diagonal matrices, use diag. The arguments to diag can be either numbers or
matrices. A number is interpreted as a 1 1 matrix. The matrices are stacked diagonally. The
remaining elements are lled with 0s.
>>>
1
0
>>>
-1
diag(1, 2, 3)
0 0
2 0
0 3
diag(-1, ones(2, 2), Matrix([5, 7, 5]))
0 0 0
1 1 0
1 1 0
0 0 5
0 0 7
0 0 5
2.9. Matrices
49
2 -1 3
4 3
2
>>> M.det()
-1
RREF
To put a matrix into reduced row echelon form, use rref. rref returns a tuple of two elements.
The rst is the reduced row echelon form, and the second is a list of indices of the pivot
columns.
>>> M = Matrix([[1, 0, 1, 3], [2, 3, 4, 7], [-1, -3, -3, -4]])
>>> M
1
0
1
3
2
3
4
7
-1 -3 -3 -4
>>> M.rref()
1 0
1
3 , [0, 1]
0 1 2/3 1/3
0 0
0
0
Note: The rst element of the tuple returned by rref is of type Matrix. The second is of
type list.
Nullspace
To nd the nullspace of a matrix, use nullspace. nullspace returns a list of column vectors
that span the nullspace of the matrix.
>>> M = Matrix([[1, 2, 3, 0, 0], [4, 10, 0, 0, 1]])
>>> M
1 2
3 0 0
4 10 0 0 1
>>> M.nullspace()
-15, 0, 1
6 0 -1/2
1 0 0
0 1 0
0 0 1
50
5 3
-3 -2
5 -2 2
-2
5 -2 -3 3
>>> M.eigenvals()
{-2: 1, 3: 1, 5: 2}
4, -2], [5,
3]])
This means that M has eigenvalues -2, 3, and 5, and that the eigenvalues -2 and 3 have algebraic multiplicity 1 and that the eigenvalue 5 has algebraic multiplicity 2.
To nd the eigenvectors of a matrix, use eigenvects. eigenvects returns a list of tuples of
the form (eigenvalue:algebraic multiplicity, [eigenvectors]).
>>> M.eigenvects()
-2, 1, 0, 3, 1, 1,
1
1
1
1
1
1
5, 2, 1,
0
-1
0
1
This shows us that, for example, the eigenvalue 5 also has geometric multiplicity 2, because
it has two eigenvectors. Because the algebraic and geometric multiplicities are the same for
all the eigenvalues, M is diagonalizable.
To diagonalize a matrix, use diagonalize. diagonalize returns a tuple (P, D), where D is
diagonal and M = P DP 1 .
>>>
>>>
0
1
>>>
-2
0
>>>
3
P, D = M.diagonalize()
P
1 1 0
1 1 -1
1 1 0
1 0 1
D
0 0 0
3 0 0
0 5 0
0 0 5
P*D*P**-1
-2 4
-2
2.9. Matrices
51
5 3
-3 -2
5 -2 2
-2
5 -2 -3 3
>>> P*D*P**-1 == M
True
Quick Tip
lambda is a reserved keyword in Python, so to create a Symbol called , while using the
same names for SymPy Symbols and Python variables, use lamda (without the b). It will
still pretty print as .
Note that since eigenvects also includes the eigenvalues, you should use it instead of eigenvals if you also want the eigenvectors. However, as computing the eigenvectors may often
be costly, eigenvals should be preferred if you only wish to nd the eigenvalues.
If all you want is the characteristic polynomial, use charpoly. This is more ecient than
eigenvals, because sometimes symbolic roots can be expensive to calculate.
>>> lamda = symbols(lamda)
>>> p = M.charpoly(lamda)
>>> factor(p)
2
( - 5) ( - 3)( + 2)
52
The easiest way to tear this apart is to look at a diagram of the expression tree:
Add
Symbol('x')
Mul
Pow
Symbol('y')
Integer(2)
Symbol('x')
Note: The above diagram was made using Graphviz and the dotprint (page 1269) function.
First, lets look at the leaves of this tree. Symbols are instances of the class Symbol. While
we have been doing
>>> x = symbols(x)
Either way, we get a Symbol with the name x 2 . For the number in the expression, 2, we
got Integer(2). Integer is the SymPy class for integers. It is similar to the Python built-in
type int, except that Integer plays nicely with other SymPy types.
When we write x**2, this creates a Pow object. Pow is short for power.
>>> srepr(x**2)
Pow(Symbol(x), Integer(2))
Note that in the srepr output, we see Integer(2), the SymPy version of integers, even though
technically, we input 2, a Python int. In general, whenever you combine a SymPy object with
a non-SymPy object via some function or operation, the non-SymPy object will be converted
into a SymPy object. The function that does this is sympify 3 .
>>> type(2)
<... int>
>>> type(sympify(2))
<class sympy.core.numbers.Integer>
2 We have been using symbols instead of Symbol because it automatically splits apart strings into multiple Symbols.
symbols(x y z) returns a tuple of three Symbols. Symbol(x y z) returns a single Symbol called x y z.
3 Technically, it is an internal function called sympify, which diers from sympify in that it does not convert
strings. x + 2 is not allowed.
53
We have seen that x**2 is represented as Pow(x, 2). What about x*y? As we might expect,
this is the multiplication of x and y. The SymPy class for multiplication is Mul.
>>> srepr(x*y)
Mul(Symbol(x), Symbol(y))
Thus, we could have created the same object by writing Mul(x, y).
>>> Mul(x, y)
x*y
Now we get to our nal expression, x**2 + x*y. This is the addition of our last two objects,
Pow(x, 2), and Mul(x, y). The SymPy class for addition is Add, so, as you might expect, to
create this object, we use Add(Pow(x, 2), Mul(x, y)).
>>> Add(Pow(x, 2), Mul(x, y))
x**2 + x*y
SymPy expression trees can have many branches, and can be quite deep or quite broad. Here
is a more complicated example
>>> expr = sin(x*y)/2 - x**2 + 1/y
>>> srepr(expr)
Add(Mul(Integer(-1), Pow(Symbol(x), Integer(2))), Mul(Rational(1, 2),
sin(Mul(Symbol(x), Symbol(y)))), Pow(Symbol(y), Integer(-1)))
Here is a diagram
Add
Pow
Symbol('y')
Integer(-1)
Mul
Rational(1, 2)
Mul
sin
Integer(-1)
Mul
Symbol('y')
Symbol('x')
Pow
Integer(2)
Symbol('x')
This expression reveals some interesting things about SymPy expression trees. Lets go
through them one by one.
Lets rst look at the term x**2. As we expected, we see Pow(x, 2). One level up, we see we
have Mul(-1, Pow(x, 2)). There is no subtraction class in SymPy. x - y is represented as
x + -y, or, more completely, x + -1*y, i.e., Add(x, Mul(-1, y)).
>>> expr = x - y
>>> srepr(x - y)
Add(Symbol(x), Mul(Integer(-1), Symbol(y)))
54
Add
Symbol('x')
Mul
Symbol('y')
Integer(-1)
Next, look at 1/y. We might expect to see something like Div(1, y), but similar to subtraction,
there is no class in SymPy for division. Rather, division is represented by a power of -1. Hence,
we have Pow(y, -1). What if we had divided something other than 1 by y, like x/y? Lets
see.
>>> expr = x/y
>>> srepr(expr)
Mul(Symbol(x), Pow(Symbol(y), Integer(-1)))
Mul
Symbol('x')
Pow
Symbol('y')
Integer(-1)
55
This because in SymPy, the arguments of the commutative operations Add and Mul are stored
in an arbitrary (but consistent!) order, which is independent of the order inputted (if youre
worried about noncommutative multiplication, dont be. In SymPy, you can create noncommutative Symbols using Symbol(A, commutative=False), and the order of multiplication
for noncommutative Symbols is kept the same as the input). Furthermore, as we shall see in
the next section, the printing order and the order in which things are stored internally need
not be the same either.
Quick Tip
The way an expression is represented internally and the way it is printed are often not
the same.
In general, an important thing to keep in mind when working with SymPy expression trees
is this: the internal representation of an expression and the way it is printed need not be the
same. The same is true for the input form. If some expression manipulation algorithm is not
working in the way you expected it to, chances are, the internal representation of the object
is dierent from what you thought it was.
We created Add(x, x), so we might expect expr.func to be Add, but instead we got Mul. Why
is that? Lets take a closer look at expr.
56
>>> expr
2*x
Add(x, x), i.e., x + x, was automatically converted into Mul(2, x), i.e., 2*x, which is a Mul.
SymPy classes make heavy use of the new class constructor, which, unlike init , allows
a dierent class to be returned from the constructor.
Second, some classes are special-cased, usually for eciency reasons 4 .
>>> Integer(2).func
<class sympy.core.numbers.Integer>
>>> Integer(0).func
<class sympy.core.numbers.Zero>
>>> Integer(-1).func
<class sympy.core.numbers.NegativeOne>
For the most part, these issues will not bother us. The special classes Zero, One, NegativeOne,
and so on are subclasses of Integer, so as long as you use isinstance, it will not be an issue.
args
args are the top-level arguments of the object. (x*y).args would be (x, y). Lets look at
some examples
>>> expr = 3*y**2*x
>>> expr.func
<class sympy.core.mul.Mul>
>>> expr.args
(3, x, y**2)
From this, we can see that expr == Mul(3, y**2, x). In fact, we can see that we can
completely reconstruct expr from its func and its args.
>>> expr.func(*expr.args)
3*x*y**2
>>> expr == expr.func(*expr.args)
True
Note that although we entered 3*y**2*x, the args are (3, x, y**2). In a Mul, the Rational
coecient will come rst in the args, but other than that, the order of everything else follows
no special pattern. To be sure, though, there is an order.
>>> expr = y**2*3*x
>>> expr.args
(3, x, y**2)
Muls args are sorted, so that the same Mul will have the same args. But the sorting is based
on some criteria designed to make the sorting unique and ecient that has no mathematical
signicance.
The srepr form of our expr is Mul(3, x, Pow(y, 2)). What if we want to get at the args of
Pow(y, 2). Notice that the y**2 is in the third slot of expr.args, i.e., expr.args[2].
4 Classes like One and Zero are singletonized, meaning that only one object is ever created, no matter how many
times the class is called. This is done for space eciency, as these classes are very common. For example, Zero
might occur very often in a sparse matrix represented densely. As we have seen, NegativeOne occurs any time we
have -x or 1/x. It is also done for speed eciency because singletonized objects can be compared by is. The unique
objects for each singletonized class can be accessed from the S object.
57
>>> expr.args[2]
y**2
Now what if we try to go deeper. What are the args of y. Or 2. Lets see.
>>> y.args
()
>>> Integer(2).args
()
They both have empty args. In SymPy, empty args signal that we have hit a leaf of the
expression tree.
So there are two possibilities for a SymPy expression. Either it has empty args, in which case
it is a leaf node in any expression tree, or it has args, in which case, it is a branch node of any
expression tree. When it has args, it can be completely rebuilt from its func and its args.
This is expressed in the key invariant.
Key Invariant
Every well-formed SymPy expression must either have empty args or satisfy expr ==
expr.func(*expr.args).
(Recall that in Python if a is a tuple, then f(*a) means to call f with arguments from the
elements of a, e.g., f(*(1, 2, 3)) is the same as f(1, 2, 3).)
This key invariant allows us to write simple algorithms that walk expression trees, change
them, and rebuild them into new expressions.
Walking the Tree
With this knowledge, lets look at how we can recurse through an expression tree. The nested
nature of args is a perfect t for recursive functions. The base case will be empty args. Lets
write a simple function that goes through an expression and prints all the args at each level.
>>> def pre(expr):
...
print(expr)
...
for arg in expr.args:
...
pre(arg)
See how nice it is that () signals leaves in the expression tree. We dont even have to write
a base case for our recursion; it is handled automatically by the for loop.
Lets test our function.
>>> expr = x*y + 1
>>> pre(expr)
x*y + 1
1
x*y
x
y
58
Can you guess why we called our function pre? We just wrote a pre-order traversal function
for our expression tree. See if you can write a post-order traversal function.
Such traversals are so common in SymPy that the generator functions preorder traversal
and postorder traversal are provided to make such traversals easy. We could have also
written our algorithm as
>>> for arg in preorder_traversal(expr):
...
print(arg)
x*y + 1
1
x*y
x
y
59
60
CHAPTER
THREE
61
If you want to test for symbolic equality, one way is to subtract one expression from the
other and run it through functions like expand(), simplify(), and trigsimp() and see if the
equation reduces to 0.
>>>
>>>
0
>>>
>>>
0
>>>
0
Note: See also Why does SymPy say that two equal expressions are unequal? in the FAQ.
3.3 Variables
3.3.1 Variables Assignment does not Create a Relation Between Expressions
When you use = to do assignment, remember that in Python, as in most programming languages, the variable does not change if you change the value you assigned to it. The equations you are typing use the values present at the time of creation to ll in values, just like
regular Python denitions. They are not altered by changes made afterwards. Consider the
following:
>>>
>>>
>>>
>>>
a +
>>>
>>>
4
>>>
a +
Changing quantity a does not change b; you are not working with a set of simultaneous equations. It might be helpful to remember that the string that gets printed when you print a
variable referring to a SymPy object is the string that was given to it when it was created;
that string does not have to be the same as the variable that you assign it to.
>>> from sympy import var
>>> r, t, d = var(rate time short_life)
>>> d = r*t
>>> print(d)
rate*time
>>> r = 80
62
>>> t = 2
>>> print(d)
rate*time
>>> d = r*t
>>> print(d)
160
If you need variables that have dependence on each other, you can dene functions. Use the
def operator. Indent the body of the function. See the Python docs for more information on
dening functions.
>>>
>>>
c
>>>
d
>>>
...
...
...
...
...
>>>
c*d
>>>
>>>
2
>>>
2*d
c, d = var(c d)
print(c)
print(d)
def ctimesd():
return c*d
ctimesd()
c = 2
print(c)
ctimesd()
3.3. Variables
63
Note: See also Why doesnt changing one variable change another that depends on it? in
the FAQ.
3.3.2 Symbols
Symbols are variables, and like all other variables, they need to be assigned before you can
use them. For example:
>>> import sympy
>>> z**2 # z is not defined yet
Traceback (most recent call last):
File <stdin>, line 1, in <module>
NameError: name z is not defined
>>> sympy.var(z) # This is the easiest way to define z as a standard symbol
z
>>> z**2
z**2
Traceback (most recent call last):
File <stdin>, line 1, in <module>
NameError: name z is not defined
If you use isympy, it runs the following commands for you, giving you some default Symbols
and Functions.
>>>
>>>
>>>
>>>
>>>
If you want control over the assumptions of the variables, use Symbol() and symbols(). See
Keyword Arguments (page 72) below.
64
Lastly, it is recommended that you not use I, E, S, N, C, O, or Q for variable or symbol names, as
those are used for the imaginary unit (i), the base of the natural logarithm (e), the sympify()
function (see Symbolic Expressions (page 65) below), numeric evaluation (N() is equivalent
to evalf() (page 331) ), the class registry (for things like C.cos(), to prevent cyclic imports
in some code), the big O order symbol (as in O(n log n)), and the assumptions object that
holds a list of supported ask keys (such as Q.real), respectively. You can use the mnemonic
QCOSINE to remember what Symbols are dened by default in SymPy. Or better yet, always
use lowercase letters for Symbol names. Python will not prevent you from overriding default
SymPy names or functions, so be careful.
>>> cos(pi) # cos and pi are a built-in sympy names.
-1
>>> pi = 3
# Notice that there is no warning for overriding pi.
>>> cos(pi)
cos(3)
>>> def cos(x): # No warning for overriding built-in functions either.
...
return 5*x
...
>>> cos(pi)
15
>>> from sympy import cos # reimport to restore normal behavior
If you have IPython installed and use isympy, you can also press the TAB key to get a list of all
built-in names and to autocomplete. Also, see this page for a trick for getting tab completion
in the regular Python console.
Note: See also What is the best way to create symbols? in the FAQ.
65
If you include numbers in a SymPy expression, they will be sympied automatically, but there
is one gotcha you should be aware of. If you do <number>/<number> inside of a SymPy
expression, Python will evaluate the two numbers before SymPy has a chance to get to them.
The solution is to sympify() one of the numbers, or use Rational.
>>> x**(1/2) # evaluates to x**0 or x**0.5
x**0.5
>>> x**(S(1)/2) # sympyify one of the ints
sqrt(x)
>>> x**Rational(1, 2) # use the Rational class
sqrt(x)
If the two integers are not directly separated by a division sign then you dont have to worry
about this problem:
>>> x**(2*x/3)
x**(2*x/3)
Note: A common mistake is copying an expression that is printed and reusing it. If the
expression has a Rational (i.e., <number>/<number>) in it, you will not get the same result,
obtaining the Python result for the division rather than a SymPy Rational.
>>> x = Symbol(x)
>>> print(solve(7*x -22, x))
[22/7]
>>> 22/7 # If we just copy and paste we get int 3 or a float
3.142857142857143
>>> # One solution is to just assign the expression to a variable
>>> # if we need to use it again.
>>> a = solve(7*x - 22, x)
>>> a
[22/7]
The other solution is to put quotes around the expression and run it through S() (i.e., sympify
it):
>>> S(22/7)
22/7
future
But be careful: you will now receive oats where you might have desired a Rational:
>>> x**(1/2)
x**0.5
66
Rational only works for number/number and is only meant for rational numbers. If you
want a fraction with symbols or expressions in it, just use /. If you do number/expression or
expression/number, then the number will automatically be converted into a SymPy Number.
You only need to be careful with number/number.
>>> Rational(2, x)
Traceback (most recent call last):
...
TypeError: invalid input: x
>>> 2/x
2/x
Traceback (most recent call last):
...
TypeError: invalid input: x
to have the precision match the number of digits, the null string can be used
for the precision
>>> Float(100, )
100.
>>> Float(12.34)
12.3400000000000
>>> Float(12.34, )
12.34
>>> s, r = [Float(j, 3) for j in (0.25, Rational(1, 7))]
>>> for f in [s, r]:
...
print(f)
0.250
0.143
Next, notice that each of those values looks correct to 3 digits. But if we try to evaluate them
to 20 digits, a dierence will become apparent:
The 0.25 (with precision of 3) represents a number that has a non-repeating binary
decimal; 1/7 is repeating in binary and decimal it cannot be represented accurately
too far past those rst 3 digits (the correct decimal is a repeating 142857):
67
>>> s.n(20)
0.25000000000000000000
>>> r.n(20)
0.14285278320312500000
It is important to realize that although a Float is being displayed in decimal at aritrary precision, it is actually stored in binary. Once the Float is created, its binary
information is set at the given precision. The accuracy of that value cannot be subsequently changed; so 1/7, at a precision of 3 digits, can be padded with binary
zeros, but these will not make it a more accurate value of 1/7.
If inexact, low-precision numbers are involved in a calculation with with higher precision
values, the evalf engine will increase the precision of the low precision values and inexact
results will be obtained. This is feature of calculations with limited precision:
>>> Float(0.1, 10) + Float(0.1, 3)
0.2000061035
Although the evalf engine tried to maintain 10 digits of precision (since that was the highest
precision represented) the 3-digit precision used limits the accuracy to about 4 digits not all
the digits you see are signicant. evalf doesnt try to keep track of the number of signicant
digits.
That very simple expression involving the addition of two numbers with dierent precisions
will hopefully be instructive in helping you understand why more complicated expressions
(like trig expressions that may not be simplied) will not evaluate to an exact zero even
though, with the right simplication, they should be zero. Consider this unsimplied trig
identity, multiplied by a big number:
>>> big = 12345678901234567890
>>> big_trig_identity = big*cos(x)**2 + big*sin(x)**2 - big*1
>>> abs(big_trig_identity.subs(x, .1).n(2)) > 1000
True
When the cos and sin terms were evaluated to 15 digits of precision and multiplied by the
big number, they gave a large number that was only precise to 15 digits (approximately) and
when the 20 digit big number was subtracted the result was not zero.
There are three things that will help you obtain more precise numerical values for expressions:
1) Pass the desired substitutions with the call to evaluate. By doing the subs rst,
the Float values can not be updated as necessary. By passing the desired substitutions with the call to evalf the ability to re-evaluate as necessary is gained and the
results are impressively better:
>>> big_trig_identity.n(2, {x: 0.1})
-0.e-91
2) Use Rationals, not Floats. During the evaluation process, the Rational can be
computed to an arbitrary precision while the Float, once created at a default of
15 digits cannot. Compare the value of -1.4e+3 above with the nearly zero value
obtained when replacing x with a Rational representing 1/10 before the call to
evaluate:
>>> big_trig_identity.subs(x, S(1/10)).n(2)
0.e-91
3) Try to simplify the expression. In this case, SymPy will recognize the trig identity
and simplify it to zero so you dont even have to evaluate it numerically:
68
>>> big_trig_identity.simplify()
0
The output shows that the subs() function has replaced variable x with variable a, and variable y with variable b:
original = 3*x + 4*y
modified = 3*a + 4*b
The subs() function does not modify the original expression expr. Rather, a modied copy of
the expression is returned. This returned object is stored in the variable expr modified. Note
that unlike C/C++ and other high-level languages, Python does not require you to declare a
variable before it is used.
69
x
- ----- + 3
x + 1
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for ^: Add and int
3.5.1 Lists
Square brackets [] denote a list. A list is a container that holds any number of dierent
objects. A list can contain anything, including items of dierent types. Lists are mutable,
which means that you can change the elements of a list after it has been created. You access
the items of a list also using square brackets, placing them after the list or list variable. Items
are numbered using the space before the item.
Note: List indexes begin at 0.
Example:
>>>
>>>
[x,
>>>
x
>>>
>>>
[2,
>>>
[-1
Note: See the Python docs for more information on lists and the square bracket notation for
accessing elements of a list.
70
3.5.2 Dictionaries
Curly brackets {} denote a dictionary, or a dict for short. A dictionary is an unordered list of
non-duplicate keys and values. The syntax is {key: value}. You can access values of keys
using square bracket notation.
>>> d = {a: 1, b: 2} # A dictionary.
>>> d
{a: 1, b: 2}
>>> d[a] # How to access items in a dict
1
>>> roots((x - 1)**2*(x - 2), x) # Some functions return dicts
{1: 2, 2: 1}
>>> # Some SymPy functions return dictionaries. For example,
>>> # roots returns a dictionary of root:multiplicity items.
>>> roots((x - 5)**2*(x + 3), x)
{-3: 1, 5: 2}
>>> # This means that the root -3 occurs once and the root 5 occurs twice.
3.5.3 Tuples
Parentheses (), aside from changing operator precedence and their use in function calls, (like
cos(x)), are also used for tuples. A tuple is identical to a list (page 70), except that it is not
mutable. That means that you can not change their values after they have been created. In
general, you will not need tuples in SymPy, but sometimes it can be more convenient to type
parentheses instead of square brackets.
>>> t = (1, 2, x) # Tuples are like lists
>>> t
(1, 2, x)
>>> t[0]
1
>>> t[0] = 4 # Except you can not change them after they have been created
Traceback (most recent call last):
File <console>, line 1, in <module>
TypeError: tuple object does not support item assignment
Traceback (most recent call last):
File <console>, line 1, in <module>
TypeError: tuple object does not support item assignment
integrate takes a sequence as the second argument if you want to integrate with
limits (and a tuple or list will work):
71
The square root will now simplify since it knows that x >= 0:
>>> sqrt(x**2)
x
Setting combine to the default value is the same as not setting it.
>>> pprint(powsimp(x**n*x**m*y**n*y**m, combine=all))
m + n
(x*y)
72
Note: See the Python docs for more information on function parameters.
In [2]: # But in ipython, you can also use ?, which is better because it
In [3]: # it gives you more information
In [4]: powsimp?
These will give you the function parameters and docstring for powsimp(). The output will
look something like this:
3.6.2 source()
Another useful option is the source() function. This will print the source code of a function,
including any docstring that it may have. You can also do function?? in ipython. For
example, from SymPy 0.6.5:
>>> source(simplify) # simplify() is actually only 2 lines of code.
In file: ./sympy/simplify/simplify.py
def simplify(expr):
Naively simplifies the given expression.
...
Simplification is not a well defined term and the exact strategies
this function tries can change in the future versions of SymPy. If
your algorithm relies on simplification (whatever it is), try to
determine what you need exactly - is it powsimp()? radsimp()?
together()?, logcombine()?, or something else? And use this particular
function directly, because those are well defined and thus your algorithm
will be robust.
...
expr = Poly.cancel(powsimp(expr))
return powsimp(together(expr.expand()), combine=exp, deep=True)
73
74
CHAPTER
FOUR
Now I start winpdb on it (if youve never used winpdb its an excellent multiplatform debugger, works on Linux, Windows and Mac OS X):
$ winpdb t.py
y + 2*x
and a winpdb window will popup, I move to the next line using F6:
75
Then I step into (F7) and after a little debugging I get for example:
Tip: Make the winpdb window larger on your screen, it was just made smaller to t in this
76
guide.
I see values of all local variables in the left panel, so its very easy to see whats happening. You
can see, that the y + 2*x is emerging in the obj variable. Observing that obj is constructed
from c part and nc part and seeing what c part contains (y and 2*x). So looking at the line
28 (the whole line is not visible on the screenshot, so here it is):
c_part, nc_part, lambda_args, order_symbols = cls.flatten(map(_sympify, args))
you can see that the simplication happens in cls.flatten. Now you can set the breakpoint
on the line 28, quit winpdb (it will remember the breakpoint), start it again, hit F5, this will
stop at this breakpoint, hit F7, this will go into the function Add.flatten():
@classmethod
def flatten(cls, seq):
Takes the sequence seq of nested Adds and returns a flatten list.
Returns: (commutative_part, noncommutative_part, lambda_args,
order_symbols)
Applies associativity, all terms are commutable with respect to
addition.
terms = {}
# term -> coeff
# e.g. x**2 -> 5
for ... + 5*x**2 + ...
coeff = S.Zero
# standalone term
# e.g. 3 + ...
lambda_args = None
order_factors = []
while seq:
o = seq.pop(0)
and then you can study how it works. I am going to stop here, this should be enough to get
you going with the above technique, I am able to understand almost any Python code.
4.3.1 Basics
All symbolic things are implemented using subclasses of the Basic class. First, you need to
create symbols using Symbol(x) or numbers using Integer(5) or Float(34.3). Then you
construct the expression using any class from SymPy. For example Add(Symbol(a), Symbol(b)) gives an instance of the Add class. You can call all methods, which the particular
class supports.
For easier use, there is a syntactic sugar for expressions like:
77
Pow(cos(x),
So, you can write normal expressions using python arithmetics like this:
a = Symbol(a)
b = Symbol(b)
e = (a + b)**2
print e
but from the SymPy point of view, we just need the classes Add, Mul, Pow, Rational, Integer.
>>> type(e)
<class sympy.core.mul.Mul>
4.3.3 Comparisons
Expressions can be compared using a regular python syntax:
>>> from sympy.abc import x, y
>>> x + y == y + x
True
>>> x + y == y - x
False
78
Sometimes, you need to have a unique symbol, for example as a temporary one in some
calculation, which is going to be substituted for something else at the end anyway. This is
achieved using Dummy(x). So, to sum it up:
>>> from sympy import Symbol, Dummy
>>> Symbol(x) == Symbol(x)
True
>>> Dummy(x) == Dummy(x)
False
4.3.4 Debugging
Starting with 0.6.4, you can turn on/o debug messages with the environment variable
SYMPY DEBUG, which is expected to have the values True or False. For example, to turn on
debugging, you would issue:
[user@localhost]: SYMPY DEBUG=True ./bin/isympy
4.3.5 Functionality
There are no given requirements on classes in the library. For example, if they dont implement the fdiff() method and you construct an expression using such a class, then trying to
use the Basic.series() method will raise an exception of not nding the fdiff() method
in your class. This duck typing has an advantage that you just implement the functionality
which you need.
You can dene the cos class like this:
class cos(Function):
pass
and use it like 1 + cos(x), but if you dont implement the fdiff() method, you will not be
able to call (1 + cos(x)).series().
The symbolic object is characterized (dened) by the things which it can do, so implementing
more methods like fdiff(), subs() etc., you are creating a shape of the symbolic object.
Useful things to implement in new classes are: hash() (to use the class in comparisons),
fdiff() (to use it in series expansion), subs() (to use it in expressions, where some parts
are being substituted) and series() (if the series cannot be computed using the general
Basic.series() method). When you create a new class, dont worry about this too much
- just try to use it in your code and you will realize immediately which methods need to be
implemented in each situation.
All objects in sympy are immutable - in the sense that any operation just returns a new instance
(it can return the same instance only if it didnt change). This is a common mistake to change
the current instance, like self.arg = self.arg + 1 (wrong!). Use arg = self.arg +
1; return arg instead. The object is immutable in the sense of the symbolic expression it
represents. It can modify itself to keep track of, for example, its hash. Or it can recalculate
anything regarding the expression it contains. But the expression cannot be changed. So you
can pass any instance to other objects, because you dont have to worry that it will change,
or that this would break anything.
79
4.3.6 Conclusion
Above are the main ideas behind SymPy that we try to obey. The rest depends on the current
implementation and may possibly change in the future. The point of all of this is that the
interdependencies inside SymPy should be kept to a minimum. If one wants to add new
functionality to SymPy, all that is necessary is to create a subclass of Basic and implement
what you want.
4.3.7 Functions
How to create a new function with one variable:
class sign(Function):
nargs = 1
@classmethod
def eval(cls, arg):
if isinstance(arg, Basic.NaN):
return S.NaN
if isinstance(arg, Basic.Zero):
return S.Zero
if arg.is_positive:
return S.One
if arg.is_negative:
return S.NegativeOne
if isinstance(arg, Basic.Mul):
coeff, terms = arg.as_coeff_mul()
if not isinstance(coeff, Basic.One):
return cls(coeff) * cls(Basic.Mul(*terms))
is_finite = True
def _eval_conjugate(self):
return self
def _eval_is_zero(self):
return isinstance(self[0], Basic.Zero)
and thats it. The eval * functions are called when something is needed. The eval is
called when the class is about to be instantiated and it should return either some simplied instance of some other class or if the class should be unmodied, return None
(see core/function.py in Function. new for implementation details). See also tests in
sympy/functions/elementary/tests/test interface.py that test this interface. You can use them
to create your own new functions.
The applied function sign(x) is constructed using
sign(x)
both inside and outside of SymPy. Unapplied functions sign is just the class itself:
sign
both inside and outside of SymPy. This is the current structure of classes in SymPy:
80
class BasicType(type):
pass
class MetaBasicMeths(BasicType):
...
class BasicMeths(AssumeMeths):
__metaclass__ = MetaBasicMeths
...
class Basic(BasicMeths):
...
class FunctionClass(MetaBasicMeths):
...
class Function(Basic, RelMeths, ArithMeths):
__metaclass__ = FunctionClass
...
The exact names of the classes and the names of the methods and how they work can be
changed in the future.
This is how to create a function with two variables:
class chebyshevt_root(Function):
nargs = 2
@classmethod
def eval(cls, n, k):
if not 0 <= k < n:
raise ValueError(must have 0 <= k < n)
return C.cos(S.Pi*(2*k + 1)/(2*n))
Note: the rst argument of a @classmethod should be cls (i.e. not self).
Here its how to dene a derivative of the function:
>>> from sympy import Function, sympify, cos
>>> class my_function(Function):
...
nargs = 1
...
...
def fdiff(self, argindex = 1):
...
return cos(self.args[0])
...
...
@classmethod
...
def eval(cls, arg):
...
arg = sympify(arg)
...
if arg == 0:
...
return sympify(0)
So guess what this my function is going to be? Well, its derivative is cos and the function
value at 0 is 0, but lets pretend we dont know:
>>> from sympy import pprint
>>> pprint(my_function(x).series(x, 0, 10))
3
5
7
9
x
x
x
x
/ 10\
x - -- + --- - ---- + ------ + O\x /
6
120
5040
362880
81
Lets try a more complicated example. Lets dene the derivative in terms of the function
itself:
>>> class what_am_i(Function):
...
nargs = 1
...
...
def fdiff(self, argindex = 1):
...
return 1 - what_am_i(self.args[0])**2
...
...
@classmethod
...
def eval(cls, arg):
...
arg = sympify(arg)
...
if arg == 0:
...
return sympify(0)
The new functions we just dened are regular SymPy objects, you can use them all over
SymPy, e.g.:
>>> from sympy import limit
>>> limit(what_am_i(x)/x, x, 0)
1
82
>>> e.args[0]
x**2
Number arguments (in Adds and Muls) will always be the first argument;
other arguments might be in arbitrary order:
>>> (1 + x + y*z).args[0]
1
>>> (1 + x + y*z).args[1] in (x, y*z)
True
>>> (y*z).args
(y, z)
>>> sin(y*z).args
(y*z,)
Never use internal methods or variables, prexed with (example: dont use args, use
.args instead).
testing the structure of a SymPy expression
Applied functions:
>>> from sympy import sign, exp, Function
>>> e = sign(x**2)
>>> isinstance(e, sign)
True
>>> isinstance(e, exp)
False
>>> isinstance(e, Function)
True
83
4.4 Contributing
We welcome every SymPy user to participate in its development. Dont worry if youve never
contributed to any open source project, well help you learn anything necessary, just ask on
our mailinglist.
Dont be afraid to ask anything and dont worry that you are wasting our time if you are new
to SymPy and ask questions that maybe most of the people know the answer to you are
not, because thats exactly what the mailinglist is for and people answer your emails because
they want to. Also we try hard to answer every email, so youll always get some feedback and
pointers what to do next.
84
CHAPTER
FIVE
If the argument is already a type that SymPy understands, it will do nothing but return
that value. This can be used at the beginning of a function to ensure you are working
with the correct type.
>>> from sympy import sympify
85
>>> sympify(2).is_integer
True
>>> sympify(2).is_real
True
>>> sympify(2.0).is_real
True
>>> sympify(2.0).is_real
True
>>> sympify(2e-45).is_real
True
last):
could not parse ux***2
last):
could not parse ux***2
Notes
Locals
The sympication happens with access to everything that is loaded by from sympy import *; anything used in a string that is not dened by that import will be converted
to a symbol. In the following, the bitcount function is treated as a symbol and the O
is interpreted as the Order object (used with series) and it raises an error when used
improperly:
>>> s = bitcount(42)
>>> sympify(s)
bitcount(42)
>>> sympify(O(x))
O(x)
>>> sympify(O + 1)
Traceback (most recent call last):
...
86
In order to have the O interpreted as a Symbol, identify it as such in the namespace dictionary. This can be done in a variety of ways; all three of the following are possibilities:
>>>
>>>
>>>
>>>
>>>
O +
If you want all single-letter and Greek-letter variables to be symbols then you can use the
clashing-symbols dictionaries that have been dened there as private variables: clash1
(single-letter variables), clash2 (the multi-letter Greek names) or clash (both single and
multi-letter names that are dened in abc).
>>> from sympy.abc import _clash1
>>> _clash1
{C: C, E: E, I: I, N: N, O: O, Q: Q, S: S}
>>> sympify(C & Q, _clash1)
And(C, Q)
Strict
If the option strict is set to True, only the types for which an explicit conversion has
been dened are converted. In the other cases, a SympifyError is raised.
>>> print(sympify(None))
None
>>> sympify(None, strict=True)
Traceback (most recent call last):
...
SympifyError: SympifyError: None
Traceback (most recent call last):
...
SympifyError: SympifyError: None
Evaluation
If the option evaluate is set to False, then arithmetic and operators will be converted
into their SymPy equivalents and the evaluate=False option will be added. Nested Add
87
or Mul will be denested rst. This is done via an AST transformation that replaces operators with their SymPy equivalents, so if an operand redenes any of those operations,
the redened operators will not be used.
>>> sympify(2**2 / 3 + 5)
19/3
>>> sympify(2**2 / 3 + 5, evaluate=False)
2**2/3 + 5
Extending
To extend sympify to convert custom objects (not derived from Basic), just dene a
sympy method to your class. You can do that even to classes that you do not own by
subclassing or adding the method at runtime.
>>> from sympy import Matrix
>>> class MyList1(object):
...
def __iter__(self):
...
yield 1
...
yield 2
...
raise StopIteration
...
def __getitem__(self, i): return list(self)[i]
...
def _sympy_(self): return Matrix(self)
>>> sympify(MyList1())
Matrix([
[1],
[2]])
If you do not have control over the class denition you could also use the converter
global dictionary. The key is the class and the value is a function that takes a single
argument and returns the desired SymPy object, e.g. converter[MyList] = lambda x:
Matrix(x).
>>> class MyList2(object):
# XXX Do not do this if you control the class!
...
def __iter__(self): #
Use _sympy_!
...
yield 1
...
yield 2
...
raise StopIteration
...
def __getitem__(self, i): return list(self)[i]
>>> from sympy.core.sympify import converter
>>> converter[MyList2] = lambda x: Matrix(x)
>>> sympify(MyList2())
Matrix([
[1],
[2]])
5.1.2 assumptions
This module contains the machinery handling assumptions.
All symbolic objects have assumption attributes that can be accessed via .is <assumption
name> attribute.
Assumptions determine certain properties of symbolic objects. Assumptions can have 3 possible values: True, False, None. None is returned when it is impossible to say something about
the property. For example, a generic Symbol is not known beforehand to be positive.
88
By default, all symbolic values are in the largest set in the given context without specifying
the property. For example, a symbol that has a property being integer, is also real, complex,
etc.
Here follows a list of possible assumption names:
commutative object commutes with any other object with respect to multiplication operation.
complex object can have only values from the set of complex numbers.
imaginary object value is a number that can be written as a real number multiplied by the
imaginary unit I. See [R26] (page 1899). Please note, that 0 is not considered to be an
imaginary number, see issue #7649.
real object can have only values from the set of real numbers.
integer object can have only values from the set of integers.
odd, even object can have only values from the set of odd (even) integers [R25] (page 1899).
prime object is a natural number greater than 1 that has no positive divisors other than 1
and itself. See [R29] (page 1899).
composite object is a positive integer that has at least one positive divisor other than 1 or
the number itself. See [R27] (page 1899).
zero, nonzero object is zero (not zero).
rational object can have only values from the set of rationals.
algebraic object can have only values from the set of algebraic numbers 1 .
transcendental object can have only values from the set of transcendental numbers 2 .
irrational object value cannot be represented exactly by Rational, see [R28] (page 1899).
nite, innite object absolute value is bounded (is value is arbitrarily large). See [R30]
(page 1899), [R31] (page 1899), [R32] (page 1899).
negative, nonnegative
(page 1899).
positive, nonpositive object can have only positive (only nonpositive) values.
hermitian, antihermitian object belongs to the eld of hermitian (antihermitian) operators.
Examples
>>> from sympy import Symbol
>>> x = Symbol(x, real = True); x
x
>>> x.is_real
True
>>> x.is_complex
True
1
2
http://en.wikipedia.org/wiki/Algebraic number
http://en.wikipedia.org/wiki/Transcendental number
89
See Also
See Also:
sympy.core.numbers.ImaginaryUnit (page 137) sympy.core.numbers.Zero (page 132)
sympy.core.numbers.One (page 133)
Notes
Assumption values are stored in obj. assumptions dictionary or are returned by getter methods (with property decorators) or are attributes of objects/classes.
References
5.1.3 cache
cacheit
sympy.core.cache.cacheit(func)
5.1.4 basic
Basic
class sympy.core.basic.Basic
Base class for all objects in SymPy.
Conventions:
1.Always use .args, when accessing parameters of some instance:
>>> from sympy import cot
>>> from sympy.abc import x, y
>>> cot(x).args
(x,)
>>> cot(x).args[0]
x
>>> (x*y).args
(x, y)
>>> (x*y).args[1]
y
args
Returns a tuple of arguments of self.
90
Notes
Never use self. args, always use self.args. Only use args in new when creating
a new function. Dont override .args() from Basic (so that its easy to change the
interface in the future if needed).
Examples
>>> from sympy import cot
>>> from sympy.abc import x, y
>>> cot(x).args
(x,)
>>> cot(x).args[0]
x
>>> (x*y).args
(x, y)
>>> (x*y).args[1]
y
as content primitive(radical=False)
A stub to allow Basic args (like Tuple) to be skipped when computing the content
and primitive components of an expression.
See docstring of Expr.as content primitive
as poly(*gens, **args)
Converts self to a polynomial or returns None.
>>> from sympy import sin
>>> from sympy.abc import x, y
>>> print((x**2 + x*y).as_poly())
Poly(x**2 + x*y, x, y, domain=ZZ)
>>> print((x**2 + x*y).as_poly(x, y))
Poly(x**2 + x*y, x, y, domain=ZZ)
>>> print((x**2 + sin(y)).as_poly(x, y))
None
assumptions0
Return object type assumptions.
For example:
Symbol(x, real=True) Symbol(x, integer=True)
are dierent objects. In other words, besides Python type (Symbol in this case), the
initial assumptions are also forming their typeinfo.
91
Examples
>>> from sympy import Symbol
>>> from sympy.abc import x
>>> x.assumptions0
{commutative: True}
>>> x = Symbol(x, positive=True)
>>> x.assumptions0
{commutative: True, complex: True, hermitian: True,
imaginary: False, negative: False, nonnegative: True,
nonpositive: False, nonzero: True, positive: True, real: True,
zero: False}
atoms(*types)
Returns the atoms that form the current object.
By default, only objects that are truly atomic and cant be divided into smaller pieces
are returned: symbols, numbers, and number symbols like I and pi. It is possible to
request atoms of any type, however, as demonstrated below.
Examples
>>> from sympy import Number, NumberSymbol, Symbol
>>> (1 + x + 2*sin(y + I*pi)).atoms(Symbol)
set([x, y])
>>> (1 + x + 2*sin(y + I*pi)).atoms(Number)
set([1, 2])
>>> (1 + x + 2*sin(y + I*pi)).atoms(Number, NumberSymbol)
set([1, 2, pi])
>>> (1 + x + 2*sin(y + I*pi)).atoms(Number, NumberSymbol, I)
set([1, 2, I, pi])
Note that I (imaginary unit) and zoo (complex innity) are special types of number
symbols and are not part of the NumberSymbol class.
The type can be given implicitly, too:
>>> (1 + x + 2*sin(y + I*pi)).atoms(x) # x is a Symbol
set([x, y])
Be careful to check your assumptions when using the implicit option since
S(1).is Integer = True but type(S(1)) is One, a special type of sympy atom,
while type(S(2)) is type Integer and will nd all integers in an expression:
>>> from sympy import S
>>> (1 + x + 2*sin(y + I*pi)).atoms(S(1))
set([1])
>>> (1 + x + 2*sin(y + I*pi)).atoms(S(2))
set([1, 2])
Finally, arguments to atoms() can select more than atomic atoms: any sympy type
(loaded in core/ init .py) can be listed as an argument and those types of atoms
as found in scanning the arguments of the expression recursively:
92
canonical variables
Return a dictionary mapping any variable dened in self.variables as underscoresuxed numbers corresponding to their position in self.variables. Enough underscores are added to ensure that there will be no clash with existing free symbols.
Examples
>>>
>>>
>>>
{x:
count(query)
Count the number of matching subexpressions.
count ops(visual=None)
wrapper for count ops that returns the operation count.
doit(**hints)
Evaluate objects that are not evaluated by default like limits, integrals, sums and
products. All objects of this kind will be evaluated recursively, unless some species
were excluded via hints or unless the deep hint was set to False.
>>> from sympy import Integral
>>> from sympy.abc import x
93
>>> 2*Integral(x, x)
2*Integral(x, x)
>>> (2*Integral(x, x)).doit()
x**2
>>> (2*Integral(x, x)).doit(deep = False)
2*Integral(x, x)
find(query, group=False)
Find all subexpressions matching a query.
free symbols
Return from the atoms of self those which are free symbols.
For most expressions, all symbols are free symbols. For some classes this is not true.
e.g. Integrals use Symbols for the dummy variables which are bound variables, so
Integral has a method to return all symbols except those. Derivative keeps track of
symbols with respect to which it will perform a derivative; those are bound variables,
too, so it has its own symbols method.
Any other method that uses bound variables should implement a symbols method.
classmethod fromiter(args, **assumptions)
Create a new object from an iterable.
This is a convenience function that allows one to create objects from any iterable,
without having to convert to a list or tuple rst.
Examples
>>> from sympy import Tuple
>>> Tuple.fromiter(i for i in range(5))
(0, 1, 2, 3, 4)
94
func
The top-level function in an expression.
The following should hold for all objects:
>> x == x.func(*x.args)
Examples
>>> from sympy.abc import x
>>> a = 2*x
>>> a.func
<class sympy.core.mul.Mul>
>>> a.args
(2, x)
>>> a.func(*a.args)
2*x
>>> a == a.func(*a.args)
True
has(*args, **kwargs)
Test whether any subexpression matches any of the patterns.
Examples
>>> from sympy import sin
>>> from sympy.abc import x, y, z
>>> (x**2 + sin(x*y)).has(z)
False
>>> (x**2 + sin(x*y)).has(x, y, z)
True
>>> x.has(x)
True
is comparable
Return True if self can be computed to a real number with precision, else False.
Examples
>>> from sympy import exp_polar, pi, I
>>> (I*exp_polar(I*pi/2)).is_comparable
True
>>> (I*exp_polar(I*pi*2)).is_comparable
False
95
match(pattern, old=False)
Pattern matching.
Wild symbols match all.
Return None when expression (self) does not match with pattern. Otherwise return
a dictionary such that:
pattern.xreplace(self.match(pattern)) == self
Examples
>>> from sympy import Wild
>>> from sympy.abc import x, y
>>> p = Wild(p)
>>> q = Wild(q)
>>> r = Wild(r)
>>> e = (x+y)**(x+y)
>>> e.match(p**p)
{p_: x + y}
>>> e.match(p**q)
{p_: x + y, q_: x + y}
>>> e = (2*x)**2
>>> e.match(p*q**r)
{p_: 4, q_: x, r_: 2}
>>> (p*q**r).xreplace(e.match(p*q**r))
4*x**2
The old ag will give the old-style pattern matching where expressions and patterns
are essentially solved to give the match. Both of the following give None unless
old=True:
>>> (x - 2).match(p - x, old=True)
{p_: 2*x - 2}
>>> (2/x).match(p*x, old=True)
{p_: 2/x**2}
rcall(*args)
Apply on the argument recursively through the expression tree.
This method is used to simulate a common abuse of notation for operators. For
instance in SymPy the the following will not work:
96
Initial setup
>>> from sympy import log, sin, cos, tan, Wild, Mul, Add
>>> from sympy.abc import x, y
>>> f = log(sin(x)) + tan(sin(x**2))
97
When the default value of False is used with patterns that have more than one
Wild symbol, non-intuitive results may be obtained:
>>> b = Wild(b)
>>> (2*x).replace(a*x + b, b - a)
2/x
For this reason, the exact option can be used to make the replacement only
when the match gives non-zero values for all Wild symbols:
>>> (2*x + y).replace(a*x + b, b - a, exact=True)
y - 2
>>> (2*x).replace(a*x + b, b - a, exact=True)
2*x
The expression itself is also targeted by the query but is done in such a fashion that
changes are not made twice.
>>> e = x*(x*y + 1)
>>> e.replace(lambda x: x.is_Mul, lambda x: 2*x)
2*x*(2*x*y + 1)
98
rewrite(*args, **hints)
Rewrite functions in terms of other functions.
Rewrites expression containing applications of functions of one kind in terms of
functions of dierent kind. For example you can rewrite trigonometric functions as
complex exponentials or combinatorial functions as gamma function.
As a pattern this function accepts a list of functions to to rewrite (instances of DenedFunction class). As rule you can use string or a destination function instance
(in this case rewrite() will use the str() function).
There is also the possibility to pass hints on how to rewrite the given expressions.
For now there is only one such hint dened called deep. When deep is set to False
it will forbid functions to rewrite their contents.
Examples
>>> from sympy import sin, exp
>>> from sympy.abc import x
subs(*args, **kwargs)
Substitutes old for new in an expression after sympifying args.
args is either:
two arguments, e.g. foo.subs(old, new)
one iterable argument, e.g. foo.subs(iterable). The iterable may be
99
If the keyword simultaneous is True, the subexpressions will not be evaluated until
all the substitutions have been made.
See Also:
replace (page 97) replacement capable of doing wildcard-like matching, parsing
of match, and conditional replacements
xreplace (page 101) exact node replacement in expr tree; also capable of using
matching rules
evalf calculates the given formula to a desired level of precision
Examples
>>> from
>>> from
>>> (1 +
pi*y + 1
>>> (1 +
1 + 2*pi
>>> (1 +
1 + 2*pi
>>> reps
>>> (x +
6
>>> (x +
x**2 + 2
To replace only the x**2 but not the x**4, use xreplace:
>>> (x**2 + x**4).xreplace({x**2: y})
x**4 + y
To delay evaluation until all substitutions have been made, set the keyword simultaneous to True:
>>> (x/y).subs([(x, 0), (y, 0)])
0
>>> (x/y).subs([(x, 0), (y, 0)], simultaneous=True)
nan
This has the added feature of not allowing subsequent substitutions to aect those
already made:
>>> ((x + y)/y).subs({x + y: y, y: x + y})
1
>>> ((x + y)/y).subs({x + y: y, y: x + y}, simultaneous=True)
y/(x + y)
100
>>>
>>>
>>>
>>>
>>>
A
B
C
D
E
=
=
=
=
=
(sqrt(sin(2*x)), a)
(sin(2*x), b)
(cos(2*x), c)
(x, d)
(exp(x), e)
The resulting expression represents a literal replacement of the old arguments with
the new arguments. This may not reect the limiting behavior of the expression:
>>> (x**3 - 3*x).subs({x: oo})
nan
>>> limit(x**3 - 3*x, x, oo)
oo
rather than
>>> (1/x).subs({x: 3.0}).evalf(21)
0.333333333333333314830
as the former will ensure that the desired level of precision is obtained.
xreplace(rule)
Replace occurrences of objects within the expression.
Parameters rule : dict-like
Expresses a replacement rule
Returns xreplace : the result of the replacement
See Also:
replace (page 97) replacement capable of doing wildcard-like matching, parsing
of match, and conditional replacements
subs (page 99) substitution of subexpressions as dened by the objects themselves.
Examples
>>> from sympy import symbols, pi, exp
>>> x, y, z = symbols(x y z)
>>> (1 + x*y).xreplace({x: pi})
pi*y + 1
>>> (1 + x*y).xreplace({x:pi, y:2})
1 + 2*pi
101
xreplace doesnt dierentiate between free and bound symbols. In the following,
subs(x, y) would not change x since it is a bound symbol, but xreplace does:
>>> from sympy import Integral
>>> Integral(x, (x, 1, 2*x)).xreplace({x: y})
Integral(y, (y, 1, 2*y))
Atom
class sympy.core.basic.Atom
A parent class for atomic things. An atom is an expression with no subexpressions.
Examples
Symbol, Number, Rational, Integer, ... But not: Add, Mul, Pow, ...
C
sympy.core.basic.C
5.1.5 singleton
S
sympy.core.singleton.S
102
5.1.6 expr
5.1.7 Expr
class sympy.core.expr.Expr
Base class for algebraic expressions.
Everything that requires arithmetic operations to be dened should subclass this class,
instead of Basic (which should be used only for argument storage and expression manipulation, i.e. pattern matching, substitutions, etc).
See Also:
sympy.core.basic.Basic (page 90)
apart(x=None, **args)
See the apart function in sympy.polys
args cnc(cset=False, warn=True, split 1=True)
Return [commutative factors, non-commutative factors] of self.
self is treated as a Mul and the ordering of the factors is maintained. If cset is True
the commutative factors will be returned in a set. If there were repeated factors
(as may happen with an unevaluated Mul) then an error will be raised unless it is
explicitly supressed by setting warn to False.
Note: -1 is always separated from a Number unless split 1 is False.
>>> from sympy import symbols, oo
>>> A, B = symbols(A B, commutative=0)
>>> x, y = symbols(x y)
>>> (-2*x*y).args_cnc()
[[-1, 2, x, y], []]
>>> (-2.5*x).args_cnc()
[[-1, 2.5, x], []]
>>> (-2*x*A*B*y).args_cnc()
[[-1, 2, x, y], [A, B]]
>>> (-2*x*A*B*y).args_cnc(split_1=False)
[[-2, x, y], [A, B]]
>>> (-2*x*y).args_cnc(cset=True)
[set([-1, 2, x, y]), []]
as coeff Add()
Eciently extract the coecient of a summation.
as coeff Mul(rational=False)
Eciently extract the coecient of a product.
as coeff add(*deps)
Return the tuple (c, args) where self is written as an Add, a.
c should be a Rational added to any terms of the Add that are independent of deps.
args should be a tuple of all other terms of a; args is empty if self is a Number or if
self is independent of deps (when given).
103
This should be used when you dont know if self is an Add or not but you want to
treat self as an Add or if you want to process the individual arguments of the tail of
self as an Add.
if you know self is an Add and want only the head, use self.args[0];
if you dont want to process the arguments of the tail but need the tail then use
self.as two terms() which gives the head and tail.
if you want to split self into an independent and dependent parts use
self.as independent(*deps)
>>> from sympy import S
>>> from sympy.abc import x, y
>>> (S(3)).as_coeff_add()
(3, ())
>>> (3 + x).as_coeff_add()
(3, (x,))
>>> (3 + x + y).as_coeff_add(x)
(y + 3, (x,))
>>> (3 + y).as_coeff_add(x)
(y + 3, ())
as coeff exponent(x)
c*x**e -> c,e where x can be any symbolic expression.
as coeff mul(*deps)
Return the tuple (c, args) where self is written as a Mul, m.
c should be a Rational multiplied by any terms of the Mul that are independent of
deps.
args should be a tuple of all other terms of m; args is empty if self is a Number or if
self is independent of deps (when given).
This should be used when you dont know if self is a Mul or not but you want to treat
self as a Mul or if you want to process the individual arguments of the tail of self as
a Mul.
if you know self is a Mul and want only the head, use self.args[0];
if you dont want to process the arguments of the tail but need the tail then use
self.as two terms() which gives the head and tail;
if you want to split self into an independent and dependent parts use
self.as independent(*deps)
>>> from sympy import S
>>> from sympy.abc import x, y
>>> (S(3)).as_coeff_mul()
(3, ())
>>> (3*x*y).as_coeff_mul()
(3, (x, y))
>>> (3*x*y).as_coeff_mul(x)
(3*y, (x,))
>>> (3*y).as_coeff_mul(x)
(3*y, ())
as coefficient(expr)
Extracts symbolic coecient at the given expression. In other words, this functions
separates self into the product of expr and expr-free coecient. If such separation is not possible it will return None.
104
See Also:
coeff (page 110) return sum of terms have a given factor
as coeff Add (page 103) separate the additive constant from an expression
as coeff Mul (page 103) separate the multiplicative constant from an expression
as independent (page 107) separate x-dependent terms/factors from others
sympy.polys.polytools.coeff monomial eciently nd the single coecient of a
monomial in Poly
sympy.polys.polytools.nth like coe monomial but powers of monomial terms
are used
Examples
>>> from sympy import E, pi, sin, I, Poly
>>> from sympy.abc import x
>>> E.as_coefficient(E)
1
>>> (2*E).as_coefficient(E)
2
>>> (2*sin(E)*E).as_coefficient(E)
Two terms have E in them so a sum is returned. (If one were desiring the coecient
of the term exactly matching E then the constant from the returned expression could
be selected. Or, for greater precision, a method of Poly can be used to indicate the
desired term from which the coecient is desired.)
>>> (2*E + x*E).as_coefficient(E)
x + 2
>>> _.args[0] # just want the exact match
2
>>> p = Poly(2*E + x*E); p
Poly(x*E + 2*E, x, E, domain=ZZ)
>>> p.coeff_monomial(E)
2
>>> p.nth(0,1)
2
as coefficients dict()
Return a dictionary mapping terms to their Rational coecient. Since the dictio-
105
nary is a defaultdict, inquiries about terms which were not present will return a
coecient of 0. If an expression is not an Add it is considered to have a single term.
Examples
>>> from sympy.abc import a, x
>>> (3*x + a*x + 4).as_coefficients_dict()
{1: 4, x: 3, a*x: 1}
>>> _[a]
0
>>> (3*a*x).as_coefficients_dict()
{a*x: 3}
as content primitive(radical=False)
This method should recursively remove a Rational from all arguments and return
that (content) and the new self (primitive). The content should always be positive and Mul(*foo.as content primitive()) == foo. The primitive need no be
in canonical form and should try to preserve the underlying structure if possible
(i.e. expand mul should not be applied to self).
Examples
>>> from sympy import sqrt
>>> from sympy.abc import x, y, z
>>> eq = 2 + 2*x + 2*y*(3 + 3*y)
((2 + 6*x)**2).as_content_primitive()
(3*x + 1)**2)
((2 + 6*x)**(2*y)).as_content_primitive()
(2*(3*x + 1))**(2*y))
Terms may end up joining once their as content primitives are added:
>>> ((5*(x*(1 + y)) + 2*x*(3 + 3*y))).as_content_primitive()
(11, x*(y + 1))
>>> ((3*(x*(1 + y)) + 2*x*(3 + 3*y))).as_content_primitive()
(9, x*(y + 1))
>>> ((3*(z*(1 + y)) + 2.0*x*(3 + 3*y))).as_content_primitive()
(1, 6.0*x*(y + 1) + 3*z*(y + 1))
>>> ((5*(x*(1 + y)) + 2*x*(3 + 3*y))**2).as_content_primitive()
(121, x**2*(y + 1)**2)
>>> ((5*(x*(1 + y)) + 2.0*x*(3 + 3*y))**2).as_content_primitive()
(1, 121.0*x**2*(y + 1)**2)
106
as expr(*gens)
Convert a polynomial to a SymPy expression.
Examples
>>> from sympy import sin
>>> from sympy.abc import x, y
>>> f = (x**2 + x*y).as_poly(x, y)
>>> f.as_expr()
x**2 + x*y
>>> sin(x).as_expr()
sin(x)
as independent(*deps, **hint)
A mostly naive separation of a Mul or Add into arguments that are not are dependent
on deps. To obtain as complete a separation of variables as possible, use a separation
method rst, e.g.:
separatevars() to change Mul, Add and Pow (including exp) into Mul
.expand(mul=True) to change Add or Mul into Add
.expand(log=True) to change log expr into an Add
The only non-naive thing that is done here is to respect noncommutative ordering
of variables.
The returned tuple (i, d) has the following interpretation:
i will has no variable that appears in deps
d will be 1 or else have terms that contain variables that are in deps
if self is an Add then self = i + d
if self is a Mul then self = i*d
if self is anything else, either tuple (self, S.One) or (S.One, self) is returned.
self is an Add
>>> from sympy import sin, cos, exp
>>> from sympy.abc import x, y, z
>>> (x + x*y).as_independent(x)
(0, x*y + x)
>>> (x + x*y).as_independent(y)
(x, x*y)
>>> (2*x*sin(x) + y + x + z).as_independent(x)
(y + z, 2*x*sin(x) + x)
107
self is a Mul
>>> (x*sin(x)*cos(y)).as_independent(x)
(cos(y), x*sin(x))
(3+x).as_independent(x, as_Add=False)
x + 3)
(-3+x).as_independent(x, as_Add=False)
x - 3)
Note how the below diers from the above in making the constant on the dep term
positive.
>>> (y*(-3+x)).as_independent(x)
(y, x - 3)
use .as independent() for true independence testing instead of .has(). The
former considers only symbols in the free symbols while the latter considers all
symbols
>>> from sympy import Integral
>>> I = Integral(x, (x, 1, 2))
>>> I.has(x)
True
>>> x in I.free_symbols
108
False
>>> I.as_independent(x) == (I, 1)
True
>>> (I + x).as_independent(x) == (I, x)
True
Note: when trying to get independent terms, a separation method might need to be
used rst. In this case, it is important to keep track of what you send to this routine
so you know how to interpret the returned values
>>> from sympy import separatevars, log
>>> separatevars(exp(x+y)).as_independent(x)
(exp(y), exp(x))
>>> (x + x*y).as_independent(y)
(x, x*y)
>>> separatevars(x + x*y).as_independent(y)
(x, y + 1)
>>> (x*(1 + y)).as_independent(y)
(x, y + 1)
>>> (x*(1 + y)).expand(mul=True).as_independent(y)
(x, x*y)
>>> a, b=symbols(a b,positive=True)
>>> (log(a*b).expand(log=True)).as_independent(b)
(log(a), log(b))
See also: .separatevars(), .expand(log=True), .as two terms(), .as coe add(),
.as coe mul()
as leading term(*args, **kwargs)
Returns the leading (nonzero) term of the series expansion of self.
The eval as leading term routines are used to do this, and they must always return
a non-zero value.
Examples
>>> from sympy.abc import x
>>> (1 + x + x**2).as_leading_term(x)
1
>>> (1/x**2 + x + x**2).as_leading_term(x)
x**(-2)
as numer denom()
expression -> a/b -> a, b
This is just a stub that should be dened by an objects class methods to get anything
else.
See Also:
normal return a/b instead of a, b
as ordered factors(order=None)
Return list of ordered factors (if Mul) else [self].
as ordered terms(order=None, data=False)
Transform an expression to an ordered list of terms.
109
Examples
>>> from sympy import sin, cos
>>> from sympy.abc import x
>>> (sin(x)**2*cos(x) + sin(x)**2 + 1).as_ordered_terms()
[sin(x)**2*cos(x), sin(x)**2, 1]
as powers dict()
Return self as a dictionary of factors with each factor being treated as a power.
The keys are the bases of the factors and the values, the corresponding exponents.
The resulting dictionary should be used with caution if the expression is a Mul and
contains non- commutative factors since the order that they appeared will be lost in
the dictionary.
as real imag(deep=True, **hints)
Performs complex expansion on self and returns a tuple containing collected both
real and imaginary parts. This method cant be confused with re() and im() functions,
which does not perform complex expansion at evaluation.
However it is possible to expand both re() and im() functions and get exactly the
same results as with a single call to this function.
>>> from sympy import symbols, I
>>> x, y = symbols(x,y, real=True)
>>> (x + y*I).as_real_imag()
(x, y)
>>> from sympy.abc import z, w
>>> (z + w*I).as_real_imag()
(re(z) - im(w), re(w) + im(z))
as terms()
Transform an expression to a list of terms.
cancel(*gens, **args)
See the cancel function in sympy.polys
coeff(x, n=1, right=False)
Returns the coecient from the term(s) containing x**n or None. If n is zero then
all terms independent of x will be returned.
When x is noncommutative, the coe to the left (default) or right of x can be returned.
The keyword right is ignored when x is commutative.
See Also:
as coefficient (page 104) separate the expression into a coecient and factor
as coeff Add (page 103) separate the additive constant from an expression
as coeff Mul (page 103) separate the multiplicative constant from an expression
as independent (page 107) separate x-dependent terms/factors from others
sympy.polys.polytools.coeff monomial eciently nd the single coecient of a
monomial in Poly
110
You can select terms that have an explicit negative in front of them:
>>> (-x + 2*y).coeff(-1)
x
>>> (x - 2*y).coeff(-1)
2*y
You can select terms that have a numerical term in front of them:
>>> (-x - 2*y).coeff(2)
-y
>>> from sympy import sqrt
>>> (x + sqrt(2)*x).coeff(sqrt(2))
x
(3 + 2*x + 4*x**2).coeff(x)
(3 + 2*x + 4*x**2).coeff(x**2)
(3 + 2*x + 4*x**2).coeff(x**3)
(z*(x + y)**2).coeff((x + y)**2)
(z*(x + y)**2).coeff(x + y)
111
n, m, o = symbols(n m o, commutative=False)
n.coeff(n)
(3*n).coeff(n)
(n*m + m*n*m).coeff(n) # = (1 + m)*n*m
m
(n*m + m*n*m).coeff(n, right=True) # = (1 + m)*n*m
collect(syms,
func=None,
evaluate=True,
tribute order term=True)
See the collect function in sympy.simplify
exact=False,
dis-
combsimp()
See the combsimp function in sympy.simplify
compute leading term(x, logx=None)
as leading term is only allowed for results of .series() This is a wrapper to compute
a series rst.
could extract minus sign()
Canonical way to choose an element in the set {e, -e} where e is any expression.
If the canonical element is e, we have e.could extract minus sign() == True, else
e.could extract minus sign() == False.
For
any
expression,
the
set
{e.could extract minus sign(),
e).could extract minus sign()} must be {True, False}.
(-
count ops(visual=None)
wrapper for count ops that returns the operation count.
equals(other, failing expression=False)
Return True if self == other, False if it doesnt, or None. If failing expression is True
then the expression which did not simplify to a 0 will be returned instead of None.
If self is a Number (or complex number) that is not zero, then the result is False.
112
If self is a number and has not evaluated to zero, evalf will be used to test whether
the expression evaluates to zero. If it does so and the result has signicance (i.e.
the precision is either -1, for a Rational result, or is greater than 1) then the evalf
value will be used to return True or False.
expand(*args, **kwargs)
Expand an expression using hints.
See the docstring of the expand() function in sympy.core.function for more information.
extract additively(c)
Return self - c if its possible to subtract c from self and make all matching coecients move towards zero, else return None.
See Also:
extract multiplicatively (page 114),
(page 104)
as coefficient
Examples
>>> from sympy.abc import x, y
>>> e = 2*x + 3
>>> e.extract_additively(x + 1)
x + 2
>>> e.extract_additively(3*x)
>>> e.extract_additively(4)
>>> (y*(x + 1)).extract_additively(x + 1)
>>> ((x + 1)*(x + 2*y + 1) + 3).extract_additively(x + 1)
(x + 1)*(x + 2*y) + 3
113
exp_polar(I*pi).extract_branch_factor(allow_half=True)
1/2)
exp_polar(2*I*pi).extract_branch_factor(allow_half=True)
1)
exp_polar(3*I*pi).extract_branch_factor(allow_half=True)
3/2)
exp_polar(-I*pi).extract_branch_factor(allow_half=True)
-1/2)
extract multiplicatively(c)
Return None if its not possible to make self in the form c * something in a nice way,
i.e. preserving the properties of arguments of self.
>>> from sympy import symbols, Rational
>>> x, y = symbols(x,y, real=True)
>>> ((x*y)**3).extract_multiplicatively(x**2 * y)
x*y**2
>>> ((x*y)**3).extract_multiplicatively(x**4 * y)
>>> (2*x).extract_multiplicatively(2)
x
>>> (2*x).extract_multiplicatively(3)
>>> (Rational(1,2)*x).extract_multiplicatively(3)
x/6
factor(*gens, **args)
See the factor() function in sympy.polys.polytools
getO()
Returns the additive O(..) symbol if there is one, else None.
getn()
Returns the order of the expression.
The order is determined either from the O(...) term. If there is no O(...) term, it
returns None.
Examples
>>>
>>>
>>>
2
>>>
integrate(*args, **kwargs)
See the integrate function in sympy.integrals
invert(g)
See the invert function in sympy.polys
114
is algebraic expr(*syms)
This tests whether a given expression is algebraic or not, in the given symbols, syms.
When syms is not given, all free symbols will be used. The rational function does
not have to be in expanded or in any kind of canonical form.
This function returns False for expressions that are algebraic expressions with
symbolic exponents. This is a simple extension to the is rational function, including
rational exponentiation.
See Also:
is rational function (page 117)
References
http://en.wikipedia.org/wiki/Algebraic expression
Examples
>>> from sympy import Symbol, sqrt
>>> x = Symbol(x, real=True)
>>> sqrt(1 + x).is_rational_function()
False
>>> sqrt(1 + x).is_algebraic_expr()
True
This function does not attempt any nontrivial simplications that may result in an
expression that does not appear to be an algebraic expression to become one.
>>> from sympy import exp, factor
>>> a = sqrt(exp(x)**2 + 2*exp(x) + 1)/(exp(x) + 1)
>>> a.is_algebraic_expr(x)
False
>>> factor(a).is_algebraic_expr()
True
is constant(*wrt, **ags)
Return True if self is constant, False if not, or None if the constancy could not be
determined conclusively.
If an expression has no free symbols then it is a constant. If there are free symbols
it is possible that the expression is a constant, perhaps (but not necessarily) zero.
To test such expressions, two strategies are tried:
1) numerical evaluation at two random points. If two such evaluations give two different values and the values have a precision greater than 1 then self is not constant.
If the evaluations agree or could not be obtained with any precision, no decision is
made. The numerical testing is done only if wrt is dierent than the free symbols.
2) dierentiation with respect to variables in wrt (or all free symbols if omitted) to
see if the expression is constant or not. This will not always lead to an expression
that is zero even though an expression is constant (see added test in test expr.py).
If all derivatives are zero then self is constant with respect to the given symbols.
If neither evaluation nor dierentiation can prove the expression is constant, None
is returned unless two numerical values happened to be the same and the ag failing number is True in that case the numerical value will be returned.
115
If ag simplify=False is passed, self will not be simplied; the default is True since
self should be simplied before testing.
Examples
>>> from sympy import cos, sin, Sum, S, pi
>>> from sympy.abc import a, n, x, y
>>> x.is_constant()
False
>>> S(2).is_constant()
True
>>> Sum(x, (x, 1, 10)).is_constant()
True
>>> Sum(x, (x, 1, n)).is_constant()
False
>>> Sum(x, (x, 1, n)).is_constant(y)
True
>>> Sum(x, (x, 1, n)).is_constant(n)
False
>>> Sum(x, (x, 1, n)).is_constant(x)
True
>>> eq = a*cos(x)**2 + a*sin(x)**2 - a
>>> eq.is_constant()
True
>>> eq.subs({x:pi, a:2}) == eq.subs({x:pi, a:3}) == 0
True
>>> (0**x).is_constant()
False
>>> x.is_constant()
False
>>> (x**x).is_constant()
False
>>> one = cos(x)**2 + sin(x)**2
>>> one.is_constant()
True
>>> ((one - 1)**(x + 1)).is_constant() in (True, False) # could be 0 or 1
True
is number
Returns True if self has no free symbols. It will be faster than if notself.f rees ymbols,
however, since isn umber will fail as soon as it hits a free symbol.
Examples
>>> from sympy import log, Integral
>>> from sympy.abc import x
>>> x.is_number
False
>>> (2*x).is_number
False
>>> (2 + log(2)).is_number
True
>>> (2 + Integral(2, x)).is_number
116
False
>>> (2 + Integral(2, (x, 1, 2))).is_number
True
is polynomial(*syms)
Return True if self is a polynomial in syms and False otherwise.
This checks if self is an exact polynomial in syms. This function returns False for
expressions that are polynomials with symbolic exponents. Thus, you should be
able to apply polynomial algorithms to expressions for which this returns True, and
Poly(expr, *syms) should work if and only if expr.is polynomial(*syms) returns True.
The polynomial does not have to be in expanded form. If no symbols are given, all
free symbols in the expression will be used.
This is not part of the assumptions system.
mial=True).
Examples
>>> from sympy import Symbol
>>> x = Symbol(x)
>>> ((x**2 + 1)**4).is_polynomial(x)
True
>>> ((x**2 + 1)**4).is_polynomial()
True
>>> (2**x + 1).is_polynomial(x)
False
>>> n = Symbol(n, nonnegative=True, integer=True)
>>> (x**n + 1).is_polynomial(x)
False
This function does not attempt any nontrivial simplications that may result in an
expression that does not appear to be a polynomial to become one.
>>> from sympy import sqrt, factor, cancel
>>> y = Symbol(y, positive=True)
>>> a = sqrt(y**2 + 2*y + 1)
>>> a.is_polynomial(y)
False
>>> factor(a)
y + 1
>>> factor(a).is_polynomial(y)
True
>>> b = (y**2 + 2*y + 1)/(y + 1)
>>> b.is_polynomial(y)
False
>>> cancel(b)
y + 1
>>> cancel(b).is_polynomial(y)
True
117
syms is not given, all free symbols will be used. The rational function does not have
to be in expanded or in any kind of canonical form.
This function returns False for expressions that are rational functions with symbolic exponents. Thus, you should be able to call .as numer denom() and apply polynomial algorithms to the result for expressions for which this returns True.
This is not part of the assumptions system.
nal function=True).
Examples
>>> from sympy import Symbol, sin
>>> from sympy.abc import x, y
>>> (x/y).is_rational_function()
True
>>> (x**2).is_rational_function()
True
>>> (x/sin(y)).is_rational_function(y)
False
>>> n = Symbol(n, integer=True)
>>> (x**n + 1).is_rational_function(x)
False
This function does not attempt any nontrivial simplications that may result in an
expression that does not appear to be a rational function to become one.
>>> from sympy import sqrt, factor
>>> y = Symbol(y, positive=True)
>>> a = sqrt(y**2 + 2*y + 1)/y
>>> a.is_rational_function(y)
False
>>> factor(a)
(y + 1)/y
>>> factor(a).is_rational_function(y)
True
118
The advantage of lseries() over nseries() is that many times you are just interested
in the next term in the series (i.e. the rst term for example), but you dont know
how many you should ask for in nseries() using the n parameter.
See also nseries().
nseries(x=None, x0=0, n=6, dir=+, logx=None)
Wrapper to eval nseries if assumptions allow, else to series.
If x is given, x0 is 0, dir=+, and self has x, then eval nseries is called. This calculates n terms in the innermost expressions and then builds up the nal series just
by cross-multiplying everything out.
The optional logx parameter can be used to replace any log(x) in the returned series
with a symbolic value to avoid evaluating log(x) at 0. A symbol to use in place of
log(x) should be provided.
Advantage its fast, because we dont have to determine how many terms we need
to calculate in advance.
Disadvantage you may end up with less terms than you may have expected, but
the O(x**n) term appended will always be correct and so the result, though perhaps
shorter, will also be correct.
If any of those assumptions is not met, this is treated like a wrapper to series which
will try harder to return the correct number of terms.
See also lseries().
Examples
>>>
>>>
>>>
x >>>
x -
Handling of the logx parameter in the following example the expansion fails since
sin does not have an asymptotic expansion at -oo (the limit of log(x) as x approaches
0):
>>> e = sin(log(x))
>>> e.nseries(x, 0, 6)
Traceback (most recent call last):
...
PoleError: ...
...
>>> logx = Symbol(logx)
>>> e.nseries(x, 0, 6, logx=logx)
sin(logx)
119
In the following example, the expansion works but gives only an Order term unless
the logx parameter is used:
>>> e = x**y
>>> e.nseries(x, 0, 2)
O(log(x)**2)
>>> e.nseries(x, 0, 2, logx=logx)
exp(logx*y)
radsimp()
See the radsimp function in sympy.simplify
ratsimp()
See the ratsimp function in sympy.simplify
refine(assumption=True)
See the rene function in sympy.assumptions
removeO()
Removes the additive O(..) symbol if there is one
round(p=0)
Return x rounded to the given decimal place.
If a complex number would results, apply round to the real and imaginary components of the number.
Notes
Do not confuse the Python builtin function, round, with the SymPy method of the
same name. The former always returns a oat (or raises an error if applied to a
120
complex value) while the latter returns either a Number or a complex number:
>>> isinstance(round(S(123), -2), Number)
False
>>> isinstance(S(123).round(-2), Number)
True
>>> isinstance((3*I).round(), Mul)
True
>>> isinstance((1 + 3*I).round(), Add)
True
Examples
>>> from sympy import pi, E, I, S, Add, Mul, Number
>>> S(10.5).round()
11.
>>> pi.round()
3.
>>> pi.round(2)
3.14
>>> (2*pi + E*I).round()
6. + 3.*I
separate(deep=False, force=False)
See the separate function in sympy.simplify
series(x=None, x0=0, n=6, dir=+, logx=None)
Series expansion of self around x = x0 yielding either terms of the series one by
one (the lazy series given when n=None), else all the terms at once when n != None.
Returns the series expansion of self around the point x = x0 with respect to x up
to O((x - x0)**n, x, x0) (default n is 6).
If x=None and self is univariate, the univariate symbol will be supplied, otherwise
an error will be raised.
>>> from sympy import cos, exp
>>> from sympy.abc import x, y
>>> cos(x).series()
1 - x**2/2 + x**4/24 + O(x**6)
>>> cos(x).series(n=4)
1 - x**2/2 + O(x**4)
>>> cos(x).series(x, x0=1, n=2)
cos(1) - (x - 1)*sin(1) + O((x - 1)**2, (x, 1))
>>> e = cos(x + exp(y))
>>> e.series(y, n=2)
cos(x + 1) - y*sin(x + 1) + O(y**2)
>>> e.series(x, n=2)
cos(exp(y)) - x*sin(exp(y)) + O(x**2)
121
For dir=+ (default) the series is calculated from the right and for dir=- the series
from the left. For smooth functions this ag will not alter the results.
>>> abs(x).series(dir=+)
x
>>> abs(x).series(dir=-)
-x
simplify(ratio=1.7, measure=None)
See the simplify function in sympy.simplify
taylor term(n, x, *previous terms)
General method for the taylor term.
This method is slow, because it dierentiates n-times. Subclasses can redene it to
make it faster by using the previous terms.
together(*args, **kwargs)
See the together function in sympy.polys
trigsimp(**args)
See the trigsimp function in sympy.simplify
5.1.8 AtomicExpr
class sympy.core.expr.AtomicExpr
A parent class for object which are both atoms and Exprs.
For example: Symbol, Number, Rational, Integer, ... But not: Add, Mul, Pow, ...
5.1.9 symbol
Symbol
class sympy.core.symbol.Symbol
Assumptions: commutative = True
You can override the default assumptions in the constructor:
>>> from sympy import symbols
>>> A,B = symbols(A,B, commutative = False)
>>> bool(A*B != B*A)
True
>>> bool(A*B*2 == 2*A*B) == True # multiplication by scalars is commutative
True
as dummy()
Return a Dummy having the same name and same assumptions as self.
122
Wild
class sympy.core.symbol.Wild
A Wild symbol matches anything, or anything without whatever is explicitly excluded.
Examples
>>> from sympy import Wild, WildFunction, cos, pi
>>> from sympy.abc import x, y, z
>>> a = Wild(a)
>>> x.match(a)
{a_: x}
>>> pi.match(a)
{a_: pi}
>>> (3*x**2).match(a*x)
{a_: 3*x}
>>> cos(x).match(a)
{a_: cos(x)}
>>> b = Wild(b, exclude=[x])
>>> (3*x**2).match(b*x)
>>> b.match(a)
{a_: b_}
>>> A = WildFunction(A)
>>> A.match(a)
{a_: A_}
Tips
When using Wild, be sure to use the exclude keyword to make the pattern more precise.
Without the exclude pattern, you may get matches that are technically correct, but not
what you wanted. For example, using the above without exclude:
>>> from sympy import symbols
>>> a, b = symbols(a b, cls=Wild)
>>> (2 + 3*y).match(a*x + b*y)
{a_: 2/x, b_: 3}
This is technically correct, because (2/x)*x + 3*y == 2 + 3*y, but you probably wanted
it to not match at all. The issue is that you really didnt want a and b to include x and
y, and the exclude parameter lets you specify exactly this. With the exclude parameter,
the pattern will not match.
>>> a = Wild(a, exclude=[x, y])
>>> b = Wild(b, exclude=[x, y])
>>> (2 + 3*y).match(a*x + b*y)
123
Dummy
class sympy.core.symbol.Dummy
Dummy symbols are each unique, identied by an internal count index:
>>> from sympy import Dummy
>>> bool(Dummy(x) == Dummy(x)) == True
False
If a name is not supplied then a string value of the count index will be used. This is
useful when a temporary variable is needed and the name of the variable used in the
expression is not important.
>>> Dummy()
_Dummy_10
symbols
sympy.core.symbol.symbols(names, **args)
Transform strings into instances of Symbol (page 122) class.
symbols() (page 124) function returns a sequence of symbols with names taken from
names argument, which can be a comma or whitespace delimited string, or a sequence
of strings:
>>> from sympy import symbols, Function
>>> x, y, z = symbols(x,y,z)
>>> a, b, c = symbols(a b c)
If an iterable container is needed for a single symbol, set the seq argument to True or
terminate the symbol name with a comma:
>>> symbols(x, seq=True)
(x,)
124
To reduce typing, range syntax is supported to create indexed symbols. Ranges are
indicated by a colon and the type of range is determined by the character to the right of
the colon. If the character is a digit then all contiguous digits to the left are taken as the
nonnegative starting value (or 0 if there is no digit left of the colon) and all contiguous
digits to the right are taken as 1 greater than the ending value:
>>> symbols(x:10)
(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9)
>>> symbols(x5:10)
(x5, x6, x7, x8, x9)
>>> symbols(x5(:2))
(x50, x51)
>>> symbols(x5:10,y:5)
(x5, x6, x7, x8, x9, y0, y1, y2, y3, y4)
>>> symbols((x5:10, y:5))
((x5, x6, x7, x8, x9), (y0, y1, y2, y3, y4))
If the character to the right of the colon is a letter, then the single letter to the left (or
a if there is none) is taken as the start and all characters in the lexicographic range
through the letter to the right are used as the range:
>>> symbols(x:z)
(x, y, z)
>>> symbols(x:c) # null range
()
>>> symbols(x(:c))
(xa, xb, xc)
>>> symbols(:c)
(a, b, c)
>>> symbols(a:d, x:z)
(a, b, c, d, x, y, z)
>>> symbols((a:d, x:z))
((a, b, c, d), (x, y, z))
Only one pair of parentheses surrounding ranges are removed, so to include parentheses
around ranges, double them. And to include spaces, commas, or colons, escape them
with a backslash:
>>> symbols(x((a:b)))
(x(a), x(b))
>>> symbols(x(:1\,:2))
(x(0,0), x(0,1))
# or x((:1)\,(:2))
125
Despite its name, symbols() (page 124) can create symbol-like objects like instances of
Function or Wild classes. To achieve this, set cls keyword argument to the desired type:
>>> symbols(f,g,h, cls=Function)
(f, g, h)
>>> type(_[0])
<class sympy.core.function.UndefinedFunction>
var
sympy.core.symbol.var(names, **args)
Create symbols and inject them into the global namespace.
This calls symbols() (page 124) with the same arguments and puts the results into the
global namespace. Its recommended not to use var() (page 126) in library code, where
symbols() (page 124) has to be used:
.. rubric:: Examples
>>> from sympy import var
>>> var(x)
x
>>> x
x
>>> var(a,ab,abc)
(a, ab, abc)
>>> abc
abc
>>> var(x,y, real=True)
(x, y)
>>> x.is_real and y.is_real
True
See symbol() documentation for more details on what kinds of arguments can be passed
to var() (page 126).
5.1.10 numbers
Number
class sympy.core.numbers.Number
Represents any kind of number in sympy.
126
Floating point numbers are represented by the Float class. Integer numbers (of any size),
together with rational numbers (again, there is no limit on their size) are represented by
the Rational class.
If you want to represent, for example, 1+sqrt(2), then you need to do:
Rational(1) + sqrt(Rational(2))
as coeff Add()
Eciently extract the coecient of a summation.
as coeff Mul(rational=False)
Eciently extract the coecient of a product.
cofactors(other)
Compute GCD and cofactors of self and other.
gcd(other)
Compute GCD of self and other.
lcm(other)
Compute LCM of self and other.
Float
class sympy.core.numbers.Float
Represents a oating point number. It is capable of representing arbitrary-precision
oating-point numbers.
Notes
Floats are inexact by their nature unless their value is a binary-exact value.
>>> approx, exact = Float(.1, 1), Float(.125, 1)
For calculation purposes, evalf needs to be able to change the precision but this will not
increase the accuracy of the inexact value. The following is the most accurate 5-digit
approximation of a value of 0.1 that had only 1 digit of precision:
>>> approx.evalf(5)
0.099609
By contrast, 0.125 is exact in binary (as it is in base 10) and so it can be passed to Float
or evalf to obtain an arbitrary precision with matching accuracy:
>>> Float(exact, 5)
0.12500
>>> exact.evalf(20)
0.12500000000000000000
Trying to make a high-precision Float from a oat is not disallowed, but one must keep
in mind that the underlying oat (not the apparent decimal value) is being obtained with
high precision. For example, 0.3 does not have a nite binary representation. The closest
rational is the fraction 5404319552844595/2**54. So if you try to obtain a Float of 0.3
to 20 digits of precision you will not see the same thing as 0.3 followed by 19 zeros:
>>> Float(0.3, 20)
0.29999999999999998890
127
If you want a 20-digit value of the decimal 0.3 (not the oating point approximation of
0.3) you should send the 0.3 as a string. The underlying representation is still binary but
a higher precision than Pythons oat is used:
>>> Float(0.3, 20)
0.30000000000000000000
Although you can increase the precision of an existing Float using Float it will not increase the accuracy the underlying value is not changed:
>>> def show(f): # binary rep of Float
...
from sympy import Mul, Pow
...
s, m, e, b = f._mpf_
...
v = Mul(int(m), Pow(2, int(e), evaluate=False), evaluate=False)
...
print(%s at prec=%s % (v, f._prec))
...
>>> t = Float(0.3, 3)
>>> show(t)
4915/2**14 at prec=13
>>> show(Float(t, 20)) # higher prec, not higher accuracy
4915/2**14 at prec=70
>>> show(Float(t, 2)) # lower prec
307/2**10 at prec=10
Finally, Floats can be instantiated with an mpf tuple (n, c, p) to produce the number
(-1)**n*c*2**p:
>>> n, c, p = 1, 5, 0
>>> (-1)**n*c*2**p
-5
>>> Float((1, 5, 0))
-5.00000000000000
An actual mpf tuple also contains the number of bits in c as the last element of the tuple:
>>> _._mpf_
(1, 5, 0, 3)
This is not needed for instantiation and is not the same thing as the precision. The mpf
tuple and the precision are two separate quantities that Float tracks.
Examples
>>> from sympy import Float
>>> Float(3.5)
3.50000000000000
>>> Float(3)
3.00000000000000
Floats can be created from a string representations of Python oats to force ints to Float
or to enter high-precision (> 15 signicant digits) values:
128
>>> Float(.0010)
0.00100000000000000
>>> Float(1e-3)
0.00100000000000000
>>> Float(1e-3, 3)
0.00100
Float can automatically count signicant gures if a null string is sent for the precision;
space are also allowed in the string. (Auto- counting is only allowed for strings, ints and
longs).
>>> Float(123 456 789 . 123 456, )
123456789.123456
>>> Float(12e-3, )
0.012
>>> Float(3, )
3.
If a number is written in scientic notation, only the digits before the exponent are
considered signicant if a decimal appears, otherwise the e signies only how to move
the decimal:
>>> Float(60.e2, ) # 2 digits significant
6.0e+3
>>> Float(60e2, ) # 4 digits significant
6000.
>>> Float(600e-2, ) # 3 digits significant
6.00
Attributes
is irrational
is rational
Rational
class sympy.core.numbers.Rational
Represents integers and rational numbers (p/q) of any size.
See Also:
sympify, sympy.simplify.simplify.nsimplify (page 1340)
Examples
>>> from sympy import Rational, nsimplify, S, pi
>>> Rational(3)
3
>>> Rational(1, 2)
1/2
129
>>> Rational(.5)
1/2
>>> Rational(.2)
3602879701896397/18014398509481984
If the simpler representation of the oat is desired then consider limiting the denominator to the desired value or convert the oat to a string (which is roughly equivalent to
limiting the denominator to 10**12):
>>> Rational(str(.2))
1/5
>>> Rational(.2).limit_denominator(10**12)
1/5
The conversion of other types of strings can be handled by the sympify() function, and
conversion of oats to expressions or simple fractions can be handled with nsimplify:
>>> S(.[3]) # repeating digits in brackets
1/3
>>> S(3**2/10) # general expressions
9/10
>>> nsimplify(.3) # numbers that have a simple form
3/10
But if the input does not reduce to a literal Rational, an error will be raised:
>>> Rational(pi)
Traceback (most recent call last):
...
TypeError: invalid input: pi
Traceback (most recent call last):
...
TypeError: invalid input: pi
Low-level
130
r = Rational(3, 4)
r
r.p
r.q
Note that p and q return integers (not SymPy Integers) so some care is needed when
using them in expressions:
>>> r.p/r.q
0.75
as content primitive(radical=False)
Return the tuple (R, self/R) where R is the positive Rational extracted from self.
Examples
>>> from sympy import S
>>> (S(-3)/2).as_content_primitive()
(3/2, -1)
Integer
class sympy.core.numbers.Integer
NumberSymbol
class sympy.core.numbers.NumberSymbol
approximation(number cls)
Return an interval with number cls endpoints that contains the value of NumberSymbol. If not implemented, then return None.
RealNumber
sympy.core.numbers.RealNumber
alias of Float (page 127)
131
igcd
sympy.core.numbers.igcd(*args)
Computes positive integer greatest common divisor.
The algorithm is based on the well known Euclids algorithm. To improve speed, igcd()
has its own caching mechanism implemented.
Examples
>>> from sympy.core.numbers import igcd
>>> igcd(2, 4)
2
>>> igcd(5, 10, 15)
5
ilcm
sympy.core.numbers.ilcm(*args)
Computes integer least common multiple.
Examples
>>>
>>>
10
>>>
21
>>>
30
seterr
sympy.core.numbers.seterr(divide=False)
Should sympy raise an exception on 0/0 or return a nan?
divide == True .... raise an exception divide == False ... return nan
Zero
class sympy.core.numbers.Zero
The number zero.
Zero is a singleton, and can be accessed by S.Zero
References
132
Examples
>>> from sympy import S, Integer, zoo
>>> Integer(0) is S.Zero
True
>>> 1/S.Zero
zoo
One
class sympy.core.numbers.One
The number one.
One is a singleton, and can be accessed by S.One.
References
NegativeOne
class sympy.core.numbers.NegativeOne
The number negative one.
NegativeOne is a singleton, and can be accessed by S.NegativeOne.
See Also:
One (page 133)
References
133
Half
class sympy.core.numbers.Half
The rational number 1/2.
Half is a singleton, and can be accessed by S.Half.
References
NaN
class sympy.core.numbers.NaN
Not a Number.
This represents the corresponding data type to oating point nan, which is dened in
the IEEE 754 oating point standard, and corresponds to the Python float(nan).
NaN serves as a place holder for numeric values that are indeterminate. Most operations
on NaN, produce another NaN. Most indeterminate forms, such as 0/0 or oo - oo
produce NaN. Two exceptions are 0**0 and oo**0, which all produce 1 (this is
consistent with Pythons oat).
NaN is mathematically not equal to anything else, even NaN itself. This explains the
initially counter-intuitive results with Eq and == in the examples below.
NaN is a singleton, and can be accessed by S.NaN, or can be imported as nan.
References
134
Attributes
is
is
is
is
is
is
is
is
is
is
algebraic
nite
integer
negative
positive
prime
rational
real
transcendental
zero
Innity
class sympy.core.numbers.Infinity
Positive innite quantity.
In real analysis the symbol denotes an unbounded limit: x means that x grows
without bound.
Innity is often used not only to dene a limit but as a value in the anely extended
real number system. Points labeled + and can be added to the topological space of
the real numbers, producing the two-point compactication of the real numbers. Adding
algebraic properties to this gives us the extended real numbers.
Innity is a singleton, and can be accessed by S.Infinity, or can be imported as oo.
See Also:
NegativeInfinity (page 135), NaN (page 134)
References
NegativeInnity
class sympy.core.numbers.NegativeInfinity
Negative innite quantity.
NegativeInnity is a singleton, and can be accessed by S.NegativeInfinity.
135
See Also:
Infinity (page 135)
ComplexInnity
class sympy.core.numbers.ComplexInfinity
Complex innity.
In complex analysis the symbol ,
called complex innity, represents a quantity with
innite magnitude, but undetermined complex phase.
ComplexInnity is a singleton, and can be accessed by S.ComplexInfinity, or can be
imported as zoo.
See Also:
Infinity (page 135)
Examples
>>>
>>>
zoo
>>>
0
>>>
nan
>>>
zoo
Exp1
class sympy.core.numbers.Exp1
The e constant.
The transcendental number e = 2.718281828 . . . is the base of the natural logarithm and
of the exponential function, e = exp(1). Sometimes called Eulers number or Napiers
constant.
Exp1 is a singleton, and can be accessed by S.Exp1, or can be imported as E.
References
136
ImaginaryUnit
class sympy.core.numbers.ImaginaryUnit
Pi
class sympy.core.numbers.Pi
The constant.
The transcendental number = 3.141592654 . . . represents the ratio of a circles circumference to its diameter, the area of the unit circle, the half-period of trigonometric functions,
and many other things in mathematics.
Pi is a singleton, and can be accessed by S.Pi, or can be imported as pi.
References
137
EulerGamma
class sympy.core.numbers.EulerGamma
The Euler-Mascheroni constant.
= 0.5772157 . . . (also called Eulers constant) is a mathematical constant recurring in
analysis and number theory. It is dened as the limiting dierence between the harmonic
series and the natural logarithm:
( n
)
1
= lim
ln n
n
k
k=1
Attributes
is irrational
Catalan
class sympy.core.numbers.Catalan
Catalans constant.
K = 0.91596559 . . . is given by the innite series
K=
k=0
(1)k
(2k + 1)2
138
Examples
>>> from sympy import S
>>> S.Catalan.is_irrational
>>> S.Catalan > 0
True
>>> S.Catalan > 1
False
Attributes
is irrational
GoldenRatio
class sympy.core.numbers.GoldenRatio
The golden ratio, .
= 1+2 5 is algebraic number. Two quantities are in the golden ratio if their ratio is the
same as the ratio of their sum to the larger of the two quantities, i.e. their maximum.
GoldenRatio is a singleton, and can be accessed by S.GoldenRatio.
References
5.1.11 power
Pow
class sympy.core.power.Pow
Denes the expression x**y as x raised to a power y
Singleton denitions involving (0, 1, -1, oo, -oo):
139
expr
z**0
z**1
(-oo)**(1)
(-1)**-1
S.Zero**1
value reason
1
Although arguments over 0**0 exist, see [2].
z
0
1**-1
oo**-1
0**oo
0**-oo
1
0
0
oo
1**oo
1**-oo
(-1)**oo
(-1)**(oo)
oo**oo
oo**-oo
(-oo)**oo
(-oo)**-oo
nan
-1
oo
nan
oo
0
nan
Because symbolic computations are more exible that oating point calculations and we
prefer to never return an incorrect answer, we choose not to conform to all IEEE 754
conventions. This helps us avoid extra test-case code in the calculation of limits.
See Also:
Infinity, NegativeInfinity, NaN
References
as content primitive(radical=False)
Return the tuple (R, self/R) where R is the positive Rational extracted from self.
140
Examples
>>>
>>>
(2,
>>>
(1,
141
5.1.12 mul
Mul
class sympy.core.mul.Mul
as coeff Mul(rational=False)
Eciently extract the coecient of a product.
as content primitive(radical=False)
Return the tuple (R, self/R) where R is the positive Rational extracted from self.
Examples
>>> from sympy import sqrt
>>> (-3*sqrt(2)*(2 - 2*sqrt(2))).as_content_primitive()
(6, -sqrt(2)*(-sqrt(2) + 1))
classmethod flatten(seq)
Return commutative, noncommutative and order arguments by combining related
terms.
142
Notes
one
would
like:
{c.f.
Powers with compound bases may not nd a single base to combine with
unless all arguments are processed at once. Post-processing may be necessary in such cases. {c.f. https://github.com/sympy/sympy/issues/5728}
>>> a = sqrt(x*sqrt(y))
>>> a**3
(x*sqrt(y))**(3/2)
>>> Mul(a,a,a)
(x*sqrt(y))**(3/2)
>>> a*a*a
x*sqrt(y)*sqrt(x*sqrt(y))
>>> _.subs(a.base, z).subs(z, a.base)
(x*sqrt(y))**(3/2)
If more than two terms are being multiplied then all the previous terms will
be re-processed for each new argument. So if each of a, b and c were Mul
(page 142) expression, then a*b*c (or building up the product with *=) will
process all the arguments of a and b twice: once when a*b is computed and
again when c is multiplied.
Using Mul(a, b, c) will process all arguments once.
The results of Mul are cached according to arguments, so atten will only be
called once for Mul(a, b, c). If you can structure a calculation so the arguments
are most likely to be repeats then this can save time in computing the answer. For
example, say you had a Mul, M, that you wished to divide by d[i] and multiply
by n[i] and you suspect there are many repeats in n. It would be better to
compute M*n[i]/d[i] rather than M/d[i]*n[i] since every time n[i] is a repeat,
the product, M*n[i] will be returned without attening the cached value will
be returned. If you divide by the d[i] rst (and those are more unique than the
n[i]) then that will create a new Mul, M/d[i] the args of which will be traversed
again when it is multiplied by n[i].
{c.f. https://github.com/sympy/sympy/issues/5706}
This consideration is moot if the cache is turned o.
143
Nb
The validity of the above notes depends on the implementation details of Mul and
atten which may change at any time. Therefore, you should only consider them
when your code is highly performance sensitive.
Removal of 1 from the sequence is already handled by AssocOp. new .
prod
sympy.core.mul.prod(a, start=1)
Return product of elements of a. Start with int 1 so if only ints are included then an int
result is returned.
Examples
>>> from sympy import prod, S
>>> prod(range(3))
0
>>> type(_) is int
True
>>> prod([S(2), 3])
6
>>> _.is_Integer
True
You can start the product at something other than 1: >>> prod([1, 2], 3) 6
5.1.13 add
Add
class sympy.core.add.Add
as coeff Add()
Eciently extract the coecient of a summation.
as coeff add(*args, **kwargs)
Returns a tuple (coe, args) where self is treated as an Add and coe is the Number
term and args is a tuple of all other terms.
Examples
>>>
>>>
(7,
>>>
(0,
144
as coefficients dict(a)
Return a dictionary mapping terms to their Rational coecient. Since the dictionary is a defaultdict, inquiries about terms which were not present will return a
coecient of 0. If an expression is not an Add it is considered to have a single term.
Examples
>>> from sympy.abc import a, x
>>> (3*x + a*x + 4).as_coefficients_dict()
{1: 4, x: 3, a*x: 1}
>>> _[a]
0
>>> (3*a*x).as_coefficients_dict()
{a*x: 3}
as content primitive(radical=False)
Return the tuple (R, self/R) where R is the positive Rational extracted from self. If
radical is True (default is False) then common radicals will be removed and included
as a factor of the primitive expression.
Examples
>>> from sympy import sqrt
>>> (3 + 3*sqrt(2)).as_content_primitive()
(3, 1 + sqrt(2))
145
if you want to process the arguments of the tail then use self.as coef add() which
gives the head and a tuple containing the arguments of the tail when treated as
an Add.
if you want the coecient when self is treated as a Mul then use
self.as coe mul()[0]
>>> from sympy.abc import x, y
>>> (3*x*y).as_two_terms()
(3, x*y)
classmethod flatten(seq)
Takes the sequence seq of nested Adds and returns a atten list.
Returns: (commutative part, noncommutative part, order symbols)
Applies associativity, all terms are commutable with respect to addition.
NB: the removal of 0 is already handled by AssocOp. new
See Also:
sympy.core.mul.Mul.flatten (page 142)
primitive()
Return (R, self/R) where R is the Rational GCD of self.
R is collected only from the leading coecient of each term.
Examples
>>> from sympy.abc import x, y
>>> (2*x + 4*y).primitive()
(2, x + 2*y)
>>> (2*x/3 + 4*y/9).primitive()
(2/9, 3*x + 2*y)
>>> (2*x/3 + 4.2*y).primitive()
(1/3, 2*x + 12.6*y)
146
5.1.14 mod
Mod
class sympy.core.mod.Mod
Represents a modulo operation on symbolic expressions.
Receives two arguments, dividend p and divisor q.
The convention used is the same as Pythons: the remainder always has the same sign
as the divisor.
Examples
>>> from sympy.abc import x, y
>>> x**2 % y
Mod(x**2, y)
>>> _.subs({x: 5, y: 6})
1
5.1.15 relational
Rel
sympy.core.relational.Rel
alias of Relational
Eq
sympy.core.relational.Eq
alias of Equality (page 148)
Ne
sympy.core.relational.Ne
alias of Unequality (page 155)
147
Lt
sympy.core.relational.Lt
alias of StrictLessThan (page 159)
Le
sympy.core.relational.Le
alias of LessThan (page 152)
Gt
sympy.core.relational.Gt
alias of StrictGreaterThan (page 156)
Ge
sympy.core.relational.Ge
alias of GreaterThan (page 149)
Equality
class sympy.core.relational.Equality
An equal relation between two objects.
Represents that two objects are equal. If they can be easily shown to be denitively equal
(or unequal), this will reduce to True (or False). Otherwise, the relation is maintained
as an unevaluated Equality object. Use the simplify function on this object for more
nontrivial evaluation of the equality relation.
See Also:
sympy.logic.boolalg.Equivalent (page 631) for representing equality between two
boolean expressions
Notes
This class is not the same as the == operator. The == operator tests for exact structural
equality between two expressions; this class compares expressions mathematically.
If either object denes an e valE q method, it can be used in place of the default algorithm.
If lhs.e valE q(rhs) or rhs.e valE q(lhs) returns anything other than None, that return value
will be substituted for the Equality. If None is returned by e valE q, an Equality object will
be created as usual.
Examples
148
GreaterThan
class sympy.core.relational.GreaterThan
Class representations of inequalities.
The *Than classes represent inequal relationships, where the left-hand side is generally
bigger or smaller than the right-hand side. For example, the GreaterThan class represents an inequal relationship where the left-hand side is at least as big as the right side,
if not bigger. In mathematical notation:
lhs >= rhs
In total, there are four *Than classes, to represent the four inequalities:
Class Name
GreaterThan
LessThan
StrictGreaterThan
StrictLessThan
Symbol
(>=)
(<=)
(>)
(<)
Math equivalent
lhs >= rhs
lhs <= rhs
lhs > rhs
lhs < rhs
In addition to the normal .lhs and .rhs of Relations, *Than inequality objects also have
the .lts and .gts properties, which represent the less than side and greater than side
of the operator. Use of .lts and .gts in an algorithm rather than .lhs and .rhs as an
assumption of inequality direction will make more explicit the intent of a certain section
of code, and will make it similarly more robust to client code changes:
>>>
>>>
>>>
>>>
>>>
from
from
from
from
from
>>> e = GreaterThan(x, 1)
>>> e
x >= 1
>>> %s >= %s is the same as %s <= %s % (e.gts, e.lts, e.lts, e.gts)
x >= 1 is the same as 1 <= x
Notes
149
two objects comparable. For example, to evaluate the statement (1 < x), Python will rst
recognize the number 1 as a native number, and then that x is not a native number. At
this point, because a native Python number does not know how to compare itself with
a SymPy object Python will try the reective operation, (x > 1). Unfortunately, there is
no way available to SymPy to recognize this has happened, so the statement (1 < x) will
turn silently into (x > 1).
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
x >
x <
x <
x >
e1 = x > 1
e2 = x >= 1
e3 = x < 1
e4 = x <= 1
e5 = 1 > x
e6 = 1 >= x
e7 = 1 < x
e8 = 1 <= x
print(%s
1
x >= 1
1
x <= 1
1
x <= 1
1
x >= 1
If the order of the statement is important (for visual output to the console, perhaps),
one can work around this annoyance in a couple ways: (1) sympify the literal before
comparison, (2) use one of the wrappers, or (3) use the less succinct methods described
above:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1 >
1 <
1 >
1 <
e1 = S(1) > x
e2 = S(1) >= x
e3 = S(1) < x
e4 = S(1) <= x
e5 = Gt(1, x)
e6 = Ge(1, x)
e7 = Lt(1, x)
e8 = Le(1, x)
print(%s
%s\n*4 % (e1, e2, e3, e4, e5, e6, e7, e8))
x
1 >= x
x
1 <= x
x
1 >= x
x
1 <= x
The other gotcha is with chained inequalities. Occasionally, one may be tempted to write
statements like:
>>> e = x < y < z
Traceback (most recent call
...
TypeError: symbolic boolean
Traceback (most recent call
...
TypeError: symbolic boolean
last):
expression has no truth value.
last):
expression has no truth value.
Due to an implementation detail or decision of Python [R48] (page 1899), there is no way
for SymPy to reliably create that as a chained inequality. To create a chained inequality,
the only method currently available is to make use of And:
>>> e = And(x < y, y < z)
>>> type( e )
And
>>> e
150
Note that this is dierent than chaining an equality directly via use of parenthesis (this
is currently an open bug in SymPy [R49] (page 1900)):
>>> e = (x < y) < z
>>> type( e )
<class sympy.core.relational.StrictLessThan>
>>> e
(x < y) < z
Any code that explicitly relies on this latter functionality will not be robust as this behaviour is completely wrong and will be corrected at some point. For the time being
(circa Jan 2012), use And to create chained inequalities.
Examples
One generally does not instantiate these classes directly, but uses various convenience
methods:
>>> e1 = Ge( x, 2 )
>>> print(e1)
x >= 2
# Ge is a convenience wrapper
Another option is to use the Python inequality operators (>=, >, <=, <) directly. Their
main advantage over the Ge, Gt, Le, and Lt counterparts, is that one can write a more
mathematical looking statement rather than littering the math with oddball function
calls. However there are certain (minor) caveats of which to be aware (search for
gotcha, below).
>>> e2 = x >= 2
>>> print(e2)
x >= 2
>>> print(e1: %s,
e2: %s % (e1, e2))
e1: x >= 2,
e2: x >= 2
>>> e1 == e2
True
However, it is also perfectly valid to instantiate a *Than class less succinctly and less
conveniently:
>>> rels = Rel(x, 1, >=), Relational(x, 1, >=), GreaterThan(x, 1)
>>> print(%s\n%s\n%s % rels)
x >= 1
x >= 1
x >= 1
>>> rels = Rel(x, 1, >), Relational(x, 1, >), StrictGreaterThan(x, 1)
>>> print(%s\n%s\n%s % rels)
x > 1
151
x > 1
x > 1
>>> rels = Rel(x, 1, <=), Relational(x, 1, <=), LessThan(x, 1)
>>> print(%s\n%s\n%s % rels)
x <= 1
x <= 1
x <= 1
>>>
>>>
x <
x <
x <
LessThan
class sympy.core.relational.LessThan
Class representations of inequalities.
The *Than classes represent inequal relationships, where the left-hand side is generally
bigger or smaller than the right-hand side. For example, the GreaterThan class represents an inequal relationship where the left-hand side is at least as big as the right side,
if not bigger. In mathematical notation:
lhs >= rhs
In total, there are four *Than classes, to represent the four inequalities:
Class Name
GreaterThan
LessThan
StrictGreaterThan
StrictLessThan
Symbol
(>=)
(<=)
(>)
(<)
Math equivalent
lhs >= rhs
lhs <= rhs
lhs > rhs
lhs < rhs
In addition to the normal .lhs and .rhs of Relations, *Than inequality objects also have
the .lts and .gts properties, which represent the less than side and greater than side
of the operator. Use of .lts and .gts in an algorithm rather than .lhs and .rhs as an
assumption of inequality direction will make more explicit the intent of a certain section
of code, and will make it similarly more robust to client code changes:
>>>
>>>
>>>
>>>
>>>
from
from
from
from
from
>>> e = GreaterThan(x, 1)
>>> e
x >= 1
152
Notes
e1 = x > 1
e2 = x >= 1
e3 = x < 1
e4 = x <= 1
e5 = 1 > x
e6 = 1 >= x
e7 = 1 < x
e8 = 1 <= x
print(%s
1
x >= 1
1
x <= 1
1
x <= 1
1
x >= 1
If the order of the statement is important (for visual output to the console, perhaps),
one can work around this annoyance in a couple ways: (1) sympify the literal before
comparison, (2) use one of the wrappers, or (3) use the less succinct methods described
above:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1 >
1 <
1 >
1 <
e1 = S(1) > x
e2 = S(1) >= x
e3 = S(1) < x
e4 = S(1) <= x
e5 = Gt(1, x)
e6 = Ge(1, x)
e7 = Lt(1, x)
e8 = Le(1, x)
print(%s
%s\n*4 % (e1, e2, e3, e4, e5, e6, e7, e8))
x
1 >= x
x
1 <= x
x
1 >= x
x
1 <= x
The other gotcha is with chained inequalities. Occasionally, one may be tempted to write
statements like:
>>> e = x < y < z
Traceback (most recent call last):
...
TypeError: symbolic boolean expression has no truth value.
Traceback (most recent call last):
153
...
TypeError: symbolic boolean expression has no truth value.
Due to an implementation detail or decision of Python [R50] (page 1900), there is no way
for SymPy to reliably create that as a chained inequality. To create a chained inequality,
the only method currently available is to make use of And:
>>> e = And(x < y, y < z)
>>> type( e )
And
>>> e
And(x < y, y < z)
Note that this is dierent than chaining an equality directly via use of parenthesis (this
is currently an open bug in SymPy [R51] (page 1900)):
>>> e = (x < y) < z
>>> type( e )
<class sympy.core.relational.StrictLessThan>
>>> e
(x < y) < z
Any code that explicitly relies on this latter functionality will not be robust as this behaviour is completely wrong and will be corrected at some point. For the time being
(circa Jan 2012), use And to create chained inequalities.
Examples
One generally does not instantiate these classes directly, but uses various convenience
methods:
>>> e1 = Ge( x, 2 )
>>> print(e1)
x >= 2
# Ge is a convenience wrapper
Another option is to use the Python inequality operators (>=, >, <=, <) directly. Their
main advantage over the Ge, Gt, Le, and Lt counterparts, is that one can write a more
mathematical looking statement rather than littering the math with oddball function
calls. However there are certain (minor) caveats of which to be aware (search for
gotcha, below).
>>> e2 = x >= 2
>>> print(e2)
x >= 2
>>> print(e1: %s,
e2: %s % (e1, e2))
e1: x >= 2,
e2: x >= 2
>>> e1 == e2
True
However, it is also perfectly valid to instantiate a *Than class less succinctly and less
conveniently:
154
Unequality
class sympy.core.relational.Unequality
An unequal relation between two objects.
Represents that two objects are not equal. If they can be shown to be denitively equal,
this will reduce to False; if denitively unequal, this will reduce to True. Otherwise, the
relation is maintained as an Unequality object.
See Also:
Equality (page 148)
Notes
This class is not the same as the != operator. The != operator tests for exact structural
equality between two expressions; this class compares expressions mathematically.
This class is eectively the inverse of Equality. As such, it uses the same algorithms,
including any available e valE q methods.
Examples
>>> from sympy import Ne
>>> from sympy.abc import x, y
>>> Ne(y, x+x**2)
y != x**2 + x
155
StrictGreaterThan
class sympy.core.relational.StrictGreaterThan
Class representations of inequalities.
The *Than classes represent inequal relationships, where the left-hand side is generally
bigger or smaller than the right-hand side. For example, the GreaterThan class represents an inequal relationship where the left-hand side is at least as big as the right side,
if not bigger. In mathematical notation:
lhs >= rhs
In total, there are four *Than classes, to represent the four inequalities:
Class Name
GreaterThan
LessThan
StrictGreaterThan
StrictLessThan
Symbol
(>=)
(<=)
(>)
(<)
Math equivalent
lhs >= rhs
lhs <= rhs
lhs > rhs
lhs < rhs
In addition to the normal .lhs and .rhs of Relations, *Than inequality objects also have
the .lts and .gts properties, which represent the less than side and greater than side
of the operator. Use of .lts and .gts in an algorithm rather than .lhs and .rhs as an
assumption of inequality direction will make more explicit the intent of a certain section
of code, and will make it similarly more robust to client code changes:
>>>
>>>
>>>
>>>
>>>
from
from
from
from
from
>>> e = GreaterThan(x, 1)
>>> e
x >= 1
>>> %s >= %s is the same as %s <= %s % (e.gts, e.lts, e.lts, e.gts)
x >= 1 is the same as 1 <= x
Notes
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
x >
x <
x <
x >
e1 = x > 1
e2 = x >= 1
e3 = x < 1
e4 = x <= 1
e5 = 1 > x
e6 = 1 >= x
e7 = 1 < x
e8 = 1 <= x
print(%s
1
x >= 1
1
x <= 1
1
x <= 1
1
x >= 1
If the order of the statement is important (for visual output to the console, perhaps),
one can work around this annoyance in a couple ways: (1) sympify the literal before
comparison, (2) use one of the wrappers, or (3) use the less succinct methods described
above:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1 >
1 <
1 >
1 <
e1 = S(1) > x
e2 = S(1) >= x
e3 = S(1) < x
e4 = S(1) <= x
e5 = Gt(1, x)
e6 = Ge(1, x)
e7 = Lt(1, x)
e8 = Le(1, x)
print(%s
%s\n*4 % (e1, e2, e3, e4, e5, e6, e7, e8))
x
1 >= x
x
1 <= x
x
1 >= x
x
1 <= x
The other gotcha is with chained inequalities. Occasionally, one may be tempted to write
statements like:
>>> e = x < y < z
Traceback (most recent call
...
TypeError: symbolic boolean
Traceback (most recent call
...
TypeError: symbolic boolean
last):
expression has no truth value.
last):
expression has no truth value.
Due to an implementation detail or decision of Python [R52] (page 1901), there is no way
for SymPy to reliably create that as a chained inequality. To create a chained inequality,
the only method currently available is to make use of And:
>>> e = And(x < y, y < z)
>>> type( e )
And
>>> e
And(x < y, y < z)
Note that this is dierent than chaining an equality directly via use of parenthesis (this
is currently an open bug in SymPy [R53] (page 1901)):
>>> e = (x < y) < z
>>> type( e )
157
<class sympy.core.relational.StrictLessThan>
>>> e
(x < y) < z
Any code that explicitly relies on this latter functionality will not be robust as this behaviour is completely wrong and will be corrected at some point. For the time being
(circa Jan 2012), use And to create chained inequalities.
Examples
One generally does not instantiate these classes directly, but uses various convenience
methods:
>>> e1 = Ge( x, 2 )
>>> print(e1)
x >= 2
# Ge is a convenience wrapper
Another option is to use the Python inequality operators (>=, >, <=, <) directly. Their
main advantage over the Ge, Gt, Le, and Lt counterparts, is that one can write a more
mathematical looking statement rather than littering the math with oddball function
calls. However there are certain (minor) caveats of which to be aware (search for
gotcha, below).
>>> e2 = x >= 2
>>> print(e2)
x >= 2
>>> print(e1: %s,
e2: %s % (e1, e2))
e1: x >= 2,
e2: x >= 2
>>> e1 == e2
True
However, it is also perfectly valid to instantiate a *Than class less succinctly and less
conveniently:
>>> rels = Rel(x, 1, >=), Relational(x, 1, >=), GreaterThan(x, 1)
>>> print(%s\n%s\n%s % rels)
x >= 1
x >= 1
x >= 1
>>>
>>>
x >
x >
x >
158
x <= 1
x <= 1
>>>
>>>
x <
x <
x <
StrictLessThan
class sympy.core.relational.StrictLessThan
Class representations of inequalities.
The *Than classes represent inequal relationships, where the left-hand side is generally
bigger or smaller than the right-hand side. For example, the GreaterThan class represents an inequal relationship where the left-hand side is at least as big as the right side,
if not bigger. In mathematical notation:
lhs >= rhs
In total, there are four *Than classes, to represent the four inequalities:
Class Name
GreaterThan
LessThan
StrictGreaterThan
StrictLessThan
Symbol
(>=)
(<=)
(>)
(<)
Math equivalent
lhs >= rhs
lhs <= rhs
lhs > rhs
lhs < rhs
In addition to the normal .lhs and .rhs of Relations, *Than inequality objects also have
the .lts and .gts properties, which represent the less than side and greater than side
of the operator. Use of .lts and .gts in an algorithm rather than .lhs and .rhs as an
assumption of inequality direction will make more explicit the intent of a certain section
of code, and will make it similarly more robust to client code changes:
>>>
>>>
>>>
>>>
>>>
from
from
from
from
from
>>> e = GreaterThan(x, 1)
>>> e
x >= 1
>>> %s >= %s is the same as %s <= %s % (e.gts, e.lts, e.lts, e.gts)
x >= 1 is the same as 1 <= x
159
Notes
e1 = x > 1
e2 = x >= 1
e3 = x < 1
e4 = x <= 1
e5 = 1 > x
e6 = 1 >= x
e7 = 1 < x
e8 = 1 <= x
print(%s
1
x >= 1
1
x <= 1
1
x <= 1
1
x >= 1
If the order of the statement is important (for visual output to the console, perhaps),
one can work around this annoyance in a couple ways: (1) sympify the literal before
comparison, (2) use one of the wrappers, or (3) use the less succinct methods described
above:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1 >
1 <
1 >
1 <
e1 = S(1) > x
e2 = S(1) >= x
e3 = S(1) < x
e4 = S(1) <= x
e5 = Gt(1, x)
e6 = Ge(1, x)
e7 = Lt(1, x)
e8 = Le(1, x)
print(%s
%s\n*4 % (e1, e2, e3, e4, e5, e6, e7, e8))
x
1 >= x
x
1 <= x
x
1 >= x
x
1 <= x
The other gotcha is with chained inequalities. Occasionally, one may be tempted to write
statements like:
>>> e = x < y < z
Traceback (most recent call
...
TypeError: symbolic boolean
Traceback (most recent call
...
TypeError: symbolic boolean
last):
expression has no truth value.
last):
expression has no truth value.
Due to an implementation detail or decision of Python [R54] (page 1901), there is no way
for SymPy to reliably create that as a chained inequality. To create a chained inequality,
160
Note that this is dierent than chaining an equality directly via use of parenthesis (this
is currently an open bug in SymPy [R55] (page 1902)):
>>> e = (x < y) < z
>>> type( e )
<class sympy.core.relational.StrictLessThan>
>>> e
(x < y) < z
Any code that explicitly relies on this latter functionality will not be robust as this behaviour is completely wrong and will be corrected at some point. For the time being
(circa Jan 2012), use And to create chained inequalities.
Examples
One generally does not instantiate these classes directly, but uses various convenience
methods:
>>> e1 = Ge( x, 2 )
>>> print(e1)
x >= 2
# Ge is a convenience wrapper
Another option is to use the Python inequality operators (>=, >, <=, <) directly. Their
main advantage over the Ge, Gt, Le, and Lt counterparts, is that one can write a more
mathematical looking statement rather than littering the math with oddball function
calls. However there are certain (minor) caveats of which to be aware (search for
gotcha, below).
>>> e2 = x >= 2
>>> print(e2)
x >= 2
>>> print(e1: %s,
e2: %s % (e1, e2))
e1: x >= 2,
e2: x >= 2
>>> e1 == e2
True
However, it is also perfectly valid to instantiate a *Than class less succinctly and less
conveniently:
>>> rels = Rel(x, 1, >=), Relational(x, 1, >=), GreaterThan(x, 1)
>>> print(%s\n%s\n%s % rels)
x >= 1
161
x >= 1
x >= 1
>>>
>>>
x >
x >
x >
5.1.16 multidimensional
vectorize
class sympy.core.multidimensional.vectorize(*mdargs)
Generalizes a function taking scalars to accept multidimensional arguments.
For example
>>>
>>>
>>>
>>>
>>> @vectorize(0)
... def vsin(x):
...
return sin(x)
>>> vsin([1, x, y])
[sin(1), sin(x), sin(y)]
>>> @vectorize(0, 1)
... def vdiff(f, y):
...
return diff(f, y)
162
5.1.17 function
Lambda
class sympy.core.function.Lambda
Lambda(x, expr) represents a lambda function similar to Pythons lambda x: expr. A
function of several variables is written as Lambda((x, y, ...), expr).
A simple example:
>>>
>>>
>>>
>>>
16
p = x, y, z
f = Lambda(p, x + y*z)
f(*p)
y*z
expr
The return value of the function
is identity
Return True if this Lambda is an identity function.
variables
The variables used in the internal representation of the function
WildFunction
class sympy.core.function.WildFunction(name, **assumptions)
A WildFunction function matches any function (with its arguments).
Examples
>>> from sympy import WildFunction, Function, cos
>>> from sympy.abc import x, y
>>> F = WildFunction(F)
>>> f = Function(f)
>>> F.nargs
Naturals0()
>>> x.match(F)
>>> F.match(F)
{F_: F_}
>>> f(x).match(F)
{F_: f(x)}
163
>>> cos(x).match(F)
{F_: cos(x)}
>>> f(x, y).match(F)
{F_: f(x, y)}
To match functions with a given number of arguments, set nargs to the desired value at
instantiation:
>>> F = WildFunction(F, nargs=2)
>>> F.nargs
{2}
>>> f(x).match(F)
>>> f(x, y).match(F)
{F_: f(x, y)}
To match functions with a range of arguments, set nargs to a tuple containing the desired
number of arguments, e.g. if nargs = (1, 2) then functions with 1 or 2 arguments will
be matched.
>>> F = WildFunction(F, nargs=(1, 2))
>>> F.nargs
{1, 2}
>>> f(x).match(F)
{F_: f(x)}
>>> f(x, y).match(F)
{F_: f(x, y)}
>>> f(x, y, 1).match(F)
Derivative
class sympy.core.function.Derivative
Carries out dierentiation of the given expression with respect to symbols.
expr must dene . eval derivative(symbol) method that returns the dierentiation result.
This function only needs to consider the non-trivial case where expr contains symbol and
it should call the di() method internally (not eval derivative); Derivative should be the
only one to call eval derivative.
Simplication of high-order derivatives:
Because there can be a signicant amount of simplication that can be done when multiple dierentiations are performed, results will be automatically simplied in a fairly
conservative fashion unless the keyword simplify is set to False.
>>>
>>>
>>>
>>>
136
>>>
30
Ordering of variables:
If evaluate is set to True and the expression can not be evaluated, the list of dierentiation symbols will be sorted, that is, the expression is assumed to have continuous
derivatives up to the order asked. This sorting assumes that derivatives wrt Symbols
164
commute, derivatives wrt non-Symbols commute, but Symbol and non-Symbol derivatives dont commute with each other.
Derivative wrt non-Symbols:
This class also allows derivatives wrt non-Symbols that have di wrt set to True, such
as Function and Derivative. When a derivative wrt a non- Symbol is attempted, the nonSymbol is temporarily converted to a Symbol while the dierentiation is performed.
Note that this may seem strange, that Derivative allows things like f(g(x)).di(g(x)), or
even f(cos(x)).di(cos(x)). The motivation for allowing this syntax is to make it easier
to work with variational calculus (i.e., the Euler-Lagrange method). The best way to
understand this is that the action of derivative with respect to a non-Symbol is dened
by the above description: the object is substituted for a Symbol and the derivative is
taken with respect to that. This action is only allowed for objects for which this can be
done unambiguously, for example Function and Derivative objects. Note that this leads
to what may appear to be mathematically inconsistent results. For example:
>>>
>>>
>>>
2
>>>
0
This appears wrong because in fact 2*cos(x) and 2*sqrt(1 - sin(x)**2) are identically
equal. However this is the wrong way to think of this. Think of it instead as if we have
something like this:
>>> from sympy.abc import c, s
>>> def F(u):
...
return 2*u
...
>>> def G(u):
...
return 2*sqrt(1 - u**2)
...
>>> F(cos(x))
2*cos(x)
>>> G(sin(x))
2*sqrt(-sin(x)**2 + 1)
>>> F(c).diff(c)
2
>>> F(c).diff(c)
2
>>> G(s).diff(c)
0
>>> G(sin(x)).diff(cos(x))
0
Here, the Symbols c and s act just like the functions cos(x) and sin(x), respectively.
Think of 2*cos(x) as f(c).subs(c, cos(x)) (or f(c) at c = cos(x)) and 2*sqrt(1 - sin(x)**2)
as g(s).subs(s, sin(x)) (or g(s) at s = sin(x)), where f(u) == 2*u and g(u) == 2*sqrt(1
- u**2). Here, we dene the function rst and evaluate it at the function, but we can
actually unambiguously do this in reverse in SymPy, because expr.subs(Function, Symbol) is well-dened: just structurally replace the function everywhere it appears in the
expression.
This is actually the same notational convenience used in the Euler-Lagrange method
when one says F(t, f(t), f(t)).di(f(t)). What is actually meant is that the expression
165
in question is represented by some F(t, u, v) at u = f(t) and v = f(t), and F(t, f(t),
f(t)).di(f(t)) simply means F(t, u, v).di(u) at u = f(t).
We do not allow derivatives to be taken with respect to expressions where this is not
so well dened. For example, we do not allow expr.di(x*y) because there are multiple
ways of structurally dening where x*y appears in an expression, some of which may
surprise the reader (for example, a very strict denition would have that (x*y*z).di(x*y)
== 0).
>>> from sympy.abc import x, y, z
>>> (x*y*z).diff(x*y)
Traceback (most recent call last):
...
ValueError: Cant differentiate wrt the variable: x*y, 1
Traceback (most recent call last):
...
ValueError: Cant differentiate wrt the variable: x*y, 1
Note that this denition also ts in nicely with the denition of the chain rule. Note how
the chain rule in SymPy is dened using unevaluated Subs objects:
>>> from sympy import symbols, Function
>>> f, g = symbols(f g, cls=Function)
>>> f(2*g(x)).diff(x)
2*Derivative(g(x), x)*Subs(Derivative(f(_xi_1), _xi_1),
(_xi_1,), (2*g(x),))
>>> f(g(x)).diff(x)
Derivative(g(x), x)*Subs(Derivative(f(_xi_1), _xi_1),
(_xi_1,), (g(x),))
Finally, note that, to be consistent with variational calculus, and to ensure that the denition of substituting a Function for a Symbol in an expression is well-dened, derivatives
of functions are assumed to not be related to the function. In other words, we have:
>>> from sympy import diff
>>> diff(f(x), x).diff(f(x))
0
Note, any class can allow derivatives to be taken with respect to itself. See the docstring
of Expr. di wrt.
Examples
166
doit numerically(a, b)
Evaluate the derivative at z numerically.
When we can represent derivatives at a point, this should be folded into the normal
evalf. For now, we need a special method.
di
sympy.core.function.diff(f, *symbols, **kwargs)
Dierentiate f with respect to symbols.
This is just a wrapper to unify .di() and the Derivative class; its interface is similar to that
of integrate(). You can use the same shortcuts for multiple variables as with Derivative.
For example, di(f(x), x, x, x) and di(f(x), x, 3) both return the third derivative of f(x).
You can pass evaluate=False to get an unevaluated Derivative class. Note that if there
are 0 symbols (such as di(f(x), x, 0), then the result will be the function (the zeroth
derivative), even if evaluate=False.
See Also:
Derivative (page 164)
sympy.geometry.util.idiff computes the derivative implicitly
References
http://reference.wolfram.com/legacy/v5 2/Built-inFunctions/AlgebraicComputation/Calculus/D.html
Examples
>>> from sympy import sin, cos, Function, diff
>>> from sympy.abc import x, y
>>> f = Function(f)
>>> diff(sin(x), x)
cos(x)
>>> diff(f(x), x, x, x)
Derivative(f(x), x, x, x)
167
>>> diff(f(x), x, 3)
Derivative(f(x), x, x, x)
>>> diff(sin(x)*cos(y), x, 2, y, 2)
sin(x)*cos(y)
>>> type(diff(sin(x), x))
cos
>>> type(diff(sin(x), x, evaluate=False))
<class sympy.core.function.Derivative>
>>> type(diff(sin(x), x, 0))
sin
>>> type(diff(sin(x), x, 0, evaluate=False))
sin
>>> diff(sin(x))
cos(x)
>>> diff(sin(x*y))
Traceback (most recent call last):
...
ValueError: specify differentiation variables to differentiate sin(x*y)
Traceback (most recent call last):
...
ValueError: specify differentiation variables to differentiate sin(x*y)
Note that diff(sin(x)) syntax is meant only for convenience in interactive sessions and
should be avoided in library code.
FunctionClass
class sympy.core.function.FunctionClass(*args, **kwargs)
Base class for function classes. FunctionClass is a subclass of type.
Use Function(<function name> [ , signature ]) to create undened function classes.
nargs
Return a set of the allowed number of arguments for the function.
Examples
>>> from sympy.core.function import Function
>>> from sympy.abc import x, y
>>> f = Function(f)
If the function can take any number of arguments, the set of whole numbers is returned:
>>> Function(f).nargs
Naturals0()
If the function was initialized to accept one or more arguments, a corresponding set
will be returned:
>>> Function(f, nargs=1).nargs
{1}
>>> Function(f, nargs=(2, 1)).nargs
{1, 2}
168
The undened function, after application, also has the nargs attribute; the actual
number of arguments is always available by checking the args attribute:
>>> f = Function(f)
>>> f(1).nargs
Naturals0()
>>> len(f(1).args)
1
Function
class sympy.core.function.Function
Base class for applied mathematical functions.
It also serves as a constructor for undened function classes.
Examples
First example shows how to use Function as a constructor for undened function classes:
>>> from sympy import Function, Symbol
>>> x = Symbol(x)
>>> f = Function(f)
>>> g = Function(g)(x)
>>> f
f
>>> f(x)
f(x)
>>> g
g(x)
>>> f(x).diff(x)
Derivative(f(x), x)
>>> g.diff(x)
Derivative(g(x), x)
In the following example Function is used as a base class for my func that represents a
mathematical function my func. Suppose that it is well known, that my func(0) is 1 and
my func at innity goes to 0, so we want those two simplications to occur automatically.
Suppose also that my func(x) is real exactly when x is real. Here is an implementation
that honours those requirements:
>>> from sympy import Function, S, oo, I, sin
>>> class my_func(Function):
...
...
@classmethod
...
def eval(cls, x):
...
if x.is_Number:
...
if x is S.Zero:
...
return S.One
...
elif x is S.Infinity:
...
return S.Zero
...
...
def _eval_is_real(self):
...
return self.args[0].is_real
...
>>> x = S(x)
169
In order for my func to become useful, several other methods would need to be implemented. See source code of some of the already implemented functions for more complete examples.
Also, if the function can take more than one argument, then nargs must be dened, e.g.
if my func can take one or two arguments then,
>>> class my_func(Function):
...
nargs = (1, 2)
...
>>>
as base exp()
Returns the method as the 2-tuple (base, exponent).
fdiff(argindex=1)
Returns the rst derivative of the function.
is commutative
Returns whether the functon is commutative.
Note: Not all functions are the same
SymPy denes many functions (like cos and factorial). It also allows the user to create
generic functions which act as argument holders. Such functions are created just like symbols:
>>> from sympy import Function, cos
>>> from sympy.abc import x
>>> f = Function(f)
>>> f(2) + f(x)
f(2) + f(x)
If you want to see which functions appear in an expression you can use the atoms method:
>>> e = (f(x) + cos(x) + 2)
>>> e.atoms(Function)
set([f(x), cos(x)])
If you just want the function you dened, not SymPy functions, the thing to search for is
AppliedUndef:
>>> from sympy.core.function import AppliedUndef
>>> e.atoms(AppliedUndef)
set([f(x)])
170
Subs
class sympy.core.function.Subs
Represents unevaluated substitutions of an expression.
Subs(expr, x, x0) receives 3 arguments: an expression, a variable or list of distinct
variables and a point or list of evaluation points corresponding to those variables.
Subs objects are generally useful to represent unevaluated derivatives calculated at a
point.
The variables may be expressions, but they are subjected to the limitations of subs(), so
it is usually a good practice to use only symbols for variables, since in that case there
can be no ambiguity.
Theres no automatic expansion - use the method .doit() to eect all possible substitutions
of the object and also of objects inside the expression.
When evaluating derivatives at a point that is not a symbol, a Subs object is returned.
One is also able to calculate derivatives of Subs objects - in this case the expression is
always expanded (for the unevaluated form, use Derivative()).
A simple example:
>>> from sympy import Subs, Function, sin
>>> from sympy.abc import x, y, z
>>> f = Function(f)
>>> e = Subs(f(x).diff(x), x, y)
>>> e.subs(y, 0)
Subs(Derivative(f(x), x), (x,), (0,))
>>> e.subs(f, sin).doit()
cos(y)
expr
The expression on which the substitution operates
point
The values for which the variables are to be substituted
variables
The variables to be evaluated
expand
sympy.core.function.expand(e, deep=True, modulus=None, power base=True,
mul=True,
log=True,
multinopower exp=True,
mial=True, basic=True, **hints)
Expand an expression using methods given as hints.
Hints evaluated unless explicitly set to False are: basic, log, multinomial, mul,
power base, and power exp The following hints are supported but not applied unless
set to True: complex, func, and trig. In addition, the following meta-hints are supported by some or all of the other hints: frac, numer, denom, modulus, and force. deep
171
is supported by all hints. Additionally, subclasses of Expr may dene their own hints or
meta-hints.
The basic hint is used for any special rewriting of an object that should be done automatically (along with the other hints like mul) when expand is called. This is a catch-all hint
to handle any sort of expansion that may not be described by the existing hint names.
To use this hint an object should override the eval expand basic method. Objects may
also dene their own expand methods, which are not run by default. See the API section
below.
If deep is set to True (the default), things like arguments of functions are recursively
expanded. Use deep=False to only expand on the top level.
If the force hint is used, assumptions about variables will be ignored in making the
expansion.
See Also:
expand log (page 178), expand mul (page 178), expand multinomial (page 179), expand complex (page 179), expand trig (page 179), expand power base (page 180), expand power exp (page 180), expand func (page 178), hyperexpand
Notes
Hints are applied in an arbitrary, but consistent order (in the current implementation, they are applied in alphabetical order, except multinomial comes before mul,
but this may change). Because of this, some hints may prevent expansion by other
hints if they are applied rst. For example, mul may distribute multiplications and
prevent log and power base from expanding them. Also, if mul is applied before
multinomial, the expression might not be fully distributed. The solution is to use the various expand hint helper functions or to use hint=False
to this function to nely control which hints are applied. Here are some examples:
>>> from sympy import expand, expand_mul, expand_power_base
>>> x, y, z = symbols(x,y,z, positive=True)
>>> expand(log(x*(y + z)))
log(x) + log(y + z)
Here, we see that log was applied before mul. To get the mul expanded form, either
of the following will work:
172
To get the power base expanded form, either of the following will work:
>>> expand((x*(y + z))**x, mul=False)
x**x*(y + z)**x
>>> expand_power_base((x*(y + z))**x)
x**x*(y + z)**x
>>> expand((x + y)*y/x)
y + y**2/x
The modulus meta-hint can be used to reduce the coecients of an expression postexpansion:
>>> expand((3*x + 1)**2)
9*x**2 + 6*x + 1
>>> expand((3*x + 1)**2, modulus=5)
4*x**2 + x + 1
Either expand() the function or .expand() the method can be used. Both are equivalent:
>>> expand((x + 1)**2)
x**2 + 2*x + 1
>>> ((x + 1)**2).expand()
x**2 + 2*x + 1
Hints
173
Multinomial
Power exp
Power base
Note that in some cases where this expansion always holds, SymPy performs it automatically:
>>> (x*y)**2
x**2*y**2
Log
Pull out power of an argument as a coecient and split logs products into sums of logs.
Note that these only work if the arguments of the log function have the proper assumptionsthe arguments must be positive and the exponents must be realor else the force
hint must be True:
>>> from sympy import log, symbols
>>> log(x**2*y).expand(log=True)
log(x**2*y)
>>> log(x**2*y).expand(log=True, force=True)
2*log(x) + log(y)
>>> x, y = symbols(x,y, positive=True)
>>> log(x**2*y).expand(log=True)
2*log(x) + log(y)
174
Basic
This hint is intended primarily as a way for custom subclasses to enable expansion by
default.
These hints are not run by default:
Complex
Note that this is just a wrapper around as real imag(). Most objects that wish to redene eval expand complex() should consider redening as real imag() instead.
Func
Trig
Do trigonometric expansions.
>>> cos(x + y).expand(trig=True)
-sin(x)*sin(y) + cos(x)*cos(y)
>>> sin(2*x).expand(trig=True)
2*sin(x)*cos(x)
Note that the forms of sin(n*x) and cos(n*x) in terms of sin(x) and cos(x) are not
unique, due to the identity sin2 (x) + cos2 (x) = 1. The current implementation uses the
form obtained from Chebyshev polynomials, but this may change. See this MathWorld
article for more information.
Api
Objects can dene their own expand hints by dening eval expand hint(). The function should take the form:
def _eval_expand_hint(self, **hints):
# Only apply the method to the top-level expression
...
175
See also the example below. Objects should dene eval expand hint() methods only
if hint applies to that specic object. The generic eval expand hint() method dened
in Expr will handle the no-op case.
Each hint should be responsible for expanding that hint only. Furthermore, the expansion
should be applied to the top-level expression only. expand() takes care of the recursion
that happens when deep=True.
You should only call eval expand hint() methods directly if you are 100% sure that
the object has the method, as otherwise you are liable to get unexpected AttributeErrors.
Note, again, that you do not need to recursively apply
the hint to args of your object:
this is handled automatically by
expand(). eval expand hint() should generally not be used at all outside of an
eval expand hint() method. If you want to apply a specic expansion from within another method, use the public expand() function, method, or expand hint() functions.
In order for expand to work, objects must be rebuildable by their args, i.e.,
obj.func(*obj.args) == obj must hold.
Expand methods are passed **hints so that expand hints may use metahintshints
that control how dierent expand methods are applied. For example, the force=True
hint described above that causes expand(log=True) to ignore assumptions is such a
metahint. The deep meta-hint is handled exclusively by expand() and is not passed to
eval expand hint() methods.
Note that expansion hints should generally be methods that perform some kind of expansion. For hints that simply rewrite an expression, use the .rewrite() API.
Example
>>> from sympy import Expr, sympify
>>> class MyClass(Expr):
...
def __new__(cls, *args):
...
args = sympify(args)
...
return Expr.__new__(cls, *args)
...
...
def _eval_expand_double(self, **hints):
...
...
Doubles the args of MyClass.
...
...
If there more than four args, doubling is not performed,
...
unless force=True is also used (False by default).
...
...
force = hints.pop(force, False)
...
if not force and len(self.args) > 4:
...
return self
...
return self.func(*(self.args + self.args))
...
>>> a = MyClass(1, 2, MyClass(3, 4))
>>> a
MyClass(1, 2, MyClass(3, 4))
>>> a.expand(double=True)
MyClass(1, 2, MyClass(3, 4, 3, 4), 1, 2, MyClass(3, 4, 3, 4))
>>> a.expand(double=True, deep=False)
MyClass(1, 2, MyClass(3, 4), 1, 2, MyClass(3, 4))
176
>>> b = MyClass(1, 2, 3, 4, 5)
>>> b.expand(double=True)
MyClass(1, 2, 3, 4, 5)
>>> b.expand(double=True, force=True)
MyClass(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
PoleError
class sympy.core.function.PoleError
count ops
sympy.core.function.count ops(expr, visual=False)
Return a representation (integer or expression) of the operations in expr.
If visual is False (default) then the sum of the coecients of the visual expression will
be returned.
If visual is True then the number of each type of operation is shown with the core class
types (or their virtual equivalent) multiplied by the number of times they occur.
If expr is an iterable, the sum of the op counts of the items will be returned.
Examples
>>> from sympy.abc import a, b, x, y
>>> from sympy import sin, count_ops
Although there isnt a SUB object, minus signs are interpreted as either negations or
subtractions:
>>> (x - y).count_ops(visual=True)
SUB
>>> (-x).count_ops(visual=True)
NEG
for a total of 5:
>>> (sin(x)*x + sin(x)**2).count_ops(visual=False)
5
Note that what you type is not always what you get. The expression 1/x/y is translated
by sympy into 1/(x*y) so it gives a DIV and MUL rather than two DIVs:
>>> (1/x/y).count_ops(visual=True)
DIV + MUL
177
The visual option can be used to demonstrate the dierence in operations for expressions
in dierent forms. Here, the Horner representation is compared with the expanded form
of a polynomial:
>>> eq=x*(1 + x*(2 + x*(3 + x)))
>>> count_ops(eq.expand(), visual=True) - count_ops(eq, visual=True)
-MUL + 3*POW
expand mul
sympy.core.function.expand mul(expr, deep=True)
Wrapper around expand that only uses the mul hint. See the expand docstring for more
information.
Examples
>>> from sympy import symbols, expand_mul, exp, log
>>> x, y = symbols(x,y, positive=True)
>>> expand_mul(exp(x+y)*(x+y)*log(x*y**2))
x*exp(x + y)*log(x*y**2) + y*exp(x + y)*log(x*y**2)
expand log
sympy.core.function.expand log(expr, deep=True, force=False)
Wrapper around expand that only uses the log hint. See the expand docstring for more
information.
Examples
>>> from sympy import symbols, expand_log, exp, log
>>> x, y = symbols(x,y, positive=True)
>>> expand_log(exp(x+y)*(x+y)*log(x*y**2))
(x + y)*(log(x) + 2*log(y))*exp(x + y)
expand func
sympy.core.function.expand func(expr, deep=True)
Wrapper around expand that only uses the func hint. See the expand docstring for more
information.
178
Examples
>>> from sympy import expand_func, gamma
>>> from sympy.abc import x
>>> expand_func(gamma(x + 2))
x*(x + 1)*gamma(x)
expand trig
sympy.core.function.expand trig(expr, deep=True)
Wrapper around expand that only uses the trig hint. See the expand docstring for more
information.
Examples
>>> from sympy import expand_trig, sin
>>> from sympy.abc import x, y
>>> expand_trig(sin(x+y)*(x+y))
(x + y)*(sin(x)*cos(y) + sin(y)*cos(x))
expand complex
sympy.core.function.expand complex(expr, deep=True)
Wrapper around expand that only uses the complex hint. See the expand docstring for
more information.
See Also:
Expr.as real imag
Examples
>>> from sympy import expand_complex, exp, sqrt, I
>>> from sympy.abc import z
>>> expand_complex(exp(z))
I*exp(re(z))*sin(im(z)) + exp(re(z))*cos(im(z))
>>> expand_complex(sqrt(I))
sqrt(2)/2 + sqrt(2)*I/2
expand multinomial
sympy.core.function.expand multinomial(expr, deep=True)
Wrapper around expand that only uses the multinomial hint. See the expand docstring
for more information.
179
Examples
>>> from sympy import symbols, expand_multinomial, exp
>>> x, y = symbols(x y, positive=True)
>>> expand_multinomial((x + exp(x + 1))**2)
x**2 + 2*x*exp(x + 1) + exp(2*x + 2)
180
sin((x*y)**z)
>>> expand_power_base(sin((x*y)**z), force=True)
sin(x**z*y**z)
>>> expand_power_base((2*sin(x))**y + (2*cos(x))**y)
2**y*sin(x)**y + 2**y*cos(x)**y
>>> expand_power_base((2*exp(y))**x)
2**x*exp(y)**x
>>> expand_power_base((2*cos(x))**y)
2**y*cos(x)**y
Notice that sums are left untouched. If this is not the desired behavior, apply full expand() to the expression:
>>> expand_power_base(((x+y)*z)**2)
z**2*(x + y)**2
>>> (((x+y)*z)**2).expand()
x**2*z**2 + 2*x*y*z**2 + y**2*z**2
>>> expand_power_base((2*y)**(1+z))
2**(z + 1)*y**(z + 1)
>>> ((2*y)**(1+z)).expand()
2*2**z*y*y**z
noat
sympy.core.function.nfloat(expr, n=15, exponent=False)
Make all Rationals in expr Floats except those in exponents (unless the exponents ag
is set to True).
Examples
>>> from sympy.core.function import nfloat
>>> from sympy.abc import x, y
>>> from sympy import cos, pi, sqrt
>>> nfloat(x**4 + x/2 + cos(pi/3) + 1 + sqrt(y))
x**4 + 0.5*x + sqrt(y) + 1.5
>>> nfloat(x**4 + sqrt(y), exponent=True)
x**4.0 + y**0.5
5.1.18 evalf
PrecisionExhausted
class sympy.core.evalf.PrecisionExhausted
181
N
class sympy.core.evalf.N
Calls x.evalf(n, **options).
Both .n() and N() are equivalent to .evalf(); use the one that you like better. See also the
docstring of .evalf() for information on the options.
Examples
>>> from sympy import Sum, oo, N
>>> from sympy.abc import k
>>> Sum(1/k**k, (k, 1, oo))
Sum(k**(-k), (k, 1, oo))
>>> N(_, 4)
1.291
5.1.19 containers
Tuple
class sympy.core.containers.Tuple
Wrapper around the builtin tuple object
The Tuple is a subclass of Basic, so that it works well in the SymPy framework. The
wrapped tuple is available as self.args, but you can also access elements or slices with
[:] syntax.
>>>
>>>
>>>
>>>
(b,
>>>
(d,
182
The args are sympied so the 1 and 2 are Integers and the values are Symbols. Queries
automatically sympify args so the following work:
>>> 1 in D
True
>>> D.has(one) # searches keys and values
True
>>> one in D # not in the keys
False
>>> D[1]
one
5.1.20 compatibility
iterable
sympy.core.compatibility.iterable(i,
exclude=((<type
str>,
<type
unicode>),
<type
dict>,
<class
sympy.core.compatibility.NotIterable
at
0x9906bfc>))
Return a boolean indicating whether i is SymPy iterable. True also indicates that the
iterator is nite, i.e. you e.g. call list(...) on the instance.
When SymPy is working with iterables, it is almost always assuming that the iterable is
not a string or a mapping, so those are excluded by default. If you want a pure Python
denition, make exclude=None. To exclude multiple items, pass them as a tuple.
See also: is sequence
Examples
>>> from sympy.utilities.iterables import iterable
>>> from sympy import Tuple
>>> things = [[1], (1,), set([1]), Tuple(1), (j for j in [1, 2]), {1:2}, 1, 1]
>>> for i in things:
...
print(%s %s % (iterable(i), type(i)))
True <... list>
True <... tuple>
True <... set>
True <class sympy.core.containers.Tuple>
True <... generator>
False <... dict>
183
is sequence
sympy.core.compatibility.is sequence(i, include=None)
Return a boolean indicating whether i is a sequence in the SymPy sense. If anything
that fails the test below should be included as being a sequence for your application, set
include to that objects type; multiple types should be passed as a tuple of types.
Note: although generators can generate a sequence, they often need special handling to
make sure their elements are captured before the generator is exhausted, so these are
not included by default in the denition of a sequence.
See also: iterable
Examples
>>> from sympy.utilities.iterables import is_sequence
>>> from types import GeneratorType
>>> is_sequence([])
True
>>> is_sequence(set())
False
>>> is_sequence(abc)
False
>>> is_sequence(abc, include=str)
True
>>> generator = (c for c in abc)
>>> is_sequence(generator)
False
>>> is_sequence(generator, include=(str, GeneratorType))
True
as int
sympy.core.compatibility.as int(n)
Convert the argument to a builtin integer.
The return value is guaranteed to be equal to the input. ValueError is raised if the input
has a non-integral value.
184
Examples
>>> from sympy.core.compatibility import as_int
>>> from sympy import sqrt
>>> 3.0
3.0
>>> as_int(3.0) # convert to int and test for equality
3
>>> int(sqrt(10))
3
>>> as_int(sqrt(10))
Traceback (most recent call last):
...
ValueError: ... is not an integer
Traceback (most recent call last):
...
ValueError: ... is not an integer
5.1.21 exprtools
gcd terms
sympy.core.exprtools.gcd terms(terms,
isprimitive=False,
tion=True)
Compute the GCD of terms and put them together.
clear=True,
frac-
185
The clear ag was ignored in this case because the returned expression was a rational
expression, not a simple sum.
factor terms
sympy.core.exprtools.factor terms(expr,
radical=False,
clear=False,
fraction=False, sign=True)
Remove common factors from terms in all arguments without changing the underlying structure of the expr. No expansion or simplication (and no processing of noncommutatives) is performed.
If radical=True then a radical common to all terms will be factored out of any Add subexpressions of the expr.
If clear=False (default) then coecients will not be separated from a single Add if they
can be distributed to leave one or more terms with integer coecients.
If fraction=True (default is False) then a common denominator will be constructed for
the expression.
If sign=True (default) then even if the only factor in common is a -1, it will be factored
out of the expression.
See Also:
gcd terms (page 185), sympy.polys.polytools.terms gcd (page 1065)
Examples
>>> from sympy import factor_terms, Symbol
>>> from sympy.abc import x, y
>>> factor_terms(x + x*(2 + 4*y)**3)
x*(8*(2*y + 1)**3 + 1)
>>> A = Symbol(A, commutative=False)
>>> factor_terms(x*A + x*A + x*y*A)
x*(y*A + 2*A)
When clear is False, a rational will only be factored out of an Add expression if all terms
of the Add have coecients that are fractions:
>>> factor_terms(x/2 + 1, clear=False)
x/2 + 1
>>> factor_terms(x/2 + 1, clear=True)
(x + 2)/2
This only applies when there is a single Add that the coecient multiplies:
186
If a -1 is all that can be factored out, to not factor it out, the ag sign must be False:
>>> factor_terms(-x - y)
-(x + y)
>>> factor_terms(-x - y, sign=False)
-x - y
>>> factor_terms(-2*x - 2*y, sign=False)
-2*(x + y)
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
RGS
Returns the restricted growth string of the partition.
The RGS is returned as a list of indices, L, where L[i] indicates the block in which
element i appears. For example, in a partition of 3 elements (a, b, c) into 2 blocks
([c], [a, b]) the RGS is [1, 1, 0]: a is in block 1, b is in block 1 and c is in block
0.
Examples
>>>
>>>
>>>
(1,
>>>
(0,
187
>>> a + 1
{{3}, {4}, {5}, {1, 2}}
>>> _.RGS
(0, 0, 1, 2, 3)
partition
Return partition as a sorted list of lists.
Examples
>>> from sympy.combinatorics.partitions import Partition
>>> Partition([1], [2, 3]).partition
[[1], [2, 3]]
rank
Gets the rank of a partition.
Examples
>>> from sympy.combinatorics.partitions import Partition
>>> a = Partition([1, 2], [3], [4, 5])
>>> a.rank
13
sort key(order=None)
Return a canonical key that can be used for sorting.
Ordering is based on the size and sorted elements of the partition and ties are broken
with the rank.
Examples
188
class sympy.combinatorics.partitions.IntegerPartition
This class represents an integer partition.
In number theory and combinatorics, a partition of a positive integer, n, also called an
integer partition, is a way of writing n as a list of positive integers that sum to n. Two
partitions that dier only in the order of summands are considered to be the same partition; if order matters then the partitions are referred to as compositions. For example,
4 has ve partitions: [4], [3, 1], [2, 2], [2, 1, 1], and [1, 1, 1, 1]; the compositions [1, 2,
1] and [1, 1, 2] are the same as partition [2, 1, 1].
See Also:
as ferrers(char=#)
Prints the ferrer diagram of a partition.
Examples
>>> from sympy.combinatorics.partitions import IntegerPartition
>>> print(IntegerPartition([1, 1, 5]).as_ferrers())
#####
#
#
conjugate
Computes the conjugate partition of itself.
189
Examples
>>>
>>>
>>>
[5,
next lex()
Return the next partition of the integer, n, in lexical order, wrapping around to [n]
if the partition is [1, ..., 1].
Examples
>>> from sympy.combinatorics.partitions import IntegerPartition
>>> p = IntegerPartition([3, 1])
>>> print(p.next_lex())
[4]
>>> p.partition < p.next_lex().partition
True
prev lex()
Return the previous partition of the integer, n, in lexical order, wrapping around to
[1, ..., 1] if the partition is [n].
Examples
>>> from sympy.combinatorics.partitions import IntegerPartition
>>> p = IntegerPartition([4])
>>> print(p.prev_lex())
[3, 1]
>>> p.partition > p.prev_lex().partition
True
For the following, a seed is given so a known value can be shown; in practice, the seed
would not be given.
>>> random_integer_partition(100, seed=[1, 1, 12, 1, 2, 1, 85, 1])
[85, 12, 2, 1]
>>> random_integer_partition(10, seed=[1, 2, 3, 1, 5, 1])
[5, 3, 1, 1]
>>> random_integer_partition(1)
[1]
sympy.combinatorics.partitions.RGS generalized(m)
Computes the m + 1 generalized unrestricted growth strings and returns them as rows
in matrix.
190
Examples
>>> from sympy.combinatorics.partitions import RGS_generalized
>>> RGS_generalized(6)
Matrix([
[ 1,
1,
1, 1, 1, 1, 1],
[ 1,
2,
3, 4, 5, 6, 0],
[ 2,
5, 10, 17, 26, 0, 0],
[ 5, 15, 37, 77, 0, 0, 0],
[ 15, 52, 151, 0, 0, 0, 0],
[ 52, 203,
0, 0, 0, 0, 0],
[203,
0,
0, 0, 0, 0, 0]])
sympy.combinatorics.partitions.RGS enum(m)
RGS enum computes the total number of restricted growth strings possible for a superset
of size m.
Examples
>>>
>>>
>>>
15
>>>
52
>>>
203
We can check that the enumeration is correct by actually generating the partitions. Here,
the 15 partitions of 4 items are generated:
>>>
>>>
>>>
...
...
...
>>>
a = Partition(list(range(4)))
s = set()
for i in range(20):
s.add(a)
a += 1
assert len(s) == 15
sympy.combinatorics.partitions.RGS unrank(rank, m)
Gives the unranked restricted growth string for a given superset size.
Examples
>>>
>>>
[0,
>>>
[0,
sympy.combinatorics.partitions.RGS rank(rgs)
Computes the rank of a restricted growth string.
191
Examples
>>> from sympy.combinatorics.partitions import RGS_rank, RGS_unrank
>>> RGS_rank([0, 1, 2, 1, 3])
42
>>> RGS_rank(RGS_unrank(4, 7))
4
Permutations
class sympy.combinatorics.permutations.Permutation
A permutation, alternatively known as an arrangement number or ordering is an arrangement of the elements of an ordered list into a one-to-one mapping with itself. The
permutation of a given arrangement is given by indicating the positions of the elements
after re-arrangement [R8] (page 1902). For example, if one started with elements [x, y,
a, b] (in that order) and they were reordered as [x, y, b, a] then the permutation would
be [0, 1, 3, 2]. Notice that (in SymPy) the rst element is always referred to as 0 and the
permutation uses the indices of the elements in the original ordering, not the elements
(a, b, etc...) themselves.
>>> from sympy.combinatorics import Permutation
>>> Permutation.print_cyclic = False
See Also:
Cycle (page 213)
References
[R7] (page 1902), [R8] (page 1902), [R9] (page 1902), [R10] (page 1902), [R11]
(page 1902), [R12] (page 1902), [R13] (page 1902)
Permutations Notation
In the 2-line form, the elements and their nal positions are shown as a matrix with 2
rows:
[0 1 2 ... n-1] [p(0) p(1) p(2) ... p(n-1)]
Since the rst line is always range(n), where n is the size of p, it is sucient to represent
the permutation by the second line, referred to as the array form of the permutation.
This is entered in brackets as the argument to the Permutation class:
>>> p = Permutation([0, 2, 1]); p
Permutation([0, 2, 1])
192
The composite of two permutations p*q means rst apply p, then q, so i(p*q) = (ip)q
which is ipq according to Python precedence rules:
>>>
>>>
[2,
>>>
[2,
q = Permutation([2, 1, 0])
[i^p^q for i in range(3)]
0, 1]
[i^(p*q) for i in range(3)]
0, 1]
One can use also the notation p(i) = ip, but then the composition rule is (p*q)(i) = q(p(i)),
not p(q(i)):
>>>
[2,
>>>
[2,
>>>
[1,
In disjoint cycle notation, only the elements that have shifted are indicated. In the above
case, the 2 and 1 switched places. This can be entered in two ways:
>>> Permutation(1, 2) == Permutation([[1, 2]]) == p
True
The disjoint cycle notation is convenient when representing permutations that have several cycles in them:
>>> Permutation(1, 2)(3, 5) == Permutation([[1, 2], [3, 5]])
True
It also provides some economy in entry when computing products of permutations that
are written in disjoint cycle notation:
>>> Permutation(1, 2)(1, 3)(2, 3)
Permutation([0, 3, 2, 1])
>>> _ == Permutation([[1, 2]])*Permutation([[1, 3]])*Permutation([[2, 3]])
True
193
Cyclic-form entry:
>>> Permutation(1, 2, size=10)
Permutation([0, 2, 1], size=10)
>>> Permutation(9)(1, 2)
Permutation([0, 2, 1], size=10)
Caution: no singleton containing an element larger than the largest in any previous cycle
can be entered. This is an important dierence in how Permutation and Cycle handle the
call syntax. A singleton argument at the start of a Permutation performs instantiation
of the Permutation and is permitted:
>>> Permutation(5)
Permutation([], size=6)
A singleton entered after instantiation is a call to the permutation a function call and
if the argument is out of range it will trigger an error. For this reason, it is better to start
the cycle with the singleton:
The following fails because there is is no element 3:
>>> Permutation(1, 2)(3)
Traceback (most recent call last):
...
IndexError: list index out of range
Traceback (most recent call last):
...
IndexError: list index out of range
This is ok: only the call to an out of range singleton is prohibited; otherwise the permutation autosizes:
>>> Permutation(3)(1, 2)
Permutation([0, 2, 1, 3])
>>> Permutation(1, 2)(3, 4) == Permutation(3, 4)(1, 2)
True
Equality Testing
The array forms must be the same in order for permutations to be equal:
>>> Permutation([1, 0, 2, 3]) == Permutation([1, 0])
False
Identity Permutation
194
Watch out for entering the range inside a set of brackets (which is cycle notation):
>>> I == Permutation([range(4)])
False
Permutation Printing
There are a few things to note about how Permutations are printed.
1) If you prefer one form (array or cycle) over another, you can set that with the
print cyclic ag.
>>> Permutation(1, 2)(4, 5)(3, 4)
Permutation([0, 2, 1, 4, 5, 3])
>>> p = _
>>> Permutation.print_cyclic = True
>>> p
Permutation(1, 2)(3, 4, 5)
>>> Permutation.print_cyclic = False
2) Regardless of the setting, a list of elements in the array for cyclic form can be obtained
and either of those can be copied and supplied as the argument to Permutation:
>>> p.array_form
[0, 2, 1, 4, 5, 3]
>>> p.cyclic_form
[[1, 2], [3, 4, 5]]
>>> Permutation(_) == p
True
3) Printing is economical in that as little as possible is printed while retaining all information about the size of the permutation:
>>> Permutation([1, 0, 2, 3])
Permutation([1, 0, 2, 3])
>>> Permutation([1, 0, 2, 3], size=20)
Permutation([1, 0], size=20)
>>> Permutation([1, 0, 2, 4, 3, 5, 6], size=20)
Permutation([1, 0, 2, 4, 3], size=20)
>>> p = Permutation([1, 0, 2, 3])
>>> Permutation.print_cyclic = True
>>> p
Permutation(3)(0, 1)
>>> Permutation.print_cyclic = False
The 2 was not printed but it is still there as can be seen with the array form and size
methods:
>>> p.array_form
[1, 0, 2, 3]
>>> p.size
4
195
The permutation can act as a bijective function, telling what element is located at a given
position
>>>
>>>
2
>>>
2
>>>
{0:
q = Permutation([5, 2, 3, 4, 1, 0])
q.array_form[1] # the hard way
q(1) # the easy way
dict([(i, q(i)) for i in range(q.size)]) # showing the bijection
5, 1: 2, 2: 3, 3: 4, 4: 1, 5: 0}
A given permutation has a rank among all the possible permutations of the same elements, but what that rank is depends on how the permutations are enumerated. (There
are a number of dierent methods of doing so.) The lexicographic rank is given by the
rank method and this rank is used to increment a permutation with addition/subtraction:
>>> p.rank()
6
>>> p + 1
Permutation([1, 0, 3, 2])
>>> p.next_lex()
Permutation([1, 0, 3, 2])
>>> _.rank()
7
>>> p.unrank_lex(p.size, rank=7)
Permutation([1, 0, 3, 2])
196
p = Permutation([1, 0, 2, 3])
q = Permutation([2, 3, 1, 0])
list(q*p)
3, 0, 1]
list(p*q)
2, 1, 0]
[q(p(i)) for i in range(p.size)]
2, 1, 0]
The permutation can be applied to any list-like object, not only Permutations:
>>> p([zero, one, four, two])
[one, zero, four, two]
>>> p(zo42)
[o, z, 4, 2]
If you have a list of arbitrary elements, the corresponding permutation can be found with
the from sequence method:
>>> Permutation.from_sequence(SymPy)
Permutation([1, 3, 2, 0, 4])
array form
Return a copy of the attribute array form Examples ========
>>>
>>>
>>>
>>>
[2,
>>>
[3,
>>>
[2,
>>>
[0,
ascents()
Returns the positions of ascents in a permutation, ie, the location where p[i] < p[i+1]
See Also:
descents (page 199), inversions (page 203), min (page 207), max (page 207)
Examples
>>>
>>>
>>>
[1,
atoms()
Returns all the elements of a permutation
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation([0, 1, 2, 3, 4, 5]).atoms()
set([0, 1, 2, 3, 4, 5])
>>> Permutation([[0, 1], [2, 3], [4, 5]]).atoms()
set([0, 1, 2, 3, 4, 5])
cardinality
Returns the number of all possible permutations.
5.2. Combinatorics Module
197
See Also:
length (page 206), order (page 208), rank (page 209), size (page 211)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation([0,1,2,3])
>>> p.cardinality
24
commutator(x)
Return the commutator of self and x: x*self*x*self
If f and g are part of a group, G, then the commutator of f and g is the group identity
i f and g commute, i.e. fg == gf.
References
http://en.wikipedia.org/wiki/Commutator
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.print_cyclic = False
>>> p = Permutation([0, 2, 3, 1])
>>> x = Permutation([2, 0, 3, 1])
>>> c = p.commutator(x); c
Permutation([2, 1, 3, 0])
>>> c == ~x*~p*x*p
True
>>> I = Permutation(3)
>>> p = [I + i for i in range(6)]
>>> for i in range(len(p)):
...
for j in range(len(p)):
...
c = p[i].commutator(p[j])
...
if p[i]*p[j] == p[j]*p[i]:
...
assert c == I
...
else:
...
assert c != I
...
commutes with(other)
Checks if the elements are commuting.
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> a = Permutation([1,4,3,0,2,5])
>>> b = Permutation([0,1,2,3,4,5])
>>> a.commutes_with(b)
True
198
>>> b = Permutation([2,3,5,4,1,0])
>>> a.commutes_with(b)
False
cycle structure
Return the cycle structure of the permutation as a dictionary indicating the multiplicity of each cycle length.
Examples
>>>
>>>
>>>
{1:
>>>
{2:
cycles
Returns the number of cycles contained in the permutation (including singletons).
See Also:
sympy.functions.combinatorial.numbers.stirling (page 374)
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation([0, 1, 2]).cycles
3
>>> Permutation([0, 1, 2]).full_cyclic_form
[[0], [1], [2]]
>>> Permutation(0, 1)(2, 3).cycles
2
cyclic form
This is used to convert to the cyclic notation from the canonical notation. Singletons
are omitted.
See Also:
array form (page 197), full cyclic form (page 200)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.print_cyclic = False
>>> p = Permutation([0, 3, 1, 2])
>>> p.cyclic_form
[[1, 3, 2]]
>>> Permutation([1, 0, 2, 4, 3, 5]).cyclic_form
[[0, 1], [3, 4]]
descents()
Returns the positions of descents in a permutation, ie, the location where p[i] >
p[i+1]
5.2. Combinatorics Module
199
See Also:
ascents (page 197), inversions (page 203), min (page 207), max (page 207)
Examples
>>>
>>>
>>>
[0,
200
[1] Reeves, Colin R. Landscapes, Operators and Heuristic search, Annals of Operational Research, 86, pp 473-490. (1999)
See Also:
get precedence matrix (page 202),
get adjacency matrix (page 201)
(page
202),
Examples
>>>
>>>
>>>
>>>
3
>>>
>>>
4
(page
202),
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation.josephus(3,6,1)
>>> p.get_adjacency_matrix()
Matrix([
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0]])
>>> q = Permutation([0, 1, 2, 3])
>>> q.get_adjacency_matrix()
Matrix([
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[0, 0, 0, 0]])
201
Examples
>>>
>>>
>>>
>>>
>>>
12
>>>
12
(page
201),
Examples
>>>
>>>
>>>
>>>
7
>>>
7
(page
201),
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation.josephus(3,6,1)
>>> p
Permutation([2, 5, 3, 1, 4, 0])
>>> p.get_precedence_matrix()
Matrix([
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 1, 0],
[1, 1, 0, 1, 1, 1],
[1, 1, 0, 0, 1, 0],
[1, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 1, 0]])
202
index()
Returns the index of a permutation.
The index of a permutation is the sum of all subscripts j such that p[j] is greater than
p[j+1].
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation([3, 0, 2, 1, 4])
>>> p.index()
2
inversion vector()
Return the inversion vector of the permutation.
The inversion vector consists of elements whose value indicates the number of elements in the permutation that are lesser than it and lie on its right hand side.
The inversion vector is the same as the Lehmer encoding of a permutation.
See Also:
from inversion vector (page 200)
Examples
>>>
>>>
>>>
[4,
>>>
>>>
[3,
The inversion vector increases lexicographically with the rank of the permutation,
the -ith element cycling through 0..i.
>>> p = Permutation(2)
>>> while p:
...
print(%s %s %s %
...
p = p.next_lex()
...
Permutation([0, 1, 2]) [0,
Permutation([0, 2, 1]) [0,
Permutation([1, 0, 2]) [1,
Permutation([1, 2, 0]) [1,
Permutation([2, 0, 1]) [2,
Permutation([2, 1, 0]) [2,
0]
1]
0]
1]
0]
1]
0
1
2
3
4
5
inversions()
Computes the number of inversions of a permutation.
An inversion is where i > j but p[i] < p[j].
For small length of p, it iterates over all i and j values and calculates the number of
inversions. For large length of p, it uses a variation of merge sort to calculate the
number of inversions.
203
See Also:
descents (page 199), ascents (page 197), min (page 207), max (page 207)
References
[1] http://www.cp.eng.chula.ac.th/piak/teaching/algo/algo2008/count-inv.htm
Examples
>>>
>>>
>>>
0
>>>
6
is Empty
Checks to see if the permutation is a set with zero elements
See Also:
is Singleton (page 204)
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation([]).is_Empty
True
>>> Permutation([0]).is_Empty
False
is Identity
Returns True if the Permutation is an identity permutation.
See Also:
order (page 208)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation([])
>>> p.is_Identity
True
>>> p = Permutation([[0], [1], [2]])
>>> p.is_Identity
True
>>> p = Permutation([0, 1, 2])
>>> p.is_Identity
True
>>> p = Permutation([0, 2, 1])
>>> p.is_Identity
False
204
is Singleton
Checks to see if the permutation contains only one number and is thus the only
possible permutation of this set of numbers
See Also:
is Empty (page 204)
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation([0]).is_Singleton
True
>>> Permutation([0, 1]).is_Singleton
False
is even
Checks if a permutation is even.
See Also:
is odd (page 205)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation([0,1,2,3])
>>> p.is_even
True
>>> p = Permutation([3,2,1,0])
>>> p.is_even
True
is odd
Checks if a permutation is odd.
See Also:
is even (page 205)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation([0,1,2,3])
>>> p.is_odd
False
>>> p = Permutation([3,2,0,1])
>>> p.is_odd
True
205
chosen
======
2
25
253
2531
25314
253140
References
1.http://en.wikipedia.org/wiki/Flavius Josephus
2.http://en.wikipedia.org/wiki/Josephus problem
3.http://www.wou.edu/burtonl/josephus.html
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation.josephus(3, 6, 2).array_form
[2, 5, 3, 1, 4, 0]
length()
Returns the number of integers moved by a permutation.
See Also:
min (page 207), max (page 207), support (page 212), cardinality (page 197), order
(page 208), rank (page 209), size (page 211)
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation([0, 3, 2, 1]).length()
2
>>> Permutation([[0, 1], [2, 3]]).length()
4
list(size=None)
Return the permutation as an explicit list, possibly trimming unmoved elements if
size is less than the maximum element in the permutation; if this is desired, setting
size=-1 will guarantee such trimming.
Examples
>>>
>>>
>>>
>>>
[0,
206
>>> p.list(10)
[0, 1, 3, 2, 5, 4, 6, 7, 8, 9]
Passing a length too small will trim trailing, unchanged elements in the permutation:
>>> Permutation(2, 4)(1, 2, 4).list(-1)
[0, 2, 1]
>>> Permutation(3).list(-1)
[]
max()
The maximum element moved by the permutation.
See Also:
min (page 207), descents (page 199), ascents (page 197), inversions (page 203)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation([1,0,2,3,4])
>>> p.max()
1
min()
The minimum element moved by the permutation.
See Also:
max (page 207), descents (page 199), ascents (page 197), inversions (page 203)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation([0,1,4,3,2])
>>> p.min()
2
mul inv(other)
other*self, self and other have array form
next lex()
Returns the next permutation in lexicographical order. If self is the last permutation
in lexicographical order it returns None. See [4] section 2.4.
See Also:
rank (page 209), unrank lex (page 212)
Examples
>>>
>>>
>>>
17
>>>
18
207
next nonlex()
Returns the next permutation in nonlex order [3]. If self is the last permutation in
this order it returns None.
See Also:
rank nonlex (page 209), unrank nonlex (page 213)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.print_cyclic = False
>>> p = Permutation([2, 0, 3, 1]); p.rank_nonlex()
5
>>> p = p.next_nonlex(); p
Permutation([3, 0, 1, 2])
>>> p.rank_nonlex()
6
next trotterjohnson()
Returns the next permutation in Trotter-Johnson order. If self is the last permutation
it returns None. See [4] section 2.4. If it is desired to generate all such permutations,
they can be generated in order more quickly with the generate bell function.
See Also:
rank trotterjohnson (page 210),
unrank trotterjohnson
sympy.utilities.iterables.generate bell (page 1557)
(page
213),
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.print_cyclic = False
>>> p = Permutation([3, 0, 2, 1])
>>> p.rank_trotterjohnson()
4
>>> p = p.next_trotterjohnson(); p
Permutation([0, 3, 2, 1])
>>> p.rank_trotterjohnson()
5
order()
Computes the order of a permutation.
When the permutation is raised to the power of its order it equals the identity permutation.
See Also:
identity, cardinality (page 197), length (page 206), rank (page 209), size
(page 211)
Examples
208
parity()
Computes the parity of a permutation.
The parity of a permutation reects the parity of the number of inversions in the
permutation, i.e., the number of pairs of x and y such that x > y but p[x] < p[y].
See Also:
af parity
Examples
>>>
>>>
>>>
0
>>>
>>>
1
classmethod random(n)
Generates a random permutation of length n.
Uses the underlying Python pseudo-random number generator.
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.random(2) in (Permutation([1, 0]), Permutation([0, 1]))
True
rank()
Returns the lexicographic rank of the permutation.
See Also:
next lex (page 207), unrank lex (page 212), cardinality (page 197), length
(page 206), order (page 208), size (page 211)
Examples
>>>
>>>
>>>
0
>>>
>>>
23
209
rank trotterjohnson()
Returns the Trotter Johnson rank, which we get from the minimal change algorithm.
See [4] section 2.4.
See Also:
unrank trotterjohnson (page 213), next trotterjohnson (page 208)
Examples
>>>
>>>
>>>
0
>>>
>>>
7
static rmul(*args)
Return product of Permutations [a, b, c, ...] as the Permutation whose ith value is
a(b(c(i))).
a, b, c, ... can be Permutation objects or tuples.
Notes
All items in the sequence will be parsed by Permutation as necessary as long as the
rst item is a Permutation:
>>> Permutation.rmul(a, [0, 2, 1]) == Permutation.rmul(a, b)
True
210
>>>
>>>
>>>
[1,
>>>
[1,
a = Permutation(a); b = Permutation(b)
list(a*b)
0, 1]
[b(a(i)) for i in range(3)]
0, 1]
signature()
Gives the signature of the permutation needed to place the elements of the permutation in canonical order.
The signature is calculated as (-1)<number of inversions>
See Also:
inversions (page 203)
Examples
>>>
>>>
>>>
0
>>>
1
>>>
>>>
1
>>>
-1
211
size
Returns the number of elements in the permutation.
See Also:
cardinality (page 197), length (page 206), order (page 208), rank (page 209)
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation([[3, 2], [0, 1]]).size
4
support()
Return the elements in permutation, P, for which P[i] != i.
Examples
>>>
>>>
>>>
[1,
>>>
[0,
transpositions()
Return the permutation decomposed into a list of transpositions.
It is always possible to express a permutation as the product of transpositions, see
[1]
References
1.http://en.wikipedia.org/wiki/Transposition %28mathematics%29#Properties
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> p = Permutation([[1, 2, 3], [0, 4, 5, 6, 7]])
>>> t = p.transpositions()
>>> t
[(0, 7), (0, 6), (0, 5), (0, 4), (1, 3), (1, 2)]
>>> print(.join(str(c) for c in t))
(0, 7)(0, 6)(0, 5)(0, 4)(1, 3)(1, 2)
>>> Permutation.rmul(*[Permutation([ti], size=p.size) for ti in t]) == p
True
212
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.print_cyclic = False
>>> a = Permutation.unrank_lex(5, 10)
>>> a.rank()
10
>>> a
Permutation([0, 2, 4, 1, 3])
class sympy.combinatorics.permutations.Cycle(*args)
Wrapper around dict which provides the functionality of a disjoint cycle.
A cycle shows the rule to use to move subsets of elements to obtain a permutation. The
Cycle class is more exible that Permutation in that 1) all elements need not be present in
order to investigate how multiple cycles act in sequence and 2) it can contain singletons:
>>> from sympy.combinatorics.permutations import Perm, Cycle
213
The array form of a Cycle can be obtained by calling the list method (or passing it to the
list function) and all elements from 0 will be shown:
>>>
>>>
[0,
>>>
[0,
a = Cycle(1, 2)
a.list()
2, 1]
list(a)
2, 1]
If a larger (or smaller) range is desired use the list method and provide the desired size
but the Cycle cannot be truncated to a size smaller than the largest element that is out
of place:
>>>
>>>
[0,
>>>
[0,
>>>
[0,
b = Cycle(2,4)(1,2)(3,1,4)(1,3)
b.list()
2, 1, 3, 4]
b.list(b.size + 1)
2, 1, 3, 4, 5]
b.list(-1)
2, 1]
Singletons are not shown when printing with one exception: the largest element is always shown as a singleton if necessary:
>>> Cycle(1, 4, 10)(4, 5)
Cycle(1, 5, 4, 10)
>>> Cycle(1, 2)(4)(5)(10)
Cycle(1, 2)(10)
The array form can be used to instantiate a Permutation so other properties of the permutation can be investigated:
>>> Perm(Cycle(1,2)(3,4).list()).transpositions()
[(1, 2), (3, 4)]
See Also:
Permutation (page 192)
Notes
The underlying structure of the Cycle is a dictionary and although the iter method
has been redened to give the array form of the cycle, the underlying dictionary items
are still available with the such methods as items():
>>> list(Cycle(1, 2).items())
[(1, 2), (2, 1)]
list(size=None)
Return the cycles as an explicit list starting from 0 up to the greater of the largest
value in the cycles and size.
Truncation of trailing unmoved items will occur when size is less than the maximum
element in the cycle; if this is desired, setting size=-1 will guarantee such trimming.
214
Examples
>>>
>>>
>>>
>>>
>>>
[0,
>>>
[0,
Passing a length too small will trim trailing, unchanged elements in the permutation:
>>> Cycle(2, 4)(1, 2, 4).list(-1)
[0, 2, 1]
Generators
static generators.symmetric(n)
Generates the symmetric group of order n, Sn.
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.generators import symmetric
>>> list(symmetric(3))
[Permutation(2), Permutation(1, 2), Permutation(2)(0, 1),
Permutation(0, 1, 2), Permutation(0, 2, 1), Permutation(0, 2)]
static generators.cyclic(n)
Generates the cyclic group of order n, Cn.
See Also:
dihedral (page 216)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.generators import cyclic
>>> list(cyclic(5))
[Permutation(4), Permutation(0, 1, 2, 3, 4), Permutation(0, 2, 4, 1, 3),
Permutation(0, 3, 1, 4, 2), Permutation(0, 4, 3, 2, 1)]
static generators.alternating(n)
Generates the alternating group of order n, An.
215
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.generators import alternating
>>> list(alternating(3))
[Permutation(2), Permutation(0, 1, 2), Permutation(0, 2, 1)]
static generators.dihedral(n)
Generates the dihedral group of order 2n, Dn.
The result is given as a subgroup of Sn, except for the special cases n=1 (the group S2)
and n=2 (the Klein 4-group) where thats not possible and embeddings in S2 and S4
respectively are given.
See Also:
cyclic (page 215)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.generators import dihedral
>>> list(dihedral(3))
[Permutation(2), Permutation(0, 2), Permutation(0, 1, 2),
Permutation(1, 2), Permutation(0, 2, 1), Permutation(2)(0, 1)]
Permutation Groups
class sympy.combinatorics.perm groups.PermutationGroup
The class dening a Permutation group.
PermutationGroup([p1, p2, ..., pn]) returns the permutation group generated by the list
of permutations. This group can be supplied to Polyhedron if one desires to decorate the
elements to which the indices of the permutation refer.
See Also:
sympy.combinatorics.polyhedron.Polyhedron
(page
sympy.combinatorics.permutations.Permutation (page 192)
243),
References
[1] Holt, D., Eick, B., OBrien, E. Handbook of Computational Group Theory
[2] Seress, A. Permutation Group Algorithms
[3] http://en.wikipedia.org/wiki/Schreier vector
[4]
http://en.wikipedia.org/wiki/Nielsen transformation
uct replacement algorithm
#Prod-
[5] Frank Celler, Charles R.Leedham-Green, Scott H.Murray, Alice C.Niemeyer, and
E.A.OBrien. Generating Random Elements of a Finite Group
[6] http://en.wikipedia.org/wiki/Block %28permutation group theory%29
216
The permutations corresponding to motion of the front, right and bottom face of a 2x2
Rubiks cube are dened:
>>> F = Permutation(2, 19, 21, 8)(3, 17, 20, 10)(4, 6, 7, 5)
>>> R = Permutation(1, 5, 21, 14)(3, 7, 23, 12)(8, 10, 11, 9)
>>> D = Permutation(6, 18, 14, 10)(7, 19, 15, 11)(20, 22, 23, 21)
The group can be supplied to a Polyhedron in order to track the objects being moved.
An example involving the 2x2 Rubiks cube is given there, but here is a simple demonstration:
>>>
>>>
>>>
>>>
>>>
(A,
>>>
>>>
(A,
>>>
>>>
(A,
a = Permutation(2, 1)
b = Permutation(1, 0)
G = PermutationGroup(a, b)
P = Polyhedron(list(ABC), pgroup=G)
P.corners
B, C)
P.rotate(0) # apply permutation 0
P.corners
C, B)
P.reset()
P.corners
B, C)
Or one can make a permutation as a product of selected permutations and apply them
to an iterable directly:
>>> P10 = G.make_perm([0, 1])
>>> P10(ABC)
[C, A, B]
base
Return a base from the Schreier-Sims algorithm.
5.2. Combinatorics Module
217
baseswap(base, strong gens, pos, randomized=False, transversals=None, basic orbits=None, strong gens distr=None)
Swap two consecutive base points in base and strong generating set.
If a base for a group G is given by (b 1, b 2, ..., b k), this function returns a
base (b 1, b 2, ..., b {i+1}, b i, ..., b k), where i is given by pos, and a
strong generating set relative to that base. The original base and strong generating
set are not modied.
The randomized version (default) is of Las Vegas type.
Parameters base, strong gens :
The base and strong generating set.
pos :
The position at which swapping is performed.
randomized :
A switch between randomized and deterministic version.
transversals :
The transversals for the basic orbits, if known.
basic orbits :
The basic orbits, if known.
strong gens distr :
The strong generators distributed by basic stabilizers, if known.
Returns (base, strong gens) :
base is the new base, and strong gens is a generating set relative to
it.
See Also:
schreier sims (page 238)
218
Notes
The deterministic version of the algorithm is discussed in [1], pp. 102-103; the
randomized version is discussed in [1], p.103, and [2], p.98. It is of Las Vegas type.
Notice that [1] contains a mistake in the pseudocode and discussion of BASESWAP:
on line 3 of the pseudocode, |\beta {i+1}{\left\langle T\right\rangle}| should
be replaced by |\beta {i}{\left\langle T\right\rangle}|, and the same for the
discussion of the algorithm.
Examples
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> S = SymmetricGroup(4)
>>> S.schreier_sims()
>>> S.base
[0, 1, 2]
>>> base, gens = S.baseswap(S.base, S.strong_gens, 1, randomized=False)
>>> base, gens
([0, 2, 1],
[Permutation(0, 1, 2, 3), Permutation(3)(0, 1), Permutation(1, 3, 2),
Permutation(2, 3), Permutation(1, 3)])
basic orbits
Return the basic orbits relative to a base and strong generating set.
If (b 1, b 2, ..., b k) is a base for a group G, and G{(i)} = G {b 1, b 2,
..., b {i-1}} is the i-th basic stabilizer (so that G{(1)} = G), the i-th basic orbit
relative to this base is the orbit of b i under G{(i)}. See [1], pp. 87-89 for more
information.
See Also:
base (page 217), strong gens (page 241), basic transversals (page 220), basic stabilizers (page 219)
Examples
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(4)
>>> S.basic_orbits
[[0, 1, 2, 3], [1, 2, 3], [2, 3]]
basic stabilizers
Return a chain of stabilizers relative to a base and strong generating set.
The i-th basic stabilizer G{(i)} relative to a base (b 1, b 2, ..., b k) is G {b 1,
b 2, ..., b {i-1}}. For more information, see [1], pp. 87-89.
See Also:
5.2. Combinatorics Module
219
ba-
Examples
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> A = AlternatingGroup(4)
>>> A.schreier_sims()
>>> A.base
[0, 1]
>>> for g in A.basic_stabilizers:
...
print(g)
...
PermutationGroup([
Permutation(3)(0, 1, 2),
Permutation(1, 2, 3)])
PermutationGroup([
Permutation(1, 2, 3)])
basic transversals
Return basic transversals relative to a base and strong generating set.
The basic transversals are transversals of the basic orbits. They are provided as a
list of dictionaries, each dictionary having keys - the elements of one of the basic
orbits, and values - the corresponding transversal elements. See [1], pp. 87-89 for
more information.
See Also:
strong gens (page 241), base (page 217),
sic stabilizers (page 219)
ba-
Examples
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> A = AlternatingGroup(4)
>>> A.basic_transversals
[{0: Permutation(3),
1: Permutation(3)(0, 1, 2),
2: Permutation(3)(0, 2, 1),
3: Permutation(0, 3, 1)},
{1: Permutation(3),
2: Permutation(1, 2, 3),
3: Permutation(1, 3, 2)}]
center()
Return the center of a permutation group.
The center for a group G is dened as Z(G) = \{z\in G | \forall g\in G, zg =
gz \}, the set of elements of G that commute with all elements of G. It is equal to the
centralizer of G inside G, and is naturally a subgroup of G ([9]).
See Also:
centralizer (page 221)
220
Notes
centralizer(other)
Return the centralizer of a group/set/element.
The centralizer of a set of permutations S inside a group G is the set of elements of
G that commute with all elements of S:
C G(S) = \{ g \in G | gs = sg \forall s \in S\} ([10])
The implementation is an application of .subgroup search() with tests using a specic base for the group G.
Examples
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... CyclicGroup)
>>> S = SymmetricGroup(6)
>>> C = CyclicGroup(6)
>>> H = S.centralizer(C)
>>> H.is_subgroup(C)
True
commutator(G, H)
Return the commutator of two subgroups.
221
The commutator of two subgroups H, G is equal to the normal closure of the commutators of all the generators, i.e. hgh{-1}g{-1} for h a generator of H and g a
generator of G ([1], p.28)
Examples
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... AlternatingGroup)
>>> S = SymmetricGroup(5)
>>> A = AlternatingGroup(5)
>>> G = S.commutator(S, A)
>>> G.is_subgroup(A)
True
contains(g, strict=True)
Test if permutation g belong to self, G.
If g is an element of G it can be written as a product of factors drawn from the cosets
of Gs stabilizers. To see if g is one of the actual generators dening the group use
G.has(g).
If strict is not True, g will be resized, if necessary, to match the size of permutations
in self.
See Also:
coset factor (page 223), has, in
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> a = Permutation(1, 2)
>>> b = Permutation(2, 3, 1)
>>> G = PermutationGroup(a, b, degree=5)
>>> G.contains(G[0]) # trivial check
True
>>> elem = Permutation([[2, 3]], size=5)
>>> G.contains(elem)
True
>>> G.contains(Permutation(4)(0, 1, 2, 3))
False
222
>>> H = PermutationGroup(Permutation(5))
>>> H.contains(Permutation(3))
False
>>> H.contains(Permutation(3), strict=False)
True
from sympy.combinatorics
Permutation.print_cyclic
a = Permutation(0, 1, 3,
b = Permutation(0, 1, 3,
G = PermutationGroup([a,
Dene g:
>>> g = Permutation(7)(1, 2, 4)(3, 6, 5)
Thus, it can be written as a product of factors (up to 3) drawn from u. See below
that a factor from u1 and u2 and the Identity permutation have been used:
>>> f = G.coset_factor(g)
>>> f[2]*f[1]*f[0] == g
True
>>> f1 = G.coset_factor(g, True); f1
[0, 4, 4]
>>> tr = G.basic_transversals
>>> f[0] == tr[0][f1[0]]
True
223
>>> c = Permutation(5, 6, 7)
>>> G.coset_factor(c)
[]
224
1
>>> G.order()
2
>>> list(G.generate())
[Permutation(2), Permutation(2)(0, 1)]
derived series()
Return the derived series for the group.
The derived series for a group G is dened as G = G 0 > G 1 > G 2 > \ldots
where G i = [G {i-1}, G {i-1}], i.e. G i is the derived subgroup of G {i-1}, for
i\in\mathbb{N}. When we have G k = G {k-1} for some k\in\mathbb{N}, the series
terminates.
Returns A list of permutation groups containing the members of the
derived :
series in the order G = G 0, G 1, G 2, ldots. :
See Also:
derived subgroup (page 225)
Examples
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... AlternatingGroup, DihedralGroup)
>>> A = AlternatingGroup(5)
>>> len(A.derived_series())
1
>>> S = SymmetricGroup(4)
>>> len(S.derived_series())
4
>>> S.derived_series()[1].is_subgroup(AlternatingGroup(4))
True
>>> S.derived_series()[2].is_subgroup(DihedralGroup(2))
True
derived subgroup()
Compute the derived subgroup.
The derived subgroup, or commutator subgroup is the subgroup generated by all
commutators [g, h] = hgh{-1}g{-1} for g, h\in G ; it is equal to the normal
closure of the set of commutators of the generators ([1], p.28, [11]).
See Also:
derived series (page 225)
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
225
>>> list(C.generate(af=True))
[[0, 1, 2, 3, 4], [0, 1, 3, 4, 2], [0, 1, 4, 2, 3]]
generate(method=coset, af=False)
Return iterator to generate the elements of the group
Iteration is done with one of these methods:
method=coset using the Schreier-Sims coset representation
method=dimino using the Dimino method
The permutation group given in the tetrahedron object is not true groups:
>>> G = tetrahedron.pgroup
>>> G.is_group()
False
But the group generated by the permutations in the tetrahedron pgroup even the
rst two is a proper group:
>>> H = PermutationGroup(G[0], G[1])
>>> J = PermutationGroup(list(H.generate())); J
PermutationGroup([
Permutation(0, 1)(2, 3),
Permutation(3),
Permutation(1, 2, 3),
Permutation(1, 3, 2),
Permutation(0, 3, 1),
Permutation(0, 2, 3),
Permutation(0, 3)(1, 2),
Permutation(0, 1, 3),
Permutation(3)(0, 2, 1),
Permutation(0, 3, 2),
Permutation(3)(0, 1, 2),
Permutation(0, 2)(1, 3)])
>>> _.is_group()
True
generate dimino(af=False)
Yield group elements using Diminos algorithm
If af == True it yields the array form of the permutations
References
[1] The Implementation of Various Algorithms for Permutation Groups in the Computer Algebra System: AXIOM, N.J. Doye, M.Sc. Thesis
226
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> a = Permutation([0, 2, 1, 3])
>>> b = Permutation([0, 2, 3, 1])
>>> g = PermutationGroup([a, b])
>>> list(g.generate_dimino(af=True))
[[0, 1, 2, 3], [0, 2, 1, 3], [0, 2, 3, 1],
[0, 1, 3, 2], [0, 3, 2, 1], [0, 3, 1, 2]]
generators
Returns the generators of the group.
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> a = Permutation([0, 2, 1])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G.generators
[Permutation(1, 2), Permutation(2)(0, 1)]
is abelian
Test if the group is Abelian.
Examples
>>>
>>>
>>>
>>>
>>>
227
The algorithm itself uses some nontrivial results from group theory and number
theory: 1) If a transitive group G of degree n contains an element with a cycle of
length n/2 < p < n-2 for p a prime, G is the symmetric or alternating group ([1],
pp. 81-82) 2) The proportion of elements in the symmetric/alternating group having
the property described in 1) is approximately \log(2)/\log(n) ([1], p.82; [2], pp.
226-227). The helper function check cycles alt sym is used to go over the cycles
in a permutation and look for ones satisfying 1).
Examples
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> D = DihedralGroup(10)
>>> D.is_alt_sym()
False
is group()
Return True if the group meets three criteria: identity is present, the inverse of
every element is also an element, and the product of any two elements is also an
element. If any of the tests fail, False is returned.
Examples
>>>
>>>
>>>
>>>
The permutation group given in the tetrahedron object is not a true group:
>>> G = tetrahedron.pgroup
>>> G.is_group()
False
228
But the group generated by the permutations in the tetrahedron pgroup is a proper
group:
>>> H = PermutationGroup(list(G.generate()))
>>> H.is_group()
True
The product of any two elements from the group is also in the group:
>>>
>>>
>>>
>>>
>>>
...
...
>>>
So we see that g[1] and g[3] are equivalent to their inverse while g[7] == g[2].
is nilpotent
Test if the group is nilpotent.
A group G is nilpotent if it has a central series of nite length. Alternatively, G is
nilpotent if its lower central series terminates with the trivial group. Every nilpotent
group is also solvable ([1], p.29, [12]).
See Also:
5.2. Combinatorics Module
229
is normal(gr)
Test if G=self is a normal subgroup of gr.
G is normal in gr if for each g2 in G, g1 in gr, g = g1*g2*g1**-1 belongs to G It is
sucient to check this for each g1 in gr.generator and g2 g2 in G.generator
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> a = Permutation([1, 2, 0])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G1 = PermutationGroup([a, Permutation([2, 0, 1])])
>>> G1.is_normal(G)
True
is primitive(randomized=True)
Test if a group is primitive.
A permutation group G acting on a set S is called primitive if S contains no nontrivial
block under the action of G (a block is nontrivial if its cardinality is more than 1).
See Also:
minimal block (page 234), random stab (page 238)
Notes
The algorithm is described in [1], p.83, and uses the function minimal block to search
for blocks of the form \{0, k\} for k ranging over representatives for the orbits of
G 0, the stabilizer of 0. This algorithm has complexity O(n2) where n is the degree
of the group, and will perform badly if G 0 is small.
There are two implementations oered: one nds G 0 deterministically using the
function stabilizer, and the other (default) produces random elements of G 0 using random stab, hoping that they generate a subgroup of G 0 with not too many
more orbits than G 0 (this is suggested in [1], p.83). Behavior is changed by the
randomized ag.
230
Examples
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> D = DihedralGroup(10)
>>> D.is_primitive()
False
is solvable
Test if the group is solvable.
G is solvable if its derived series terminates with the trivial group ([1], p.29).
See Also:
is nilpotent (page 229), derived series (page 225)
Examples
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(3)
>>> S.is_solvable
True
is subgroup(G, strict=True)
Return True if all elements of self belong to G.
If strict is False then if selfs degree is smaller than Gs, the elements will be
resized to have the same degree.
Examples
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
...
CyclicGroup)
Testing is strict by default: the degree of each group must be the same:
>>> p = Permutation(0, 1, 2, 3, 4, 5)
>>> G1 = PermutationGroup([Permutation(0, 1, 2), Permutation(0, 1)])
>>> G2 = PermutationGroup([Permutation(0, 2), Permutation(0, 1, 2)])
>>> G3 = PermutationGroup([p, p**2])
>>> assert G1.order() == G2.order() == G3.order() == 6
>>> G1.is_subgroup(G2)
True
>>> G1.is_subgroup(G3)
False
>>> G3.is_subgroup(PermutationGroup(G3[1]))
False
>>> G3.is_subgroup(PermutationGroup(G3[0]))
True
231
True
>>> C7 = CyclicGroup(7)
>>> G = S5*C7
>>> S5.is_subgroup(G, False)
True
>>> C7.is_subgroup(G, 0)
False
is transitive(strict=True)
Test if the group is transitive.
A group is transitive if it has a single orbit.
If strict is False the group is transitive if it has a single orbit of length dierent
from 1.
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> a = Permutation([0, 2, 1, 3])
>>> b = Permutation([2, 0, 1, 3])
>>> G1 = PermutationGroup([a, b])
>>> G1.is_transitive()
False
>>> G1.is_transitive(strict=False)
True
>>> c = Permutation([2, 3, 0, 1])
>>> G2 = PermutationGroup([a, c])
>>> G2.is_transitive()
True
>>> d = Permutation([1,0,2,3])
>>> e = Permutation([0,1,3,2])
>>> G3 = PermutationGroup([d, e])
>>> G3.is_transitive() or G3.is_transitive(strict=False)
False
is trivial
Test if the group is the trivial group.
This is true if the group contains only the identity permutation.
Examples
>>> from sympy.combinatorics import Permutation
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> G = PermutationGroup([Permutation([0, 1, 2])])
>>> G.is_trivial
True
232
max div
Maximum proper divisor of the degree of a permutation group.
See Also:
minimal block (page 234), union find merge
Notes
Obviously, this is the degree divided by its minimal proper divisor (larger than 1, if
one exists). As it is guaranteed to be prime, the sieve from sympy.ntheory is used.
233
This function is also used as an optimization tool for the functions minimal block
and union find merge.
Examples
>>>
>>>
>>>
>>>
2
minimal block(points)
For a transitive group, nds the block system generated by points.
If a group G acts on a set S, a nonempty subset B of S is called a block under the
action of G if for all g in G we have gB = B (g xes B) or gB and B have no common
points (g moves B entirely). ([1], p.23; [6]).
The distinct translates gB of a block B for g in G partition the set S and this set of
translates is known as a block system. Moreover, we obviously have that all blocks
in the partition have the same size, hence the block size divides |S| ([1], p.23). A Gcongruence is an equivalence relation on the set S such that a b implies g(a)
g(b) for all g in G. For a transitive group, the equivalence classes of a G-congruence
and the blocks of a block system are the same thing ([1], p.23).
The algorithm below checks the group for transitivity, and then nds the Gcongruence generated by the pairs (p 0, p 1), (p 0, p 2), ..., (p 0,p {k-1})
which is the same as nding the maximal block system (i.e., the one with minimum
block size) such that p 0, ..., p {k-1} are in the same block ([1], p.83).
It is an implementation of Atkinsons algorithm, as suggested in [1], and manipulates
an equivalence relation on the set S using a union-nd data structure. The running
time is just above O(|points||S|). ([1], pp. 83-87; [7]).
See Also:
union find rep,
(page 230)
Examples
>>>
>>>
>>>
>>>
[0,
>>>
[0,
Parameters other :
a subgroup/list of permutations/single permutation
k:
an implementation-specic parameter that determines the number of
conjugates that are adjoined to other at once
See Also:
commutator (page 221), derived subgroup (page 225), random pr (page 238)
Notes
The algorithm is described in [1], pp. 73-74; it makes use of the generation of random elements for permutation groups by the product replacement algorithm.
Examples
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... CyclicGroup, AlternatingGroup)
>>> S = SymmetricGroup(5)
>>> C = CyclicGroup(5)
>>> G = S.normal_closure(C)
>>> G.order()
60
>>> G.is_subgroup(AlternatingGroup(5))
True
orbit(alpha, action=tuples)
Compute the orbit of alpha \{g(\alpha) | g \in G\} as a set.
The time complexity of the algorithm used here is O(|Orb|*r) where |Orb| is the size
of the orbit and r is the number of generators of the group. For a more detailed
analysis, see [1], p.78, [2], pp. 19-21. Here alpha can be a single point, or a list of
points.
If alpha is a single point, the ordinary orbit is computed. if alpha is a list of points,
there are three available options:
union - computes the union of the orbits of the points in the list tuples - computes
the orbit of the list interpreted as an ordered tuple under the group action ( i.e.,
g((1,2,3)) = (g(1), g(2), g(3)) ) sets - computes the orbit of the list interpreted as a
sets
See Also:
orbit transversal (page 236)
Examples
>>>
>>>
>>>
>>>
>>>
235
set([0, 1, 2])
>>> G.orbit([0,4], union)
set([0, 1, 2, 3, 4, 5, 6])
orbits(rep=False)
Return the orbits of self, ordered according to lowest element in each orbit.
236
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> a = Permutation(1,5)(2,3)(4,0,6)
>>> b = Permutation(1,5)(3,4)(2,6,0)
>>> G = PermutationGroup([a, b])
>>> G.orbits()
[set([0, 2, 3, 4, 6]), set([1, 5])]
order()
Return the order of the group: the number of permutations that can be generated
from elements of the group.
The number of permutations comprising the group is given by len(group); the length
of each permutation in the group is given by group.size.
See Also:
degree (page 224)
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> a = Permutation([1, 0, 2])
>>> G = PermutationGroup([a])
>>> G.degree
3
>>> len(G)
1
>>> G.order()
2
>>> list(G.generate())
[Permutation(2), Permutation(2)(0, 1)]
>>>
>>>
>>>
>>>
6
a = Permutation([0, 2, 1])
b = Permutation([1, 0, 2])
G = PermutationGroup([a, b])
G.order()
237
Notes
When incremental == True, rather than the obvious implementation using successive calls to .stabilizer(), this uses the incremental Schreier-Sims algorithm to obtain
a base with starting segment - the given points.
Examples
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(7)
>>> Stab = S.pointwise_stabilizer([2, 3, 5])
>>> Stab.is_subgroup(S.stabilizer(2).stabilizer(3).stabilizer(5))
True
random(af=False)
Return a random group element
random pr(gen count=11, iterations=50, random prec=None)
Return a random group element using product replacement.
For the details of the product replacement algorithm, see random pr init In random pr the actual product replacement is performed. Notice that if the attribute
random gens is empty, it needs to be initialized by random pr init.
See Also:
random pr init
random stab(alpha, schreier vector=None, random prec=None)
Random element from the stabilizer of alpha.
The schreier vector for alpha is an optional argument used for speeding up repeated
calls. The algorithm is described in [1], p.81
See Also:
random pr (page 238), orbit rep (page 236)
schreier sims()
Schreier-Sims algorithm.
It computes the generators of the chain of stabilizers G > G {b 1} > .. > G {b1,..,b r}
> 1 in which G {b 1,..,b i} stabilizes b 1,..,b i, and the corresponding s cosets. An
element of the group can be written as the product h 1*..*h s.
We use the incremental Schreier-Sims algorithm.
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> a = Permutation([0, 2, 1])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G.schreier_sims()
>>> G.basic_transversals
[{0: Permutation(2)(0, 1), 1: Permutation(2), 2: Permutation(1, 2)},
{0: Permutation(2), 2: Permutation(0, 2)}]
238
This version of the Schreier-Sims algorithm runs in polynomial time. There are certain assumptions in the implementation - if the trivial group is provided, base and
gens are returned immediately, as any sequence of points is a base for the trivial
group. If the identity is present in the generators gens, it is removed as it is a redundant generator. The implementation is described in [1], pp. 90-93.
Examples
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> A = AlternatingGroup(7)
>>> base = [2, 3]
>>> seq = [2, 3]
>>> base, strong_gens = A.schreier_sims_incremental(base=seq)
>>> _verify_bsgs(A, base, strong_gens)
True
>>> base[:2]
[2, 3]
consec succ=10,
The randomized Schreier-Sims algorithm takes the sequence base and the generating set gens, and extends base to a base, and gens to a strong generating set
relative to that base with probability of a wrong answer at most 2{-consec\ succ},
provided the random generators are suciently random.
Parameters base :
The sequence to be extended to a base.
gens :
5.2. Combinatorics Module
239
The algorithm is described in detail in [1], pp. 97-98. It extends the orbits orbs and
the permutation groups stabs to basic orbits and basic stabilizers for the base and
strong generating set produced in the end. The idea of the extension process is to
sift random group elements through the stabilizer chain and amend the stabilizers/orbits along the way when a sift is not successful. The helper function strip
is used to attempt to decompose a random group element according to the current
state of the stabilizer chain and report whether the element was fully decomposed
(successful sift) or not (unsuccessful sift). In the latter case, the level at which the
sift failed is reported and used to amend stabs, base, gens and orbs accordingly.
The halting condition is for consec succ consecutive successful sifts to pass. This
makes sure that the current base and gens form a BSGS with probability at least 1
- 1/\text{consec\ succ}.
Examples
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(5)
>>> base, strong_gens = S.schreier_sims_random(consec_succ=5)
>>> _verify_bsgs(S, base, strong_gens)
True
schreier vector(alpha)
Computes the schreier vector for alpha.
The Schreier vector eciently stores information about the orbit of alpha. It can
later be used to quickly obtain elements of the group that send alpha to a particular
element in the orbit. Notice that the Schreier vector depends on the order in which
the group generators are listed. For a denition, see [3]. Since list indices start from
zero, we adopt the convention to use None instead of 0 to signify that an element
doesnt belong to the orbit. For the algorithm and its correctness, see [2], pp.78-80.
See Also:
orbit (page 235)
240
Examples
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.permutations import Permutation
>>> a = Permutation([2,4,6,3,1,5,0])
>>> b = Permutation([0,1,3,5,4,6,2])
>>> G = PermutationGroup([a,b])
>>> G.schreier_vector(0)
[-1, None, 0, 1, None, 1, 0]
stabilizer(alpha)
Return the stabilizer subgroup of alpha.
The stabilizer of \alpha is the group G \alpha = \{g \in G | g(\alpha) = \alpha\}.
For a proof of correctness, see [1], p.79.
See Also:
orbit (page 235)
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> G = DihedralGroup(6)
>>> G.stabilizer(5)
PermutationGroup([
Permutation(5)(0, 4)(1, 3),
Permutation(5)])
strong gens
Return a strong generating set from the Schreier-Sims algorithm.
A generating set S = \{g 1, g 2, ..., g t\} for a permutation group G is a strong
generating set relative to the sequence of points (referred to as a base) (b 1, b 2,
..., b k) if, for 1 \leq i \leq k we have that the intersection of the pointwise
stabilizer G{(i+1)} := G {b 1, b 2, ..., b i} with S generates the pointwise
stabilizer G{(i+1)}. The concepts of a base and strong generating set and their
applications are discussed in depth in [1], pp. 87-89 and [2], pp. 55-57.
See Also:
base (page 217), basic transversals (page 220), basic orbits (page 219), basic stabilizers (page 219)
Examples
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> D = DihedralGroup(4)
>>> D.strong_gens
[Permutation(0, 1, 2, 3), Permutation(0, 3)(1, 2), Permutation(1, 3)]
>>> D.base
[0, 1]
241
subgroup search(prop,
base=None,
strong gens=None,
init subgroup=None)
Find the subgroup of all elements satisfying the property prop.
tests=None,
This is done by a depth-rst search with respect to base images that uses several
tests to prune the search tree.
Parameters prop :
The property to be used. Has to be callable on group elements and
always return True or False. It is assumed that all group elements
satisfying prop indeed form a subgroup.
base :
A base for the supergroup.
strong gens :
A strong generating set for the supergroup.
tests :
A list of callables of length equal to the length of base. These are
used to rule out group elements by partial base images, so that
tests[l](g) returns False if the element g is known not to satisfy
prop base on where g sends the rst l + 1 base points.
init subgroup :
if a subgroup of the sought group is known in advance, it can be
passed to the function as this parameter.
Returns res :
The subgroup of all elements satisfying prop. The generating set for
this group is guaranteed to be a strong generating set relative to the
base base.
Notes
This function is extremely lenghty and complicated and will require some careful
attention. The implementation is described in [1], pp. 114-117, and the comments
for the code here follow the lines of the pseudocode in the book for clarity.
The complexity is exponential in general, since the search process by itself visits
all members of the supergroup. However, there are a lot of tests which are used to
prune the search tree, and users can dene their own tests via the tests parameter,
so in practice, and for some computations, its not terrible.
A crucial part in the procedure is the frequent base change performed (this is line
11 in the pseudocode) in order to obtain a new basic stabilizer. The book mentiones
that this can be done by using .baseswap(...), however the current imlementation
uses a more straightforward way to nd the next basic stabilizer - calling the function
.stabilizer(...) on the previous basic stabilizer.
Examples
242
transitivity degree
Compute the degree of transitivity of the group.
A permutation group G acting on \Omega = \{0, 1, ..., n-1\} is k-fold transitive,
if, for any k points (a 1, a 2, ..., a k)\in\Omega and any k points (b 1, b 2,
..., b k)\in\Omega there exists g\in G such that g(a 1)=b 1, g(a 2)=b 2, ...,
g(a k)=b k The degree of transitivity of G is the maximum k such that G is k-fold
transitive. ([8])
See Also:
is transitive (page 232), orbit (page 235)
Examples
>>>
>>>
>>>
>>>
>>>
>>>
3
Polyhedron
class sympy.combinatorics.polyhedron.Polyhedron
Represents the polyhedral symmetry group (PSG).
The PSG is one of the symmetry groups of the Platonic solids. There are three polyhedral
groups: the tetrahedral group of order 12, the octahedral group of order 24, and the
icosahedral group of order 60.
All doctests have been given in the docstring of the constructor of the object.
References
http://mathworld.wolfram.com/PolyhedralGroup.html
array form
Return the indices of the corners.
The indices are given relative to the original position of corners.
See Also:
5.2. Combinatorics Module
243
>>>
>>>
[0,
>>>
[0,
tetrahedron.rotate(0)
tetrahedron.array_form
2, 3, 1]
tetrahedron.pgroup[0].array_form
2, 3, 1]
corners
Get the corners of the Polyhedron.
The method vertices is an alias for corners.
See Also:
array form (page 243), cyclic form (page 244)
Examples
>>> from sympy.combinatorics import Polyhedron
>>> from sympy.abc import a, b, c, d
>>> p = Polyhedron(list(abcd))
>>> p.corners == p.vertices == (a, b, c, d)
True
cyclic form
Return the indices of the corners in cyclic notation.
The indices are given relative to the original position of corners.
See Also:
corners (page 244), array form (page 243)
edges
Given the faces of the polyhedra we can get the edges.
Examples
>>> from sympy.combinatorics import Polyhedron
>>> from sympy.abc import a, b, c
>>> corners = (a, b, c)
>>> faces = [(0, 1, 2)]
>>> Polyhedron(corners, faces).edges
{(0, 1), (0, 2), (1, 2)}
faces
Get the faces of the Polyhedron.
244
pgroup
Get the permutations of the Polyhedron.
reset()
Return corners to their original positions.
Examples
>>>
>>>
(0,
>>>
>>>
(0,
>>>
>>>
(0,
rotate(perm)
Apply a permutation to the polyhedron in place. The permutation may be given as
a Permutation instance or an integer indicating which permutation from pgroup of
the Polyhedron should be applied.
This is an operation that is analogous to rotation about an axis by a xed increment.
Notes
When a Permutation is applied, no check is done to see if that is a valid permutation for the Polyhedron. For example, a cube could be given a permutation which
eectively swaps only 2 vertices. A valid permutation (that rotates the object in a
physical way) will be obtained if one only uses permutations from the pgroup of the
Polyhedron. On the other hand, allowing arbitrary rotations (applications of permutations) gives a way to follow named elements rather than indices since Polyhedron
allows vertices to be named while Permutation works only with indices.
Examples
>>>
>>>
>>>
(0,
>>>
>>>
(1,
cube.reset()
cube.rotate(Permutation([[1,2]], size=8))
cube.corners
2, 1, 3, 4, 5, 6, 7)
Polyhedron can be used to follow elements of set that are identied by letters instead
of integers:
245
size
Get the number of corners of the Polyhedron.
vertices
Get the corners of the Polyhedron.
The method vertices is an alias for corners.
See Also:
array form (page 243), cyclic form (page 244)
Examples
>>> from sympy.combinatorics import Polyhedron
>>> from sympy.abc import a, b, c, d
>>> p = Polyhedron(list(abcd))
>>> p.corners == p.vertices == (a, b, c, d)
True
Prufer Sequences
class sympy.combinatorics.prufer.Prufer
The Prufer correspondence is an algorithm that describes the bijection between labeled
trees and the Prufer code. A Prufer code of a labeled tree is unique up to isomorphism
and has a length of n - 2.
Prufer sequences were rst used by Heinz Prufer to give a proof of Cayleys formula.
References
246
Examples
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer.edges([1, 2, 3], [2, 4, 5]) # a T
([[0, 1], [1, 2], [1, 3], [3, 4]], 5)
next(delta=1)
Generates the Prufer sequence that is delta beyond the current one.
See Also:
prufer rank (page 248), rank (page 248), prev (page 247), size (page 248)
Examples
>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [0, 2], [0, 3]])
>>> b = a.next(1) # == a.next()
>>> b.tree_repr
[[0, 2], [0, 1], [1, 3]]
>>> b.rank
1
nodes
Returns the number of nodes in the tree.
Examples
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]).nodes
6
>>> Prufer([1, 0, 0]).nodes
5
prev(delta=1)
Generates the Prufer sequence that is -delta before the current one.
See Also:
prufer rank (page 248), rank (page 248), next (page 247), size (page 248)
Examples
>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [1, 2], [2, 3], [1, 4]])
>>> a.rank
36
>>> b = a.prev()
>>> b
Prufer([1, 2, 0])
247
>>> b.rank
35
prufer rank()
Computes the rank of a Prufer sequence.
See Also:
rank (page 248), next (page 247), prev (page 247), size (page 248)
Examples
>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [0, 2], [0, 3]])
>>> a.prufer_rank()
0
prufer repr
Returns Prufer sequence for the Prufer object.
This sequence is found by removing the highest numbered vertex, recording the
node it was attached to, and continuuing until only two verices remain. The Prufer
sequence is the list of recorded nodes.
See Also:
to prufer (page 249)
Examples
>>>
>>>
[3,
>>>
[1,
rank
Returns the rank of the Prufer sequence.
See Also:
prufer rank (page 248), next (page 247), prev (page 247), size (page 248)
Examples
>>>
>>>
>>>
778
>>>
779
>>>
777
size
Return the number of possible trees of this Prufer object.
248
See Also:
prufer rank (page 248), rank (page 248), next (page 247), prev (page 247)
Examples
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([0]*4).size == Prufer([6]*4).size == 1296
True
static to prufer(tree, n)
Return the Prufer sequence for a tree given as a list of edges where n is the number
of nodes in the tree.
See Also:
prufer repr (page 248) returns Prufer sequence of a Prufer object.
Examples
>>>
>>>
>>>
[0,
>>>
[0,
static to tree(prufer)
Return the tree (as a list of edges) of the given Prufer sequence.
See Also:
tree repr (page 249) returns tree representation of a Prufer object.
References
http://hamberg.no/erlend/posts/2010-11-06-prufer-sequence-compact-treerepresentation.html
Examples
>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([0, 2], 4)
>>> a.tree_repr
[[0, 1], [0, 2], [2, 3]]
>>> Prufer.to_tree([0, 2])
[[0, 1], [0, 2], [2, 3]]
tree repr
Returns the tree representation of the Prufer object.
See Also:
to tree (page 249)
249
Examples
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]).tree_repr
[[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]
>>> Prufer([1, 0, 0]).tree_repr
[[1, 2], [0, 1], [0, 3], [0, 4]]
classmethod unrank(rank, n)
Finds the unranked Prufer sequence.
Examples
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer.unrank(0, 4)
Prufer([0, 0])
Subsets
class sympy.combinatorics.subsets.Subset
Represents a basic subset object.
We generate subsets using essentially two techniques, binary enumeration and lexicographic enumeration. The Subset class takes two arguments, the rst one describes the
initial subset to consider and the second describes the superset.
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([c,d], [a,b,c,d])
>>> a.next_binary().subset
[b]
>>> a.prev_binary().subset
[c]
cardinality
Returns the number of all possible subsets.
See Also:
250
subset (page 254), superset (page 255), size (page 254), superset size
(page 255)
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([c,d], [a,b,c,d])
>>> a.cardinality
16
iterate binary(k)
This is a helper function. It iterates over the binary subsets by k steps. This variable
can be both positive or negative.
See Also:
next binary (page 251), prev binary (page 252)
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([c,d], [a,b,c,d])
>>> a.iterate_binary(-2).subset
[d]
>>> a = Subset([a,b,c], [a,b,c,d])
>>> a.iterate_binary(2).subset
[]
iterate graycode(k)
Helper function used for prev gray and next gray. It performs k step overs to get
the respective Gray codes.
See Also:
next gray (page 252), prev gray (page 253)
Examples
>>>
>>>
>>>
[1,
>>>
[1,
next binary()
Generates the next binary ordered subset.
See Also:
prev binary (page 252), iterate binary (page 251)
251
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([c,d], [a,b,c,d])
>>> a.next_binary().subset
[b]
>>> a = Subset([a,b,c,d], [a,b,c,d])
>>> a.next_binary().subset
[]
next gray()
Generates the next Gray code ordered subset.
See Also:
iterate graycode (page 251), prev gray (page 253)
Examples
>>>
>>>
>>>
[1,
next lexicographic()
Generates the next lexicographically ordered subset.
See Also:
prev lexicographic (page 253)
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([c,d], [a,b,c,d])
>>> a.next_lexicographic().subset
[d]
>>> a = Subset([d], [a,b,c,d])
>>> a.next_lexicographic().subset
[]
prev binary()
Generates the previous binary ordered subset.
See Also:
next binary (page 251), iterate binary (page 251)
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([], [a,b,c,d])
>>> a.prev_binary().subset
[a, b, c, d]
>>> a = Subset([c,d], [a,b,c,d])
252
>>> a.prev_binary().subset
[c]
prev gray()
Generates the previous Gray code ordered subset.
See Also:
iterate graycode (page 251), next gray (page 252)
Examples
>>>
>>>
>>>
[2,
prev lexicographic()
Generates the previous lexicographically ordered subset.
See Also:
next lexicographic (page 252)
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([], [a,b,c,d])
>>> a.prev_lexicographic().subset
[d]
>>> a = Subset([c,d], [a,b,c,d])
>>> a.prev_lexicographic().subset
[c]
rank binary
Computes the binary ordered rank.
See Also:
iterate binary (page 251), unrank binary (page 255)
Examples
>>>
>>>
>>>
0
>>>
>>>
3
rank gray
Computes the Gray code ranking of the subset.
See Also:
iterate graycode (page 251), unrank gray (page 256)
5.2. Combinatorics Module
253
Examples
>>>
>>>
>>>
2
>>>
>>>
27
rank lexicographic
Computes the lexicographic ranking of the subset.
Examples
>>>
>>>
>>>
14
>>>
>>>
43
size
Gets the size of the subset.
See Also:
subset (page 254), superset (page 255), superset size (page 255), cardinality
(page 250)
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([c,d], [a,b,c,d])
>>> a.size
2
subset
Gets the subset represented by the current instance.
See Also:
superset (page 255), size (page 254), superset size (page 255), cardinality
(page 250)
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([c,d], [a,b,c,d])
>>> a.subset
[c, d]
254
superset
Gets the superset of the subset.
See Also:
subset (page 254), size (page 254), superset size (page 255), cardinality
(page 250)
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([c,d], [a,b,c,d])
>>> a.superset
[a, b, c, d]
superset size
Returns the size of the superset.
See Also:
subset (page 254), superset (page 255), size (page 254), cardinality (page 250)
Examples
>>> from sympy.combinatorics.subsets import Subset
>>> a = Subset([c,d], [a,b,c,d])
>>> a.superset_size
4
255
static subsets.ksubsets(superset, k)
Finds the subsets of size k in lexicographic order.
This uses the itertools generator.
See Also:
class Subset
Examples
>>> from sympy.combinatorics.subsets import ksubsets
>>> list(ksubsets([1,2,3], 2))
[(1, 2), (1, 3), (2, 3)]
>>> list(ksubsets([1,2,3,4,5], 2))
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4),
(2, 5), (3, 4), (3, 5), (4, 5)]
Gray Code
class sympy.combinatorics.graycode.GrayCode
A Gray code is essentially a Hamiltonian walk on a n-dimensional cube with edge length
of one. The vertices of the cube are represented by vectors whose values are binary.
The Hamilton walk visits each vertex exactly once. The Gray code for a 3d cube is
[000,100,110,010,011,111,101, 001].
A Gray code solves the problem of sequentially generating all possible subsets of n objects in such a way that each subset is obtained from the previous one by either deleting
256
or adding a single object. In the above example, 1 indicates that the object is present,
and 0 indicates that its absent.
Gray codes have applications in statistics as well when we want to compute various
statistics related to subsets in an ecient manner.
References: [1] Nijenhuis,A. and Wilf,H.S.(1978). Combinatorial Algorithms. Academic
Press. [2] Knuth, D. (2011). The Art of Computer Programming, Vol 4 Addison Wesley
Examples
>>> from sympy.combinatorics.graycode import GrayCode
>>> a = GrayCode(3)
>>> list(a.generate_gray())
[000, 001, 011, 010, 110, 111, 101, 100]
>>> a = GrayCode(4)
>>> list(a.generate_gray())
[0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100,
current
Returns the currently referenced Gray code as a bit string.
Examples
>>> from sympy.combinatorics.graycode import GrayCode
>>> GrayCode(3, start=100).current
100
generate gray(**hints)
Generates the sequence of bit vectors of a Gray Code.
[1] Knuth, D. (2011). The Art of Computer Programming, Vol 4, Addison Wesley
See Also:
skip (page 258)
Examples
>>> from sympy.combinatorics.graycode import GrayCode
>>> a = GrayCode(3)
>>> list(a.generate_gray())
[000, 001, 011, 010, 110, 111, 101, 100]
>>> list(a.generate_gray(start=011))
[011, 010, 110, 111, 101, 100]
>>> list(a.generate_gray(rank=4))
[110, 111, 101, 100]
n
Returns the dimension of the Gray code.
257
Examples
>>> from sympy.combinatorics.graycode import GrayCode
>>> a = GrayCode(5)
>>> a.n
5
next(delta=1)
Returns the Gray code a distance delta (default = 1) from the current value in
canonical order.
Examples
>>> from sympy.combinatorics.graycode import GrayCode
>>> a = GrayCode(3, start=110)
>>> a.next().current
111
>>> a.next(-1).current
010
rank
Ranks the Gray code.
A ranking algorithm determines the position (or rank) of a combinatorial object
among all the objects w.r.t. a given order. For example, the 4 bit binary reected
Gray code (BRGC) 0101 has a rank of 6 as it appears in the 6th position in the
canonical ordering of the family of 4 bit Gray codes.
References: [1] http://statweb.stanford.edu/susan/courses/s208/node12.html
See Also:
unrank (page 259)
Examples
>>> from sympy.combinatorics.graycode import GrayCode
>>> a = GrayCode(3)
>>> list(a.generate_gray())
[000, 001, 011, 010, 110, 111, 101, 100]
>>> GrayCode(3, start=100).rank
7
>>> GrayCode(3, rank=7).current
100
selections
Returns the number of bit vectors in the Gray code.
Examples
>>> from sympy.combinatorics.graycode import GrayCode
>>> a = GrayCode(3)
>>> a.selections
8
258
skip()
Skips the bit generation.
See Also:
generate gray (page 257)
Examples
>>> from sympy.combinatorics.graycode import GrayCode
>>> a = GrayCode(3)
>>> for i in a.generate_gray():
...
if i == 010:
...
a.skip()
...
print(i)
...
000
001
011
010
111
101
100
259
260
Named Groups
sympy.combinatorics.named groups.SymmetricGroup(n)
Generates the symmetric group on n elements as a permutation group.
The generators taken are the n-cycle (0 1 2 ... n-1) and the transposition (0 1) (in
cycle notation). (See [1]). After the group is generated, some of its basic properties are
set.
See Also:
CyclicGroup (page 261), DihedralGroup (page 261), AlternatingGroup (page 262)
References
sympy.combinatorics.named groups.CyclicGroup(n)
Generates the cyclic group of order n as a permutation group.
The generator taken is the n-cycle (0 1 2 ... n-1) (in cycle notation). After the group
is generated, some of its basic properties are set.
See Also:
SymmetricGroup (page 261), DihedralGroup (page 261), AlternatingGroup (page 262)
Examples
>>> from sympy.combinatorics.named_groups import CyclicGroup
>>> G = CyclicGroup(6)
>>> G.is_group()
False
>>> G.order()
6
>>> list(G.generate_schreier_sims(af=True))
[[0, 1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 0], [2, 3, 4, 5, 0, 1],
[3, 4, 5, 0, 1, 2], [4, 5, 0, 1, 2, 3], [5, 0, 1, 2, 3, 4]]
261
sympy.combinatorics.named groups.DihedralGroup(n)
Generates the dihedral group Dn as a permutation group.
The dihedral group Dn is the group of symmetries of the regular n-gon. The generators
taken are the n-cycle a = (0 1 2 ... n-1) (a rotation of the n-gon) and b = (0 n-1)(1
n-2)... (a reection of the n-gon) in cycle rotation. It is easy to see that these satisfy
a**n = b**2 = 1 and bab = a so they indeed generate Dn (See [1]). After the group is
generated, some of its basic properties are set.
See Also:
SymmetricGroup (page 261), CyclicGroup (page 261), AlternatingGroup (page 262)
References
sympy.combinatorics.named groups.AlternatingGroup(n)
Generates the alternating group on n elements as a permutation group.
For n > 2, the generators taken are (0 1 2), (0 1 2 ... n-1) for n odd and (0 1 2),
(1 2 ... n-1) for n even (See [1], p.31, ex.6.9.). After the group is generated, some of
its basic properties are set. The cases n = 1, 2 are handled separately.
See Also:
SymmetricGroup (page 261), CyclicGroup (page 261), DihedralGroup (page 261)
References
262
Utilities
sympy.combinatorics.util. base ordering(base, degree)
Order {0, 1, ..., n 1} so that base points come rst and in order.
Parameters base - the base :
degree - the degree of the associated permutation group :
Returns A list base ordering such that base ordering[point] is the
:
number of point in the ordering. :
Examples :
======== :
>>> from sympy.combinatorics.named groups import SymmetricGroup :
>>> from sympy.combinatorics.util import base ordering :
>>> S = SymmetricGroup(4) :
>>> S.schreier sims() :
>>> base ordering(S.base, S.degree) :
[0, 1, 2, 3] :
263
Notes
This is used in backtrack searches, when we dene a relation << on the underlying set
for a permutation group of degree n, {0, 1, ..., n 1}, so that if (b1 , b2 , ..., bk ) is a base we
have bi << bj whenever i < j and bi << a for all i {1, 2, ..., k} and a is not in the base. The
idea is developed and applied to backtracking algorithms in [1], pp.108-132. The points
that are not in the base are taken in increasing order.
References
[1] Holt, D., Eick, B., OBrien, E. Handbook of computational group theory
sympy.combinatorics.util. check cycles alt sym(perm)
Checks for cycles of prime length p with n/2 < p < n-2.
Here n is the degree of the permutation. This is a helper function for the function
is alt sym from sympy.combinatorics.perm groups.
See Also:
sympy.combinatorics.perm groups.PermutationGroup.is alt sym (page 228)
Examples
>>> from sympy.combinatorics.util import _check_cycles_alt_sym
>>> from sympy.combinatorics.permutations import Permutation
>>> a = Permutation([[0,1,2,3,4,5,6,7,8,9,10], [11, 12]])
>>> _check_cycles_alt_sym(a)
False
>>> b = Permutation([[0,1,2,3,4,5,6], [7,8,9,10]])
>>> _check_cycles_alt_sym(b)
True
264
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> from sympy.combinatorics.util import _distribute_gens_by_base
>>> D = DihedralGroup(3)
>>> D.schreier_sims()
>>> D.strong_gens
[Permutation(0, 1, 2), Permutation(0, 2), Permutation(1, 2)]
>>> D.base
[0, 1]
>>> _distribute_gens_by_base(D.base, D.strong_gens)
[[Permutation(0, 1, 2), Permutation(0, 2), Permutation(1, 2)],
[Permutation(1, 2)]]
basic orbits,
where
are the basic transversals, basic orbits are the basic orbits, and :
strong gens distr are the strong generators distributed by membership :
in basic stabilizers. :
See Also:
orbits transversals from bsgs (page 266), distribute gens by base
Examples
>>>
>>>
>>>
>>>
>>>
>>>
265
266
stabilizers :
Returns A strong generating set with respect to base which is a subset of :
strong gens. :
Notes
[1] Holt, D., Eick, B., OBrien, E. Handbook of computational group theory
Examples
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.util import _remove_gens
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> S = SymmetricGroup(15)
>>> base, strong_gens = S.schreier_sims_incremental()
>>> len(strong_gens)
26
>>> new_gens = _remove_gens(base, strong_gens)
>>> len(new_gens)
14
>>> _verify_bsgs(S, base, new_gens)
True
267
238),
Notes
The algorithm is described in [1],pp.89-90. The reason for returning both the current
state of the element being decomposed and the level at which the sifting ends is that
they provide important information for the randomized version of the Schreier-Sims algorithm.
References
[1] Holt, D., Eick, B., OBrien, E. Handbook of computational group theory
Examples
>>> from sympy.combinatorics import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.util import _strip
>>> S = SymmetricGroup(5)
>>> S.schreier_sims()
>>> g = Permutation([0, 2, 3, 1, 4])
>>> _strip(g, S.base, S.basic_orbits, S.basic_transversals)
(Permutation(4), 5)
268
... _distribute_gens_by_base)
>>> S = SymmetricGroup(3)
>>> S.schreier_sims()
>>> S.strong_gens
[Permutation(0, 1, 2), Permutation(2)(0, 1), Permutation(1, 2)]
>>> strong_gens_distr = _distribute_gens_by_base(S.base, S.strong_gens)
>>> _strong_gens_from_distr(strong_gens_distr)
[Permutation(0, 1, 2), Permutation(2)(0, 1), Permutation(1, 2)]
Group constructors
sympy.combinatorics.group constructs.DirectProduct(*groups)
Returns the direct product of several groups as a permutation group.
This is implemented much like the mul procedure for taking the direct product of two
permutation groups, but the idea of shifting the generators is realized in the case of an
arbitrary number of groups. A call to DirectProduct(G1, G2, ..., Gn) is generally expected
to be faster than a call to G1*G2*...*Gn (and thus the need for this algorithm).
See Also:
mul
Examples
>>>
>>>
>>>
>>>
>>>
64
Test Utilities
sympy.combinatorics.testutil. cmp perm lists(rst, second)
Compare two lists of permutations as sets.
This is used for testing purposes. Since the array form of a permutation is currently a
list, Permutation is not hashable and cannot be put into a set.
Examples
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.testutil import _cmp_perm_lists
>>> a = Permutation([0, 2, 3, 4, 1])
>>> b = Permutation([1, 2, 0, 4, 3])
>>> c = Permutation([3, 4, 0, 1, 2])
>>> ls1 = [a, b, c]
>>> ls2 = [b, c, a]
>>> _cmp_perm_lists(ls1, ls2)
True
269
two types of indices [a, b, c, d, e, f ] and [m, n], in this order, both with commuting metric
f abc antisymmetric, commuting
271
Algorithm
First one uses canonical free to get the minimum tensor under lexicographic order, using only the slot symmetries. If the component tensors have not minimal BSGS, it is
attempted to nd it; if the attempt fails canonicalize naive is used instead.
Compute the residual slot symmetry keeping xed the free indices using tensor gens(base, gens, list free indices, sym).
Reduce the problem eliminating the free indices.
Then use double coset can rep and lift back the result reintroducing the free indices.
sympy.combinatorics.tensor can.double coset can rep(dummies, sym, b S, sgens,
S transversals, g)
Butler-Portugal algorithm for tensor canonicalization with dummy indices
dummies list of lists of dummy indices, one list for each type of index; the
dummy indices are put in order contravariant, covariant [d0, -d0, d1, -d1,
...].
sym list of the symmetries of the index metric for each type.
possible symmetries of the metrics
0 symmetric
1 antisymmetric
None no symmetry
tensors with many indices are equal becomes computationally very slow in absence of
an ecient algorithm.
The Butler-Portugal algorithm [3] is an ecient algorithm to put tensors in canonical
form, solving the above problem.
Portugal observed that a tensor can be represented by a permutation, and that the class
of tensors equivalent to it under slot and dummy symmetries is equivalent to the double
coset D g S (Note: in this documentation we use the conventions for multiplication
of permutations p, q with (p*q)(i) = p[q[i]] which is opposite to the one used in the
Permutation class)
Using the algorithm by Butler to nd a representative of the double coset one can nd a
canonical form for the tensor.
To see this correspondence, let g be a permutation in array form; a tensor with indices
ind (the indices including both the contravariant and the covariant ones) can be written
as
t = T (ind[g[0], ..., ind[g[n 1]]),
where n = len(ind); g has size n + 2, the last two indices for the sign of the tensor (trick
introduced in [4]).
A slot symmetry transformation s is a permutation acting on the slots t > T (ind[(g
s)[0]], ..., ind[(g s)[n 1]])
A dummy symmetry transformation acts on ind t > T (ind[(d g)[0]], ..., ind[(d g)[n 1]])
Being interested only in the transformations of the tensor under these symmetries, one
can represent the tensor by g, which transforms as
g > d g s, so it belongs to the coset D g S.
Let us explain the conventions by an example.
Given a tensor T d3d2d1 d1d2d3 with the slot symmetries T a0a1a2a3a4a5 = T a2a1a0a3a4a5
T a0a1a2a3a4a5 = T a4a1a2a3a0a5
and symmetric metric, nd the tensor equivalent to it which is the lowest under the
ordering of indices: lexicographic ordering d1, d2, d3 then and contravariant index before
covariant index; that is the canonical form of the tensor.
The canonical form is T d1d2d3 d1d2d3 obtained using T a0a1a2a3a4a5 = T a2a1a0a3a4a5 .
To convert this problem in the input for this function, use the following labelling of the
index names (- for covariant for short) d1, d1, d2, d2, d3, d3
T d3d2d1 d1d2d3 corresponds to g = [4, 2, 0, 1, 3, 5, 6, 7] where the last two indices are for the sign
sgens = [P ermutation(0, 2)(6, 7), P ermutation(0, 4)(6, 7)]
sgens[0] is the slot symmetry (0, 2) T a0a1a2a3a4a5 = T a2a1a0a3a4a5
sgens[1] is the slot symmetry (0, 4) T a0a1a2a3a4a5 = T a4a1a2a3a0a5
The dummy symmetry group D is generated by the strong base generators
[(0, 1), (2, 3), (4, 5), (0, 1)(2, 3), (2, 3)(4, 5)]
The dummy symmetry acts from the left d = [1, 0, 2, 3, 4, 5, 6, 7] exchange d1 > d1
T d3d2d1 d1d2d3 == T d3d2 d1 d1 d2d3
g = [4, 2, 0, 1, 3, 5, 6, 7] > [4, 2, 1, 0, 3, 5, 6, 7] =a fr mul(d, g) which diers from a fr mul(g, d).
The slot symmetry acts from the right s = [2, 1, 0, 3, 4, 5, 7, 6] exchanges slots 0 and 2 and
changes sign T d3d2d1 d1d2d3 == T d1d2d3 d1d2d3
273
274
This algorithm diers slightly from the original algorithm [3]: the
canonical
form is minimal lexicographically, and the BSGS has minimal base under lexicographic order. Equal tensors h are eliminated from TAB.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
[0,
>>> g = Permutation([4,1,3,0,5,2,6,7])
>>> double_coset_can_rep([list(range(6))], [0], base, gens, transversals, g)
0
275
extend(n)
Grow the sieve to cover all primes <= n (a real number).
Examples
>>> from sympy import sieve
>>> from array import array # this line and next for doctest only
>>> sieve._list = array(l, [2, 3, 5, 7, 11, 13])
>>> sieve.extend(30)
>>> sieve[10] == 29
True
extend to no(i)
Extend to include the ith prime number.
i must be an integer.
The list is extended by 50% if it is too short, so it is likely that it will be longer than
requested.
Examples
>>> from sympy import sieve
>>> from array import array # this line and next for doctest only
>>> sieve._list = array(l, [2, 3, 5, 7, 11, 13])
>>> sieve.extend_to_no(9)
>>> sieve._list
array(l, [2, 3, 5, 7, 11, 13, 17, 19, 23])
primerange(a, b)
Generate all prime numbers in the range [a, b).
276
Examples
>>> from sympy import sieve
>>> print([i for i in sieve.primerange(7, 18)])
[7, 11, 13, 17]
search(n)
Return the indices i, j of the primes that bound n.
If n is prime then i == j.
Although n can be an expression, if ceiling cannot convert it to an integer then an n
error will be raised.
Examples
>>>
>>>
(9,
>>>
(9,
http://primes.utm.edu/glossary/xpage/BertrandsPostulate.html
Examples
>>> from sympy import prime
>>> prime(10)
29
>>> prime(1)
2
sympy.ntheory.generate.primepi(n)
Return the value of the prime counting function pi(n) = the number of prime numbers
less than or equal to n.
See Also:
277
sympy.ntheory.generate.nextprime(n, ith=1)
Return the ith prime greater than n.
i must be an integer.
See Also:
prevprime (page 278) Return the largest prime smaller than n
primerange (page 278) Generate all primes in a given range
Notes
Potential primes are located at 6*j +/- 1. This property is used during searching.
>>> from sympy import nextprime
>>> [(i, nextprime(i)) for i in range(10, 15)]
[(10, 11), (11, 13), (12, 13), (13, 17), (14, 17)]
>>> nextprime(2, ith=2) # the 2nd prime after 2
5
sympy.ntheory.generate.prevprime(n)
Return the largest prime smaller than n.
See Also:
nextprime (page 278) Return the ith prime greater than n
primerange (page 278) Generates all primes in a given range
Notes
Potential primes are located at 6*j +/- 1. This property is used during searching.
>>> from sympy import prevprime
>>> [(i, prevprime(i)) for i in range(10, 15)]
[(10, 7), (11, 7), (12, 11), (13, 11), (14, 13)]
sympy.ntheory.generate.primerange(a, b)
Generate a list of all prime numbers in the range [a, b).
If the range exists in the default sieve, the values will be returned from there; otherwise
values will be returned but will not modify the sieve.
See Also:
nextprime (page 278) Return the ith prime greater than n
278
Some famous conjectures about the occurence of primes in a given range are [1]:
Twin primes: though often not, the following will give 2 primes
The average gap between primes is log(n) [2]; the gap between primes can be arbitrarily
large since sequences of composite numbers are arbitrarily large, e.g. the numbers in
the sequence n! + 2, n! + 3 ... n! + n are all composite.
References
1.http://en.wikipedia.org/wiki/Prime number
2.http://primes.utm.edu/notes/gaps.html
Examples
>>> from sympy import primerange, sieve
>>> print([i for i in primerange(1, 30)])
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
The Sieve method, primerange, is generally faster but it will occupy more memory as
the sieve stores values. The default instance of Sieve, named sieve, can be used:
>>> list(sieve.primerange(1, 30))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
sympy.ntheory.generate.randprime(a, b)
Return a random prime number in the range [a, b).
Bertrands postulate assures that randprime(a, 2*a) will always succeed for a > 1.
See Also:
primerange (page 278) Generate all primes in a given range
279
References
http://en.wikipedia.org/wiki/Bertrands postulate
Examples
>>> from sympy import randprime, isprime
>>> randprime(1, 30)
13
>>> isprime(randprime(1, 30))
True
sympy.ntheory.generate.primorial(n, nth=True)
Returns the product of the rst n primes (default) or the primes less than or equal to n
(when nth=False).
>>>
>>>
>>>
210
>>>
6
>>>
2
>>>
1
>>>
210
One can argue that the primes are innite since if you take a set of primes and multiply
them together (e.g. the primorial) and then add or subtract 1, the result cannot be
divided by any of the original factors, hence either 1 or more new primes must divide
this product of primes.
In this case, the number itself is a new prime:
>>> factorint(primorial(4) + 1)
{211: 1}
Here, some primes smaller and larger than the primes multiplied together are obtained:
>>> p = list(primerange(10, 20))
>>> sorted(set(primefactors(Mul(*p) + 1)).difference(set(p)))
[2, 5, 31, 149]
See Also:
primerange (page 278) Generate all primes in a given range
sympy.ntheory.generate.cycle length(f, x0, nmax=None, values=False)
For a given iterated sequence, return a generator that gives the length of the iterated
cycle (lambda) and the length of terms before the cycle begins (mu); if values is True
280
then the terms of the sequence will be returned instead. The sequence is started with
value x0.
Note: more than the rst lambda + mu terms may be returned and this is the cost of
cycle detection with Brents method; there are, however, generally less terms calculated
than would have been calculated if the proper ending point were determined, e.g. by
using Floyds method.
>>> from sympy.ntheory.generate import cycle_length
A function is dened:
>>> func = lambda i: (i**2 + 1) % 51
281
See Also:
factorint (page 287), smoothness p (page 282)
sympy.ntheory.factor .smoothness p(n, m=-1, power=0, visual=None)
Return a list of [m, (p, (M, sm(p + m), psm(p + m)))...] where:
1.p**M is the base-p divisor of n
2.sm(p + m) is the smoothness of p + m (m = -1 by default)
3.psm(p + m) is the power smoothness of p + m
The list is sorted according to smoothness (default) or by power smoothness if power=1.
The smoothness of the numbers to the left (m = -1) or right (m = 1) of a factor govern
the results that are obtained from the p +/- 1 type factoring methods.
>>> from sympy.ntheory.factor_ import smoothness_p, factorint
>>> smoothness_p(10431, m=1)
(1, [(3, (2, 2, 4)), (19, (1, 5, 5)), (61, (1, 31, 31))])
>>> smoothness_p(10431)
(-1, [(3, (2, 2, 2)), (19, (1, 3, 9)), (61, (1, 5, 5))])
>>> smoothness_p(10431, power=1)
(-1, [(3, (2, 2, 2)), (61, (1, 5, 5)), (19, (1, 3, 9))])
This string can also be generated directly from a factorization dictionary and vice versa:
>>> factorint(17*9)
{3: 2, 17: 1}
>>> smoothness_p(_)
p**i=3**2 has p-1 B=2, B-pow=2\np**i=17**1 has p-1 B=2, B-pow=16
>>> smoothness_p(_)
{3: 2, 17: 1}
Input
dict
str
tuple
n
mul
True
str
str
str
str
str
False
tuple
tuple
tuple
tuple
tuple
other
str
dict
str
tuple
tuple
See Also:
factorint (page 287), smoothness (page 281)
sympy.ntheory.factor .trailing(n)
Count the number of trailing zero digits in the binary representation of n, i.e. determine
the largest power of 2 that divides n.
282
Examples
>>> from sympy import trailing
>>> trailing(128)
7
>>> trailing(63)
0
sympy.ntheory.factor .multiplicity(p, n)
Find the greatest integer m such that p**m divides n.
Examples
>>>
>>>
>>>
[0,
>>>
-2
283
For a given function, very dierent leader-loop values can be obtained so it is a good
idea to allow for retries:
>>> from sympy.ntheory.generate import cycle_length
>>> n = 16843009
>>> F = lambda x:(2048*pow(x, 2, n) + 32767) % n
>>> for s in range(5):
...
print(loop length = %4i; leader length = %3i % next(cycle_length(F, s)))
...
loop length = 2489; leader length = 42
loop length =
78; leader length = 120
loop length = 1482; leader length = 99
loop length = 1482; leader length = 285
loop length = 1482; leader length = 100
Instead of checking the dierences of all generated values for a gcd with n, only the kth
and 2*kth numbers are checked, e.g. 1st and 2nd, 2nd and 4th, 3rd and 6th until it has
been detected that the loop has been traversed. Loops may be many thousands of steps
long before rho nds a factor or reports failure. If max steps is specied, the iteration
is cancelled with a failure after the specied number of steps.
References
Richard Crandall & Carl Pomerance (2005), Prime Numbers: A Computational Perspective, Springer, 2nd edition, 229-231
Examples
>>>
>>>
>>>
>>>
257
284
If retries is > 0 then perhaps the problem will correct itself when new values are generated for a:
>>> pollard_rho(n, a=n-2, retries=1)
257
But if the value of a is changed we nd that only multiples of 257 work, e.g.:
>>> pollard_pm1(n, B=256, a=257)
1009
Checking dierent a values shows that all the ones that didnt work had a gcd value not
equal to n but equal to one of the factors:
>>> from sympy.core.numbers import ilcm, igcd
>>> from sympy import factorint, Pow
>>> M = 1
>>> for i in range(2, 256):
...
M = ilcm(M, i)
...
>>> set([igcd(pow(a, M, n) - 1, n) for a in range(2, 256) if
...
igcd(pow(a, M, n) - 1, n) != n])
set([1009])
285
No, only one of them. So perhaps the principle is that a root will be found for a given
value of B provided that:
1.the power smoothness of the p - 1 value next to the root does not exceed B
2.a**M % p != 1 for any of the divisors of n.
By trying more than one a it is possible that one of them will yield a factor.
References
Richard Crandall & Carl Pomerance (2005), Prime Numbers: A Computational Perspective, Springer, 2nd edition, 236-238
http://modular.math.washington.edu/edu/2007/spring/ent/ent-html/node81.html
http://www.cs.toronto.edu/yuvalf/Factorization.pdf
Examples
The B and B-pow are the same for the p - 1 factorizations of the divisors because those
factorizations had a very large prime factor:
>>>
{2:
>>>
{2:
factorint(4410317 - 1)
2, 617: 1, 1787: 1}
factorint(4869863-1)
1, 2434931: 1}
Note that until B reaches the B-pow value of 1787, the number is not cracked;
>>> pollard_pm1(21477639576571, B=1786)
>>> pollard_pm1(21477639576571, B=1787)
4410317
286
The B value has to do with the factors of the number next to the divisor, not the divisors themselves. A worst case scenario is that the number next to the factor p has a
large prime divisisor or is a perfect power. If these conditions apply then the powersmoothness will be about p/2 or p. The more realistic is that there will be a large prime
factor next to p requiring a B value on the order of p/2. Although primes may have been
searched for up to this level, the p/2 is a factor of p - 1, something that we dont know.
The modular.math reference below states that 15% of numbers in the range of 10**15
to 15**15 + 10**4 are 10**6 power smooth so a B of 10**6 will fail 85% of the time in
that range. From 10**8 to 10**8 + 10**3 the percentages are nearly reversed...but in
that range the simple trial division is quite fast.
sympy.ntheory.factor .factorint(n, limit=None, use trial=True, use rho=True,
use pm1=True, verbose=False, visual=None)
Given a positive integer n, factorint(n) returns a dict containing the prime factors of
n as keys and their respective multiplicities as values. For example:
>>> from sympy.ntheory import factorint
>>> factorint(2000)
# 2000 = (2**4) * (5**3)
{2: 4, 5: 3}
>>> factorint(65537)
# This number is prime
{65537: 1}
Partial Factorization:
If limit (> 3) is specied, the search is stopped after performing trial division up to (and
including) the limit (or taking a corresponding number of rho/p-1 steps). This is useful if
one has a large number and only is interested in nding small factors (if any). Note that
setting a limit does not prevent larger factors from being found early; it simply means
that the largest factor may be composite. Since checking for perfect power is relatively
cheap, it is done regardless of the limit setting.
This number, for example, has two small factors and a huge semi-prime factor that cannot
be reduced easily:
>>> from sympy.ntheory import isprime
>>> from sympy.core.compatibility import long
>>> a = 1407633717262338957430697921446883
>>> f = factorint(a, limit=10000)
>>> f == {991: 1, long(202916782076162456022877024859): 1, 7: 1}
True
>>> isprime(max(f))
False
This number has a small factor and a residual perfect power whose base is greater than
the limit:
>>> factorint(3*101**7, limit=5)
{3: 1, 101: 7}
Visual Factorization:
If visual is set to True, then it will return a visual factorization of the integer. For
example:
287
Note that this is achieved by using the evaluate=False ag in Mul and Pow. If you do other
manipulations with an expression where evaluate=False, it may evaluate. Therefore, you
should use the visual option only for visualization, and use the normal dictionary returned
by visual=False if you want to perform operations on the factors.
You can easily switch between the two forms by sending them back to factorint:
>>> from sympy import Mul, Pow
>>> regular = factorint(1764); regular
{2: 2, 3: 2, 7: 2}
>>> pprint(factorint(regular))
2 2 2
2 *3 *7
>>> visual = factorint(1764, visual=True); pprint(visual)
2 2 2
2 *3 *7
>>> print(factorint(visual))
{2: 2, 3: 2, 7: 2}
If you want to send a number to be factored in a partially factored form you can do so
with a dictionary or unevaluated expression:
>>>
{2:
>>>
{2:
True
mul
mul
mul
False
dict
dict
dict
other
mul
dict
dict
See Also:
smoothness (page 281), smoothness p (page 282), divisors (page 289)
Notes
Algorithm:
The function switches between multiple algorithms. Trial division quickly nds small
factors (of the order 1-5 digits), and nds all large factors if given enough time. The
Pollard rho and p-1 algorithms are used to nd large factors ahead of time; they will
often nd factors of the order of 10 digits within a few seconds:
>>> factors = factorint(12345678910111213141516)
>>> for base, exp in sorted(factors.items()):
...
print(%s %s % (base, exp))
...
2 2
288
2507191691 1
1231026625769 1
Any of these methods can optionally be disabled with the following boolean parameters:
use trial: Toggle use of trial division
use rho: Toggle use of Pollards rho method
use pm1: Toggle use of Pollards p-1 method
factorint also periodically checks if the remaining part is a prime number or a perfect
power, and in those cases stops.
If verbose is set to True, detailed progress is printed.
sympy.ntheory.factor .primefactors(n, limit=None, verbose=False)
Return a sorted list of ns prime factors, ignoring multiplicity and any composite factor
that remains if the limit was set too low for complete factorization. Unlike factorint(),
primefactors() does not return -1 or 0.
See Also:
divisors (page 289)
Examples
>>>
>>>
[2,
>>>
[5]
>>> sorted(factorint(123456).items())
[(2, 6), (3, 1), (643, 1)]
>>> primefactors(123456)
[2, 3, 643]
>>> sorted(factorint(10000000001, limit=200).items())
[(101, 1), (99009901, 1)]
>>> isprime(99009901)
False
>>> primefactors(10000000001, limit=300)
[101]
289
Examples
>>>
>>>
[1,
>>>
8
This
is
a
slightly
modied
version
of
Tim
Peters
http://stackoverow.com/questions/1010381/python-factorization
referenced
at:
http://www.mayer.dial.pipex.com/maths/formulae.htm
>>> from sympy import divisor_count
>>> divisor_count(6)
4
sympy.ntheory.factor .totient()
Calculate the Euler totient function phi(n)
>>> from sympy.ntheory import totient
>>> totient(1)
1
>>> totient(25)
20
See Also:
divisor count (page 290)
sympy.ntheory.modular.symmetric residue(a, m)
Return the residual mod m such that it is within half of the modulus.
>>> from sympy.ntheory.modular import symmetric_residue
>>> symmetric_residue(1, 6)
1
>>> symmetric_residue(4, 6)
-2
290
If the moduli are not co-prime the correct result will be returned if/when the test of the
result is found to be incorrect. This result will be None if there is no solution.
The keyword check can be set to False if it is known that the moduli are coprime.
As an example consider a set of residues U = [49, 76, 65] and a set of moduli M =
[99, 97, 95]. Then we have:
>>> from sympy.ntheory.modular import crt, solve_congruence
>>> crt([99, 97, 95], [49, 76, 65])
(639985, 912285)
If the moduli are not co-prime, you may receive an incorrect result if you use
check=False:
>>> crt([12, 6, 17], [3, 4, 2], check=False)
(954, 1224)
>>> [954 % m for m in [12, 6, 17]]
[6, 0, 2]
>>> crt([12, 6, 17], [3, 4, 2]) is None
True
>>> crt([3, 6], [2, 5])
(5, 6)
Note:
the order of gf crts arguments is reversed relative to crt,
solve congruence takes residue, modulus pairs.
and that
Programmers note: rather than checking that all pairs of moduli share no GCD (an
O(n**2) test) and rather than factoring all moduli and seeing that there is no factor in
common, a check that the result gives the indicated residuals is performed an O(n)
operation.
See Also:
solve congruence (page 292)
sympy.polys.galoistools.gf crt (page 1197) low level crt routine used by this routine
sympy.ntheory.modular.crt1(m)
First part of Chinese Remainder Theorem, for multiple application.
Examples
>>> from sympy.ntheory.modular import crt1
>>> crt1([18, 42, 6])
(4536, [252, 108, 756], [0, 2, 0])
291
Examples
>>>
>>>
>>>
(0,
If you prefer to work with all remainder in one list and all moduli in another, send the
arguments like this:
>>> solve_congruence(*zip((2, 3, 2), (3, 5, 7)))
(23, 105)
The moduli need not be co-prime; in this case there may or may not be a solution:
>>> solve_congruence((2, 3), (4, 6)) is None
True
>>> solve_congruence((2, 3), (5, 6))
(5, 6)
The symmetric ag will make the result be within 1/2 of the modulus:
>>> solve_congruence((2, 3), (5, 6), symmetric=True)
(-1, 6)
sympy.ntheory.multinomial.binomial coefficients(n)
Return a dictionary containing pairs (k1, k2) : Ck n where Ck n are binomial coecients and
n = k1 + k2. Examples ========
292
See Also:
binomial coefficients list (page 293), multinomial coefficients (page 293)
sympy.ntheory.multinomial.binomial coefficients list(n)
Return a list of binomial coecients as rows of the Pascals triangle.
See Also:
binomial coefficients (page 292), multinomial coefficients (page 293)
Examples
>>> from sympy.ntheory import binomial_coefficients_list
>>> binomial_coefficients_list(9)
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
sympy.ntheory.multinomial.multinomial coefficients(m, n)
Return a dictionary containing pairs {(k1,k2,..,km) : C kn} where C kn are multinomial coecients such that n=k1+k2+..+km.
For example:
>>> from sympy.ntheory import multinomial_coefficients
>>> multinomial_coefficients(2, 5) # indirect doctest
{(0, 5): 1, (1, 4): 5, (2, 3): 10, (3, 2): 10, (4, 1): 5, (5, 0): 1}
n
k1 , . . . , k m
)
m (
k1 + 1
n
=
n k1 i=2 k1 + 1, . . . , ki 1, . . .
Code contributed to Sage by Yann Laigle-Chapuy, copied with permission of the author.
See Also:
binomial coefficients list (page 293), binomial coefficients (page 292)
sympy.ntheory.multinomial.multinomial coefficients iterator(m,
tuple=<type
tuple>)
multinomial coecient iterator
n,
This routine has been optimized for m large with respect to n by taking advantage of the
fact that when the monomial tuples t are stripped of zeros, their coecient is the same
as that of the monomial tuples from multinomial coefficients(n, n). Therefore, the
latter coecients are precomputed to save memory and time.
>>> from sympy.ntheory.multinomial import multinomial_coefficients
>>> m53, m33 = multinomial_coefficients(5,3), multinomial_coefficients(3,3)
>>> m53[(0,0,0,1,2)] == m53[(0,0,1,0,2)] == m53[(1,0,2,0,0)] == m33[(0,1,2)]
True
293
Examples
>>> from sympy.ntheory.multinomial import multinomial_coefficients_iterator
>>> it = multinomial_coefficients_iterator(20,3)
>>> next(it)
((3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1)
sympy.ntheory.primetest.mr(n, bases)
Perform a Miller-Rabin strong pseudoprime test on n using a given list of
bases/witnesses.
References
Richard Crandall & Carl Pomerance (2005), Prime Numbers: A Computational Perspective, Springer, 2nd edition, 135-138
A
list
of
thresholds
and
the
bases
they
require
are
here:
http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin primality test#Deterministic variants of the tes
Examples
>>> from sympy.ntheory.primetest import mr
>>> mr(1373651, [2, 3])
False
>>> mr(479001599, [31, 73])
True
sympy.ntheory.primetest.isprime(n)
Test if n is a prime number (True) or not (False). For n < 10**16 the answer is accurate;
greater n values have a small probability of actually being pseudoprimes.
Negative primes (e.g. -2) are not considered prime.
The function rst looks for trivial factors, and if none is found, performs a safe MillerRabin strong pseudoprime test with bases that are known to prove a number prime.
Finally, a general Miller-Rabin test is done with the rst k bases which will report a
pseudoprime as a prime with an error of about 4**-k. The current value of k is 46 so the
error is about 2 x 10**-28.
See Also:
294
295
References
[1] W. Stein Elementary Number Theory (2011), page 44 [2] P. Hackman Elementary
Number Theory (2009), Chapter C
Examples
>>> from sympy.ntheory.residue_ntheory import primitive_root
>>> primitive_root(19)
2
If there is no root it is returned None; else the returned root is less or equal to p // 2;
in general is not the smallest one. It is returned p // 2 only if it is the only root.
Use all roots only when it is expected that all the roots t in memory; otherwise use
sqrt mod iter.
Examples
>>>
>>>
21
>>>
[7,
296
Examples
>>>
>>>
8
>>>
[8,
>>>
23
See Also:
legendre symbol (page 297), jacobi symbol (page 297)
sympy.ntheory.residue ntheory.legendre symbol(a, p)
Returns 1. 0 if a is multiple of p :
2. 1 if a is a quadratic residue of p :
3. -1 otherwise :
p should be an odd prime by denition :
See Also:
is quad residue (page 297), jacobi symbol (page 297)
Examples
>>>
>>>
[0,
>>>
[0,
297
3. -1 otherwise :
See Also:
is quad residue (page 297), legendre symbol (page 297)
Examples
>>>
>>>
>>>
-1
>>>
1
The relationship between the jacobi symbol and legendre symbol can be demonstrated
as follows:
>>> L = legendre_symbol
>>> S(45).factors()
{3: 2, 5: 1}
>>> jacobi_symbol(7, 45) == L(7, 3)**2 * L(7, 5)**1
True
continued_fraction_convergents, con
298
104348/33215
208341/66317
p+ d
i.e. q , where p, q and d 0 are integers.
Returns the continued fraction representation (canonical form) as a list of integers, optionally ending (for quadratic irrationals) with repeating block as the last term of this
list.
Parameters p : int
the rational part of the numbers numerator
q : int
the denominator of the number
d : int, optional
the irrational part (discriminator) of the numbers numerator
See Also:
continued fraction iterator (page 299), continued fraction reduce (page 300)
299
References
If the discriminator is zero or a perfect square then the number will be a rational number:
>>>
[1,
>>>
[3,
continued_fraction_periodic(4, 3, 0)
3]
continued_fraction_periodic(4, 3, 49)
1, 2]
300
class sympy.ntheory.mobius
Mbius function maps natural number to {-1, 0, 1}
It is dened as follows:
1. 1 if n = 1.
2. 0 if n has a squared prime factor.
3. (1)k if n is a square-free positive integer with k number of prime factors.
It is an important multiplicative function in number theory and combinatorics. It has
applications in mathematical series, algebraic number theory and also physics (Fermion
operator has very concrete realization with Mbius Function model).
Parameters n : positive integer
References
301
[R316] (page 1902), [R317] (page 1902), [R318] (page 1902), [R319] (page 1902)
Examples
>>>
>>>
>>>
[3,
>>>
[7,
>>>
[4,
>>>
[3,
>>>
[1,
302
sympy.crypto.crypto.alphabet of cipher(symbols=ABCDEFGHIJKLMNOPQRSTUVWXYZ)
Returns the list of characters in the string input dening the alphabet.
Notes
alphabet_of_cipher
H, I, J, K, L, M,
U, V, W, X, Y, Z]
+ [a, b, c]; L
7, 8, 9, a, b, c]
7, 8, 9, a, b, c]
H, I, J, K, L, M,
U, V, W, X, Y, Z]
303
sympy.crypto.crypto.cycle list(k, n)
Returns the cyclic shift of the list range(n) by k.
Examples
>>> from sympy.crypto.crypto import cycle_list, alphabet_of_cipher
>>> L = cycle_list(3,26); L
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 1, 2]
>>> A = alphabet_of_cipher(); A
[A, B, C, D, E, F, G, H, I, J, K, L, M,
N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
>>> [A[i] for i in L]
[D, E, F, G, H, I, J, K, L, M, N, O, P,
Q, R, S, T, U, V, W, X, Y, Z, A, B, C]
The shift cipher is also called the Caesar cipher, after Julius Caesar, who, according
to Suetonius, used it with a shift of three to protect messages of military signicance.
Caesars nephew Augustus reportedtly used a similar cipher, but with a right shift of 1.
ALGORITHM:
INPUT:
k: an integer from 0 to 25 (the secret key)
m: string of upper-case letters (the plaintext message)
OUTPUT:
c: string of upper-case letters (the ciphertext message)
STEPS:
0. Identify the alphabet A, ..., Z with the integers 0, ..., 25.
1. Compute from the string m a list L1 of corresponding integers.
2. Compute from the list L1 a new list L2, given by adding (k mod 26) to
each element in L1.
3. Compute from the list L2 a string c of corresponding letters.
Examples
>>> from sympy.crypto.crypto import encipher_shift
>>> pt = GONAVYBEATARMY
>>> encipher_shift(pt, 1)
HPOBWZCFBUBSNZ
>>> encipher_shift(pt, 0)
GONAVYBEATARMY
>>> encipher_shift(pt, -1)
FNMZUXADZSZQLX
304
sympy.crypto.crypto.encipher substitution(pt,
key,
symbols=ABCDEFGHIJKLMNOPQRSTUVWXYZ)
Performs the substitution cipher encryption on plaintext pt, and returns the ciphertext.
Assumes the pt has only letters taken from symbols. Assumes key is a permutation of
the symbols. This function permutes the letters of the plaintext using the permutation
given in key. The decription uses the inverse permutation. Note that if the permutation
in key is order 2 (eg, a transposition) then the encryption permutation and the decryption
permutation are the same.
305
Examples
>>> from sympy.crypto.crypto import alphabet_of_cipher, encipher_substitution
>>> symbols = ABCDEFGHIJKLMNOPQRSTUVWXYZ
>>> A = alphabet_of_cipher(symbols)
>>> key = BACDEFGHIJKLMNOPQRSTUVWXYZ
>>> pt = go navy! beat army!
>>> encipher_substitution(pt, key)
GONBVYAEBTBRMY
>>> ct = GONBVYAEBTBRMY
>>> encipher_substitution(ct, key)
GONAVYBEATARMY
The Vigenre cipher is named after Blaise de Vigenre, a sixteenth century diplomat
and cryptographer, by a historical accident. Vigenre actually invented a dierent and
more complicated cipher. The so-called Vigenre cipher was actually invented by Giovan
Batista Belaso in 1553.
This cipher was used in the 1800s, for example, during the American Civil War. The
Confederacy used a brass cipher disk to implement the Vigenre cipher (now on display
in the NSA Museum in Fort Meade) [R56] (page 1902).
The Vigenre cipher is a generalization of the shift cipher. Whereas the shift cipher
shifts each letter by the same amount (that amount being the key of the shift cipher) the
Vigenre cipher shifts a letter by an amount determined by the key (which is a word or
phrase known only to the sender and receiver).
For example, if the key was a single letter, such as C, then the so-called Vigenere cipher
is actually a shift cipher with a shift of 2 (since C is the 2nd letter of the alphabet, if
you start counting at 0). If the key was a word with two letters, such as CA, then the socalled Vigenre cipher will shift letters in even positions by 2 and letters in odd positions
are left alone (shifted by 0, since A is the 0th letter, if you start counting at 0).
ALGORITHM:
INPUT:
key: a string of upper-case letters (the secret key)
m: string of upper-case letters (the plaintext message)
OUTPUT:
c: string of upper-case letters (the ciphertext message)
STEPS:
0. Identify the alphabet A, ..., Z with the integers 0, ..., 25.
1. Compute from the string key a list L1 of corresponding integers. Let n1
= len(L1).
2. Compute from the string m a list L2 of corresponding integers. Let n2 =
len(L2).
306
3. Break L2 up sequencially into sublists of size n1, and one sublist at the
end of size smaller or equal to n1.
4. For each of these sublists L of L2, compute a new list C given by C[i] =
L[i] + L1[i] (mod 26) to the i-th element in the sublist, for each i.
5. Assemble these lists C by concatenation into a new list of length n2.
6. Compute from the new list a string c of corresponding letters.
Once it is known that the key is, say, n characters long, frequency analysis can be applied
to every n-th letter of the ciphertext to determine the plaintext. This method is called
Kasiski examination (although it was rst discovered by Babbage).
The cipher Vigenre actually discovered is an auto-key cipher described as follows.
ALGORITHM:
INPUT:
key: a string of upper-case letters (the secret key)
m: string of upper-case letters (the plaintext message)
OUTPUT:
c: string of upper-case letters (the ciphertext message)
STEPS:
0. Identify the alphabet A, ..., Z with the integers 0, ..., 25.
1. Compute from the string m a list L2 of corresponding integers. Let n2 =
len(L2).
2. Let n1 be the length of the key. Concatenate the string key with the rst
n2 - n1 characters of the plaintext message. Compute from this string
of length n2 a list L1 of corresponding integers. Note n2 = len(L1).
3. Compute a new list C given by C[i] = L1[i] + L2[i] (mod 26), for
each i. Note n2 = len(C).
4. Compute from the new list a string c of corresponding letters.
References
307
Examples
>>> from sympy.crypto.crypto import decipher_vigenere
>>> key = encrypt
>>> ct = QRGK kt HRZQE BPR
>>> decipher_vigenere(ct, key)
MEETMEONMONDAY
The Hill cipher [R57] (page 1902), invented by Lester S. Hill in the 1920s [R58]
(page 1902), was the rst polygraphic cipher in which it was practical (though barely)
to operate on more than three symbols at once. The following discussion assumes an
elementary knowledge of matrices.
First, each letter is rst encoded as a number. We assume here that A 0, B 1, ...,
Z 25. We denote the integers {0, 1, ..., 25} by Z26 . Suppose your message m consists
of n capital letters, with no spaces. This may be regarded an n-tuple M of elements of
Z26 . A key in the Hill cipher is a kxk matrix K, all of whose entries are in Z26 , such that
k
k
is one-to-one).
Z26
the matrix K is invertible (ie, that the linear transformation K : Z26
ALGORITHM:
INPUT:
key: a kxk invertible matrix K, all of whose entries are in Z26
m: string of n upper-case letters (the plaintext message) (Note: Sage
assumes that n is a multiple of k.)
OUTPUT:
c: string of upper-case letters (the ciphertext message)
STEPS:
0. Identify the alphabet A, ..., Z with the integers 0, ..., 25.
1. Compute from the string m a list L of corresponding integers. Let n =
len(L).
2. Break the list L up into t = ceiling(n/k) sublists L 1, ..., L t of size k
(where the last list might be padded by 0s to ensure it is size k).
3. Compute new list C 1, ..., C t given by C[i] = K*L i (arithmetic is done
mod 26), for each i.
4. Concatenate these into a list C = C 1 + ... + C t.
5. Compute from C a string c of corresponding letters. This has length k*t.
References
308
Examples
>>> from sympy.crypto.crypto import encipher_hill
>>> from sympy import Matrix
>>> pt = meet me on monday
>>> key = Matrix([[1, 2], [3, 5]])
>>> encipher_hill(pt, key)
UEQDUEODOCTCWQ
>>> pt = meet me on tuesday
>>> encipher_hill(pt, key)
UEQDUEODHBOYDJYU
>>> pt = GONAVYBEATARMY
>>> key = Matrix([[1, 0, 1], [0, 1, 1], [2, 2, 3]])
>>> encipher_hill(pt, key)
TBBYTKBEKKRLMYU
The Bid cipher was invented around 1901 by Felix Delastelle. It is a fractional substitution cipher, where letters are replaced by pairs of symbols from a smaller alphabet.
The cipher uses a 5 5 square lled with some ordering of the alphabet, except that is
and js are identied (this is a so-called Polybius square; there is a 6 6 analog if you
add back in j and also append onto the usual 26 letter alphabet, the digits 0, 1, ..., 9).
According to Helen Gaines book Cryptanalysis, this type of cipher was used in the eld
by the German Army during World War I.
ALGORITHM: (5x5 case)
INPUT:
pt: plaintext string (no js)
key: short string for key (no repetitions, no js)
OUTPUT:
ciphertext (using Bid5 cipher in all caps, no spaces, no Js)
309
STEPS:
1. Create the 5 5 Polybius square S associated to the k as follows:
(a) starting top left, moving left-to-right, top-to-bottom, place the letters
of the key into a 5x5 matrix,
(b) when nished, add the letters of the alphabet not in the key until the
5x5 square is lled
2. Create a list P of pairs of numbers which are the coordinates in the Polybius square of the letters in pt.
3. Let L1 be the list of all rst coordinates of P (length of L1 = n), let L2 be
the list of all second coordinates of P (so the length of L2 is also n).
4. Let L be the concatenation of L1 and L2 (length L = 2*n), except that
consecutive numbers are paired (L[2*i], L[2*i + 1]). You can regard
L as a list of pairs of length n.
5. Let C be the list of all letters which are of the form S[i, j], for all (i,
j) in L. As a string, this is the ciphertext ct.
Examples
>>> from sympy.crypto.crypto import encipher_bifid5
>>> pt = meet me on monday
>>> key = encrypt
>>> encipher_bifid5(pt, key)
LNLLQNPPNPGADK
>>> pt = meet me on friday
>>> encipher_bifid5(pt, key)
LNLLFGPPNPGRSK
310
sympy.crypto.crypto.bifid5 square(key)
5x5 Polybius square.
Produce the Polybius square for the 5 5 Bid cipher.
Examples
>>> from sympy.crypto.crypto import bifid5_square
>>> bifid5_square(gold bug)
Matrix([
[G, O, L, D, B],
[U, A, C, E, F],
[H, I, K, M, N],
[P, Q, R, S, T],
[V, W, X, Y, Z]])
311
Examples
>>> from sympy.crypto.crypto import encipher_bifid6, decipher_bifid6
>>> key = encrypt
>>> pt = meet me on monday at 8am
>>> encipher_bifid6(pt, key)
HNHOKNTA5MEPEGNQZYG
>>> ct = HNHOKNTA5MEPEGNQZYG
>>> decipher_bifid6(ct, key)
MEETMEONMONDAYAT8AM
sympy.crypto.crypto.bifid6 square(key)
6x6 Polybius square.
Produces the Polybius square for the 6 6 Bid cipher. Assumes alphabet of symbols is
A, ..., Z, 0, ..., 9.
Examples
>>> from sympy.crypto.crypto import bifid6_square
>>> key = encrypt
>>> bifid6_square(key)
Matrix([
[E, N, C, R, Y, P],
[T, A, B, D, F, G],
[H, I, J, K, L, M],
[O, Q, S, U, V, W],
[X, Z, 0, 1, 2, 3],
[4, 5, 6, 7, 8, 9]])
sympy.crypto.crypto.bifid7 square(key)
7x7 Polybius square.
312
Produce the Polybius square for the 7 7 Bid cipher. Assumes alphabet of symbols is
A, ..., Z, 0, ..., 22. (Also, assumes you have some way of distinguishing 22 from
2, 2 juxtaposed together for deciphering...)
Examples
>>> from sympy.crypto.crypto import bifid7_square
>>> bifid7_square(gold bug)
Matrix([
[ G, O, L, D, B, U, A],
[ C, E, F, H, I, J, K],
[ M, N, P, Q, R, S, T],
[ V, W, X, Y, Z, 0, 1],
[ 2, 3, 4, 5, 6, 7, 8],
[ 9, 10, 11, 12, 13, 14, 15],
[16, 17, 18, 19, 20, 21, 22]])
313
>>> pt = 12
>>> encipher_rsa(pt, puk)
3
314
Examples
>>>
>>>
>>>
>>>
>>>
161
sympy.crypto.crypto.encode morse(pt)
Encodes a plaintext into popular Morse Code with letters separated by | and words by
||.
References
sympy.crypto.crypto.decode morse(mc)
Decodes a Morse Code with letters separated by | and words by || into plaintext.
References
315
S. Golomb [G60] (page 1902) gives a list of three statistical properties a sequence of
numbers a = {an }
n=1 , an {0, 1}, should display to be considered random. Dene the
autocorrelation of a to be
N
1
(1)an +an+k .
N N
n=1
P
1
(1)an +an+k .
P n=1
P
an
(1) 1.
n=1
low autocorrelation:
{
C(k) =
1,
,
k = 0,
k 6= 0.
(For sequences satisfying these rst two properties, it is known that = 1/P must
hold.)
proportional runs property: In each period, half the runs have length 1, one-fourth
have length 2, etc. Moreover, there are as many runs of 1s as there are of 0s.
References
Examples
>>> from sympy.crypto.crypto import lfsr_sequence
>>> from sympy.polys.domains import FF
>>> F = FF(2)
>>> fill = [F(1), F(1), F(0), F(1)]
>>> key = [F(1), F(0), F(0), F(1)]
>>> lfsr_sequence(key, fill, 10)
[1 mod 2, 1 mod 2, 0 mod 2, 1 mod 2, 0 mod 2, 1 mod 2, 1 mod 2, 0 mod 2, 0 mod 2, 1 mod 2]
sympy.crypto.crypto.lfsr autocorrelation(L, P, k)
This function computes the lsfr autocorrelation function.
INPUT:
L: is a periodic sequence of elements of GF (2). L must have length larger than
P.
P: the period of L
k: an integer (0 < k < p)
OUTPUT:
the k-th value of the autocorrelation of the LFSR L
Examples
>>> from sympy.crypto.crypto import lfsr_sequence, lfsr_autocorrelation
>>> from sympy.polys.domains import FF
>>> F = FF(2)
>>> fill = [F(1), F(1), F(0), F(1)]
>>> key = [F(1), F(0), F(0), F(1)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_autocorrelation(s, 15, 7)
-1/15
>>> lfsr_autocorrelation(s, 15, 0)
1
317
Examples
>>> from sympy.crypto.crypto import lfsr_sequence, lfsr_connection_polynomial
>>> from sympy.polys.domains import FF
>>> F = FF(2)
>>> fill = [F(1), F(1), F(0), F(1)]
>>> key = [F(1), F(0), F(0), F(1)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_connection_polynomial(s)
x**4 + x + 1
>>> fill = [F(1), F(0), F(0), F(1)]
>>> key = [F(1), F(1), F(0), F(1)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_connection_polynomial(s)
x**3 + 1
>>> fill = [F(1), F(0), F(1)]
>>> key = [F(1), F(1), F(0)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_connection_polynomial(s)
x**3 + x**2 + 1
>>> fill = [F(1), F(0), F(1)]
>>> key = [F(1), F(0), F(1)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_connection_polynomial(s)
x**3 + x + 1
318
1
c2
cd
1
1
mea
r ad
1
c
r ad 2
1
mrda
r ad
(mod p)
m (mod p)
Examples
>>> from sympy.crypto.crypto import decipher_elgamal
>>> decipher_elgamal((835, 271), (1031, 14, 636))
100
319
words if we are given term a(n) then it is hypergeometric if its consecutive term ratio is a
rational function in n.
To check if a sequence is of this type you can use the is hypergeometric method which is
available in Basic class. Here is simple example involving a polynomial:
>>> from sympy import *
>>> n, k = symbols(n,k)
>>> (n**2 + 1).is_hypergeometric(n)
True
Of course polynomials are hypergeometric but are there any more complicated sequences of
this type? Here are some trivial examples:
>>> factorial(n).is_hypergeometric(n)
True
>>> binomial(n, k).is_hypergeometric(n)
True
>>> rf(n, k).is_hypergeometric(n)
True
>>> ff(n, k).is_hypergeometric(n)
True
>>> gamma(n).is_hypergeometric(n)
True
>>> (2**n).is_hypergeometric(n)
True
We see that all species used in summations and other parts of concrete mathematics are
hypergeometric. Note also that binomial coecients and both rising and falling factorials
are hypergeometric in both their arguments:
>>> binomial(n, k).is_hypergeometric(k)
True
>>> rf(n, k).is_hypergeometric(k)
True
>>> ff(n, k).is_hypergeometric(k)
True
To say more, all previously shown examples are valid for integer linear arguments:
>>> factorial(2*n).is_hypergeometric(n)
True
>>> binomial(3*n+1, k).is_hypergeometric(n)
True
>>> rf(n+1, k-1).is_hypergeometric(n)
True
>>> ff(n-1, k+1).is_hypergeometric(n)
True
>>> gamma(5*n).is_hypergeometric(n)
True
>>> (2**(n-7)).is_hypergeometric(n)
True
320
If not only the knowledge of being hypergeometric or not is needed, you can use hypersimp()
function. It will try to simplify combinatorial expression and if the term given is hypergeometric it will return a quotient of polynomials of minimal degree. Otherwise is will return
N one to say that sequence is not hypergeometric:
>>> hypersimp(factorial(2*n), n)
2*(n + 1)*(2*n + 1)
>>> hypersimp(factorial(n**2), n)
An example showing that the symbolic result of a summation is still valid for seemingly
nonsensical values of the limits. Then the Karr convention allows us to give a perfectly
valid interpretation to those sums by interchanging the limits according to the above
rules:
>>> S = Sum(i, (i,1,n)).doit()
>>> S
n**2/2 + n/2
321
Finite Sums
For nite sums (and sums with symbolic limits assumed to be nite) we follow the summation convention described by Karr [1], especially denition 3 of section 1.4. The sum:
f (i)
mi<n
f (i) = f (m) + f (m + 1) + . . . + f (n 2) + f (n 1)
mi<n
with the upper limit value f (n) excluded. The sum over an empty set is zero if and only
if m = n:
f (i) = 0 for m = n
mi<n
Finally, for all other sums over empty sets we assume the following denition:
ni<m
It is important to note that Karr denes all sums with the upper limit being exclusive.
This is in contrast to the usual mathematical notation, but does not aect the summation
convention. Indeed we have:
mi<n
f (i) =
n1
f (i)
i=m
where the dierence in notation is intentional to emphasize the meaning, with limits
typeset on the top being inclusive.
322
With a nonzero eps specied, the summation is ended as soon as the remainder term
is less than the epsilon.
reverse order(*indices)
Reverse the order of a limit in a Sum.
See Also:
index, reorder limit, reorder
References
323
While one should prefer variable names when specifying which limits to reverse, the
index counting notation comes in handy in case there are several symbols with the
same name.
>>> S = Sum(x**2, (x, a, b), (x, c, d))
>>> S
Sum(x**2, (x, a, b), (x, c, d))
>>> S0 = S.reverse_order( 0)
>>> S0
Sum(-x**2, (x, b + 1, a - 1), (x, c, d))
>>> S1 = S0.reverse_order( 1)
>>> S1
Sum(x**2, (x, b + 1, a - 1), (x, d + 1, c - 1))
(x,
b +
(x,
b +
a,
1,
a,
1,
b),
a b),
a -
(y,
1),
(y,
1),
2, 5)).reverse_order( x, 1)
(y, 6, 1))
2, 5)).reverse_order( y, x)
(y, 6, 1))
Usage
reverse order(self, *indices) reverses some limits in the expression self which
can be either a Sum or a Product. The selectors in the argument indices specify
some indices whose limits get reversed. These selectors are either variable names
or numerical indices counted starting from the inner-most limit tuple.
class sympy.concrete.products.Product
Represents unevaluated products.
Product represents a nite or innite product, with the rst argument being the general
form of terms in the series, and the second argument being (dummy variable, start,
end), with dummy variable taking all integer values from start through end. In accordance with long-standing mathematical convention, the end term is included in the
product.
See Also:
Sum, summation, product
References
324
Examples
>>> from sympy.abc import a, b, i, k, m, n, x
>>> from sympy import Product, factorial, oo
>>> Product(k,(k,1,m))
Product(k, (k, 1, m))
>>> Product(k,(k,1,m)).doit()
factorial(m)
>>> Product(k**2,(k,1,m))
Product(k**2, (k, 1, m))
>>> Product(k**2,(k,1,m)).doit()
(factorial(m))**2
Products with the lower limit being larger than the upper one:
>>> Product(1/i, (i, 6, 1)).doit()
120
325
An example showing that the symbolic result of a product is still valid for seemingly
nonsensical values of the limits. Then the Karr convention allows us to give a perfectly
valid interpretation to those products by interchanging the limits according to the above
rules:
>>> P = Product(2, (i, 10, n)).doit()
>>> P
2**(n - 9)
>>> P.subs(n, 5)
1/16
>>> Product(2, (i, 10, 5)).doit()
1/16
>>> 1/Product(2, (i, 6, 9)).doit()
1/16
Finite Products
For nite products (and products with symbolic limits assumed to be nite) we follow
the analogue of the summation convention described by Karr [1], especially denition 3
of section 1.4. The product:
f (i)
mi<n
326
with the upper limit value f (n) excluded. The product over an empty set is one if and
only if m = n:
f (i) = 1 for m = n
mi<n
Finally, for all other products over empty sets we assume the following denition:
f (i) =
ni<m
mi<n
f (i)
for
m>n
It is important to note that above we dene all products with the upper limit being exclusive. This is in contrast to the usual mathematical notation, but does not aect the
product convention. Indeed we have:
f (i) =
mi<n
n1
f (i)
i=m
where the dierence in notation is intentional to emphasize the meaning, with limits
typeset on the top being inclusive.
reverse order(expr, *indices)
Reverse the order of a limit in a Product.
See Also:
index, reorder limit, reorder
References
327
While one should prefer variable names when specifying which limits to reverse, the
index counting notation comes in handy in case there are several symbols with the
same name.
>>> S = Sum(x*y, (x, a, b), (y, c, d))
>>> S
Sum(x*y, (x, a, b), (y, c, d))
>>> S0 = S.reverse_order( 0)
>>> S0
Sum(-x*y, (x, b + 1, a - 1), (y, c, d))
>>> S1 = S0.reverse_order( 1)
>>> S1
Sum(x*y, (x, b + 1, a - 1), (y, d + 1, c - 1))
(x,
b +
(x,
b +
a,
1,
a,
1,
b),
a b),
a -
(y,
1),
(y,
1),
2, 5)).reverse_order( x, 1)
(y, 6, 1))
2, 5)).reverse_order( y, x)
(y, 6, 1))
Usage
reverse order(expr, *indices) reverses some limits in the expression expr which
can be either a Sum or a Product. The selectors in the argument indices specify
some indices whose limits get reversed. These selectors are either variable names
or numerical indices counted starting from the inner-most limit tuple.
)
f
/ ,
i = a
If it cannot compute the sum, it returns an unevaluated Sum object. Repeated sums can
be computed by introducing additional symbols tuples:
>>> from sympy import summation, oo, symbols, log
>>> i, n, m = symbols(i n m, integer=True)
>>> summation(2*i - 1, (i, 1, n))
n**2
>>> summation(1/2**i, (i, 0, oo))
2
>>> summation(1/log(n)**n, (n, 2, oo))
Sum(log(n)**(-n), (n, 2, oo))
328
See Also:
Sum, Product, product
sympy.concrete.products.product(*args, **kwargs)
Compute the product.
The notation for symbols is similiar to the notation used in Sum or Integral. product(f,
(i, a, b)) computes the product of f with respect to i from a to b, i.e.,
b
product(f(n), (i, a, b)) = |
| f(n)
|
|
i = a
k))
k))
k), (k, 1, n))
(k, 1, n))
where Z is an arbitrary constant and A, B, C are monic polynomials in n with the following
properties:
1.gcd(A(n), B(n + h)) = 1h N
2.gcd(B(n), C(n + 1)) = 1
3.gcd(A(n), C(n)) = 1
This normal form, or rational factorization in other words, is a crucial step in Gospers
algorithm and in solving of dierence equations. It can be also used to decide if two
hypergeometric terms are similar or not.
This procedure will return a tuple containing elements of this factorization in the form
(Z*A, B, C).
5.5. Concrete Mathematics
329
Examples
>>> from sympy.concrete.gosper import gosper_normal
>>> from sympy.abc import n
>>> gosper_normal(4*n+5, 2*(4*n+1)*(2*n+3), n, polys=False)
(1/4, n + 3/2, n + 1/4)
sympy.concrete.gosper.gosper term(f, n)
Compute Gospers hypergeometric term for f.
Suppose f is a hypergeometric term such that:
sn =
n1
fk
k=0
sympy.concrete.gosper.gosper sum(f, k)
Gospers hypergeometric summation algorithm.
Given a hypergeometric term f such that:
sn =
n1
fk
k=0
and f (n) doesnt depend on n, returns gn g(0) where gn+1 gn = fn , or None if sn can not
be expressed in closed form as a sum of hypergeometric terms.
References
330
If the expression contains symbols or for some other reason cannot be evaluated numerically,
calling .evalf() or N() returns the original expression, or in some cases a partially evaluated expression. For example, when the expression is a polynomial in expanded form, the
coecients are evaluated:
>>> x = Symbol(x)
>>> (pi*x**2 + x/3).evalf()
3.14159265358979*x**2 + 0.333333333333333*x
You can also use the standard Python functions float(), complex() to convert SymPy expressions to regular Python numbers:
>>> float(pi)
3.1415926535...
>>> complex(pi+E*I)
(3.1415926535...+2.7182818284...j)
331
If these functions are used, failure to evaluate the expression to an explicit number (for example if the expression contains symbols) will raise an exception.
There is essentially no upper precision limit. The following command, for example, computes
the rst 100,000 digits of /e:
>>> N(pi/E, 100000)
...
As the last example shows, some Python oats are only accurate to about 15 digits as inputs,
while others (those that have a denominator that is a power of 2, like .125 = 1/4) are exact. To
create a Float from a high-precision decimal number, it is better to pass a string, Rational,
or evalf a Rational:
>>> Float(0.1, 30)
0.100000000000000000000000000000
>>> Float(Rational(1, 10), 30)
0.100000000000000000000000000000
>>> Rational(1, 10).evalf(30)
0.100000000000000000000000000000
The precision of a number determines 1) the precision to use when performing arithmetic
with the number, and 2) the number of digits to display when printing the number. When two
numbers with dierent precision are used together in an arithmetic operation, the higher of
the precisions is used for the result. The product of 0.1 +/- 0.001 and 3.1415 +/- 0.0001 has
an uncertainty of about 0.003 and yet 5 digits of precision are shown.
>>> Float(0.1, 3)*Float(3.1415, 5)
0.31417
So the displayed precision should not be used as a model of error propagation or signicance
arithmetic; rather, this scheme is employed to ensure stability of numerical algorithms.
N and evalf can be used to change the precision of existing oating-point numbers:
332
>>> N(3.5)
3.50000000000000
>>> N(3.5, 5)
3.5000
>>> N(3.5, 30)
3.50000000000000000000000000000
(but not exact) approximation 100 / 5 where is the golden ratio. With ordinary oatingpoint arithmetic, subtracting these numbers from each other erroneously results in a complete cancellation:
>>> a, b = GoldenRatio**1000/sqrt(5), fibonacci(1000)
>>> float(a)
4.34665576869e+208
>>> float(b)
4.34665576869e+208
>>> float(a) - float(b)
0.0
N and evalf keep track of errors and automatically increase the precision used internally in
order to obtain a correct result:
>>> N(fibonacci(100) - GoldenRatio**100/sqrt(5))
-5.64613129282185e-22
Unfortunately, numerical evaluation cannot tell an expression that is exactly zero apart from
one that is merely very small. The working precision is therefore capped, by default to around
100 digits. If we try with the 1000th Fibonacci number, the following happens:
>>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5))
0.e+85
The lack of digits in the returned number indicates that N failed to achieve full accuracy. The
result indicates that the magnitude of the expression is something less than 1084, but that
is not a particularly good answer. To force a higher working precision, the maxn keyword
argument can be used:
>>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5), maxn=500)
-4.60123853010113e-210
Normally, maxn can be set very high (thousands of digits), but be aware that this may cause
signicant slowdown in extreme cases. Alternatively, the strict=True option can be set to
force an exception instead of silently returning a value with less than the requested accuracy:
>>> N(fibonacci(1000) - (GoldenRatio)**1000/sqrt(5), strict=True)
Traceback (most recent call last):
...
PrecisionExhausted: Failed to distinguish the expression:
-sqrt(5)*GoldenRatio**1000/5 + 4346655768693745643568852767504062580256466051737178040248172908953655
from zero. Try simplifying the input, using chop=True, or providing a higher maxn for evalf
Traceback (most recent call last):
333
...
PrecisionExhausted: Failed to distinguish the expression:
If we add a term so that the Fibonacci approximation becomes exact (the full form of Binets
formula), we get an expression that is exactly zero, but N does not know this:
>>> f = fibonacci(100) - (GoldenRatio**100 - (GoldenRatio-1)**100)/sqrt(5)
>>> N(f)
0.e-104
>>> N(f, maxn=1000)
0.e-1336
In situations where such cancellations are known to occur, the chop options is useful. This
basically replaces very small numbers in the real or imaginary portions of a number with
exact zeros:
>>> N(f, chop=True)
0
>>> N(3 + I*f, chop=True)
3.00000000000000
In situations where you wish to remove meaningless digits, re-evaluation or the use of the
round method are useful:
>>> Float(.1, )*Float(.12345, )
0.012297
>>> ans = _
>>> N(ans, 1)
0.01
>>> ans.round(2)
0.01
If you are dealing with a numeric expression that contains no oats, it can be evaluated to
arbitrary precision. To round the result relative to a given decimal, the round method is
useful:
>>> v = 10*pi + cos(1)
>>> N(v)
31.9562288417661
>>> v.round(3)
31.956
334
By default, the tanh-sinh quadrature algorithm is used to evaluate integrals. This algorithm
is very ecient and robust for smooth integrands (and even integrals with endpoint singularities), but may struggle with integrals that are highly oscillatory or have mid-interval discontinuities. In many cases, evalf/N will correctly estimate the error. With the following integral,
the result is accurate but only good to four digits:
>>> f = abs(sin(x))
>>> Integral(abs(sin(x)), (x, 0, 4)).evalf()
2.346
It can be dealt with much more eciently by telling evalf or N to use an oscillatory quadrature
algorithm:
>>> Integral(sin(x)/x**2, (x, 1, oo)).evalf(quad=osc)
0.504067061906928
>>> Integral(sin(x)/x**2, (x, 1, oo)).evalf(20, quad=osc)
0.50406706190692837199
Innite series use direct summation if the series converges quickly enough. Otherwise, extrapolation methods (generally the Euler-Maclaurin formula but also Richardson extrapolation) are used to speed up convergence. This allows high-precision evaluation of slowly convergent series:
>>> var(k)
k
>>> Sum(1/k**2, (k, 1, oo)).evalf()
1.64493406684823
335
>>> zeta(2).evalf()
1.64493406684823
>>> Sum(1/k-log(1+1/k), (k, 1, oo)).evalf()
0.577215664901533
>>> Sum(1/k-log(1+1/k), (k, 1, oo)).evalf(50)
0.57721566490153286060651209008240243104215933593992
>>> EulerGamma.evalf(50)
0.57721566490153286060651209008240243104215933593992
The Euler-Maclaurin formula is also used for nite series, allowing them to be approximated
quickly without evaluating all terms:
>>> Sum(1/k, (k, 10000000, 20000000)).evalf()
0.693147255559946
Note that evalf makes some assumptions that are not always optimal. For ne-tuned
control over numerical summation, it might be worthwhile to manually use the method
Sum.euler maclaurin.
Special optimizations are used for rational hypergeometric series (where the term is a product
of polynomials, powers, factorials, binomial coecients and the like). N/evalf sum series of
this type very rapidly to high precision. For example, this Ramanujan formula for pi can be
summed to 10,000 digits in a fraction of a second with a simple command:
>>> f = factorial
>>> n = Symbol(n, integer=True)
>>> R = 9801/sqrt(8)/Sum(f(4*n)*(1103+26390*n)/f(n)**4/396**(4*n),
...
(n, 0, oo))
>>> N(R, 10000)
3.141592653589793238462643383279502884197169399375105820974944592307816406286208
99862803482534211706798214808651328230664709384460955058223172535940812848111745
02841027019385211055596446229489549303819644288109756659334461284756482337867831
...
336
1/3
>>> nsimplify(2.0**(1/3.), tolerance=0.001)
635
--504
>>> nsimplify(2.0**(1/3.), tolerance=0.001, full=True)
3 ___
\/ 2
337
you to create mathematical expressions in SymPy and then ship them o to the numeric
system of your choice. This page documents many of the options available including the math
library, the popular array computing package numpy, code generation in Fortran or C, and
the use of the array compiler Theano.
5.7.1 Subs/evalf
Subs is the slowest but simplest option. It runs at SymPy speeds. The .subs(...).evalf()
method can substitute a numeric value for a symbolic one and then evaluate the result within
SymPy.
>>> from sympy import *
>>> from sympy.abc import x
>>> expr = sin(x)/x
>>> expr.evalf(subs={x: 3.14})
0.000507214304613640
This method is slow. You should use this method production only if performance is not an
issue. You can expect .subs to take tens of microseconds. It can be useful while prototyping
or if you just want to see a value once.
5.7.2 Lambdify
The lambdify function translates SymPy expressions into Python functions, leveraging a variety of numerical libraries. It is used as follows:
>>> from sympy import *
>>> from sympy.abc import x
>>> expr = sin(x)/x
>>> f = lambdify(x, expr)
>>> f(3.14)
0.000507214304614
Here lambdify makes a function that computes f(x) = sin(x)/x. By default lambdify relies
on implementations in the math standard library. This numerical evaluation takes on the order
of hundreds of nanoseconds, roughly two orders of magnitude faster than the .subs method.
This is the speed dierence between SymPy and raw Python.
Lambdify can leverage a variety of numerical backends. By default it uses the math library.
However it also supports mpmath and most notably, numpy. Using the numpy library gives the
generated function access to powerful vectorized ufuncs that are backed by compiled C code.
>>>
>>>
>>>
>>>
If you have array-based data this can confer a considerable speedup, on the order of 10 nanoseconds per element. Unfortunately numpy incurs some start-up time and introduces an
overhead of a few microseconds.
338
5.7.3 uFuncify
While NumPy operations are very ecient for vectorized data they sometimes incur unnecessary costs when chained together. Consider the following operation
>>> x = get_numpy_array(...)
>>> y = sin(x) / x
The operators sin and / call routines that execute tight for loops in C. The resulting computation looks something like this
for(int i = 0; i < n; i++)
{
temp[i] = sin(x[i]);
}
for(int i = i; i < n; i++)
{
y[i] = temp[i] / x[i];
}
Statically compiled projects like NumPy are unable to take advantage of such optimizations.
Fortunately, SymPy is able to generate ecient low-level C or Fortran code. It can then
depend on projects like Cython or f2py to compile and reconnect that code back up to Python.
Fortunately this process is well automated and a SymPy user wishing to make use of this code
generation should call the ufuncify function
>>> from sympy import *
>>> from sympy.abc import x
>>> expr = sin(x)/x
>>> from sympy.utilities.autowrap import ufuncify
>>> f = ufuncify([x], expr)
This function f consumes and returns a NumPy array. Generally ufuncify performs at least
as well as lambdify. If the expression is complicated then ufuncify often signicantly outperforms the NumPy backed solution. Jensen has a good blog post on this topic.
5.7.4 Theano
SymPy has a strong connection with Theano, a mathematical array compiler. SymPy expressions can be easily translated to Theano graphs and then compiled using the Theano compiler
chain.
339
If array broadcasting or types are desired then Theano requires this extra information
>>> f = theano_function([x], [expr], dims={x: 1}, dtypes={x: float64})
Theano has a more sophisticated code generation system than SymPys C/Fortran code printers. Among other things it handles common sub-expressions and compilation onto the GPU.
Theano also supports SymPy Matrix and Matrix Expression objects.
Speed
50us
1us
10ns
10ns
10ns
Qualities
Simple
Scalar functions
Vector functions
Complex vector expressions
Many outputs, CSE, GPUs
Dependencies
None
math
numpy
f2py, Cython
Theano
documented
below,
inherited
from
class sympy.core.function.Function
Base class for applied mathematical functions.
It also serves as a constructor for undened function classes.
Examples
First example shows how to use Function as a constructor for undened function classes:
>>> from sympy import Function, Symbol
>>> x = Symbol(x)
>>> f = Function(f)
>>> g = Function(g)(x)
>>> f
f
>>> f(x)
f(x)
>>> g
g(x)
>>> f(x).diff(x)
340
Derivative(f(x), x)
>>> g.diff(x)
Derivative(g(x), x)
In the following example Function is used as a base class for my func that represents a
mathematical function my func. Suppose that it is well known, that my func(0) is 1 and
my func at innity goes to 0, so we want those two simplications to occur automatically.
Suppose also that my func(x) is real exactly when x is real. Here is an implementation
that honours those requirements:
>>> from sympy import Function, S, oo, I, sin
>>> class my_func(Function):
...
...
@classmethod
...
def eval(cls, x):
...
if x.is_Number:
...
if x is S.Zero:
...
return S.One
...
elif x is S.Infinity:
...
return S.Zero
...
...
def _eval_is_real(self):
...
return self.args[0].is_real
...
>>> x = S(x)
>>> my_func(0) + sin(0)
1
>>> my_func(oo)
0
>>> my_func(3.54).n() # Not yet implemented for my_func.
my_func(3.54)
>>> my_func(I).is_real
False
In order for my func to become useful, several other methods would need to be implemented. See source code of some of the already implemented functions for more complete examples.
Also, if the function can take more than one argument, then nargs must be dened, e.g.
if my func can take one or two arguments then,
>>> class my_func(Function):
...
nargs = (1, 2)
...
>>>
341
5.8.1 Contents
Elementary
This module implements elementary functions, as well as functions like Abs, Max, etc.
Abs
class sympy.functions.elementary.complexes.Abs
Return the absolute value of the argument.
This is an extension of the built-in function abs() to accept symbolic values. If you pass
a SymPy expression to the built-in abs(), it will pass it automatically to Abs().
See Also:
sign, conjugate
Examples
>>> from sympy import Abs, Symbol, S
>>> Abs(-1)
1
>>> x = Symbol(x, real=True)
>>> Abs(-x)
Abs(x)
>>> Abs(x**2)
x**2
>>> abs(-x) # The Python built-in
Abs(x)
Note that the Python built-in will return either an Expr or int depending on the argument:
>>> type(abs(-1))
<... int>
>>> type(abs(S.NegativeOne))
<class sympy.core.numbers.One>
342
acos
class sympy.functions.elementary.trigonometric.acos
The inverse cosine function.
Returns the arc cosine of x (measured in radians).
See Also:
sin, csc, cos, sec, tan, cot, asin, acsc, asec, atan, acot, atan2
Notes
inverse(argindex=1)
Returns the inverse of this function.
acosh
class sympy.functions.elementary.hyperbolic.acosh
The inverse hyperbolic cosine function.
acosh(x) -> Returns the inverse hyperbolic cosine of x
See Also:
asinh, atanh, cosh
inverse(argindex=1)
Returns the inverse of this function.
343
acot
class sympy.functions.elementary.trigonometric.acot
The inverse cotangent function.
Returns the arc cotangent of x (measured in radians).
See Also:
sin, csc, cos, sec, tan, cot, asin, acsc, acos, asec, atan, atan2
References
class sympy.functions.elementary.hyperbolic.acoth
The inverse hyperbolic cotangent function.
acoth(x) -> Returns the inverse hyperbolic cotangent of x
inverse(argindex=1)
Returns the inverse of this function.
arg
Returns the argument (in radians) of a complex number. For a real number, the argument is
always 0.
Examples:
>>> from sympy.functions import arg
>>> from sympy import I, sqrt
>>> arg(2.0)
0
>>> arg(I)
pi/2
>>> arg(sqrt(2) + I*sqrt(2))
pi/4
class sympy.functions.elementary.complexes.arg
Returns the argument (in radians) of a complex number
asin
class sympy.functions.elementary.trigonometric.asin
The inverse sine function.
Returns the arcsine of x in radians.
See Also:
sin, csc, cos, sec, tan, cot, acsc, acos, asec, atan, acot, atan2
344
Notes
asin(x) will evaluate automatically in the cases oo, -oo, 0, 1, -1 and for some instances
when the result is a rational multiple of pi (see the eval class method).
References
inverse(argindex=1)
Returns the inverse of this function.
asinh
class sympy.functions.elementary.hyperbolic.asinh
The inverse hyperbolic sine function.
asinh(x) -> Returns the inverse hyperbolic sine of x
See Also:
acosh, atanh, sinh
inverse(argindex=1)
Returns the inverse of this function.
atan
class sympy.functions.elementary.trigonometric.atan
The inverse tangent function.
Returns the arc tangent of x (measured in radians).
See Also:
sin, csc, cos, sec, tan, cot, asin, acsc, acos, asec, acot, atan2
Notes
345
Examples
>>> from sympy import atan, oo, pi
>>> atan(0)
0
>>> atan(1)
pi/4
>>> atan(oo)
pi/2
inverse(argindex=1)
Returns the inverse of this function.
atan2
This function is like atan, but considers the sign of both arguments in order to correctly
determine the quadrant of its result.
class sympy.functions.elementary.trigonometric.atan2
The function atan2(y, x) computes atan(y/x) taking two arguments y and x. Signs of
both y and x are considered to determine the appropriate quadrant of atan(y/x). The
range is (, ]. The complete denition reads as follows:
( )
x>0
arctan xy
(y)
arctan x +
y 0, x < 0
arctan ( y )
y < 0, x < 0
x
atan2(y, x) =
+
y > 0, x = 0
2
y < 0, x = 0
undened
y = 0, x = 0
Attention: Note the role reversal of both arguments. The y-coordinate is the rst argument and the x-coordinate the second.
See Also:
sin, csc, cos, sec, tan, cot, asin, acsc, acos, asec, atan, acot
References
346
3*pi/4
>>> atan2(0, -1)
pi
>>> atan2(-1, -1)
-3*pi/4
>>> atan2(-1, 0)
-pi/2
>>> atan2(-1, 1)
-pi/4
which are all correct. Compare this to the results of the ordinary atan function for the
point (x, y) = (1, 1)
>>> from sympy import atan, S
>>> atan(S(1) / -1)
-pi/4
>>> atan2(1, -1)
3*pi/4
where only the atan2 function reurns what we expect. We can dierentiate the function
with respect to both arguments:
>>> from sympy import diff
>>> from sympy.abc import x, y
>>> diff(atan2(y, x), x)
-y/(x**2 + y**2)
>>> diff(atan2(y, x), y)
x/(x**2 + y**2)
but note that this form is undened on the negative real axis.
atanh
class sympy.functions.elementary.hyperbolic.atanh
The inverse hyperbolic tangent function.
atanh(x) -> Returns the inverse hyperbolic tangent of x
See Also:
asinh, acosh, tanh
inverse(argindex=1)
Returns the inverse of this function.
347
ceiling
class sympy.functions.elementary.integers.ceiling
Ceiling is a univariate function which returns the smallest integer value not less than its
argument. Ceiling function is generalized in this implementation to complex numbers.
More information can be found in Concrete mathematics by Graham, pp. 87 or visit
http://mathworld.wolfram.com/CeilingFunction.html.
>>>
>>>
17
>>>
3
>>>
6
>>>
0
>>>
I
See Also:
floor
conjugate
class sympy.functions.elementary.complexes.conjugate
Changes the sign of the imaginary part of a complex number.
See Also:
sign, Abs
Examples
>>> from sympy import conjugate, I
348
>>> conjugate(1 + I)
1 - I
cos
class sympy.functions.elementary.trigonometric.cos
The cosine function.
Returns the cosine of x (measured in radians).
See Also:
sin, csc, sec, tan, cot, asin, acsc, acos, asec, atan, acot, atan2
Notes
cosh
class sympy.functions.elementary.hyperbolic.cosh
x
x
The hyperbolic cosine function, e +e
.
2
cosh(x) -> Returns the hyperbolic cosine of x
See Also:
sinh, tanh, acosh
349
cot
class sympy.functions.elementary.trigonometric.cot
The cotangent function.
Returns the cotangent of x (measured in radians).
See Also:
sin, csc, cos, sec, tan, asin, acsc, acos, asec, atan, acot, atan2
Notes
inverse(argindex=1)
Returns the inverse of this function.
coth
class sympy.functions.elementary.hyperbolic.coth
The hyperbolic cotangent function, cosh(x)
sinh(x) .
coth(x) -> Returns the hyperbolic cotangent of x
inverse(argindex=1)
Returns the inverse of this function.
exp
class sympy.functions.elementary.exponential.exp
The exponential function, ex .
See Also:
log
as real imag(deep=True, **hints)
Returns this function as a 2-tuple representing a complex number.
See Also:
350
sympy.functions.elementary.complexes.re
sympy.functions.elementary.complexes.im
(page
357),
Examples
>>> from sympy import I
>>> from sympy.abc import x
>>> from sympy.functions import exp
>>> exp(x).as_real_imag()
(exp(re(x))*cos(im(x)), exp(re(x))*sin(im(x)))
>>> exp(1).as_real_imag()
(E, 0)
>>> exp(I).as_real_imag()
(cos(1), sin(1))
>>> exp(1+I).as_real_imag()
(E*cos(1), E*sin(1))
base
Returns the base of the exponential function.
fdiff(argindex=1)
Returns the rst derivative of this function.
static taylor term(*args, **kwargs)
Calculates the next term in the Taylor series expansion.
See Also:
classes sympy.functions.elementary.exponential.log (page 353)
ExprCondPair
class sympy.functions.elementary.piecewise.ExprCondPair
Represents an expression, condition pair.
cond
Returns the condition of this pair.
expr
Returns the expression of this pair.
free symbols
Return the free symbols of this pair.
oor
class sympy.functions.elementary.integers.floor
Floor is a univariate function which returns the largest integer value not greater than
its argument. However this implementation generalizes oor to complex numbers.
More information can be found in Concrete mathematics by Graham, pp. 87 or visit
http://mathworld.wolfram.com/FloorFunction.html.
>>> from sympy import floor, E, I, Float, Rational
>>> floor(17)
17
>>> floor(Rational(23, 10))
351
2
>>> floor(2*E)
5
>>> floor(-Float(0.567))
-1
>>> floor(-I/2)
-I
See Also:
ceiling
HyperbolicFunction
class sympy.functions.elementary.hyperbolic.HyperbolicFunction
Base class for hyperbolic functions.
See Also:
sinh, cosh, tanh, coth
IdentityFunction
class sympy.functions.elementary.miscellaneous.IdentityFunction
The identity function
Examples
>>> from sympy import Id, Symbol
>>> x = Symbol(x)
>>> Id(x)
x
im
See Also:
sympy.functions.elementary.complexes.re (page 357)
LambertW
class sympy.functions.elementary.exponential.LambertW
The Lambert W function W (z) is dened as the inverse function of w exp(w) [R108]
(page 1903).
352
In other words, the value of W (z) is such that z = W (z) exp(W (z)) for any complex number
z. The Lambert W function is a multivalued function with innitely many branches Wk (z),
indexed by k Z. Each branch gives a dierent solution w of the equation z = w exp(w).
The Lambert W function has two partially real branches: the principal branch (k = 0) is
real for real z > 1/e, and the k = 1 branch is real for 1/e < z < 0. All branches except
k = 0 have a logarithmic singularity at z = 0.
References
fdiff(argindex=1)
Return the rst derivative of this function.
log
class sympy.functions.elementary.exponential.log
The natural logarithm function ln(x) or log(x). Logarithms are taken with the natural
base, e. To get a logarithm of a dierent base b, use log(x, b), which is essentially
short-hand for log(x)/log(b).
See Also:
exp
as base exp()
Returns this function in the form (base, exponent).
as real imag(deep=True, **hints)
Returns this function as a complex coordinate.
Examples
>>> from sympy import I
>>> from sympy.abc import x
>>> from sympy.functions import log
>>> log(x).as_real_imag()
(log(Abs(x)), arg(x))
>>> log(I).as_real_imag()
(0, pi/2)
>>> log(1 + I).as_real_imag()
(log(sqrt(2)), pi/4)
353
>>> log(I*x).as_real_imag()
(log(Abs(x)), arg(I*x))
fdiff(argindex=1)
Returns the rst derivative of the function.
inverse(argindex=1)
Returns ex , the inverse function of log(x).
static taylor term(*args, **kwargs)
Returns the next term in the Taylor series expansion of log(1 + x).
See Also:
classes sympy.functions.elementary.exponential.exp (page 350)
Min
It is named Min and not min to avoid conicts with the built-in function min.
class sympy.functions.elementary.miscellaneous.Min
Return, if possible, the minimum value of the list.
See Also:
Max nd maximum values
Examples
>>>
>>>
>>>
>>>
354
Max
355
Algorithm
The task can be considered as searching of supremums in the directed complete partial
orders [R109] (page 1903).
The source values are sequentially allocated by the isolated subsets in which supremums
are searched and result as Max arguments.
If the resulted supremum is single, then it is returned.
The isolated subsets are the sets of values which are only the comparable with each
other in the current set. E.g. natural numbers are comparable with each other, but not
comparable with the x symbol. Another example: the symbol x with negative assumption
is comparable with a natural number.
Also there are least elements, which are comparable with all others, and have a zero
property (maximum or minimum for all elements). E.g. oo. In case of it the allocation
operation is terminated and only this value is returned.
Assumption:
if A > B > C then A > C
if A==B then B can be removed
Piecewise
class sympy.functions.elementary.piecewise.Piecewise
Represents a piecewise function.
Usage:
Piecewise( (expr,cond), (expr,cond), ... )
Each argument is a 2-tuple dening an expression and condition
The conds are evaluated in turn returning the rst that is True. If any of
the evaluated conds are not determined explicitly False, e.g. x < 1, the
function is returned in symbolic form.
If the function is evaluated at a place where all conditions are False, a
ValueError exception will be raised.
Pairs where the cond is explicitly False, will be removed.
See Also:
piecewise fold
356
Examples
>>> from sympy import Piecewise, log
>>> from sympy.abc import x
>>> f = x**2
>>> g = log(x)
>>> p = Piecewise( (0, x<-1), (f, x<=1), (g, True))
>>> p.subs(x,1)
1
>>> p.subs(x,5)
log(5)
doit(**hints)
Evaluate this piecewise function.
sympy.functions.elementary.piecewise.piecewise fold(expr)
Takes an expression containing a piecewise function and returns the expression in piecewise form.
See Also:
Piecewise
Examples
>>> from sympy import Piecewise, piecewise_fold, sympify as S
>>> from sympy.abc import x
>>> p = Piecewise((x, x < 1), (1, S(1) <= x))
>>> piecewise_fold(x*p)
Piecewise((x**2, x < 1), (x, 1 <= x))
re
class sympy.functions.elementary.complexes.re
Returns real part of expression. This function performs only elementary analysis and so
it will fail to decompose properly more complicated expressions. If completely simplied
result is needed then use Basic.as real imag() or perform complex expansion on instance
of this function.
>>> from sympy import re, im, I, E
>>> from sympy.abc import x, y
>>> re(2*E)
2*E
>>> re(2*I + 17)
17
357
>>> re(2*I)
0
>>> re(im(x) + x*I + 2)
2
See Also:
im
as real imag(deep=True, **hints)
Returns the real number with a zero complex part.
See Also:
sympy.functions.elementary.complexes.im
root
sympy.functions.elementary.miscellaneous.root(arg, n)
The n-th root function (a shortcut for arg**(1/n))
root(x, n) -> Returns the principal n-th root of x.
See Also:
sympy.polys.rootoftools.RootOf (page 1119), sympy.core.power.integer nthroot
(page 141), sqrt, real root
References
http://en.wikipedia.org/wiki/Square root
http://en.wikipedia.org/wiki/Real root
http://en.wikipedia.org/wiki/Root of unity
http://en.wikipedia.org/wiki/Principal value
http://mathworld.wolfram.com/CubeRoot.html
Examples
>>> from sympy import root, Rational
>>> from sympy.abc import x, n
>>> root(x, 2)
sqrt(x)
>>> root(x, 3)
x**(1/3)
>>> root(x, n)
x**(1/n)
>>> root(x, -Rational(2, 3))
x**(-3/2)
358
To get all n n-th roots you can use the RootOf function. The following examples show the
roots of unity for n equal 2, 3 and 4:
>>> from sympy import RootOf, I
>>> [ RootOf(x**2-1,i) for i in (0,1) ]
[-1, 1]
>>> [ RootOf(x**3-1,i) for i in (0,1,2) ]
[1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2]
>>> [ RootOf(x**4-1,i) for i in (0,1,2,3) ]
[-1, 1, -I, I]
SymPy, like other symbolic algebra systems, returns the complex root of negative numbers. This is the principal root and diers from the text-book result that one might be
expecting. For example, the cube root of -8 does not come back as -2:
>>> root(-8, 3)
2*(-1)**(1/3)
The real root function can be used to either make such a result real or simply return the
real root in the rst place:
>>> from sympy import real_root
>>> real_root(_)
-2
>>> real_root(-32, 5)
-2
RoundFunction
class sympy.functions.elementary.integers.RoundFunction
The base class for rounding functions.
sin
class sympy.functions.elementary.trigonometric.sin
The sine function.
Returns the sine of x (measured in radians).
See Also:
csc, cos, sec, tan, cot, asin, acsc, acos, asec, atan, acot, atan2
Notes
This function will evaluate automatically in the case x/pi is some rational number [R114]
(page 1903). For example, if x is a multiple of pi, pi/2, pi/3, pi/4 and pi/6.
References
[R111] (page 1903), [R112] (page 1903), [R113] (page 1903), [R114] (page 1903)
5.8. Functions Module
359
Examples
>>> from sympy import sin, pi
>>> from sympy.abc import x
>>> sin(x**2).diff(x)
2*x*cos(x**2)
>>> sin(1).diff(x)
0
>>> sin(pi)
0
>>> sin(pi/2)
1
>>> sin(pi/6)
1/2
sinh
class sympy.functions.elementary.hyperbolic.sinh
x
x
.
The hyperbolic sine function, e e
2
sinh(x) -> Returns the hyperbolic sine of x
See Also:
cosh, tanh, asinh
as real imag(deep=True, **hints)
Returns this function as a complex coordinate.
fdiff(argindex=1)
Returns the rst derivative of this function.
inverse(argindex=1)
Returns the inverse of this function.
static taylor term(*args, **kwargs)
Returns the next term in the Taylor series expansion.
sqrt
class sympy.functions.elementary.miscellaneous.sqrt
The square root function
sqrt(x) -> Returns the principal square root of x.
See Also:
sympy.polys.rootoftools.RootOf (page 1119), root, real root
360
References
http://en.wikipedia.org/wiki/Square root
http://en.wikipedia.org/wiki/Principal value
Examples
>>> from sympy import sqrt, Symbol
>>> x = Symbol(x)
>>> sqrt(x)
sqrt(x)
>>> sqrt(x)**2
x
This is because the two are not equal to each other in general. For example, consider x
== -1:
>>> from sympy import Eq
>>> Eq(sqrt(x**2), x).subs(x, -1)
False
This is because sqrt computes the principal square root, so the square may put the argument in a dierent branch. This identity does hold if x is positive:
>>> y = Symbol(y, positive=True)
>>> sqrt(y**2)
y
You can force this simplication by using the powdenest() function with the force option
set to True:
>>> from sympy import powdenest
>>> sqrt(x**2)
sqrt(x**2)
>>> powdenest(sqrt(x**2), force=True)
x
To get both branches of the square root you can use the RootOf function:
>>> from sympy import RootOf
>>> [ RootOf(x**2-3,i) for i in (0,1) ]
[-sqrt(3), sqrt(3)]
sign
class sympy.functions.elementary.complexes.sign
Returns the complex sign of an expression:
5.8. Functions Module
361
Otherwise an unevaluated expression will be returned. When evaluated, the result (in
general) will be cos(arg(expr)) + I*sin(arg(expr)).
See Also:
Abs, conjugate
Examples
>>> from sympy.functions import sign
>>> from sympy.core.numbers import I
>>> sign(-1)
-1
>>> sign(0)
0
>>> sign(-3*I)
-I
>>> sign(1 + I)
sign(1 + I)
>>> _.evalf()
0.707106781186548 + 0.707106781186548*I
tan
class sympy.functions.elementary.trigonometric.tan
The tangent function.
Returns the tangent of x (measured in radians).
See Also:
sin, csc, cos, sec, cot, asin, acsc, acos, asec, atan, acot, atan2
Notes
362
Examples
>>> from sympy import tan
>>> from sympy.abc import x
>>> tan(x**2).diff(x)
2*x*(tan(x**2)**2 + 1)
>>> tan(1).diff(x)
0
inverse(argindex=1)
Returns the inverse of this function.
tanh
class sympy.functions.elementary.hyperbolic.tanh
sinh(x)
The hyperbolic tangent function, cosh(x)
.
tanh(x) -> Returns the hyperbolic tangent of x
See Also:
sinh, cosh, atanh
inverse(argindex=1)
Returns the inverse of this function.
Combinatorial
This module implements various combinatorial functions.
bell
class sympy.functions.combinatorial.numbers.bell
Bell numbers / Bell polynomials
The Bell numbers satisfy B0 = 1 and
Bn =
n1
(
)
n1
Bk .
k
k=0
1 kn
.
Bn =
e
k!
k=0
n1
(
k=1
)
n1
Bk1 (x).
k1
363
The second kind of Bell polynomials (are sometimes called partial Bell polynomials or
incomplete Bell polynomials) are dened as
(
)jnk+1
( x )j 1 ( x )j 2
n!
xnk+1
1
2
Bn,k (x1 , x2 , . . . xnk+1 ) =
.
j1 !j2 ! jnk+1 ! 1!
2!
(n k + 1)!
j +j +j +=k
1
2
2
j1 +2j2 +3j2 +=n
...))
gives
Bell
polynomials
of
the
second
kind,
See Also:
bernoulli, catalan, euler, fibonacci, harmonic, lucas
Notes
Not to be confused with Bernoulli numbers and Bernoulli polynomials, which use the
same notation.
References
bernoulli
class sympy.functions.combinatorial.numbers.bernoulli
Bernoulli numbers / Bernoulli polynomials
The Bernoulli numbers are a sequence of rational numbers dened by B 0 = 1 and the
recursive relation (n > 0):
n
0 =
364
\
/ n + 1 \
)
|
| * B .
\
k
/
k
/
k = 0
They are also commonly dened by their exponential generating function, which is
x/(exp(x) - 1). For odd indices > 1, the Bernoulli numbers are zero.
The Bernoulli polynomials satisfy the analogous formula:
n
\
/ n \
n-k
B (x) = )
|
| * B * x
.
\ k /
k
n
/
k = 0
(A(n) - S(n))
/ n + 3 \
|
|
\
n
/
where A(n) = (n+3)/3 when n = 0 or 2 (mod 6), A(n) = -(n+3)/6 when n = 4 (mod 6), and:
[n/6]
S(n) =
\
/ n + 3 \
)
|
| * B
/
\ n - 6*k /
n-6*k
k = 1
This formula is similar to the sum given in the denition, but cuts 2/3 of the terms. For
Bernoulli polynomials, we use the formula in the denition.
bernoulli(n) gives the nth Bernoulli number, B n
bernoulli(n, x) gives the nth Bernoulli polynomial in x, B n(x)
See Also:
bell, catalan, euler, fibonacci, harmonic, lucas
References
[R66] (page 1904), [R67] (page 1904), [R68] (page 1904), [R69] (page 1904)
Examples
>>> from sympy import bernoulli
>>> [bernoulli(n) for n in range(11)]
[1, -1/2, 1/6, 0, -1/30, 0, 1/42, 0, -1/30, 0, 5/66]
>>> bernoulli(1000001)
0
binomial
class sympy.functions.combinatorial.factorials.binomial
Implementation of the binomial coecient. It can be dened in two ways depending on
its desired interpretation:
5.8. Functions Module
365
i) for i in range(2)]
i) for i in range(3)]
i) for i in range(4)]
i) for i in range(5)]
>>> binomial(Rational(5,4), 3)
-5/128
>>> binomial(n, 3)
binomial(n, 3)
>>> binomial(n, 3).expand(func=True)
n**3/6 - n**2/2 + n/3
>>> expand_func(binomial(n, 3))
n*(n - 2)*(n - 1)/6
catalan
class sympy.functions.combinatorial.numbers.catalan
Catalan numbers
The n-th catalan number is given by:
366
1
/ 2*n \
C = ----- |
|
n
n + 1 \ n /
See Also:
bell,
bernoulli,
euler,
fibonacci,
harmonic,
sympy.functions.combinatorial.factorials.binomial (page 365)
lucas,
References
[R70] (page 1904), [R71] (page 1904), [R72] (page 1904), [R73] (page 1904)
Examples
>>> from sympy import (Symbol, binomial, gamma, hyper, polygamma,
...
catalan, diff, combsimp, Rational, I)
>>> [ catalan(i) for i in range(1,10) ]
[1, 2, 5, 14, 42, 132, 429, 1430, 4862]
>>> n = Symbol(n, integer=True)
>>> catalan(n)
catalan(n)
Catalan numbers can be transformed into several other, identical expressions involving
other mathematical functions
>>> catalan(n).rewrite(binomial)
binomial(2*n, n)/(n + 1)
>>> catalan(n).rewrite(gamma)
4**n*gamma(n + 1/2)/(sqrt(pi)*gamma(n + 2))
>>> catalan(n).rewrite(hyper)
hyper((-n + 1, -n), (2,), 1)
For some non-integer values of n we can get closed form expressions by rewriting in
terms of gamma functions:
>>> catalan(Rational(1,2)).rewrite(gamma)
8/(3*pi)
We can dierentiate the Catalan numbers C(n) interpreted as a continuous real funtion
in n:
>>> diff(catalan(n), n)
(polygamma(0, n + 1/2) - polygamma(0, n + 2) + log(4))*catalan(n)
As a more advanced example consider the following ratio between consecutive numbers:
367
euler
class sympy.functions.combinatorial.numbers.euler
Euler numbers
The euler numbers are given by:
2*n+1
j
2*n+1
\
\
/ k \ (-1) * (k-2*j)
E
= I )
)
|
| -------------------2n
/
/
\ j /
k
k
k = 1 j = 0
2 * I * k
E
= 0
2n+1
See Also:
bell, bernoulli, catalan, fibonacci, harmonic, lucas
References
[R74] (page 1904), [R75] (page 1904), [R76] (page 1904), [R77] (page 1904)
Examples
>>> from sympy import Symbol
>>> from sympy.functions import euler
>>> [euler(n) for n in range(10)]
[1, 0, -1, 0, 5, 0, -61, 0, 1385, 0]
>>> n = Symbol(n)
>>> euler(n+2*n)
euler(3*n)
368
factorial
class sympy.functions.combinatorial.factorials.factorial
Implementation of factorial function over nonnegative integers. By convention (consistent with the gamma function and the binomial coecients), factorial of a negative
integer is complex innity.
The factorial is very important in combinatorics where it gives the number of ways in
which n objects can be permuted. It also arises in calculus, probability, number theory,
etc.
There is strict relation of factorial with gamma function. In fact n! = gamma(n+1)
for nonnegative integers. Rewrite of this kind is very useful in case of combinatorial
simplication.
Computation of the factorial is done using two algorithms. For small arguments naive
product is evaluated. However for bigger input algorithm Prime-Swing is used. It is
the fastest algorithm known and computes n! via prime factorization of special class of
numbers, called here the Swing Numbers.
See Also:
factorial2, RisingFactorial, FallingFactorial
Examples
>>> from sympy import Symbol, factorial, S
>>> n = Symbol(n, integer=True)
>>> factorial(0)
1
>>> factorial(7)
5040
>>> factorial(-2)
zoo
>>> factorial(n)
factorial(n)
>>> factorial(2*n)
factorial(2*n)
>>> factorial(S(1)/2)
factorial(1/2)
class sympy.functions.combinatorial.factorials.factorial2
The double factorial n!!, not to be confused with (n!)!
The double factorial is dened for integers >= -1 as:
369
,
| n*(n - 2)*(n - 4)* ... * 1
n!! = { n*(n - 2)*(n - 4)* ... * 2
| 1
for n odd
for n even
for n = 0, -1
See Also:
factorial, RisingFactorial, FallingFactorial
Examples
>>> from sympy import factorial2, var
>>> var(n)
n
>>> factorial2(n + 1)
factorial2(n + 1)
>>> factorial2(5)
15
>>> factorial2(-1)
1
FallingFactorial
class sympy.functions.combinatorial.factorials.FallingFactorial
Falling factorial (related to rising factorial) is a double valued function arising in concrete
mathematics, hypergeometric functions and series expansions. It is dened by
(x, k) = x * (x-1) * ... * (x - k+1)
where x can be arbitrary expression and k is an integer.
information check Concrete mathematics by Graham, pp.
http://mathworld.wolfram.com/FallingFactorial.html page.
66
For more
or visit
See Also:
factorial, factorial2, RisingFactorial
bonacci
class sympy.functions.combinatorial.numbers.fibonacci
Fibonacci numbers / Fibonacci polynomials
370
The Fibonacci numbers are the integer sequence dened by the initial terms F 0 = 0,
F 1 = 1 and the two-term recurrence relation F n = F {n-1} + F {n-2}.
The Fibonacci polynomials are dened by F 1(x) = 1, F 2(x) = x, and F n(x) = x*F {n-1}(x)
+ F {n-2}(x) for n > 2. For all positive integers n, F n(1) = F n.
bonacci(n) gives the nth Fibonacci number, F n
bonacci(n, x) gives the nth Fibonacci polynomial in x, F n(x)
See Also:
bell, bernoulli, catalan, euler, harmonic, lucas
References
harmonic
class sympy.functions.combinatorial.numbers.harmonic
Harmonic numbers
The nth harmonic number is given by Hn = 1 +
1
2
1
3
+ . . . + n1 .
More generally:
Hn,m =
1
km
k=1
See Also:
bell, bernoulli, catalan, euler, fibonacci, lucas
References
371
Examples
>>> from sympy import harmonic, oo
>>> [harmonic(n) for n in range(6)]
[0, 1, 3/2, 11/6, 25/12, 137/60]
>>> [harmonic(n, 2) for n in range(6)]
[0, 1, 5/4, 49/36, 205/144, 5269/3600]
>>> harmonic(oo, 2)
pi**2/6
>>> from sympy import Symbol, Sum
>>> n = Symbol(n)
>>> harmonic(n).rewrite(Sum)
Sum(1/_k, (_k, 1, n))
We can evaluate harmonic numbers for all integral and positive rational arguments:
>>> from sympy import S, expand_func, simplify
>>> harmonic(8)
761/280
>>> harmonic(11)
83711/27720
>>> H = harmonic(1/S(3))
>>> H
harmonic(1/3)
>>> He = expand_func(H)
>>> He
-log(6) - sqrt(3)*pi/6 + 2*Sum(log(sin(_k*pi/3))*cos(2*_k*pi/3), (_k, 1, 1))
+ 3*Sum(1/(3*_k + 1), (_k, 0, 0))
>>> He.doit()
-log(6) - sqrt(3)*pi/6 - log(sqrt(3)/2) + 3
>>> H = harmonic(25/S(7))
>>> He = simplify(expand_func(H).doit())
>>> He
log(sin(pi/7)**(-2*cos(pi/7))*sin(2*pi/7)**(2*cos(16*pi/7))*cos(pi/14)**(-2*sin(pi/14))/14)
+ pi*tan(pi/14)/2 + 30247/9900
>>> He.n(40)
1.983697455232980674869851942390639915940
>>> harmonic(25/S(7)).n(40)
1.983697455232980674869851942390639915940
372
>>> harmonic(n,m).rewrite(polygamma)
(-1)**m*(polygamma(m - 1, 1) - polygamma(m - 1, n + 1))/factorial(m - 1)
class sympy.functions.combinatorial.numbers.lucas
Lucas numbers
Lucas numbers satisfy a recurrence relation similar to that of the Fibonacci sequence,
in which each term is the sum of the preceding two. They are generated by choosing the
initial values L 0 = 2 and L 1 = 1.
lucas(n) gives the nth Lucas number
See Also:
bell, bernoulli, catalan, euler, fibonacci, harmonic
References
373
MultiFactorial
class sympy.functions.combinatorial.factorials.MultiFactorial
RisingFactorial
class sympy.functions.combinatorial.factorials.RisingFactorial
Rising factorial (also called Pochhammer symbol) is a double valued function arising in
concrete mathematics, hypergeometric functions and series expansions. It is dened by:
rf(x, k) = x * (x+1) * ... * (x + k-1)
where x can be arbitrary expression and k is an integer.
information check Concrete mathematics by Graham, pp.
http://mathworld.wolfram.com/RisingFactorial.html page.
66
For more
or visit
See Also:
factorial, factorial2, FallingFactorial
Examples
>>> from sympy import rf
>>> from sympy.abc import x
>>> rf(x, 0)
1
>>> rf(1, 5)
120
>>> rf(x, 5) == x*(1 + x)*(2 + x)*(3 + x)*(4 + x)
True
stirling
sympy.functions.combinatorial.numbers.stirling(n,
k,
d=None,
signed=False)
Return Stirling number S(n, k) of the rst or second (default) kind.
kind=2,
The sum of all Stirling numbers of the second kind for k = 1 through n is bell(n). The
recurrence relationship for these numbers is:
{0}
{ } = 1;
{0}
374
{n}
{0}
{n + 1}
{n}
{ n }
{ } = { } = 0; {
} = j*{ } + {
}
{0}
{k}
{ k }
{k}
{k - 1}
where j is:: n for Stirling numbers of the rst kind -n for signed Stirling numbers of
the rst kind k for Stirling numbers of the second kind
The rst kind of Stirling number counts the number of permutations of n distinct items
that have k cycles; the second kind counts the ways in which n distinct items can be
partitioned into k parts. If d is given, the reduced Stirling number of the second kind
is returned: S{d}(n, k) = S(n - d + 1, k - d + 1) with n >= k >= d. (This counts
the ways to partition n consecutive integers into k groups with no pairwise dierence
less than d. See example below.)
To obtain the signed Stirling numbers of the rst kind, use keyword signed=True. Using
this keyword automatically sets kind to 1.
See Also:
sympy.utilities.iterables.multiset partitions (page 1563)
References
Second kind:
>>> [stirling(10, i) for i in range(12)]
[0, 1, 511, 9330, 34105, 42525, 22827, 5880, 750, 45, 1, 0]
>>> sum(_) == bell(10)
True
>>> len(list(multiset_partitions(range(4), 2))) == stirling(4, 2)
True
375
...
>>>
>>>
>>>
7
>>>
7
Enumeration
Three functions are available. Each of them attempts to eciently compute a given combinatorial quantity for a given set or multiset which can be entered as an integer, sequence or
multiset (dictionary with elements as keys and multiplicities as values). The k parameter indicates the number of elements to pick (or the number of partitions to make). When k is None,
the sum of the enumeration for all k (from 0 through the number of items represented by n)
is returned. A replacement parameter is recognized for combinations and permutations; this
indicates that any item may appear with multiplicity as high as the number of items in the
original set.
>>> from sympy.functions.combinatorial.numbers import nC, nP, nT
>>> items = baby
nC
nP
nT
376
Note that the integer for n indicates identical items for nT but indicates n dierent items for
nC and nP.
Special
DiracDelta
f(a)
and
See Also:
simplify, Directdelta
Examples
>>> from sympy import DiracDelta, cos
>>> from sympy.abc import x, y
377
>>> DiracDelta(x*y).is_simple(x)
True
>>> DiracDelta(x*y).is_simple(y)
True
>>> DiracDelta(x**2+x-2).is_simple(x)
False
>>> DiracDelta(cos(x)).is_simple(x)
False
simplify(self, x)
Compute a simplied representation of the function using property number 4.
x can be:
a symbol
See Also:
is simple, Directdelta
Examples
>>> from sympy import DiracDelta
>>> from sympy.abc import x, y
>>> DiracDelta(x*y).simplify(x)
DiracDelta(x)/Abs(y)
>>> DiracDelta(x*y).simplify(y)
DiracDelta(y)/Abs(x)
>>> DiracDelta(x**2 + x - 2).simplify(x)
DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3
Heaviside
Regarding to the value at 0, Mathematica denes H(0) = 1, but Maple uses H(0) = undefined
378
The gamma function implements the function which passes through the values of the
factorial function, i.e. (n) = (n 1)! when n is an integer. More general, (z) is dened
in the whole complex plane except at the negative integers where there are simple poles.
See Also:
lowergamma (page 385) Lower incomplete gamma function.
uppergamma (page 384) Upper incomplete gamma function.
polygamma (page 382) Polygamma function.
loggamma (page 380) Log Gamma function.
digamma (page 383) Digamma function.
trigamma (page 384) Trigamma function.
sympy.functions.special.beta functions.beta (page 386) Euler Beta function.
References
[R120] (page 1904), [R121] (page 1904), [R122] (page 1904), [R123] (page 1904)
Examples
>>> from sympy import S, I, pi, oo, gamma
>>> from sympy.abc import x
379
>>> gamma(1)
1
>>> gamma(4)
6
>>> gamma(S(3)/2)
sqrt(pi)/2
We can numerically evaluate the gamma function to arbitrary precision on the whole
complex plane:
>>> gamma(pi).evalf(40)
2.288037795340032417959588909060233922890
>>> gamma(1+I).evalf(20)
0.49801566811835604271 - 0.15494982830181068512*I
[R124] (page 1904), [R125] (page 1904), [R126] (page 1904), [R127] (page 1904)
Examples
Several special values are known. For numerical integral arguments we have:
380
381
We can numerically evaluate the gamma function to arbitrary precision on the whole
complex plane:
>>> from sympy import I
>>> loggamma(5).evalf(30)
3.17805383034794561964694160130
>>> loggamma(I).evalf(20)
-0.65092319930185633889 - 1.8724366472624298171*I
(n) (z) :=
d
log (z).
dz n+1
See Also:
gamma (page 379) Gamma function.
lowergamma (page 385) Lower incomplete gamma function.
uppergamma (page 384) Upper incomplete gamma function.
loggamma (page 380) Log Gamma function.
digamma (page 383) Digamma function.
trigamma (page 384) Trigamma function.
sympy.functions.special.beta functions.beta (page 386) Euler Beta function.
References
[R128] (page 1904), [R129] (page 1904), [R130] (page 1904), [R131] (page 1904)
Examples
382
Symbol, diff
x), x)
x), x, 2)
x), x, 3)
x), x)
x), x, 2)
x), x)
x), x, 2)
>>> n = Symbol(n)
>>> diff(polygamma(n, x), x)
polygamma(n + 1, x)
>>> diff(polygamma(n, x), x, 2)
polygamma(n + 2, x)
sympy.functions.special.gamma functions.digamma(x)
383
The digamma function is the rst derivative of the loggamma function i.e,
(x) :=
d
0 (z)
log (z) =
dz
(z)
(1) (z) :=
d
log (z).
dz 2
384
where (s, x) is the lower incomplete gamma function, lowergamma (page 385). This can
be shown to be the same as
)
(
xs
s
(s, x) = (s) 1 F1
x ,
s
s + 1
See Also:
gamma (page 379) Gamma function.
lowergamma (page 385) Lower incomplete gamma function.
polygamma (page 382) Polygamma function.
loggamma (page 380) Log Gamma function.
digamma (page 383) Digamma function.
trigamma (page 384) Trigamma function.
sympy.functions.special.beta functions.beta (page 386) Euler Beta function.
References
[R138] (page 1905), [R139] (page 1905), [R140] (page 1905), [R141] (page 1905), [R142]
(page 1905), [R143] (page 1905)
Examples
>>> from sympy import uppergamma, S
>>> from sympy.abc import s, x
>>> uppergamma(s, x)
uppergamma(s, x)
>>> uppergamma(3, x)
x**2*exp(-x) + 2*x*exp(-x) + 2*exp(-x)
>>> uppergamma(-S(1)/2, x)
-2*sqrt(pi)*(-erf(sqrt(x)) + 1) + 2*exp(-x)/sqrt(x)
>>> uppergamma(-2, x)
expint(3, x)/x**2
385
xs
1 F1
s
)
s
x ,
s + 1
[R144] (page 1905), [R145] (page 1905), [R146] (page 1905), [R147] (page 1905), [R148]
(page 1905)
Examples
>>> from sympy import lowergamma, S
>>> from sympy.abc import s, x
>>> lowergamma(s, x)
lowergamma(s, x)
>>> lowergamma(3, x)
-x**2*exp(-x) - 2*x*exp(-x) + 2 - 2*exp(-x)
>>> lowergamma(-S(1)/2, x)
-2*sqrt(pi)*erf(sqrt(x)) - 2*exp(-x)/sqrt(x)
B(x, y) :=
0
386
Beta function or Eulers rst integral is closely associated with gamma function. The
Beta function often used in probability theory and mathematical statistics. It satises
properties like:
1
a
B(a, b) = B(b, a)
B(a, 1) =
B(a, b) =
(a)(b)
(a + b)
(a 1)!(b 1)!
(a + b 1)!
See Also:
sympy.functions.special.gamma functions.gamma (page 379) Gamma function.
sympy.functions.special.gamma functions.uppergamma (page 384) Upper
plete gamma function.
incom-
incom-
func-
func-
References
387
We can numerically evaluate the gamma function to arbitrary precision on the whole
complex plane:
>>> from sympy import beta
>>> beta(pi,pi).evalf(40)
0.02671848900111377452242355235388489324562
>>> beta(1+I,1+I).evalf(20)
-0.2112723729365330143 - 0.7655283165378005676*I
See Also:
erfc (page 389) Complementary error function.
erfi (page 390) Imaginary error function.
erf2 (page 391) Two-argument error function.
erfinv (page 392) Inverse error function.
erfcinv (page 393) Inverse Complementary error function.
erf2inv (page 394) Inverse two-argument error function.
References
[R152] (page 1905), [R153] (page 1905), [R154] (page 1905), [R155] (page 1905)
Examples
>>> from sympy import I, oo, erf
>>> from sympy.abc import z
388
>>> erf(0)
0
>>> erf(oo)
1
>>> erf(-oo)
-1
>>> erf(I*oo)
oo*I
>>> erf(-I*oo)
-oo*I
In general one can pull out factors of -1 and I from the argument:
>>> erf(-z)
-erf(z)
We can numerically evaluate the error function to arbitrary precision on the whole complex plane:
>>> erf(4).evalf(30)
0.999999984582742099719981147840
>>> erf(-4*I).evalf(30)
-1296959.73071763923152794095062*I
See Also:
erf (page 388) Gaussian error function.
erfi (page 390) Imaginary error function.
erf2 (page 391) Two-argument error function.
erfinv (page 392) Inverse error function.
erfcinv (page 393) Inverse Complementary error function.
erf2inv (page 394) Inverse two-argument error function.
References
[R156] (page 1905), [R157] (page 1905), [R158] (page 1905), [R159] (page 1905)
5.8. Functions Module
389
Examples
>>> from sympy import I, oo, erfc
>>> from sympy.abc import z
It also follows
>>> erfc(-z)
-erfc(z) + 2
See Also:
erf (page 388) Gaussian error function.
erfc (page 389) Complementary error function.
erf2 (page 391) Two-argument error function.
erfinv (page 392) Inverse error function.
390
erfi(0)
erfi(oo)
erfi(-oo)
erfi(I*oo)
erfi(-I*oo)
In general one can pull out factors of -1 and I from the argument:
>>> erfi(-z)
-erfi(z)
>>> from sympy import conjugate
>>> conjugate(erfi(z))
erfi(conjugate(z))
We can numerically evaluate the imaginary error function to arbitrary precision on the
whole complex plane:
>>> erfi(2).evalf(30)
18.5648024145755525987042919132
>>> erfi(-2*I).evalf(30)
-0.995322265018952734162069256367*I
391
See Also:
erf (page 388) Gaussian error function.
erfc (page 389) Complementary error function.
erfi (page 390) Imaginary error function.
erfinv (page 392) Inverse error function.
erfcinv (page 393) Inverse Complementary error function.
erf2inv (page 394) Inverse two-argument error function.
References
392
erfinv(y) = x
See Also:
erf (page 388) Gaussian error function.
erfc (page 389) Complementary error function.
erfi (page 390) Imaginary error function.
erf2 (page 391) Two-argument error function.
erfcinv (page 393) Inverse Complementary error function.
erf2inv (page 394) Inverse two-argument error function.
References
We can numerically evaluate the inverse error function to arbitrary precision on [-1, 1]:
>>> erfinv(0.2).evalf(30)
0.179143454621291692285822705344
erfcinv(y) = x
See Also:
erf (page 388) Gaussian error function.
erfc (page 389) Complementary error function.
5.8. Functions Module
393
erf2inv(x, y) = w
See Also:
erf (page 388) Gaussian error function.
erfc (page 389) Complementary error function.
erfi (page 390) Imaginary error function.
erf2 (page 391) Two-argument error function.
erfinv (page 392) Inverse error function.
erfcinv (page 393) Inverse complementary error function.
References
394
Examples
>>> from sympy import I, oo, erf2inv, erfinv, erfcinv
>>> from sympy.abc import x, y
S(z) =
sin
0
2
t dt.
2
It is an entire function.
See Also:
fresnelc (page 396) Fresnel cosine integral.
References
[R169] (page 1906), [R170] (page 1906), [R171] (page 1906), [R172] (page 1906), [R173]
(page 1906)
Examples
>>> from sympy import I, oo, fresnels
>>> from sympy.abc import z
395
>>> fresnels(0)
0
>>> fresnels(oo)
1/2
>>> fresnels(-oo)
-1/2
>>> fresnels(I*oo)
-I/2
>>> fresnels(-I*oo)
I/2
In general one can pull out factors of -1 and i from the argument:
>>> fresnels(-z)
-fresnels(z)
>>> fresnels(I*z)
-I*fresnels(z)
We can numerically evaluate the Fresnel integral to arbitrary precision on the whole
complex plane:
>>> fresnels(2).evalf(30)
0.343415678363698242195300815958
>>> fresnels(-2*I).evalf(30)
0.343415678363698242195300815958*I
C(z) =
cos
0
2
t dt.
2
It is an entire function.
See Also:
fresnels (page 395) Fresnel sine integral.
396
References
[R174] (page 1906), [R175] (page 1906), [R176] (page 1906), [R177] (page 1906), [R178]
(page 1906)
Examples
>>> from sympy import I, oo, fresnelc
>>> from sympy.abc import z
In general one can pull out factors of -1 and i from the argument:
>>> fresnelc(-z)
-fresnelc(z)
>>> fresnelc(I*z)
I*fresnelc(z)
We can numerically evaluate the Fresnel integral to arbitrary precision on the whole
complex plane:
>>> fresnelc(2).evalf(30)
0.488253406075340754500223503357
>>> fresnelc(-2*I).evalf(30)
-0.488253406075340754500223503357*I
397
xn
+ log(x) + ,
n n!
n=1
If the integral is interpreted as a Cauchy principal value, this statement holds for x > 0
and Ei(x) as dened above.
Note that we carefully avoided dening Ei(x) for negative real x. This is because above
integral formula does not hold for any polar lift of such x, indeed all branches of Ei(x)
above the negative reals are imaginary.
However, the following statement holds for all x R :
(
)
(
)
x t
Ei |x|ei arg(x) + Ei |x|ei arg(x)
e
dt =
,
2
t
where the integral is again understood to be a principal value if x > 0, and |x|ei arg(x) ,
|x|ei arg(x) denote two conjugate polar lifts of x.
See Also:
expint (page 399) Generalised exponential integral.
E1 (page 401) Special case of the generalised exponential integral.
li (page 401) Logarithmic integral.
Li (page 403) Oset logarithmic integral.
Si (page 404) Sine integral.
Ci (page 405) Cosine integral.
Shi (page 406) Hyperbolic sine integral.
Chi (page 407) Hyperbolic cosine integral.
sympy.functions.special.gamma functions.uppergamma (page 384) Upper
plete gamma function.
398
incom-
References
The exponential integral in SymPy is strictly undened for negative values of the argument. For convenience, exponential integrals with negative arguments are immediately
converted into an expression that agrees with the classical integral denition:
>>> Ei(-1)
-I*pi + Ei(exp_polar(I*pi))
Dierentiation is supported:
>>> Ei(x).diff(x)
exp(x)/x
The exponential integral is related to many other special functions. For example:
>>> from sympy import uppergamma, expint, Shi
>>> Ei(x).rewrite(expint)
-expint(1, x*exp_polar(I*pi)) - I*pi
>>> Ei(x).rewrite(Shi)
Chi(x) + Shi(x)
E (z) =
1
ezt
dt,
z
399
At non-postive integer orders, the exponential integral reduces to the exponential function:
>>> expint(0, z)
exp(-z)/z
>>> expint(-1, z)
exp(-z)/z + exp(-z)/z**2
400
At positive integer orders it can be rewritten in terms of exponentials and expint(1, z).
Use expand func() to do this:
>>> from sympy import expand_func
>>> expand_func(expint(5, z))
z**4*expint(1, z)/24 + (-z**3 + z**2 - 2*z + 6)*exp(-z)/24
sympy.functions.special.error functions.E1(z)
Classical case of the generalized exponential integral.
This is equivalent to expint(1, z).
See Also:
Ei (page 398) Exponential integral.
expint (page 399) Generalised exponential integral.
li (page 401) Logarithmic integral.
Li (page 403) Oset logarithmic integral.
Si (page 404) Sine integral.
Ci (page 405) Cosine integral.
Shi (page 406) Hyperbolic sine integral.
Chi (page 407) Hyperbolic cosine integral.
class sympy.functions.special.error functions.li
The classical logarithmic integral.
For the use in SymPy, this function is dened as
x
1
li(x) =
dt .
0 log(t)
See Also:
Li (page 403) Oset logarithmic integral.
Ei (page 398) Exponential integral.
expint (page 399) Generalised exponential integral.
E1 (page 401) Special case of the generalised exponential integral.
Si (page 404) Sine integral.
5.8. Functions Module
401
[R185] (page 1906), [R186] (page 1906), [R187] (page 1906), [R188] (page 1906)
Examples
>>> from sympy import I, oo, li
>>> from sympy.abc import z
We can numerically evaluate the logarithmic integral to arbitrary precision on the whole
complex plane (except the singular points):
>>> li(2).evalf(30)
1.04516378011749278484458888919
>>> li(2*I).evalf(30)
1.0652795784357498247001125598 + 3.08346052231061726610939702133*I
402
Chi
log(log(z))/2 + Ci(I*log(z)) + Shi(log(z))
log(log(z))/2 + Ci(I*log(z)) + Shi(log(z))
Chi(log(z)) - Shi(log(z))
Chi(log(z)) - Shi(log(z))
See Also:
li (page 401) Logarithmic integral.
Ei (page 398) Exponential integral.
expint (page 399) Generalised exponential integral.
E1 (page 401) Special case of the generalised exponential integral.
Si (page 404) Sine integral.
Ci (page 405) Cosine integral.
Shi (page 406) Hyperbolic sine integral.
Chi (page 407) Hyperbolic cosine integral.
References
403
We can numerically evaluate the logarithmic integral to arbitrary precision on the whole
complex plane (except the singular points):
>>> Li(2).evalf(30)
0
>>> Li(4).evalf(30)
1.92242131492155809316615998938
Si(z) =
0
sin t
dt.
t
It is an entire function.
See Also:
Ci (page 405) Cosine integral.
Shi (page 406) Hyperbolic sine integral.
Chi (page 407) Hyperbolic cosine integral.
Ei (page 398) Exponential integral.
expint (page 399) Generalised exponential integral.
E1 (page 401) Special case of the generalised exponential integral.
li (page 401) Logarithmic integral.
Li (page 403) Oset logarithmic integral.
References
It is unbranched:
404
It can also be expressed in terms of exponential integrals, but beware that the latter is
branched:
>>> from sympy import expint
>>> Si(z).rewrite(expint)
-I*(-expint(1, z*exp_polar(-I*pi/2))/2 +
expint(1, z*exp_polar(I*pi/2))/2) + pi/2
(
)
(
)
E1 ei/2 z + E1 ei/2 z
Ci(z) =
2
which holds for all polar z and thus provides an analytic continuation to the Riemann
surface of the logarithm.
The formula also holds as stated for z C with <(z) > 0. By lifting to the principal branch
we obtain an analytic function on the cut complex plane.
See Also:
Si (page 404) Sine integral.
Shi (page 406) Hyperbolic sine integral.
Chi (page 407) Hyperbolic cosine integral.
Ei (page 398) Exponential integral.
expint (page 399) Generalised exponential integral.
E1 (page 401) Special case of the generalised exponential integral.
li (page 401) Logarithmic integral.
Li (page 403) Oset logarithmic integral.
References
405
Examples
>>> from sympy import Ci
>>> from sympy.abc import z
The cosine integral behaves somewhat like ordinary cos under multiplication by i:
>>> from sympy import polar_lift
>>> Ci(polar_lift(I)*z)
Chi(z) + I*pi/2
>>> Ci(polar_lift(-1)*z)
Ci(z) + I*pi
Shi(z) =
0
sinh t
dt.
t
It is an entire function.
See Also:
Si (page 404) Sine integral.
Ci (page 405) Cosine integral.
Chi (page 407) Hyperbolic cosine integral.
Ei (page 398) Exponential integral.
expint (page 399) Generalised exponential integral.
E1 (page 401) Special case of the generalised exponential integral.
li (page 401) Logarithmic integral.
Li (page 403) Oset logarithmic integral.
References
Examples
>>> from sympy import Shi
>>> from sympy.abc import z
It is unbranched:
>>> from sympy import exp_polar, I, pi
>>> Shi(z*exp_polar(2*I*pi))
Shi(z)
The sinh integral behaves much like ordinary sinh under multiplication by i:
>>> Shi(I*z)
I*Si(z)
>>> Shi(-z)
-Shi(z)
It can also be expressed in terms of exponential integrals, but beware that the latter is
branched:
>>> from sympy import expint
>>> Shi(z).rewrite(expint)
expint(1, z)/2 - expint(1, z*exp_polar(I*pi))/2 - I*pi/2
Chi(x) = + log x +
0
cosh t 1
dt,
t
(
)
Chi(z) = Ci ei/2 z i ,
2
which holds for all polar z and thus provides an analytic continuation to the Riemann
surface of the logarithm. By lifting to the principal branch we obtain an analytic function
on the cut complex plane.
See Also:
Si (page 404) Sine integral.
Ci (page 405) Cosine integral.
Shi (page 406) Hyperbolic sine integral.
Ei (page 398) Exponential integral.
expint (page 399) Generalised exponential integral.
5.8. Functions Module
407
The cosh integral behaves somewhat like ordinary cosh under multiplication by i:
>>> from sympy import polar_lift
>>> Chi(polar_lift(I)*z)
Ci(z) + I*pi/2
>>> Chi(polar_lift(-1)*z)
Chi(z) + I*pi
class sympy.functions.special.bessel.BesselBase
Abstract base class for bessel-type functions.
This class is meant to reduce code duplication. All Bessel type functions can 1) be dierentiated, and the derivatives expressed in terms of similar functions and 2) be rewritten
in terms of other bessel-type functions.
Here bessel-type functions are assumed to have one complex parameter.
To use this base class, dene class attributes a and b such that 2*F n = - a*F {n+1}
+ b*F {n-1}.
argument
The argument of the bessel-type function.
408
order
The order of the bessel-type function.
class sympy.functions.special.bessel.besselj
Bessel function of the rst kind.
The Bessel J function of order is dened to be the function satisfying Bessels dierential equation
2
z2
d w
dw
+ (z 2 2 )w = 0,
+z
dz 2
dz
)
1
2
+ O(z ) ,
( + 1)2
See Also:
bessely (page 409), besseli (page 410), besselk (page 411)
References
[R196] (page 1906), [R197] (page 1906), [R198] (page 1906), [R199] (page 1906)
Examples
Dierentiate it:
>>> b.diff(z)
besselj(n - 1, z)/2 - besselj(n + 1, z)/2
409
class sympy.functions.special.bessel.bessely
Bessel function of the second kind.
The Bessel Y function of order is dened as
Y (z) = lim
class sympy.functions.special.bessel.besseli
Modied Bessel function of the rst kind.
The Bessel I function is a solution to the modied Bessel equation
2
z2
d w
dw
+z
+ (z 2 + 2 )2 w = 0.
dz 2
dz
It can be dened as
I (z) = i J (iz),
410
Examples
>>> from sympy import besseli
>>> from sympy.abc import z, n
>>> besseli(n, z).diff(z)
besseli(n - 1, z)/2 + besseli(n + 1, z)/2
class sympy.functions.special.bessel.besselk
Modied Bessel function of the second kind.
The Bessel K function of order is dened as
K (z) = lim
I (z) I (z)
,
2
sin()
class sympy.functions.special.bessel.hankel1
Hankel function of the rst kind.
This function is dened as
H(1) = J (z) + iY (z),
where J (z) is the Bessel function of the rst kind, and Y (z) is the Bessel function of the
second kind.
It is a solution to Bessels equation.
See Also:
hankel2 (page 412), besselj (page 409), bessely (page 409)
References
411
Examples
>>> from sympy import hankel1
>>> from sympy.abc import z, n
>>> hankel1(n, z).diff(z)
hankel1(n - 1, z)/2 - hankel1(n + 1, z)/2
class sympy.functions.special.bessel.hankel2
Hankel function of the second kind.
This function is dened as
H(2) = J (z) iY (z),
where J (z) is the Bessel function of the rst kind, and Y (z) is the Bessel function of the
second kind.
(1)
class sympy.functions.special.bessel.jn
Spherical Bessel function of the rst kind.
This function is a solution to the spherical Bessel equation
2
z2
d w
dw
+ 2z
+ (z 2 ( + 1))w = 0.
dz 2
dz
It can be dened as
j (z) =
J 1 (z),
2z + 2
412
Examples
>>> from sympy import Symbol, jn, sin, cos, expand_func
>>> z = Symbol(z)
>>> print(jn(0, z).expand(func=True))
sin(z)/z
>>> jn(1, z).expand(func=True) == sin(z)/z**2 - cos(z)/z
True
>>> expand_func(jn(3, z))
(-6/z**2 + 15/z**4)*sin(z) + (1/z - 15/z**3)*cos(z)
The spherical Bessel functions of integral order are calculated using the formula:
jn (z) = fn (z) sin z + (1)n+1 fn1 (z) cos z,
where the coecients fn (z) are available as polys.orthopolys.spherical bessel fn().
class sympy.functions.special.bessel.yn
Spherical Bessel function of the second kind.
This function is another solution to the spherical Bessel equation, and linearly independent from jn . It can be dened as
j (z) =
Y 1 (z),
2z + 2
where Y (z) is the Bessel function of the second kind.
See Also:
besselj (page 409), bessely (page 409), besselk (page 411), jn (page 412)
Examples
>>> from sympy import Symbol, yn, sin, cos, expand_func
>>> z = Symbol(z)
>>> print(expand_func(yn(0, z)))
-cos(z)/z
>>> expand_func(yn(1, z)) == -cos(z)/z**2-sin(z)/z
True
413
See Also:
jn (page 412), yn (page 413), besselj (page 409), besselk (page 411), bessely
(page 409)
Examples
>>> from sympy import jn_zeros
>>> jn_zeros(2, 4, dps=5)
[5.7635, 9.095, 12.323, 15.515]
Airy Functions
class sympy.functions.special.bessel.AiryBase
Abstract base class for Airy functions.
This class is meant to reduce code duplication.
class sympy.functions.special.bessel.airyai
The Airy function Ai of the rst kind.
The Airy function Ai(z) is dened to be the function satisfying Airys dierential equation
2
d w(z)
zw(z) = 0.
dz 2
Equivalently, for real z
1
Ai(z) :=
cos
0
)
t3
+ zt dt.
3
See Also:
airybi (page 415) Airy function of the second kind.
airyaiprime (page 417) Derivative of the Airy function of the rst kind.
airybiprime (page 418) Derivative of the Airy function of the second kind.
References
[R205] (page 1906), [R206] (page 1907), [R207] (page 1907), [R208] (page 1907)
Examples
414
>>> airyai(z)
airyai(z)
We can numerically evaluate the Airy function to arbitrary precision on the whole complex plane:
>>> airyai(-2).evalf(50)
0.22740742820168557599192443603787379946077222541710
class sympy.functions.special.bessel.airybi
The Airy function Bi of the second kind.
The Airy function Bi(z) is dened to be the function satisfying Airys dierential equation
2
d w(z)
zw(z) = 0.
dz 2
Equivalently, for real z
1
Bi(z) :=
)
( 3
)
t3
t
exp + zt + sin
+ zt dt.
3
3
415
See Also:
airyai (page 414) Airy function of the rst kind.
airyaiprime (page 417) Derivative of the Airy function of the rst kind.
airybiprime (page 418) Derivative of the Airy function of the second kind.
References
[R209] (page 1907), [R210] (page 1907), [R211] (page 1907), [R212] (page 1907)
Examples
We can numerically evaluate the Airy function to arbitrary precision on the whole complex plane:
>>> airybi(-2).evalf(50)
-0.41230258795639848808323405461146104203453483447240
416
class sympy.functions.special.bessel.airyaiprime
The derivative Ai0 of the Airy function of the rst kind.
The Airy function Ai0 (z) is dened to be the function
Ai0 (z) :=
d Ai(z)
.
dz
See Also:
airyai (page 414) Airy function of the rst kind.
airybi (page 415) Airy function of the second kind.
airybiprime (page 418) Derivative of the Airy function of the second kind.
References
[R213] (page 1907), [R214] (page 1907), [R215] (page 1907), [R216] (page 1907)
Examples
417
We can numerically evaluate the Airy function to arbitrary precision on the whole complex plane:
>>> airyaiprime(-2).evalf(50)
0.61825902074169104140626429133247528291577794512415
class sympy.functions.special.bessel.airybiprime
The derivative Bi0 of the Airy function of the rst kind.
The Airy function Bi0 (z) is dened to be the function
Bi0 (z) :=
d Bi(z)
.
dz
See Also:
airyai (page 414) Airy function of the rst kind.
airybi (page 415) Airy function of the second kind.
airyaiprime (page 417) Derivative of the Airy function of the rst kind.
References
[R217] (page 1907), [R218] (page 1907), [R219] (page 1907), [R220] (page 1907)
Examples
418
We can numerically evaluate the Airy function to arbitrary precision on the whole complex plane:
>>> airybiprime(-2).evalf(50)
0.27879516692116952268509756941098324140300059345163
B-Splines
For a given (d, knots) there are len(knots)-d-1 B-splines dened, that are indexed
by n (starting at 0).
Here is an example of a cubic B-spline:
>>> bspline_basis(3, range(5), 0, x)
Piecewise((x**3/6, And(x < 1, x >= 0)),
(-x**3/2 + 2*x**2 - 2*x + 2/3, And(x < 2, x >= 1)),
(x**3/2 - 4*x**2 + 10*x - 22/3, And(x < 3, x >= 2)),
(-x**3/6 + 2*x**2 - 8*x + 32/3, And(x <= 4, x >= 3)),
(0, True))
419
By repeating knot points, you can introduce discontinuities in the B-splines and their
derivatives:
>>> d = 1
>>> knots = [0,0,2,3,4]
>>> bspline_basis(d, knots, 0, x)
Piecewise((-x/2 + 1, And(x <= 2, x >= 0)), (0, True))
It is quite time consuming to construct and evaluate B-splines. If you need to evaluate a
B-splines many times, it is best to lambdify them rst:
>>>
>>>
>>>
>>>
>>>
>>>
See Also:
bsplines basis set
References
420
1
,
(n
+
a)s
n=0
where the standard choice of argument for n + a is used. For xed a with Re(a) > 0 the
Hurwitz zeta function admits a meromorphic continuation to all of C, it is an unbranched
function with a simple pole at s = 1.
Analytic continuation to other a is possible under some circumstances, but this is not
typically done.
The Hurwitz zeta function is a special case of the Lerch transcendent:
(s, a) = (1, s, a).
This formula denes an analytic continuation for all possible values of s and a (also
Re(a) < 0), see the documentation of lerchphi (page 424) for a description of the branching behavior.
If no value is passed for a, by this function assumes a default value of a = 1, yielding the
Riemann zeta function.
See Also:
dirichlet eta (page 422), lerchphi (page 424), polylog (page 423)
References
For a = 1 the Hurwitz zeta function reduces to the famous Riemann zeta function:
(s, 1) = (s) =
1
.
s
n
n=1
The Riemann zeta function can also be expressed using the Dirichlet eta function:
421
The Riemann zeta function at positive even integer and negative odd integer values is
related to the Bernoulli numbers:
>>> zeta(2)
pi**2/6
>>> zeta(4)
pi**4/90
>>> zeta(-1)
-1/12
(n) =
B2n (2)2n
2(2n)!
Bn+1
n+1
No closed-form expressions are known at positive odd integers, but numerical evaluation
is possible:
>>> zeta(3).n()
1.20205690315959
However the derivative with respect to s has no useful closed form expression:
>>> zeta(s, a).diff(s)
Derivative(zeta(s, a), s)
The Hurwitz zeta function can be expressed in terms of the Lerch transcendent,
sympy.functions.special.lerchphi:
>>> from sympy import lerchphi
>>> zeta(s, a).rewrite(lerchphi)
lerchphi(1, s, a)
422
(1)n
.
ns
n=1
The Dirichlet eta function is closely related to the Riemann zeta function:
>>> from sympy import dirichlet_eta, zeta
>>> from sympy.abc import s
>>> dirichlet_eta(s).rewrite(zeta)
(-2**(-s + 1) + 1)*zeta(s)
zn
,
ns
n=1
where the standard branch of the argument is used for n. It admits an analytic continuation which is branched at z = 1 (notably not on the sheet of initial denition), z = 0 and
z = .
The name polylogarithm comes from the fact that for s = 1, the polylogarithm is related
to the ordinary logarithm (see examples), and that
z
Lis (t)
Lis+1 (z) =
dt.
t
0
See Also:
zeta (page 421), lerchphi (page 424)
423
Examples
For z {0, 1, 1}, the polylogarithm is automatically expressed using other functions:
>>> from sympy import polylog
>>> from sympy.abc import s
>>> polylog(s, 0)
0
>>> polylog(s, 1)
zeta(s)
>>> polylog(s, -1)
dirichlet_eta(s)
zn
,
(n + a)s
n=0
where the standard branch of the argument is used for n+a, and by analytic continuation
for other values of the parameters.
A commonly used related function is the Lerch zeta function, dened by
L(q, s, a) = (e2iq , s, a).
0
0
2i log
x
,
xa (s)
using the standard branch for both log x and log log x (a branch of log log x is needed to
evaluate log xs1 ). This concludes the analytic continuation. The Lerch transcendent is
thus branched at z {0, 1, } and a Z0 . For xed z, a outside these branch points, it is
an entire function of s.
See Also:
polylog (page 423), zeta (page 421)
References
The Lerch transcendent is a fairly general function, for this reason it does not automatically evaluate to simpler functions. Use expand func() to achieve this.
If z = 1, the Lerch transcendent reduces to the Hurwitz zeta function:
>>> from sympy import lerchphi, expand_func
>>> from sympy.abc import z, s, a
>>> expand_func(lerchphi(1, s, a))
zeta(s, a)
More generally, if z is a root of unity, the Lerch transcendent reduces to a sum of Hurwitz
zeta functions:
>>> expand_func(lerchphi(-1, s, a))
2**(-s)*zeta(s, a/2) - 2**(-s)*zeta(s, a/2 + 1/2)
425
a).diff(z)
a) + lerchphi(z, s - 1, a))/z
a).diff(a)
1, a)
Hypergeometric Functions
class sympy.functions.special.hyper.hyper
The (generalized) hypergeometric function is dened by a series where the ratios of
successive terms are a rational function of the summation index. When convergent, it is
continued analytically to the largest possible domain.
The hypergeometric function depends on two vectors of parameters, called the numerator parameters ap , and the denominator parameters bq . It also has an argument z. The
series denition is
)
(
(a1 )n . . . (ap )n z n
a1 , . . . , ap
F
z
=
,
p q
b1 , . . . , bq
(b1 )n . . . (bq )n n!
n=0
where (a)n = (a)(a + 1) . . . (a + n 1) denotes the rising factorial.
If one of the bq is a non-positive integer then the series is undened unless one of the
ap is a larger (i.e. smaller in magnitude) non-positive integer. If none of the bq is a nonpositive integer and one of the ap is a non-positive integer, then the series reduces to a
polynomial. To simplify the following discussion, we assume that none of the ap or bq is
a non-positive integer. For more details, see the references.
The series converges for all z if p q, and thus denes an entire single-valued function
in this case. If p = q + 1 the series converges for |z| < 1, and can be continued analytically
into a half-plane. If p > q + 1 the series is divergent for all z.
Note: The hypergeometric function constructor currently does not check if the parameters actually yield a well-dened function.
See Also:
sympy.simplify.hyperexpand (page 1347), sympy.functions.special.gamma functions.gamma
(page 379), meijerg
References
426
The parameters must always be iterables, even if they are vectors of length one or zero:
>>> hyper((1, ), [], x)
hyper((1,), (), x)
But of course they may be variables (but if they depend on x then you should not expect
much implemented functionality):
>>> hyper((n, a), (n**2,), x)
hyper((n, a), (n**2,), x)
The hypergeometric function generalizes many named special functions. The function
hyperexpand() tries to express a hypergeometric function using named special functions.
For example:
>>> from sympy import hyperexpand
>>> hyperexpand(hyper([], [], x))
exp(x)
More examples:
>>> from sympy import S
>>> hyperexpand(hyper([], [S(1)/2], -x**2/4))
cos(x)
>>> hyperexpand(x*hyper([S(1)/2, S(1)/2], [S(3)/2], x**2))
asin(x)
ap
Numerator parameters of the hypergeometric function.
argument
Argument of the hypergeometric function.
bq
Denominator parameters of the hypergeometric function.
convergence statement
Return a condition on z under which the series converges.
eta
A quantity related to the convergence of the series.
5.8. Functions Module
427
radius of convergence
Compute the radius of convergence of the dening series.
Note that even if this is not oo, the function may still be evaluated outside of the
radius of convergence by analytic continuation. But if this is zero, then the function
is not actually dened anywhere else.
>>>
>>>
>>>
1
>>>
0
>>>
oo
class sympy.functions.special.hyper.meijerg
The Meijer G-function is dened by a Mellin-Barnes type integral that resembles an inverse Mellin transform. It generalizes the hypergeometric functions.
The Meijer G-function depends on four sets of parameters. There are numerator parameters a1 , . . . , an and an+1 , . . . , ap , and there are denominator parameters b1 , . . . , bm
and bm+1 , . . . , bq . Confusingly, it is traditionally denoted as follows (note the position of
m, n, p, q, and how they relate to the lengths of the four parameter vectors):
)
(
a1 , . . . , an an+1 , . . . , ap
Gm,n
z .
p,q
b1 , . . . , bm bm+1 , . . . , bq
However, in sympy the four parameter vectors are always available separately (see examples), so that there is no need to keep track of the decorating sub- and super-scripts
on the G symbol.
The G function is dened as the following integral:
n
m
1
j=1 (1 aj + s)
j=1 (bj s)
q
z s ds,
2i L j=m+1 (1 bj + s) pj=n+1 (aj s)
where (z) is the gamma function. There are three possible contours which we will not
describe in detail here (see the references). If the integral converges along more than
one of them the denitions agree. The contours all separate the poles of (1 aj + s) from
the poles of (bk s), so in particular the G function is undened if aj bk Z>0 for some
j n and k m.
The conditions under which one of the contours yields a convergent integral are complicated and we do not state them here, see the references.
Note: Currently the Meijer G-function constructor does not check any convergence conditions.
See Also:
hyper, sympy.simplify.hyperexpand (page 1347)
References
428
Examples
As with the hypergeometric function, the parameters may be passed as arbitrary iterables. Vectors of length zero and one also have to be passed as iterables. The parameters
need not be constants, but if they depend on the argument then not much implemented
functionality should be expected.
All the subvectors of parameters are available:
>>> from sympy import pprint
>>> g = meijerg([1], [2], [3], [4], x)
>>> pprint(g, use_unicode=False)
__1, 1 /1 2 | \
/__
|
| x|
\_|2, 2 \3 4 | /
>>> g.an
(1,)
>>> g.ap
(1, 2)
>>> g.aother
(2,)
>>> g.bm
(3,)
>>> g.bq
(3, 4)
>>> g.bother
(4,)
The Meijer G-function generalizes the hypergeometric functions. In some cases it can be
expressed in terms of hypergeometric functions, using Slaters theorem. For example:
>>> from sympy import hyperexpand
>>> from sympy.abc import a, b, c
>>> hyperexpand(meijerg([a], [], [c], [b], x), allow_hyper=True)
x**c*gamma(-a + c + 1)*hyper((-a + c + 1,),
(-b + c + 1,), -x)/gamma(-b + c + 1)
Thus the Meijer G-function also subsumes many named functions as special cases. You
can use expand func or hyperexpand to (try to) rewrite a Meijer G-function in terms of
named special functions. For example:
429
an
First set of numerator parameters.
aother
Second set of numerator parameters.
ap
Combined numerator parameters.
argument
Argument of the Meijer G-function.
bm
First set of denominator parameters.
bother
Second set of denominator parameters.
bq
Combined denominator parameters.
delta
A quantity related to the convergence region of the integral, c.f. references.
get period()
Return a number P such that G(x*exp(I*P)) == G(x).
>>> from sympy.functions.special.hyper import meijerg
>>> from sympy.abc import z
>>> from sympy import pi, S
>>> meijerg([1], [], [], [], z).get_period()
2*pi
>>> meijerg([pi], [], [], [], z).get_period()
oo
>>> meijerg([1, 2], [], [], [], z).get_period()
oo
>>> meijerg([1,1], [2], [1, S(1)/2, S(1)/3], [1], z).get_period()
12*pi
integrand(s)
Get the dening integrand D(s).
nu
A quantity related to the convergence region of the integral, c.f. references.
Elliptic integrals
430
where F (z|m) is the Legendre incomplete elliptic integral of the rst kind.
The function K(z) is a single-valued function on the complex plane with branch cut along
the interval (1, ).
See Also:
elliptic f (page 431)
References
F (z|m) =
0
1 m sin2 t
This function reduces to a complete elliptic integral of the rst kind, K(m), when z = /2.
See Also:
elliptic k (page 430)
References
431
E (z|m) =
1 m sin2 tdt
Called with a single argument z, evaluates the Legendre complete elliptic integral of the
second kind
( )
E(z) = E 2 z
The function E(z) is a single-valued function on the complex plane with branch cut along
the interval (1, ).
References
Called with two arguments n and m, evaluates the complete elliptic integral of the third
kind:
)
(
(n|m) = n; 2 m
References
432
Examples
>>> from sympy import elliptic_pi, I, pi, O, S
>>> from sympy.abc import z, n, m
>>> elliptic_pi(n, z, m).series(z, n=4)
z + z**3*(m/6 + n/3) + O(z**4)
>>> elliptic_pi(0.5 + I, 1.0 - I, 1.2)
2.50232379629182 - 0.760939574180767*I
>>> elliptic_pi(0, 0)
pi/2
>>> elliptic_pi(1.0 - I/3, 2.0 + I)
3.29136443417283 + 0.32555634906645*I
Orthogonal Polynomials
(x).
The Jacobi polynomials are orthogonal on [1, 1] with respect to the weight
(1 x) (1 + x) .
See Also:
gegenbauer
(page
435),
chebyshevt root
(page
438),
chebyshevu
(page 437),
chebyshevu root (page 438),
legendre (page 439),
assoc legendre (page 439),
hermite (page 440),
laguerre (page 441),
assoc laguerre
(page
442),
sympy.polys.orthopolys.jacobi poly
(page
1120),
sympy.polys.orthopolys.gegenbauer poly
(page
1120),
sympy.polys.orthopolys.chebyshevt poly (page 1120), sympy.polys.orthopolys.chebyshevu poly
(page
1120),
sympy.polys.orthopolys.hermite poly
(page
1120),
sympy.polys.orthopolys.legendre poly (page 1120), sympy.polys.orthopolys.laguerre poly
(page 1120)
References
433
0)
+ 1)*hyper((-b - n, -n), (a + 1,), -1)/(factorial(n)*gamma(a + 1))
1)
1, n)/factorial(n)
sympy.functions.special.polynomials.jacobi normalized(n, a, b, x)
(,)
(x)
Jacobi polynomial Pn
(,)
(x).
The Jacobi polynomials are orthogonal on [1, 1] with respect to the weight
(1 x) (1 + x) .
This functions returns the polynomials normilzed:
1
1
(,)
Pm
(x)Pn(,) (x)(1 x) (1 + x) dx = m,n
See Also:
gegenbauer
(page
435),
chebyshevt root
(page
438),
chebyshevu
(page 437),
chebyshevu root (page 438),
legendre (page 439),
assoc legendre (page 439),
hermite (page 440),
laguerre (page 441),
assoc laguerre
(page
442),
sympy.polys.orthopolys.jacobi poly
(page
1120),
sympy.polys.orthopolys.gegenbauer poly
(page
1120),
sympy.polys.orthopolys.chebyshevt poly (page 1120), sympy.polys.orthopolys.chebyshevu poly
(page
1120),
sympy.polys.orthopolys.hermite poly
(page
1120),
434
>>> jacobi_normalized(n, a, b, x)
jacobi(n, a, b, x)/sqrt(2**(a + b + 1)*gamma(a + n + 1)*gamma(b + n + 1)/((a + b + 2*n + 1)*fact
Gegenbauer Polynomials
class sympy.functions.special.polynomials.gegenbauer
()
Gegenbauer polynomial Cn (x)
()
jacobi
(page
433),
chebyshevt root
(page
438),
chebyshevu
(page 437),
chebyshevu root (page 438),
legendre (page 439),
assoc legendre (page 439),
hermite (page 440),
laguerre (page 441),
assoc laguerre
(page
442),
sympy.polys.orthopolys.jacobi poly
(page
1120),
sympy.polys.orthopolys.gegenbauer poly
(page
1120),
sympy.polys.orthopolys.chebyshevt poly (page 1120), sympy.polys.orthopolys.chebyshevu poly
(page
1120),
sympy.polys.orthopolys.hermite poly
(page
1120),
sympy.polys.orthopolys.legendre poly (page 1120), sympy.polys.orthopolys.laguerre poly
(page 1120)
References
435
>>> gegenbauer(3, a, x)
x**3*(4*a**3/3 + 4*a**2 + 8*a/3) + x*(-2*a**2 - 2*a)
>>> gegenbauer(n, a, x)
gegenbauer(n, a, x)
>>> gegenbauer(n, a, -x)
(-1)**n*gegenbauer(n, a, x)
>>> gegenbauer(n, a, 0)
2**n*sqrt(pi)*gamma(a + n/2)/(gamma(a)*gamma(-n/2 + 1/2)*gamma(n + 1))
>>> gegenbauer(n, a, 1)
gamma(2*a + n)/(gamma(2*a)*gamma(n + 1))
>>> conjugate(gegenbauer(n, a, x))
gegenbauer(n, conjugate(a), conjugate(x))
>>> diff(gegenbauer(n, a, x), x)
2*a*gegenbauer(n - 1, a + 1, x)
Chebyshev Polynomials
class sympy.functions.special.polynomials.chebyshevt
Chebyshev polynomial of the rst kind, Tn (x)
chebyshevt(n, x) gives the nth Chebyshev polynomial (of the rst kind) in x, Tn (x).
The Chebyshev polynomials of the rst kind are orthogonal on [1, 1] with respect to the
1
weight 1x
.
2
See Also:
jacobi (page 433), gegenbauer (page 435), chebyshevt root (page 438),
chebyshevu (page 437), chebyshevu root (page 438), legendre (page 439),
assoc legendre (page 439),
hermite (page 440),
laguerre (page 441),
assoc laguerre
(page
442),
sympy.polys.orthopolys.jacobi poly
(page
1120),
sympy.polys.orthopolys.gegenbauer poly
(page
1120),
sympy.polys.orthopolys.chebyshevt poly (page 1120), sympy.polys.orthopolys.chebyshevu poly
(page
1120),
sympy.polys.orthopolys.hermite poly
(page
1120),
sympy.polys.orthopolys.legendre poly (page 1120), sympy.polys.orthopolys.laguerre poly
(page 1120)
References
[R251] (page 1908), [R252] (page 1908), [R253] (page 1908), [R254] (page 1908), [R255]
(page 1908)
Examples
>>>
>>>
>>>
1
>>>
x
436
>>> chebyshevt(2, x)
2*x**2 - 1
>>> chebyshevt(n, x)
chebyshevt(n, x)
>>> chebyshevt(n, -x)
(-1)**n*chebyshevt(n, x)
>>> chebyshevt(-n, x)
chebyshevt(n, x)
>>> chebyshevt(n, 0)
cos(pi*n/2)
>>> chebyshevt(n, -1)
(-1)**n
>>> diff(chebyshevt(n, x), x)
n*chebyshevu(n - 1, x)
class sympy.functions.special.polynomials.chebyshevu
Chebyshev polynomial of the second kind, Un (x)
chebyshevu(n, x) gives the nth Chebyshev polynomial of the second kind in x, Un (x).
The Chebyshev
polynomials of the second kind are orthogonal on [1, 1] with respect to
the weight 1 x2 .
See Also:
[R256] (page 1908), [R257] (page 1908), [R258] (page 1908), [R259] (page 1908), [R260]
(page 1908)
Examples
>>> from sympy import chebyshevt, chebyshevu, diff
>>> from sympy.abc import n,x
>>> chebyshevu(0, x)
1
>>> chebyshevu(1, x)
2*x
>>> chebyshevu(2, x)
4*x**2 - 1
437
>>> chebyshevu(n, x)
chebyshevu(n, x)
>>> chebyshevu(n, -x)
(-1)**n*chebyshevu(n, x)
>>> chebyshevu(-n, x)
-chebyshevu(n - 2, x)
>>> chebyshevu(n, 0)
cos(pi*n/2)
>>> chebyshevu(n, 1)
n + 1
>>> diff(chebyshevu(n, x), x)
(-x*chebyshevu(n, x) + (n + 1)*chebyshevt(n + 1, x))/(x**2 - 1)
jacobi (page 433), gegenbauer (page 435), chebyshevt (page 436), chebyshevu (page 437), chebyshevu root (page 438), legendre (page 439), assoc legendre (page 439),
hermite (page 440),
laguerre (page 441),
assoc laguerre
(page
442),
sympy.polys.orthopolys.jacobi poly
(page
1120),
sympy.polys.orthopolys.gegenbauer poly
(page
1120),
sympy.polys.orthopolys.chebyshevt poly (page 1120), sympy.polys.orthopolys.chebyshevu poly
(page
1120),
sympy.polys.orthopolys.hermite poly
(page
1120),
sympy.polys.orthopolys.legendre poly (page 1120), sympy.polys.orthopolys.laguerre poly
(page 1120)
Examples
>>> from sympy import chebyshevt, chebyshevt_root
>>> chebyshevt_root(3, 2)
-sqrt(3)/2
>>> chebyshevt(3, chebyshevt_root(3, 2))
0
chebyshevt (page 436), chebyshevt root (page 438), chebyshevu (page 437),
legendre (page 439), assoc legendre (page 439), hermite (page 440), laguerre
(page 441), assoc laguerre (page 442), sympy.polys.orthopolys.jacobi poly
(page
1120),
sympy.polys.orthopolys.gegenbauer poly
(page
1120),
sympy.polys.orthopolys.chebyshevt poly (page 1120), sympy.polys.orthopolys.chebyshevu poly
(page
1120),
sympy.polys.orthopolys.hermite poly
(page
1120),
sympy.polys.orthopolys.legendre poly (page 1120), sympy.polys.orthopolys.laguerre poly
(page 1120)
438
Examples
>>> from sympy import chebyshevu, chebyshevu_root
>>> chebyshevu_root(3, 2)
-sqrt(2)/2
>>> chebyshevu(3, chebyshevu_root(3, 2))
0
Legendre Polynomials
class sympy.functions.special.polynomials.legendre
legendre(n, x) gives the nth Legendre polynomial of x, Pn (x)
The Legendre polynomials are orthogonal on [-1, 1] with respect to the constant weight
1. They satisfy Pn (1) = 1 for all n; further, Pn is odd for odd n and even for even n.
See Also:
[R261] (page 1908), [R262] (page 1908), [R263] (page 1908), [R264] (page 1908)
Examples
>>> from sympy import legendre, diff
>>> from sympy.abc import x, n
>>> legendre(0, x)
1
>>> legendre(1, x)
x
>>> legendre(2, x)
3*x**2/2 - 1/2
>>> legendre(n, x)
legendre(n, x)
>>> diff(legendre(n,x), x)
n*(x*legendre(n, x) - legendre(n - 1, x))/(x**2 - 1)
d Pn (x)
dxm
439
See Also:
[R265] (page 1908), [R266] (page 1908), [R267] (page 1908), [R268] (page 1908)
Examples
>>> from sympy import assoc_legendre
>>> from sympy.abc import x, m, n
>>> assoc_legendre(0,0, x)
1
>>> assoc_legendre(1,0, x)
x
>>> assoc_legendre(1,1, x)
-sqrt(-x**2 + 1)
>>> assoc_legendre(n,m,x)
assoc_legendre(n, m, x)
Hermite Polynomials
class sympy.functions.special.polynomials.hermite
hermite(n, x) gives the nth Hermite polynomial in x, Hn (x)
The ( Hermite
polynomials are orthogonal on (, ) with respect to the weight
)
x2
exp 2 .
See Also:
440
References
Laguerre Polynomials
class sympy.functions.special.polynomials.laguerre
Returns the nth Laguerre polynomial in x, Ln (x).
Parameters n : int
Degree of Laguerre polynomial. Must be n >= 0.
See Also:
[R272] (page 1908), [R273] (page 1908), [R274] (page 1908), [R275] (page 1908)
Examples
>>> from sympy import laguerre, diff
>>> from sympy.abc import x, n
>>> laguerre(0, x)
1
441
>>> laguerre(1, x)
-x + 1
>>> laguerre(2, x)
x**2/2 - 2*x + 1
>>> laguerre(3, x)
-x**3/6 + 3*x**2/2 - 3*x + 1
>>> laguerre(n, x)
laguerre(n, x)
>>> diff(laguerre(n, x), x)
-assoc_laguerre(n - 1, 1, x)
[R276] (page 1908), [R277] (page 1908), [R278] (page 1908), [R279] (page 1908)
Examples
>>> from sympy import laguerre,
>>> from sympy.abc import x, n,
>>> assoc_laguerre(0, a, x)
1
>>> assoc_laguerre(1, a, x)
a - x + 1
>>> assoc_laguerre(2, a, x)
a**2/2 + 3*a/2 + x**2/2 + x*(-a
>>> assoc_laguerre(3, a, x)
a**3/6 + a**2 + 11*a/6 - x**3/6
x*(-a**2/2 - 5*a/2 - 3) + 1
assoc_laguerre, diff
a
- 2) + 1
+ x**2*(a/2 + 3/2) +
>>> assoc_laguerre(n, a, 0)
binomial(a + n, a)
442
>>> assoc_laguerre(n, a, x)
assoc_laguerre(n, a, x)
>>> assoc_laguerre(n, 0, x)
laguerre(n, x)
>>> diff(assoc_laguerre(n, a, x), x)
-assoc_laguerre(n - 1, a + 1, x)
>>> diff(assoc_laguerre(n, a, x), a)
Sum(assoc_laguerre(_k, a, x)/(-a + n), (_k, 0, n - 1))
Spherical Harmonics
Ynm() gives the spherical harmonic function of order n and m in and , Ynm (, ). The
four parameters are as follows: n 0 an integer and m an integer such that n m n
holds. The two angles are real-valued with [0, ] and [0, 2].
See Also:
Ynm c, Znm
References
[R280] (page 1908), [R281] (page 1909), [R282] (page 1909), [R283] (page 1909)
Examples
>>>
>>>
>>>
>>>
443
For specic integers n and m we can evalute the harmonics to more useful expressions
>>> simplify(Ynm(0, 0, theta, phi).expand(func=True))
1/(2*sqrt(pi))
>>> simplify(Ynm(1, -1, theta, phi).expand(func=True))
sqrt(6)*exp(-I*phi)*sin(theta)/(4*sqrt(pi))
>>> simplify(Ynm(1, 0, theta, phi).expand(func=True))
sqrt(3)*cos(theta)/(2*sqrt(pi))
>>> simplify(Ynm(1, 1, theta, phi).expand(func=True))
-sqrt(6)*exp(I*phi)*sin(theta)/(4*sqrt(pi))
>>> simplify(Ynm(2, -2, theta, phi).expand(func=True))
sqrt(30)*exp(-2*I*phi)*sin(theta)**2/(8*sqrt(pi))
>>> simplify(Ynm(2, -1, theta, phi).expand(func=True))
sqrt(30)*exp(-I*phi)*sin(2*theta)/(8*sqrt(pi))
>>> simplify(Ynm(2, 0, theta, phi).expand(func=True))
sqrt(5)*(3*cos(theta)**2 - 1)/(4*sqrt(pi))
>>> simplify(Ynm(2, 1, theta, phi).expand(func=True))
-sqrt(30)*exp(I*phi)*sin(2*theta)/(8*sqrt(pi))
>>> simplify(Ynm(2, 2, theta, phi).expand(func=True))
sqrt(30)*exp(2*I*phi)*sin(theta)**2/(8*sqrt(pi))
444
>>>
>>>
>>>
>>>
To get back the well known expressions in spherical coordinates we use full expansion
>>>
>>>
>>>
>>>
See Also:
Ynm, Znm
References
m>0
2
m
m
Zn (, ) := Yn (, )
m=0
m (,)
Ynm (,)Y
n
m<0
i 2
2
m
m
Zn (, ) = Yn (, )
m m
Yn (,)
Ynm (,)(1)
i 2
m>0
m=0
m<0
See Also:
Ynm, Ynm c
References
445
Tensor Functions
446
Examples
Symbolic indices:
>>> from sympy.abc import
>>> KroneckerDelta(i, j)
KroneckerDelta(i, j)
>>> KroneckerDelta(i, i)
1
>>> KroneckerDelta(i, i +
0
>>> KroneckerDelta(i, i +
KroneckerDelta(i, i + k +
i, j, k
1)
1 + k)
1)
classmethod eval(i, j)
Evaluates the discrete delta function.
Examples
>>> from sympy.functions.special.tensor_functions import KroneckerDelta
>>> from sympy.abc import i, j, k
>>> KroneckerDelta(i,
KroneckerDelta(i, j)
>>> KroneckerDelta(i,
1
>>> KroneckerDelta(i,
0
>>> KroneckerDelta(i,
KroneckerDelta(i, i +
j)
i)
i + 1)
i + 1 + k)
k + 1)
# indirect doctest
indices contain equal information
Returns True if indices are either both above or below fermi.
Examples
>>> from sympy.functions.special.tensor_functions import KroneckerDelta
>>> from sympy import Symbol
>>> a = Symbol(a, above_fermi=True)
>>> i = Symbol(i, below_fermi=True)
>>> p = Symbol(p)
>>> q = Symbol(q)
>>> KroneckerDelta(p, q).indices_contain_equal_information
True
>>> KroneckerDelta(p, q+1).indices_contain_equal_information
447
True
>>> KroneckerDelta(i, p).indices_contain_equal_information
False
is above fermi
True if Delta can be non-zero above fermi
See Also:
is below fermi, is only below fermi, is only above fermi
Examples
>>> from sympy.functions.special.tensor_functions import KroneckerDelta
>>> from sympy import Symbol
>>> a = Symbol(a, above_fermi=True)
>>> i = Symbol(i, below_fermi=True)
>>> p = Symbol(p)
>>> q = Symbol(q)
>>> KroneckerDelta(p, a).is_above_fermi
True
>>> KroneckerDelta(p, i).is_above_fermi
False
>>> KroneckerDelta(p, q).is_above_fermi
True
is below fermi
True if Delta can be non-zero below fermi
See Also:
is above fermi, is only above fermi, is only below fermi
Examples
>>> from sympy.functions.special.tensor_functions import KroneckerDelta
>>> from sympy import Symbol
>>> a = Symbol(a, above_fermi=True)
>>> i = Symbol(i, below_fermi=True)
>>> p = Symbol(p)
>>> q = Symbol(q)
>>> KroneckerDelta(p, a).is_below_fermi
False
>>> KroneckerDelta(p, i).is_below_fermi
True
>>> KroneckerDelta(p, q).is_below_fermi
True
448
Examples
>>> from sympy.functions.special.tensor_functions import KroneckerDelta
>>> from sympy import Symbol
>>> a = Symbol(a, above_fermi=True)
>>> i = Symbol(i, below_fermi=True)
>>> p = Symbol(p)
>>> q = Symbol(q)
>>> KroneckerDelta(p, a).is_only_above_fermi
True
>>> KroneckerDelta(p, q).is_only_above_fermi
False
>>> KroneckerDelta(p, i).is_only_above_fermi
False
killable index
Returns the index which is preferred to substitute in the nal expression.
The index to substitute is the index with less information regarding fermi level. If
indices contain same information, a is preferred before b.
See Also:
preferred index
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
p
449
preferred index
Returns the index which is preferred to keep in the nal expression.
The preferred index is the index with more information regarding fermi level. If
indices contain same information, a is preferred before b.
See Also:
killable index
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
i
>>>
a
>>>
i
450
Abstract
This document describes the implementation, installation and use of a geometric algebra
module written in python that utilizes the sympy (page 704) symbolic algebra library. The
python module galgebra has been developed for coordinate free calculations using the
operations (geometric, outer, and inner products etc.) of geometric algebra. The operations can be dened using a completely arbitrary metric dened by the inner products of
a set of arbitrary vectors or the metric can be restricted to enforce orthogonality and signature constraints on the set of vectors. In addition the module includes the geometric,
outer (curl) and inner (div) derivatives and the ability to dene a curvilinear coordinate
system. The module requires the sympy module and the numpy module for numerical
linear algebra calculations. For latex output a latex distribution must be installed.
c = (a + b)2
c2 = a2 + ab + ba + b2
a b = (c2 a2 b2 )/2 <
Thus a b is real. The objects generated from linear combinations of the geometric products of
vectors are called multivectors. If a basis for the underlying vector space is the set of vectors
formed from e1 , . . . , en a complete basis for the geometric algebra is given by the scalar 1, the
vectors e1 , . . . , en and all geometric products of vectors
ei1 ei2 . . . eir where 0 r n, 0 ij n and 0 < i1 < i2 < < ir n
Each base of the complete basis is represented by a noncommutative symbol (except for the
scalar 1) with name ei1 . . . eir so that the general multivector A is represented by (A is the
scalar part of the multivector and the Ai1 ,...,ir are scalars)
A=A+
451
The critical operation in setting up the geometric algebra is reducing the geometric product
of any two bases to a linear combination of bases so that we can calculate a multiplication
table for the bases. Since the geometric product is associative we can use the operation (by
denition for two vectors a b (ab + ba)/2 which is a scalar)
eij+1 eij = 2eij+1 eij eij eij+1
(5.1)
These processes are repeated untill every basis list in A is in normal (ascending) order with
no repeated elements. As an example consider the following
e3 e2 e1 = (2(e2 e3 ) e2 e3 )e1
= 2(e2 e3 )e1 e2 e3 e1
= 2(e2 e3 )e1 e2 (2(e1 e3 ) e1 e3 )
= 2((e2 e3 )e1 (e1 e3 )e2 ) + e2 e1 e3
= 2((e2 e3 )e1 (e1 e3 )e2 + (e1 e2 )e3 ) e1 e2 e3
which results from repeated application of equation 5.1 (page 452). If the product of basis
vectors contains repeated factors equation 5.1 (page 452) can be used to bring the repeated
factors next to one another so that if eij = eij+1 then eij eij+1 = eij eij+1 which is a scalar that
commutes with all the terms in the product and can be brought to the front of the product.
Since every repeated pair of vectors in a geometric product of r factors reduces the number
of noncommutative factors in the product by r 2. (The
) number of bases in the multivector
algebra is 2n and the number containing r factors is nr which is the number of combinations
or n things taken r at a time (binominal coecient).
The other construction required for formulating the geometric algebra is the outer or wedge
product (symbol ) of r vectors denoted by a1 ar . The wedge product of r vectors is
called an r-blade and is dened by ([Doran] (page 1909),p86)
a1 ar
ij1 ...ijr aij1 . . . aij1
ij1 ...ijr
where ij1 ...ijr is the contravariant permutation symbol which is +1 for an even permutation
of the superscripts, 0 if any superscripts are repeated, and 1 for an odd permutation of the
superscripts. From the denition a1 ar is antisymmetric in all its arguments and the
following relation for the wedge product of a vector a and an r-blade Br can be derived
a Br = (aBr + (1)r Br a)/2
(5.2)
Using equation 5.2 (page 452) one can represent the wedge product of all the basis vectors
in terms of the geometric product of all the basis vectors so that one can solve (the system of
equations is lower diagonal) for the geometric product of all the basis vectors in terms of the
wedge product of all the basis vectors. Thus a general multivector B can be represented as
a linear combination of a scalar and the basis blades.
B=B+
Using the blades ei1 ei2 er creates a graded algebra where r is the grade of the basis
blades. The grade-r part of B is the linear combination of all terms with grade r basis blades.
The scalar part of B is dened to be grade-0. Now that the blade expansion of B is dened
we can also dene the grade projection operator hBir by
hBir =
B i1 ,...,ir ei1 ei2 er
i1 ,...,ir , 0ij n
452
and
hBi hBi0 = B
Then if Ar is an r-grade multivector and B s is an s-grade multivector we have
Ar B s = hAr B s i|rs| + hAr B s i|rs|+2 + hAr B s ir+s
and dene ([Hestenes] (page 1909),p6)
Ar B s hAr B s ir+s
{
r or s 6= 0 :
Ar B s
r or s = 0 :
hAr B s i|rs|
0
where Ar B s is called the dot or inner product of two pure grade multivectors. For the case
of two non-pure grade multivectors
AB =
hAir hBis
r,s
AB =
hAir hBis
r,s6=0
Two other products, the right (c) and left (b) contractions, are dened by
{ hAr B s i
rs
AbB
0
r,s
{ hAr B s i
sr
AcB
0
r,s
rs
r<s
sr
s<r
}
}
A nal operation for multivectors is the reverse. If a multivector A is the geometric product
of r vectors (versor) so that A = a1 . . . ar the reverse is dened by
A ar . . . a 1
where for a general multivector we have (the the sum of the reverse of versors)
A = A +
(1)r(r1)/2
r=1
i1 ,...,ir , 0ij n
A
AA
453
(e_1,...,e_n) = symbols(e_1,...,e_n,commutative=False)
Several software packages for numerical geometric algebra calculations are available from
Doran-Lasenby group and the Dorst group. Symbolic packages for Cliord algebra using
orthongonal bases such as ei ej + ej ei = 2ij , where ij is a numeric array are available in
Maple and Mathematica. The symbolic algebra module, galgebra, developed for python does
not depend on an orthogonal basis representation, but rather is generated from a set of n
arbitrary symbolic vectors, e1 , e2 , . . . , en and a symbolic metric tensor gij = ei ej .
In order not to reinvent the wheel all scalar symbolic algebra is handled by the python module sympy (page 704) and the abstract basis vectors are encoded as noncommuting sympy
symbols.
The basic geometic algebra operations will be implemented in python by dening a multivector class, MV, and overloading the python operators in Table 5.1 (page 454) where A and B
are any two multivectors (In the case of +, -, *, , and | the operation is also dened if A or B
is a sympy symbol or a sympy real number).
Operation
A+B
A-B
A*B
AB
A|B
A<B
A>B
Result
sum of multivectors
dierence of multivectors
geometric product
outer product of multivectors
inner product of multivectors
left contraction of multivectors
right contraction of multivectors
sympy.galgebra.precedence.GAeval(s, pstr=False)
The function GAeval() returns a multivector expression dened by the string s where
the operations in the string are parsed according to the precedences dened by dene precedence(). pstr is a ag to print the input and output of GAeval() for debugging
purposes. GAeval() works by adding parenthesis to the input string s with the precedence dened by op ord=<>|,,*. Then the parsed string is converted to a sympy expression using the python eval() function. For example consider where X, Y, Z, and W
are multivectors
define_precedence(globals())
V = GAeval(X|Y^Z*W)
that would be input into the multivector setup function. The next step would be to dene the
symbolic metric for the geometric algebra of the basis we have dened. The default metric
is the most general and is the matrix of the following symbols
g=
(a0.a2) (a1.a2) (a2.a2) 0 0
0
0
0
0 2
0
0
0
2 0
tensor
Here we have specied that n and nbar are orthonal to all the as, (n.n) = (nbar.nbar) = 0, and
(n.nbar) = 2. Using # in the metric denition string just tells the program to use the default
symbol for that value.
5.9. Geometric Algebra Module
455
When MV.setup is called multivector representations of the basis local to the program are
instantiated. For our rst example that means that the symbolic vectors named a0, a1, and
a2 are created and returned from MV.setup via a tuple as in (a_1,a_2,a3) = MV.setup(a_1 a_2 a_3,metric=metric)
Note that the python variable name for a basis vector does not have to correspond to the
name give in MV.setup(), one may wish to use a shorted python variable name to reduce
programming (typing) errors, for example one could use (a1,a2,a3) = MV.setup(a_1 a_2 a_3,metric=metric)
or
(g1,g2,g3) = MV.setup(gamma_1 gamma_2 gamma_3,metric=metric)
In the simplist case of two basis vectors a 1 and a 2 we have a list of bases
MV.bases = [[Symbol(ONE,commutative=False)],[Symbol(a_1,commutative=False),\
Symbol(a_2,commutative=False)],[Symbol(a_1*a_2,commutative=False)]]
Note: The reason that the base for the scalar component of the multivector is dened as
Symbol(ONE,commutative=False), a noncommutative symbol is because of the properties
of the left and right contraction operators which are non commutative if one is contracting a
multivector with a scalar.
For the case of the basis blades we have
MV.blades = [[Symbol(ONE,commutative=False)],[Symbol(a_1,commutative=False),\
Symbol(a_2,commutative=False)],[Symbol(a_1^a_2,commutative=False)]]
456
Note: For all grades/pseudo-grades greater than one (vectors) the * in the name of the
base symbol is replaced with a in the name of the blade symbol so that for all basis bases
and blades of grade/pseudo-grade greater than one there are dierent symbols for the corresponding bases and blades.
The function that builds all the required arrays and dictionaries upto the base multiplication
table is shown below. MV.dim is the number of basis vectors and the combinations functions
from itertools constructs the index tupels for the bases of each pseudo grade. Then the noncommutative symbol representing each base is constructed from each index tuple. MV.ONE
is the noncommutative symbol for the scalar base. For example if MV.dim = 3 then
MV.index = ((),((0,),(1,),(2,)),((0,1),(0,2),(1,2)),((0,1,2)))
Note: In the case that the metric tensor is diagonal (orthogonal basis vectors) both base
and blade bases are identical and fewer arrays and dictionaries need to be constructed.
@staticmethod
def build_base_blade_arrays(debug):
indexes = tuple(range(MV.dim))
MV.index = [()]
for i in indexes:
MV.index.append(tuple(combinations(indexes,i+1)))
MV.index = tuple(MV.index)
#Set up base and blade and index arrays
if not MV.is_orthogonal:
MV.bases_flat = []
MV.bases = [MV.ONE]
MV.base_to_index = {MV.ONE:()}
MV.index_to_base = {():MV.ONE}
MV.base_grades
= {MV.ONE:0}
MV.base_grades[ONE] = 0
MV.blades = [MV.ONE]
MV.blades_flat = []
MV.blade_grades
= {MV.ONE:0}
MV.blade_grades[ONE] = 0
MV.blade_to_index = {MV.ONE:()}
MV.index_to_blade = {():MV.ONE}
ig = 1 #pseudo grade and grade index
for igrade in MV.index[1:]:
if not MV.is_orthogonal:
= [] #base symbol array within pseudo grade
bases
blades
= [] #blade symbol array within grade
ib = 0 #base index within grade
for ibase in igrade:
#build base name string
(base_sym,base_str,blade_sym,blade_str) = MV.make_base_blade_symbol(ibase)
if not MV.is_orthogonal:
bases.append(base_sym)
MV.bases_flat.append(base_sym)
457
blades.append(blade_sym)
MV.blades_flat.append(blade_sym)
base_index = MV.index[ig][ib]
#Add to dictionarys relating symbols and indexes
if not MV.is_orthogonal:
MV.base_to_index[base_sym]
= base_index
MV.index_to_base[base_index] = base_sym
MV.base_grades[base_sym]
= ig
MV.blade_to_index[blade_sym] = base_index
MV.index_to_blade[base_index] = blade_sym
MV.blade_grades[blade_sym] = ig
ib += 1
ig += 1
if not MV.is_orthogonal:
MV.bases.append(tuple(bases))
MV.blades.append(tuple(blades))
if not MV.is_orthogonal:
= tuple(MV.bases)
MV.bases
MV.bases_flat = tuple(MV.bases_flat)
MV.bases_flat1 = (MV.ONE,)+MV.bases_flat
MV.bases_set
= set(MV.bases_flat[MV.dim:])
MV.blades
MV.blades_flat
MV.blades_flat1
MV.blades_set
=
=
=
=
tuple(MV.blades)
tuple(MV.blades_flat)
(MV.ONE,)+MV.blades_flat
set(MV.blades_flat[MV.dim:])
return
If we have another multivector B to multiply with A we can calculate the product in terms of
a linear combination of bases if we have a multiplication table for the bases.
Blade Representation of Multivectors
Since we can now calculate the symbolic geometric product of any two multivectors we can
also calculate the blades corresponding to the product of the symbolic basis vectors using the
formula
1
r
Ar b = (Ar b (1) bAr ) ,
2
where Ar is a multivector of grade r and b is a vector. For our example basis the result is
shown in Table 5.3 (page 458).
458
1 = 1
a0 = a0
a1 = a1
a2 = a2
a0a1 = {-(a0.a1)}1+a0a1
a0a2 = {-(a0.a2)}1+a0a2
a1a2 = {-(a1.a2)}1+a1a2
a0a1a2 = {-(a1.a2)}a0+{(a0.a2)}a1+{-(a0.a1)}a2+a0a1a2
A=
Ar
r=0
The geometric product of two pure grade multivectors Ar and Bs has the form
Ar Bs = hAr Bs i|rs| + hAr Bs i|rs|+2 + + hAr Bs ir+s
459
where hit projects the t grade components of the multivector argument. The inner and outer
products of Ar and Bs are then dened to be
Ar Bs = hAr Bs i|rs|
Ar Bs = hAr Bs ir+s
and
AB =
Ar Bs
r,s
AB =
Ar Bs
r,s
Likewise the right (b) and left (c) contractions are dened as
{
}
hAr Bs irs r s
Ar bBs =
0
r<s
{
}
hAr Bs isr s r
Ar cBs =
0
s<r
and
AbB =
Ar bBs
r,s
AcB =
Ar cBs
r,s
Warning: In the MV class we have overloaded the operator to represent the outer
product so that instead of calling the outer product function we can write mv1 mv2. Due
to the precedence rules for python it is absolutely essential to enclose outer products in
parenthesis.
Warning: In the MV class we have overloaded the | operator for the inner product, >
operator for the right contraction, and < operator for the left contraction. Instead of calling
the inner product function we can write mv1|mv2, mv1>mv2, or mv1<mv2 respectively
for the inner product, right contraction, or left contraction. Again, due to the precedence
rules for python it is absolutely essential to enclose inner products and/or contractions
in parenthesis.
Reverse of Multivector
If A is the geometric product of r vectors
A = a1 . . . ar
then the reverse of A designated A is dened by
A ar . . . a 1 .
The reverse is simply the product with the order of terms reversed. The reverse of a sum of
products is dened as the sum of the reverses so that for a general multivector A we have
A =
hAii
i=0
460
but
hAii = (1)
i(i1)
2
hAii
(5.4)
which is proved by expanding the blade bases in terms of orthogonal vectors and showing
that equation 5.4 (page 461) holds for the geometric product of orthogonal vectors.
The reverse is important in the theory of rotations in n-dimensions. If R is the product of an
even number of vectors and RR = 1 then RaR is a composition of rotations of the vector a.
If R is the product of two vectors then the plane that R denes is the plane of the rotation.
That is to say that RaR rotates the component of a that is projected into the plane dened by
2U
a and b where
( 2 R = )ab. R may be written R = e , where is the angle of rotation and u is a
unit blade u = 1 that denes the plane of rotation.
Reciprocal Frames
If we have M linearly independent vectors (a frame), a1 , . . . , aM , then the reciprocal frame is
a1 , . . . , aM where ai aj = ij , ij is the Kronecker delta (zero if i 6= j and one if i = j). The
reciprocal frame is constructed as follows:
EM = a1 aM
1
EM
=
Then
i1
ai = (1)
EM
2
EM
1
(a1 a
i aM ) EM
where a
i indicates that ai is to be deleted from the product. In the standard notation if a
vector is denoted with a subscript the reciprocal vector is denoted with a superscript. The
multivector setup function MV.setup(basis,metric,rframe) has the argument rframe with a
default value of False. If it is set to True the reciprocal frame of the basis vectors is calculated.
Additionally there is the function reciprocal frame(vlst,names=) external to the MV class
that will calculate the reciprocal frame of a list, vlst, of vectors. If the argument names is set
to a space delimited string of names for the vectors the reciprocal vectors will be given these
names.
Geometric Derivative
If F is a multivector eld that is a function of a vector x = xi ei (we are using the summation
convention that pairs of subscripts and superscripts are summed over the dimension of the
vector space) then the geometric derivative F is given by (in this section the summation
convention is used):
F
F = ei i
x
If FR is a grade-R multivector and FR = FRi1 ...iR ei1 eiR then
FR =
FRi1 ...iR j
e (ei1 eiR )
xj
Note that ej (ei1 eiR ) can only contain grades R 1 and R + 1 so that FR also can only
contain those grades. For a grade-R multivector FR the inner (div) and outer (curl) derivatives
are dened as
FR = hFR iR1
and
FR = hFR iR+1
5.9. Geometric Algebra Module
461
For a general multivector function F the inner and outer derivatives are just the sum of the
inner and outer dervatives of each grade of the multivector function.
Curvilinear coordinates are derived from a vector function x() where = (1 , . . . , N ) where
the number of coordinates is equal to the dimension of the vector space. In the case of 3dimensional spherical coordinates = (r, , ) and the coordinate generating function x()
is
x = r cos () sin () ex + r sin () sin () ey + r cos () ez
x
A coordinate frame is derived from x by ei = i . The following show the frame for spherical
coordinates.
er = cos () sin () ex + sin () sin () ey + cos () ez
e = cos () cos () ex + r cos () sin () ey r sin () ez
e = r sin () sin () ex + r cos () sin () ey
The coordinate frame generated in this manner is not necessarily normalized so dene a
normalized frame by
ei
ei
e
i = 2 =
|ei |
|ei |
2
This works for all ei 6= 0 since we have dened |ei | = |e2i |. For spherical coordinates the
normalized frame vectors are
e
r = cos () sin () ex + sin () sin () ey + cos () ez
e
= cos () cos () ex + cos () sin () ey sin () ez
e
= sin () ex + cos () ey
The geometric derivative in curvilinear coordinates is given by
)
(
FR = ei i FRi1 ...iR e
i1 e
iR
x
( i1 ...iR
)
j
=e
FR
e
i1 e
iR
j
(
)
i1 ...iR
=
F
ej (
e i1 e
iR ) + FRi1 ...iR ej j (
ei1 e
iR )
j R
(
)
i1 ...iR
=
F
ej (
e i1 e
iR ) + FRi1 ...iR C {
ei1 e
iR }
j R
where
(
e i1 e
iR )
j
are the connection multivectors for the curvilinear coordinate system. For a spherical coordinate system they are
2
C {
er } =
r
cos ()
1
C {
e } =
+ e
r e
r sin () r
1
cos ()
C {
e } = e
r e
+
e
e
r
r sin ()
cos ()
1
C {
er e } =
e
r + e
r sin ()
r
1
cos ()
C {
er e
} = e
e
r e
e
r
r sin ()
2
C {
e e
} = e
r e
e
r
C {
er e
e
} = 0
C {
e i1 e
iR } = ej
462
463
vectors. These symbols are used as the arguments of a multivector eld as a function
of position and for calculating the derivatives of a multivector eld (if coords is dened
then rframe is automatically set equal to True). Additionally, MV.setup() calculates the
pseudo scalar, I and makes them available to the programmer as MV.I and MV.Iinv.
MV.setup() always returns a tuple containing the basis vectors (as multivectors) so that
if we have the code
(e1,e2,e3) = MV.setup(e_1 e_2 e_3)
Another option is
(e1,e2,e3) = MV.setup(e*1|2|3)
which produce the same results as the previous method. Note that if we had used
(e1,e2,e3) = MV.setup(e*x|y|z)
then the basis vectors would have been labeled e x, e y, and e z. If coords is dened then
MV.setup() returns the tuple
X = (x,y.z) = symbols(x y z)
(ex,ey,ez,grad) = MV.setup(e,coords=X)
the basis vectros are again labeled e x, e y, and e z and the additional vector grad is
returned. grad acts as the gradient operator (geometric derivative) so that if F() is a
multivector function of (x,y,z) then
DFl = grad*F
DFr = F*grad
This is the position vector for the spherical coordinate system expressed in terms of the
rectangular coordinate components given in terms of the spherical coordinates r, th, and
phi. The second component of curv is
[1,r,r*sin(th)]
The components of curv[1] are the normalizing factors for the basis vectors of the spherical coordinate system that are calculated from the derivatives of curv[0] with respect to
the coordinates r, th, and phi. In theory the normalizing factors can be calculated from
the derivatives of curv[0]. In practice one cannot currently specify in sympy that the
square of a function is always positive which leads to problems when the normalizing
464
factor is the square root of a squared function. To avoid these problems the normalizing
factors are explicitly dened in curv[1].
Note: In the case of curvlinear coordinates debug also prints the connection multivectors.
Instantiating a Multivector
Now that grades and bases have been described we can show all the ways that a multivector
can be instantiated. As an example assume that the multivector space is initialized with
(e1,e2,e3) = MV.setup(e_1 e_2 e_3)
base
default
string s
string s
string s
string s,n
string s
string s
string s
sympy scalar c
multivector
result
Zero multivector
symbolic scalar of value Symbol(s)
symbolic vector
symbolic bivector
symbolic n-grade multivector
symbolic pseudoscalar
symbolic even multivector
symbolic general multivector
zero grade multivector with coecient c
copy constructor for multivector
If the base argument is a string s then the coecients of the resulting multivector are
named as follows:
The grade r coecients consist of the base string, s, followed by a double underscore, , and an index string of r symbols. If coords is dened the index string
will consist of coordinate names in a normal order dened by the coords tuple.
If coords is not dened the index string will be integers in normal (ascending)
order (for an n dimensional vector space the indices will be 1 to n). The double
underscore is used because the latex printer interprets it as a superscript and
superscripts in the coecients will balance subscripts in the bases.
For example if If coords=(x,y,z) and the base is A, the list of all possible coecients for the most general multivector would be A, A x, A y, A z, A xy, A xz,
A yz, and A xyz. If the latex printer is used and e is the base for the basis vectors then the pseudo scalar would print as Axyz ex ey ez . If coordinates are
5.9. Geometric Algebra Module
465
not dened it would print as A123 e1 e2 e3 . For printed output all multivectors
are represented in terms of products of the basis vectors, either as geometric
products or wedge products. This is also true for the output of expressions
containing reciprocal basis vectors.
If the fct argument of MV() is set to True and the coords argument in MV.setup() is
dened the symbolic coecients of the multivector are functions of the coordinates.
Basic Multivector Class Functions
sympy.galgebra.ga.MV.convert to blades(self)
Convert multivector from the base representation to the blade representation. If multivector is already in blade representation nothing is done.
sympy.galgebra.ga.MV.convert from blades(self)
Convert multivector from the blade representation to the base representation. If multivector is already in base representation nothing is done.
sympy.galgebra.ga.MV.dd(self, v)
For a mutivector function F and a vector v then F.dd(v) is the directional derivate of F in
the direction v, (v )F .
sympy.galgebra.ga.MV.diff(self, var)
Calculate derivative of each multivector coecient with resepect to variable var and
form new multivector from coecients.
sympy.galgebra.ga.MV.dual(self)
Return dual of multivector which is multivector left multiplied by pseudoscalar MV.I
([Hestenes] (page 1909),p22).
sympy.galgebra.ga.MV.even(self)
Return the even grade components of the multivector.
sympy.galgebra.ga.MV.exp(self, alpha=1, norm=0, mode=T)
Return exponential of a blade (if self is not a blade error message is generated). If A is
the blade then eA is returned where the default mode, T, assumes AA < 0 so that
(
)
(
) A
eA = cos A2 + sin A2
.
A2
If the mode is not T then AA > 0 is assumed so that
( )
( ) A
eA = cosh A2 + sinh A2 .
A2
If norm = N > 0 then
eA = cos (N ) + sin (N )
A
N
or
eA = cosh (N ) + sinh (N )
A
N
466
sympy.galgebra.ga.MV.func(self, fct)
Apply the sympy scalar function fct to each coecient of the multivector.
sympy.galgebra.ga.MV.grade(self, igrade=0)
Return a multivector that consists of the part of the multivector of grade equal to igrade.
If the multivector has no igrade part return a zero multivector.
sympy.galgebra.ga.MV.inv(self)
Return the inverse of the multivector if self*se.rev() is a nonzero ctor.
sympy.galgebra.ga.MV.norm(self)
sympy.galgebra.ga.diagpq(p, q=0)
Returns string equivalent metric tensor for signature (p, q).
sympy.galgebra.ga.arbitrary metric(n)
Returns string equivalent metric tensor for arbitrary signature.
sympy.galgebra.ga.arbitrary metric conformal(n)
Returns string equivalent metric tensor for arbitrary signature (n+1,1).
sympy.galgebra.ga.Com(A, B)
Calulate commutator of multivectors A and B. Returns (AB BA)/2.
sympy.galgebra.ga.DD(v, f)
Calculate directional derivative of multivector function f in direction of vector v. Returns
f.dd(v).
sympy.galgebra.ga.Format(Fmode=True, Dmode=True, ipy=False)
See latex printing.
5.9. Geometric Algebra Module
467
sympy.galgebra.precedence.GAeval(s, pstr=False)
Returns multivector expression for string s with operator precedence for string s dened
by inputs to function dene precedence(). if pstr=True s and s with parenthesis added
to enforce operator precedence are printed.
sympy.galgebra.ga.Nga(x, prec=5)
If x is a multivector with coecients that contain oating point numbers, Nga() rounds
all these numbers to a precision of prec and returns the rounded multivector.
sympy.galgebra.ga.ReciprocalFrame(basis, mode=norm)
If basis is a list/tuple of vectors, ReciprocalFrame() returns a tuple of reciprocal vectors.
If mode=norm the vectors are normalized. If mode is anything other than norm the
vectors are unnormalized and the normalization coecient is added to the end of the
tuple. One must divide by the coecient to normalize the vectors.
sympy.galgebra.ga.ScalarFunction(TheFunction)
If TheFuction is a real sympy fuction a scalar multivector function is returned.
sympy.galgebra.ga.cross(M1, M2)
If M1 and M2 are 3-dimensional euclidian vectors the vector cross product is returned,
v1 v2 = I (v1 v2 ).
sympy.galgebra.precedence.define precedence(gd, op ord=<>|, , *)
This is used with the GAeval() fuction to evaluate a string representing a multivector
expression with a revised operator precedence. dene precedence() redenes the operator precedence for multivectors. dene precedence() must be called in the main program an the argument gd must be globals(). The argument op ord denes the order of
operator precedence from high to low with groups of equal precedence separated by
commas. the default precedence op ord=<>|,,* is that used by Hestenes ([Hestenes]
(page 1909),p7,[Doran] ,p38).
sympy.galgebra.ga.dual(M)
Return the dual of the multivector M, M I 1 .
sympy.galgebra.ga.inv(B)
If for the multivector B, BB is a nonzero scalar, return B 1 = B /(BB ).
sympy.galgebra.ga.proj(B, A)
Project blade A on blade B returning (AbB) B 1 .
sympy.galgebra.ga.refl(B, A)
Reect blade A in blade B. If r is grade of A and s is grade of B returns (1)s(r+1) BAB 1 .
sympy.galgebra.ga.rot(itheta, A)
Rotate blade A by 2-blade itheta. Is is assumed that itheta*itheta > 0 so that the rotation
is Euclidian and not hyperbolic so that the angle of rotation is theta = itheta.norm().
Ther in 3-dimensional Euclidian space. theta is the angle of rotation (scalar in radians)
and n is the vector axis of rotation. Returned is the rotor cos(theta)+sin(theta)*N where
N is the normalized dual of n.
Multivector Derivatives
468
Then the gradient operator vector is grad (actually the user can give it any name he wants
to). Then the derivatives of the multivector function F are given by
F = MV(F,mv,fct=True)
F = grad F
F = F grad
F = grad F
F = F grad
F = grad|F
F F = F |grad
bF = grad < F
F b = F < grad
cF = grad > F
F c = F > grad
The preceding code block gives examples of all possible multivector derivatives of the multivector function F where * give the left and right geometric derivatives, gives the left and
right exterior (curl) derivatives, | gives the left and right interior (div) derivatives, < give the
left and right derivatives for the left contraction, and > give the left and right derivatives
for the right contraction. To understand the left and right derivatives see a reference on
geometric calculus ([Doran] (page 1909),chapter6).
If one is taking the derivative of a complex expression that expression should be in parenthesis. Additionally, whether or not one is taking the derivative of a complex expression the grad
vector and the expression it is operating on should always be in parenthesis unless the grad
operator and the expression it is operating on are the only objects in the expression.
Vector Manifolds
In addtition to the galgebra module there is a manifold module that allows for the denition of a geometric algebra and calculus on a vector manifold. The vector mainfold is
dened by a vector function of some coordinates in an embedding vector space ([Doran]
(page 1909),p202,[Hestenes] ,p139). For example the unit 2-sphere would be the collection
of vectors on the unit shpere in 3-dimensions with possible coordinates of and the angles
of elevation and azimuth. A vector function X (, ) that denes the manifold would be given
by
X (, ) = cos () ez + cos () (cos () ex + sin () ey )
The module manifold.py is transitionary in that all calculation are performed in the embedding vector space (geometric algebra). Thus due to the limitations on sympys simplify() and
trigsimp(), simple expressions may appear to be very complicated since they are expressed
in terms of the basis vectors (bases/blades) of the embedding space and not in terms of the
vector space (geometric algebra) formed from the manifolds basis vectors. A future implementation of Manifold.py will correct this diciency. The member functions of the vector
manifold follow.
sympy.galgebra.ga.Manifold(x, coords, debug=False, I=None)
Initializer for vector manifold where x is the vector function of the coords that denes
the manifold and coords is the list/tuple of sympy symbols that are the coordinates. The
basis vectors of the manifold as a fuction of the coordinates are returned as a tuple. I
is the pseudo scalar for the manifold. The default is for the initializer to calculate I,
however for complicated x functions (especially where trigonometric functions of the
5.9. Geometric Algebra Module
469
coordinates are involved) it is sometimes a good idea to calculate I separately and input
it to Manifold().
sympy.galgebra.ga.Basis(self)
Return the basis vectors of the manifold as a tuple.
sympy.galgebra.ga.DD(self, v, F, opstr=False)
Return the manifold directional derivative of a multivector function F dened on the
manifold in the vector direction v.
sympy.galgebra.ga.Grad(self, F)
Return the manifold multivector derivative of the multivector function F dened on the
manifold.
sympy.galgebra.ga.Proj(self, F)
Return the projection of the multivector F onto the manifold tangent space.
An example of a simple vector manifold is shown below which demonstrates the instanciation
of a manifold, the dening of vector and scalar functions on the manifold and the calculation
of the geometric derivative of those functions.
Standard Printing
GA LatexPrinter, derived from the sympy latex printer class. Additionally, there is an enhanced print class that enhances the console output of sympy to make the printed output
multivectors, functions, and derivatives more readable. enhanced print requires an ansi console such as is supplied in linux or the program ansicon (github.com/adoxa/ansicon) for windows which replaces cmd.exe.
For a windows user the simplest way to implement ansicon is to use the geany editor and in
the Edit->Preferences->Tools menu replace cmd.exe with ansicon.exe (be sure to supply the
path to ansicon).
If enhanced print is called in a program (linux) when multivectors are printed the basis blades
or bases are printed in bold text, functions are printed in red, and derivative operators in
green.
For formatting the multivector output there is the member function
sympy.galgebra.ga.Fmt(self, fmt=1, title=None)
Fmt is used to control how the multivector is printed with the argument fmt. If fmt=1 the
entire multivector is printed on one line. If fmt=2 each grade of the multivector is printed
on one line. If fmt=3 each component (base) of the multivector is printed on one line. If a
title is given then title = multivector is printed. If the usual print command is used the entire
multivector is printed on one line.
sympy.galgebra.ga.ga print on()
Redirects printer output from standard sympy print handler. Needed if one wishes to use
compact forms of function and derivative output strings for interactive use.
sympy.galgebra.ga.ga print off()
Restores standard sympy print handler.
sympy.galgebra.printing.GA Printer()
Context handler for use inside Sympy code. The code indented under the with GA Printer():
statement will run with the compact forms of function and derivative output strings, and have
the printing restored to standard sympy printing after it has nished, even if it is aborted with
an exception.
Latex Printing
For latex printing one uses one functions from the galgebra module and one function from
the galgebra/printing module. The functions are
sympy.galgebra.printing.Format(Fmode=True, Dmode=True, ipy=False)
This function from the galgebra module turns on latex printing with the following options
argument
Fmode
Dmode
ipy
value
True
False
True
False
False
True
result
Print functions without argument list, f
Print functions with standard sympy latex formatting, f (x, y, z)
Print partial derivatives with condensed notatation, x f
Print partial derivatives with standard sympy latex formatting f
x
Redirect print output to le for post-processing by latex
Do not redirect print output (This is used for Ipython with MathJax)
471
on your computer. If you are running ubuntu the evince viewer is automatically used.
On other operating systems if pdf = the name of the pdf le is executed. If the pdf le
type is associated with a viewer this will launch the viewer with the associated le. All
latex les except the pdf le are deleted. If debug = True the le lename is printed
to standard output for debugging purposes and lename (the tex le) is saved. If lename is not entered the default lename is the root name of the python program being
executed with .tex appended. The format for the paper is
paper=(w,h)
paper=letter
The default of paper=(14,11) was chosen so that long multivector expressions would not
be truncated on the display.
The xdvi function requires that latex and a pdf viewer be installed on the computer.
As an example of using the latex printing options when the following code is executed
from sympy.galgebra.printing import xdvi
from sympy.galgebra.ga import *
Format()
(ex,ey,ez) = MV.setup(e*x|y|z)
A = MV(A,mv)
print r\bm{A} =,A
A.Fmt(2,r\bm{A})
A.Fmt(3,r\bm{A})
xdvi()
472
f = MV(f,scalar,fct=True)
A = MV(A,vector,fct=True)
B = MV(B,grade2,fct=True)
print r\bm{A} =,A
print r\bm{B} =,B
print grad*f =,grad*f
print rgrad|\bm{A} =,grad|A
print rgrad*\bm{A} =,grad*A
print
print
print
print
r-I*(grad^\bm{A}) =,-MV.I*(grad^A)
rgrad*\bm{B} =,grad*B
rgrad^\bm{B} =,grad^B
rgrad|\bm{B} =,grad|B
xdvi()
A =Ax ex + Ay ey + Az ez
B =B xy ex ey + B xz ex ez + B yz ey ez
f =x f ex + y f ey + z f ez
A =x Ax + y Ay + z Az
A =x Ax + y Ay + z Az + (y Ax + x Ay ) ex ey + (z Ax + x Az ) ex ez
+ (z Ay + y Az ) ey ez
I( A) = (z Ay + y Az ) ex + (z Ax x Az ) ey + (y Ax + x Ay ) ez
B = (y B xy z B xz ) ex + (x B xy z B yz ) ey + (x B xz + y B yz ) ez
+ (z B xy y B xz + x B yz ) ex ey ez
B = (z B xy y B xz + x B yz ) ex ey ez
B = (y B xy z B xz ) ex + (x B xy z B yz ) ey + (x B xz + y B yz ) ez
This example also demonstrates several other features of the latex printer.
In the
case that strings are input into the latex printer such as rgrad*\boldsymbol{A},
rgrad\boldsymbol{A}, or rgrad*\boldsymbol{A}. The text symbols grad, , |, and *
are mapped by the xdvi() post-processor as follows if the string contains an =.
original
grad*A
AB
A|B
A*B
A<B
A>B
replacement
\boldsymbol{\nabla}A
A\wedge B
A\cdot B
AB
A\lfloor B
A\rfloor B
displayed latex
A
AB
AB
AB
AbB
AcB
If the string to be printed contains a % none of the above substitutions are made before the
latex processor is applied. In general for the latex printer strings are assumed to be in a math
environment (equation* or align*) unless the string contains a #.
Note: Except where noted the conventions for latex printing follow those of the latex printing
module of sympy. This includes translating sympy variables with Greek name (such as alpha)
to the equivalent Greek symbol () for the purpose of latex printing. Also a single underscore
5.9. Geometric Algebra Module
473
in the variable name (such as X j) indicates a subscript (Xj ), and a double underscore (such
as X k) a superscript (X k ). The only other change with regard to the sympy latex printer is
that matrices are printed full size (equation displaystyle).
Printer Redirection
In order to print transparently, that is to simply use the print statement with both text and
LaTeX printing the printer output is redirected. In the case of text printing the reason for
redirecting the printer output is because the sympy printing functions print Derivative and
print Function are redened to make the output more compact. If one does not wish to use
the compact notation redirection is not required for the text printer. If one wishes to use
the redened print Derivative and print Function the printer should be redirected with the
function ga print on() and restored with the function ga print o(). Both functions can be
imported from sympy.galgebra.ga (see examples/galgebra/terminal check.py for usage).
SymPy provides a context handler that will allow you to rewrite any ga print on(); do something; ga print o(); sequence like this:
with GA_printer:
do something
This has the advantage that even in the case of an exception inside do something, the
ga print o(); call will be made.
For LaTeX printing the Format() (import from sympy.galgebra.ga) redirects the printer output to a string. After all printing requests one must call the function xdvi() (import from
sympy.galgebra.printing) tp process the string to a LaTeX format, compile with pdatex, and
displayed the resulting pdf le. The function xdvi() also restores the printer output to normal
for standard sympy printing. If Format(ipy=True) is used there is no printer redirection and
the LaTeX output is simply sent to sys.stdout for use in Ipython (Ipython LaTeX interface for
galgebra not yet implemented).
Other Printing Functions
These functions are used together if one wishes to print both code and output in a single le.
They work for text printing and for latex printing.
For these functions to work properly the last function dened must not contain a
Print Function() call (the last function dened is usually a dummy() function that does nothing).
Additionally, to work properly none of the functions containing Print Function() can contain
function denintions (local functions).
sympy.galgebra.printing.Get Program(o=False)
Tells program to print both code and output from functions that have been properly
tagged with Print Function(). Get Program() must be in main program before the functions that you wish code printing from are executed. the o argument in Get Program()
allows one to turn o the printing of the code by changing one line in the entire program
(o=True).
sympy.galgebra.printing.Print Function()
Print Function() is included in those functions where one wishes to print the code block
along with (before) the usual printed output. The Print Function() statement should
474
be included immediately after the function def statement. For proper usage of both
Print Function() and Get Program() see the following example.
As an example consider the following code
from sympy.galgebra.printing import xdvi,Get_Program,Print_Function
from sympy.galgebra.ga import *
Format()
def basic_multivector_operations_3D():
Print_Function()
(ex,ey,ez) = MV.setup(e*x|y|z)
A = MV(A,mv)
A.Fmt(1,A)
A.Fmt(2,A)
A.Fmt(3,A)
A.even().Fmt(1,%A_{+})
A.odd().Fmt(1,%A_{-})
X = MV(X,vector)
Y = MV(Y,vector)
print g_{ij} =,MV.metric
X.Fmt(1,X)
Y.Fmt(1,Y)
(X*Y).Fmt(2,X*Y)
(X^Y).Fmt(2,X^Y)
(X|Y).Fmt(2,X|Y)
return
def basic_multivector_operations_2D():
Print_Function()
(ex,ey) = MV.setup(e*x|y)
print g_{ij} =,MV.metric
X = MV(X,vector)
A = MV(A,spinor)
X.Fmt(1,X)
A.Fmt(1,A)
(X|A).Fmt(2,X|A)
(X<A).Fmt(2,X<A)
(A>X).Fmt(2,A>X)
return
def dummy():
return
Get_Program()
basic_multivector_operations_3D()
475
basic_multivector_operations_2D()
xdvi()
476
Examples
Algebra
BAC-CAB Formulas This example demonstrates the most general metric tensor
(a a) (a b) (a c) (a d)
(a b) (b b) (b c) (b d)
gij =
(a c) (b c) (c c) (c d)
(a d) (b d) (c d) (d d)
and how the galgebra module can be used to verify and expand geometric algebra identities
consisting of relations between the abstract vectors a, b, c, and d.
from sympy.galgebra.printing import xdvi
from sympy.galgebra.ga import *
Format()
(a,b,c,d) = MV.setup(a b c d)
print \\bm{a|(b*c)} =,a|(b*c)
print \\bm{a|(b^c)} =,a|(b^c)
print \\bm{a|(b^c^d)} =,a|(b^c^d)
print \\bm{a|(b^c)+c|(a^b)+b|(c^a)} =,(a|(b^c))+(c|(a^b))+(b|(c^a))
print \\bm{a*(b^c)-b*(a^c)+c*(a^b)} =,a*(b^c)-b*(a^c)+c*(a^b)
print \\bm{a*(b^c^d)-b*(a^c^d)+c*(a^b^d)-d*(a^b^c)} =,a*(b^c^d)-b*(a^c^d)+c*(a^b^d)-d*(a^b^c)
print \\bm{(a^b)|(c^d)} =,(a^b)|(c^d)
print \\bm{((a^b)|c)|d} =,((a^b)|c)|d
print \\bm{(a^b)\\times (c^d)} =,Com(a^b,c^d)
xdvi()
The preceeding code block also demonstrates the mapping of *, , and | to appropriate latex
symbols.
Note: The symbol is the commutator product of two multivectors, A B = (AB BA)/2.
a (bc) = (a c) b + (a b) c
a (b c) = (a c) b + (a b) c
a (b c d) = (a d) b c (a c) b d + (a b) c d
a (b c) + c (a b) + b (c a) =0
a(b c) b(a c) + c(a b) =3a b c
a(b c d) b(a c d) + c(a b d) d(a b c) =4a b c d
(a b) (c d) = (a c) (b d) + (a d) (b c)
((a b) c) d = (a c) (b d) + (a d) (b c)
(a b) (c d) = (b d) a c + (b c) a d + (a d) b c (a c) b d
Reciprocal Frame The reciprocal frame of vectors with respect to the basis vectors is required for the evaluation of the geometric dervative. The following example demonstrates
that for the case of an arbitrary 3-dimensional Euclidian basis the reciprocal basis vectors
are correctly calculated.
477
The preceeding code also demonstrated the use of the % directive in printing a string so that
is treated literally and not translated to \wedge. Note that %E{2} = is printed as E 2 =
478
and not as E 2 =.
E =e1 e2 e3
2
479
The preceeding code also demonstrates how to use the sympy subs functions to perform the hyperbolic half angle transformation.
The code
also shows the use of both the # and % directives in the text string
r#%t\bm{\gamma {t}}+x\bm{\gamma {x}}
=
t\bm{\gamma {t}}+x\bm{\gamma {x}}
=
R\left ( t\bm{\gamma {t}}+x\bm{\gamma {x}}\right ) R{\dagger}. Both the # and %
are needed in this text string for two reasons. First, the text string contains an = sign. The
latex preprocessor uses this a key to combine the text string with a sympy expression to be
printed after the text string. The # is required to inform the preprocessor that there is no
sympy expression to follow. Second, the % is requires to inform the preprocessor that the
text string is to be displayed in latex math mode and not in text mode (if # is present the
default latex mode is text mode unless overridden by the % directive).
( )
( )
1
1
+ sinh
t x
R = cosh
2
2
tt + xx =t0 t0 + x0 x0 = R (t0 t + x0 x ) R
tt + xx = (t0 cosh () x0 sinh ()) t + (t0 sinh () + x0 cosh ()) x
sinh () =
cosh () =
tt + xx = ( (x0 + t0 )) t + ( (t0 + x0 )) x
Calculus
Derivatives in Spherical Coordinates The following code shows how to use galgebra to
use spherical coordinates. The gradient of a scalar function, f , the divergence and curl of a
vector function, A, and the exterior derivative (curl) of a bivector function, B are calculated.
Note that to get the standard curl of a 3-dimension function the result is multiplied by I the
negative of the pseudoscalar.
Note: In geometric calculus the operator 2 is well dened on its own as the geometic
derivative of the geometric derivative. However, if needed we have for the vector function
A the relations (since A is a scalar its curl is equal to its geometric derivative and its
divergence is zero) A = A + A
2 A = ( A) + ( A)
2 A = ( A) + ( A) + ( A) + ( A)
2 A = ( A) + ( ) A ( A) + ( A)
2 A = A + ( ) A
In the derivation we have used that ( A) = ( ) A ( A) which is implicit in the
second BAC-CAB formula. No parenthesis is needed for the geometric curl of the curl (exterior
derivative of exterior derivative) since the operation is associative unlike the vector curl
operator and is the usual Laplacian operator.
480
grad*f =,grad*f
grad|A =,grad|A
-I*(grad^A) =,-MV.I*(grad^A)
grad^B =,grad^B
xdvi()
Results of code
A =Ar er + A e + A e
B =B r er e + B r er e + B e e
f
f
f =r f er +
e +
e
r
r sin ()
A
Ar
A
A
A =r Ar +
+2
+
+
r tan ()
r
r
r sin ()
(
)
(
)
(
)
A cos () + sin () A A
A
Ar
rr A + A Ar
I( A) =
er + r A
+
e +
e
r sin ()
r
r sin ()
r
(
)
B
B r
B r
B r
B = r B + 2
+
er e e
r
r tan ()
r
r sin ()
Maxwells Equations The geometric algebra formulation of Maxwells equations is deomonstrated with the formalism developed in Geometric Algebra for Physicists [Doran]
(page 1909). In this formalism the signature of the metric is (1, 1, 1, 1) and the basis vectors are t , x , y , and z . The if E and B are the normal electric and magnetic eld vectors
the electric and magnetic bivectors are given by E = Et and B = Bt . The electromagnetic
bivector is then F = E + IB where I = t x y z is the pesudo-scalar for the Minkowski space.
Note that the electromagnetic bivector is isomorphic to the electromagnetic tensor. Then if J
is the 4-current all of Maxwells equations are given by F = J. For more details see [Doran]
(page 1909) chapter 7.
from sympy import symbols,sin,cos
from sympy.galgebra.printing import xdvi
from sympy.galgebra.ga import *
Format()
vars = symbols(t x y z)
(g0,g1,g2,g3,grad) = MV.setup(gamma*t|x|y|z,metric=[1,-1,-1,-1],coords=vars)
481
I = MV.I
B = MV(B,vector,fct=True)
E = MV(E,vector,fct=True)
B.set_coef(1,0,0)
E.set_coef(1,0,0)
B *= g0
E *= g0
J = MV(J,vector,fct=True)
F = E+I*B
print B = \\bm{B\\gamma_{t}} =,B
print E = \\bm{E\\gamma_{t}} =,E
print F = E+IB =,F
print J =,J
gradF = grad*F
gradF.Fmt(3,grad*F)
print grad*F = J
(gradF.grade(1)-J).Fmt(3,%\\grade{\\nabla F}_{1} -J = 0)
(gradF.grade(3)).Fmt(3,%\\grade{\\nabla F}_{3} = 0)
xdvi()
B =Bt = B x t x B y t y B z t z
E =Et = E x t x E y t y E z t z
F =E + IB = E x t x E y t y E z t z B z x y + B y x z B x y z
J =J t t + J x x + J y y + J z z
F = (x E x + y E y + z E z ) t
+ (z B y + y B z t E x ) x
+ (z B x x B z t E y ) y
+ (y B x + x B y t E z ) z
+ (t B z + y E x x E y ) t x y
+ (t B y + z E x x E z ) t x z
+ (t B x + z E y y E z ) t y z
+ (x B x + y B y + z B z ) x y z
F =J
(
)
hF i1 J = 0 = J t + x E x + y E y + z E z t
+ (J x z B y + y B z t E x ) x
+ (J y + z B x x B z t E y ) y
+ (J z y B x + x B y t E z ) z
hF i3 = 0 = (t B z + y E x x E y ) t x y
+ (t B y + z E x x E z ) t x z
+ (t B x + z E y y E z ) t y z
+ (x B x + y B y + z B z ) x y z
Dirac Equation In [Doran] (page 1909) equation 8.89 (page 283) is the geometric algebra
formulation of the Dirac equation. In this equation is an 8-component real spinor which
482
is to say that it is a multivector with sacalar, bivector, and pseudo-vector components in the
space-time geometric algebra (it consists only of even grade components).
from sympy import symbols,sin,cos
from sympy.galgebra.printing import xdvi
from sympy.galgebra.ga import *
Format()
vars = symbols(t x y z)
(g0,g1,g2,g3,grad) = MV.setup(gamma*t|x|y|z,metric=[1,-1,-1,-1],coords=vars)
I = MV.I
(m,e) = symbols(m e)
psi = MV(psi,spinor,fct=True)
A = MV(A,vector,fct=True)
sig_z = g3*g0
print \\bm{A} =,A
print \\bm{\\psi} =,psi
dirac_eq = (grad*psi)*I*sig_z-e*A*psi-m*psi*g0
dirac_eq.simplify()
dirac_eq.Fmt(3,r\nabla \bm{\psi} I \sigma_{z}-e\bm{A}\bm{\psi}-m\bm{\psi}\gamma_{t} = 0)
xdvi()
The equations displayed are the partial dierential equations for each component of the Dirac
equation in rectangular coordinates we the driver for the equations is the 4-potential A. One
utility of these equations is to setup a numerical solver for the Dirac equation.
A =At t + Ax x + Ay y + Az z
= + tx t x + ty t y + tz t z + xy x y + xz x z + yz y z
+ txyz t x y z
(
)
Iz eA mt = 0 = eAt eAx tx eAy ty eAz tz m y tx z txyz + x ty + t xy t
(
)
+ eAt tx eAx eAy xy eAz xz + m tx + y t ty x xy + z yz x
(
)
+ eAt ty + eAx xy eAy eAz yz + m ty x + t tx y xy z xz y
(
)
+ eAt tz + eAx xz + eAy yz eAz + m tz + t txyz z xy + y xz x yz z
(
)
+ eAt xy + eAx ty eAy tx eAz txyz m xy t + x tx + y ty + z tz t x
(
)
+ eAt xz + eAx tz + eAy txyz eAz tx m xz + x txyz + z ty y tz t yz t
(
)
+ eAt yz eAx txyz + eAy tz eAz ty m yz z tx + y txyz + x tz + t xz t
(
)
+ eAt txyz eAx yz + eAy xz eAz xy + m txyz + z t tz x xz y yz x
483
484
sympy.galgebra.precedence.parse line(line)
sympy.galgebra.precedence.parse paren(line)
sympy.galgebra.precedence.sub paren(s)
sympy.galgebra.precedence.unparse paren(level lst)
485
everthing in the title processing still applies except that the multivector formatting is
one multivector per line.
For print statements of the form print(title)
where no program variables are printed if title contains # then title is printed as regular
latex line. If title does not contain # then title is printed in equation mode. % has the
same eect in title as in the Fmt() member function.
Function Reference
sympy.galgebra.printing.find executable(executable, path=None)
Try to nd executable in the directories listed in path (a string listing directories separated by os.pathsep; defaults to os.environ[PATH]). Returns the complete lename
or None if not found
sympy.galgebra.printing.Get Program(o=False)
sympy.galgebra.printing.latex(expr, **settings)
Return the LaTeX representation of the given expression.
sympy.galgebra.printing.Print Function()
sympy.galgebra.printing.print latex(expr, **settings)
Print the LaTeX representation of the given expression.
sympy.galgebra.printing.xdvi(lename=None, debug=False, paper=(14, 11))
Post processes LaTeX output (see comments below), adds preamble and postscript, generates tex le, inputs le to latex, displays resulting pdf le.
sympy.galgebra.ncutil.linear expand(expr)
If a sympy Expr is of the form:
expr = expr 0 + expr 1*a 1 + ... + expr n*a n
where all the a j are noncommuting symbols in basis then
(expr 0, ..., expr n) and (1, a 1, ..., a n) are returned. Note that expr j*a j does not have
to be of that form, but rather can be any Mul with a j as a factor (it doen not have to be
a postmultiplier). expr 0 is the scalar part of the expression.
sympy.galgebra.ncutil.linear function(expr, fct)
If a sympy Expr is of the form:
expr = expr 0 + expr 1*a 1 + ... + expr n*a n
where all the a j are noncommuting symbols in basis then
f(expr) = expr 0 + expr 1*f(a 1) + ... + expr n*f(a n)
is returned
sympy.galgebra.ncutil.linear projection(expr, plist=None)
If a sympy Expr is of the form:
expr = expr 0 + expr 1*a 1 + ... + expr n*a n
where all the a j are noncommuting symbols in basis then
proj(expr) returns the sum of those terms where a j is in plist
sympy.galgebra.ncutil.multilinear derivation(F, fct, x)
If a sympy Expr is of the form (summation convention):
expr = expr 0 + expr i1i2...ir*a i1*...*a ir
where all the a j are noncommuting symbols in basis then
dexpr = di(expr 0, x) + d(expr i1i2...ir*a i1*...*a ir)
is returned where d() is the product derivation
sympy.galgebra.ncutil.multilinear function(expr, fct)
If a sympy Expr is of the form summation convention):
expr = expr 0 + Sum{0 < r <= n}{expr i1i2...ir*a i1*a i2*...*a ir}
487
where all the a j are noncommuting symbols in basis then and the dimension of the basis
in n then
bilinear function(expr) = multilinear product(expr 0)
Sum{0<r<=n}multilinear product(expr i1i2...ir*a i1*a i2*...*a ir)
488
[v 1,v 2,v 3]
str array(v,n=3)
In the case of LaTeX printing the would give a subscript and the a super
script.
For two dimensional arrays: base is string where elements are separated by spaces and rows by commas so
that str array(a b,c d) = [[a,b],[c,d]]
sympy.galgebra.stringarrays.str combinations(base, lst, rank=1, mode= )
Construct a list of strings of the form base+mode+indexes where the indexes are
formed by converting lst to a list of strings and then forming the indexes by concatenating combinations of elements from lst taken rank at a time.
sympy.galgebra.stringarrays.symbol array(base, n=None)
Generates a string arrary with str array and replaces each string in array with Symbol
of same name.
op=*,
489
Most of the work one will do will be through the properties and methods of these entities, but
several global methods exist:
intersection(entity1, entity2)
are similar(entity1, entity2)
convex hull(points)
For a full API listing and an explanation of the methods and their return values please see the
list of classes at the end of this document.
490
x
y
z
t
=
=
=
=
Point(0, 0)
Point(a, 0)
Point(2*a, b)
Triangle(x, y, z)
>>> t.area
a*b/2
>>> t.medians[x]
Segment(Point(0, 0), Point(3*a/2, b/2))
>>> intersection(t.medians[x], t.medians[y], t.medians[z])
[Point(a, b/3)]
491
References
Even though the result is currently False, this is not always true. If the quantity z y 2
y z + 2 y 2 == 0 then the points will be collinear. It would be really nice to inform the
user of this because such a quantity may be useful to a user for further calculation and, at
the very least, being nice to know. This could be potentially done by returning an object (e.g.,
GeometryResult) that the user could use. This actually would not involve an extensive amount
of work.
Three Dimensions and Beyond
Currently there are no plans for extending the module to three dimensions, but it certainly
would be a good addition. This would probably involve a fair amount of work since many of
the algorithms used are specic to two dimensions.
Geometry Visualization
The plotting module is capable of plotting geometric entities. See Plotting Geometric Entities
(page 1286) in the plotting module entry.
492
Submodules
Entities
class sympy.geometry.entity.GeometryEntity
The base class for all geometrical entities.
This class doesnt represent any particular geometric entity, it only provides the implementation of some methods common to all subclasses.
encloses(o)
Return True if o is inside (not on or outside) the boundaries of self.
The object will be decomposed into Points and individual Entities need only dene
an encloses point method for their class.
See Also:
sympy.geometry.ellipse.Ellipse.encloses point
(page
sympy.geometry.polygon.Polygon.encloses point (page 560)
545),
Examples
>>> from sympy import RegularPolygon, Point, Polygon
>>> t = Polygon(*RegularPolygon(Point(0, 0), 1, 3).vertices)
>>> t2 = Polygon(*RegularPolygon(Point(0, 0), 2, 3).vertices)
>>> t2.encloses(t)
True
>>> t.encloses(t2)
False
intersection(o)
Returns a list of all of the intersections of self with o.
See Also:
sympy.geometry.util.intersection (page 495)
Notes
493
Notes
This method is not intended to be used directly but rather through the ares imilar
function found in util.py. An entity is not required to implement this method. If two
dierent types of entities can be similar, it is only required that one of them be able
to determine this.
rotate(angle, pt=None)
Rotate angle radians counterclockwise about Point pt.
The default pt is the origin, Point(0, 0)
See Also:
scale (page 494), translate (page 494)
Examples
>>> from sympy import Point, RegularPolygon, Polygon, pi
>>> t = Polygon(*RegularPolygon(Point(0, 0), 1, 3).vertices)
>>> t # vertex on x axis
Triangle(Point(1, 0), Point(-1/2, sqrt(3)/2), Point(-1/2, -sqrt(3)/2))
>>> t.rotate(pi/2) # vertex on y axis now
Triangle(Point(0, 1), Point(-sqrt(3)/2, -1/2), Point(sqrt(3)/2, -1/2))
translate(x=0, y=0)
Shift the object by adding to the x,y-coordinates the values x and y.
See Also:
rotate (page 494), scale (page 494)
Examples
494
Utils
sympy.geometry.util.intersection(*entities)
The intersection of a collection of GeometryEntity instances.
Parameters entities : sequence of GeometryEntity
Returns intersection : list of GeometryEntity
Raises NotImplementedError :
When unable to calculate intersection.
See Also:
sympy.geometry.entity.GeometryEntity.intersection (page 493)
Notes
The intersection of any geometrical entity with itself should return a list with one item:
the entity in question. An intersection requires two or more entities. If only a single entity is given then the function will return an empty list. It is possible for intersection to miss
intersections that one knows exists because the required quantities were not fully simplied internally. Reals should be converted to Rationals, e.g. Rational(str(real num))
or else failures due to oating point issues may result.
Examples
>>> from sympy.geometry import Point, Line, Circle, intersection
>>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(-1, 5)
>>> l1, l2 = Line(p1, p2), Line(p3, p2)
>>> c = Circle(p2, 1)
>>> intersection(l1, p2)
[Point(1, 1)]
>>> intersection(l1, l2)
[Point(1, 1)]
>>> intersection(c, p2)
[]
>>> intersection(c, Point(1, 0))
[Point(1, 0)]
>>> intersection(c, l2)
[Point(-sqrt(5)/5 + 1, 2*sqrt(5)/5 + 1),
Point(sqrt(5)/5 + 1, -2*sqrt(5)/5 + 1)]
sympy.geometry.util.convex hull(*args)
The convex hull surrounding the Points contained in the list of entities.
5.10. Geometry Module
495
(page
497),
sympy.geometry.polygon.Polygon
Notes
496
sympy.geometry.util.centroid(*args)
Find the centroid (center of mass) of the collection containing only Points, Segments
or Polygons. The centroid is the weighted average of the individual centroid where the
weights are the lengths (of segments) or areas (of polygons). Overlapping regions will
add to the weight of that region.
If there are no objects (or a mixture of objects) then None is returned.
See Also:
sympy.geometry.point.Point (page 497), sympy.geometry.line.Segment (page 522),
sympy.geometry.polygon.Polygon (page 556)
Examples
>>> from sympy import Point, Segment, Polygon
>>> from sympy.geometry.util import centroid
>>> p = Polygon((0, 0), (10, 0), (10, 10))
>>> q = p.translate(0, 20)
>>> p.centroid, q.centroid
(Point(20/3, 10/3), Point(20/3, 70/3))
>>> centroid(p, q)
Point(20/3, 40/3)
>>> p, q = Segment((0, 0), (2, 0)), Segment((0, 0), (2, 2))
>>> centroid(p, q)
Point(1, -sqrt(2) + 2)
>>> centroid(Point(0, 0), Point(2, 0))
Point(1, 0)
Stacking 3 polygons on top of each other eectively triples the weight of that polygon:
>>> p = Polygon((0, 0), (1, 0), (1, 1), (0, 1))
>>> q = Polygon((1, 0), (3, 0), (3, 1), (1, 1))
>>> centroid(p, q)
Point(3/2, 1/2)
>>> centroid(p, p, p, q) # centroid x-coord shifts left
Point(11/10, 1/2)
Stacking the squares vertically above and below p has the same eect:
>>> centroid(p, p.translate(0, 1), p.translate(0, -1), q)
Point(11/10, 1/2)
Points
class sympy.geometry.point.Point
A point in a 2-dimensional Euclidean space.
5.10. Geometry Module
497
Attributes
x
y
length
distance(p)
The Euclidean distance from self to point p.
Parameters p : Point
Returns distance : number or symbolic expression.
See Also:
sympy.geometry.line.Segment.length (page 523)
Examples
>>> from sympy.geometry import Point
>>> p1, p2 = Point(1, 1), Point(4, 5)
>>> p1.distance(p2)
5
498
dot(p2)
Return dot product of self with another Point.
evalf(prec=None, **options)
Evaluate the coordinates of the point.
This method will, where possible, create and return a new Point where the coordinates are evaluated as oating point numbers to the precision indicated (default=15).
Returns point : Point
Examples
>>> from sympy import Point, Rational
>>> p1 = Point(Rational(1, 2), Rational(3, 2))
>>> p1
Point(1/2, 3/2)
>>> p1.evalf()
Point(0.5, 1.5)
intersection(o)
The intersection between this point and another point.
Parameters other : Point
Returns intersection : list of Points
Notes
The return value will either be an empty list if there is no intersection, otherwise it
will contain this point.
Examples
>>> from sympy import Point
>>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(0, 0)
>>> p1.intersection(p2)
[]
>>> p1.intersection(p3)
[Point(0, 0)]
is collinear(*points)
Is a sequence of points collinear?
Test whether or not a set of points are collinear. Returns True if the set of points
are collinear, or False otherwise.
Parameters points : sequence of Point
Returns is collinear : boolean
499
See Also:
sympy.geometry.line.Line (page 517)
Notes
Slope is preserved everywhere on a line, so the slope between any two points on
the line should be the same. Take the rst two points, p1 and p2, and create a
translated point v1 with p1 as the origin. Now for every other point we create a
translated point, vi with p1 also as the origin. Note that these translations preserve
slope since everything is consistently translated to a new origin of p1. Since slope
is preserved then we have the following equality:
v1 slope = vi slope
v1.y/v1.x = vi.y/vi.x (due to translation)
v1.y*vi.x = vi.y*v1.x
v1.y*vi.x - vi.y*v1.x = 0 (*)
Hence, if we have a vi such that the equality in (*) is False then the points are not
collinear. We do this test for every point in the list, and if all pass then they are
collinear.
Examples
>>> from sympy import Point
>>> from sympy.abc import x
>>> p1, p2 = Point(0, 0), Point(1, 1)
>>> p3, p4, p5 = Point(2, 2), Point(x, x), Point(1, 2)
>>> Point.is_collinear(p1, p2, p3, p4)
True
>>> Point.is_collinear(p1, p2, p3, p5)
False
is concyclic(*points)
Is a sequence of points concyclic?
Test whether or not a sequence of points are concyclic (i.e., they lie on a circle).
Parameters points : sequence of Points
Returns is concyclic : boolean
True if points are concyclic, False otherwise.
See Also:
sympy.geometry.ellipse.Circle (page 554)
Notes
No points are not considered to be concyclic. One or two points are denitely concyclic and three points are conyclic i they are not collinear.
For more than three points, create a circle from the rst three points. If the circle
cannot be created (i.e., they are collinear) then all of the points cannot be concyclic.
500
If the circle is created successfully then simply check the remaining points for containment in the circle.
Examples
>>> from sympy.geometry import Point
>>> p1, p2 = Point(-1, 0), Point(1, 0)
>>> p3, p4 = Point(0, 1), Point(-1, 2)
>>> Point.is_concyclic(p1, p2, p3)
True
>>> Point.is_concyclic(p1, p2, p3, p4)
False
length
Treating a Point as a Line, this returns 0 for the length of a Point.
Examples
>>> from sympy import Point
>>> p = Point(0, 1)
>>> p.length
0
midpoint(p)
The midpoint between self and point p.
Parameters p : Point
Returns midpoint : Point
See Also:
sympy.geometry.line.Segment.midpoint (page 524)
Examples
>>> from sympy.geometry import Point
>>> p1, p2 = Point(1, 1), Point(13, 5)
>>> p1.midpoint(p2)
Point(7, 3)
n(prec=None, **options)
Evaluate the coordinates of the point.
This method will, where possible, create and return a new Point where the coordinates are evaluated as oating point numbers to the precision indicated (default=15).
Returns point : Point
Examples
501
rotate(angle, pt=None)
Rotate angle radians counterclockwise about Point pt.
See Also:
rotate (page 502), scale (page 502)
Examples
>>> from sympy import Point, pi
>>> t = Point(1, 0)
>>> t.rotate(pi/2)
Point(0, 1)
>>> t.rotate(pi/2, (2, 0))
Point(2, -1)
transform(matrix)
Return the point after applying the transformation described by the 3x3 Matrix,
matrix.
See Also:
geometry.entity.rotate, geometry.entity.scale, geometry.entity.translate
translate(x=0, y=0)
Shift the Point by adding x and y to the coordinates of the Point.
See Also:
rotate (page 502), scale (page 502)
502
Examples
>>> from sympy import Point
>>> t = Point(0, 1)
>>> t.translate(2)
Point(2, 1)
>>> t.translate(2, 2)
Point(2, 3)
>>> t + Point(2, 2)
Point(2, 3)
x
Returns the X coordinate of the Point.
Examples
>>> from sympy import Point
>>> p = Point(0, 1)
>>> p.x
0
y
Returns the Y coordinate of the Point.
Examples
>>> from sympy import Point
>>> p = Point(0, 1)
>>> p.y
1
3D Point
Geometrical Points.
Contains Point3D
class sympy.geometry.point3d.Point3D
A point in a 3-dimensional Euclidean space.
Parameters coords : sequence of 3 coordinate values.
Raises NotImplementedError :
When trying to create a point other than 2 or 3 dimensions. When
intersection is called with object other than a Point.
TypeError :
When trying to add or subtract points with dierent dimensions.
Notes
503
Examples
>>> from sympy import Point3D
>>> from sympy.abc import x
>>> Point3D(1, 2, 3)
Point3D(1, 2, 3)
>>> Point3D([1, 2, 3])
Point3D(1, 2, 3)
>>> Point3D(0, x, 3)
Point3D(0, x, 3)
Attributes
x
y
z
length
static are collinear(*points)
Is a sequence of points collinear?
Test whether or not a set of points are collinear. Returns True if the set of points
are collinear, or False otherwise.
Parameters points : sequence of Point
Returns are collinear : boolean
See Also:
sympy.geometry.line3d.Line3D (page 525)
Examples
>>> from sympy import Point3D, Matrix
>>> from sympy.abc import x
>>> p1, p2 = Point3D(0, 0, 0), Point3D(1, 1, 1)
>>> p3, p4, p5 = Point3D(2, 2, 2), Point3D(x, x, x), Point3D(1, 2, 6)
>>> Point3D.are_collinear(p1, p2, p3, p4)
True
>>> Point3D.are_collinear(p1, p2, p3, p5)
False
Returns boolean :
Examples
>>> from sympy import Point3D
>>> p1 = Point3D(1, 2, 2)
>>> p2 = Point3D(2, 7, 2)
>>> p3 = Point3D(0, 0, 2)
>>> p4 = Point3D(1, 1, 2)
>>> Point3D.are_coplanar(p1, p2, p3, p4)
True
>>> p5 = Point3D(0, 1, 3)
>>> Point3D.are_coplanar(p1, p2, p3, p5)
False
direction cosine(point)
Gives the direction cosine between 2 points
Parameters p : Point3D
Returns list :
Examples
>>> from sympy import Point3D
>>> p1 = Point3D(1, 2, 3)
>>> p1.direction_cosine(Point3D(2, 3, 5))
[sqrt(6)/6, sqrt(6)/6, sqrt(6)/3]
direction ratio(point)
Gives the direction ratio between 2 points
Parameters p : Point3D
Returns list :
Examples
>>>
>>>
>>>
[1,
distance(p)
The Euclidean distance from self to point p.
Parameters p : Point
Returns distance : number or symbolic expression.
See Also:
sympy.geometry.line.Segment.length (page 523)
505
Examples
>>> from sympy import Point3D
>>> p1, p2 = Point3D(1, 1, 1), Point3D(4, 5, 0)
>>> p1.distance(p2)
sqrt(26)
>>> from sympy.abc import x, y, z
>>> p3 = Point3D(x, y, z)
>>> p3.distance(Point3D(0, 0, 0))
sqrt(x**2 + y**2 + z**2)
dot(p2)
Return dot product of self with another Point.
evalf(prec=None, **options)
Evaluate the coordinates of the point.
This method will, where possible, create and return a new Point where the coordinates are evaluated as oating point numbers to the precision indicated (default=15).
Returns point : Point
Examples
>>> from sympy import Point3D, Rational
>>> p1 = Point3D(Rational(1, 2), Rational(3, 2), Rational(5, 2))
>>> p1
Point3D(1/2, 3/2, 5/2)
>>> p1.evalf()
Point3D(0.5, 1.5, 2.5)
intersection(o)
The intersection between this point and another point.
Parameters other : Point
Returns intersection : list of Points
Notes
The return value will either be an empty list if there is no intersection, otherwise it
will contain this point.
Examples
>>> from sympy import Point3D
>>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(0, 0, 0)
>>> p1.intersection(p2)
[]
>>> p1.intersection(p3)
[Point3D(0, 0, 0)]
506
length
Treating a Point as a Line, this returns 0 for the length of a Point.
Examples
>>> from sympy import Point3D
>>> p = Point3D(0, 1, 1)
>>> p.length
0
midpoint(p)
The midpoint between self and point p.
Parameters p : Point
Returns midpoint : Point
See Also:
sympy.geometry.line.Segment.midpoint (page 524)
Examples
>>> from sympy import Point3D
>>> p1, p2 = Point3D(1, 1, 1), Point3D(13, 5, 1)
>>> p1.midpoint(p2)
Point3D(7, 3, 1)
n(prec=None, **options)
Evaluate the coordinates of the point.
This method will, where possible, create and return a new Point where the coordinates are evaluated as oating point numbers to the precision indicated (default=15).
Returns point : Point
Examples
>>> from sympy import Point3D, Rational
>>> p1 = Point3D(Rational(1, 2), Rational(3, 2), Rational(5, 2))
>>> p1
Point3D(1/2, 3/2, 5/2)
>>> p1.evalf()
Point3D(0.5, 1.5, 2.5)
507
Examples
>>> from sympy import Point3D
>>> t = Point3D(1, 1, 1)
>>> t.scale(2)
Point3D(2, 1, 1)
>>> t.scale(2, 2)
Point3D(2, 2, 1)
transform(matrix)
Return the point after applying the transformation described by the 3x3 Matrix,
matrix.
See Also:
geometry.entity.rotate, geometry.entity.scale, geometry.entity.translate
translate(x=0, y=0, z=0)
Shift the Point by adding x and y to the coordinates of the Point.
See Also:
rotate, scale (page 507)
Examples
>>> from sympy import Point3D
>>> t = Point3D(0, 1, 1)
>>> t.translate(2)
Point3D(2, 1, 1)
>>> t.translate(2, 2)
Point3D(2, 3, 1)
>>> t + Point3D(2, 2, 2)
Point3D(2, 3, 3)
x
Returns the X coordinate of the Point.
Examples
>>> from sympy import Point3D
>>> p = Point3D(0, 1, 3)
>>> p.x
0
y
Returns the Y coordinate of the Point.
Examples
>>> from sympy import Point3D
>>> p = Point3D(0, 1, 2)
>>> p.y
1
508
z
Returns the Z coordinate of the Point.
Examples
>>> from sympy import Point3D
>>> p = Point3D(0, 1, 1)
>>> p.z
1
Lines
class sympy.geometry.line.LinearEntity
A base class for all linear entities (line, ray and segment) in a 2-dimensional Euclidean
space.
See Also:
sympy.geometry.entity.GeometryEntity (page 493)
Notes
p1
p2
coecients
slope
points
angle between(l1, l2)
The angle formed between the two linear entities.
Parameters l1 : LinearEntity
l2 : LinearEntity
Returns angle : angle in radians
See Also:
is perpendicular (page 512)
Notes
509
Examples
>>> from sympy import Point, Line
>>> p1, p2, p3 = Point(0, 0), Point(0, 4), Point(2, 0)
>>> l1, l2 = Line(p1, p2), Line(p1, p3)
>>> l1.angle_between(l2)
pi/2
arbitrary point(parameter=t)
A parameterized point on the Line.
Parameters parameter : str, optional
The name of the parameter which will be used for the parametric
point. The default value is t. When this parameter is 0, the rst
point used to dene the line will be returned, and when it is 1 the
second point will be returned.
Returns point : Point
Raises ValueError :
When parameter already appears in the Lines denition.
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy import Point, Line
>>> p1, p2 = Point(1, 0), Point(5, 3)
>>> l1 = Line(p1, p2)
>>> l1.arbitrary_point()
Point(4*t + 1, 3*t)
Simply take the rst two lines and nd their intersection. If there is no intersection,
then the rst two lines were parallel and had no intersection so concurrency is impossible amongst the whole set. Otherwise, check to see if the intersection point of
the rst two lines is a member on the rest of the lines. If so, the lines are concurrent.
510
Examples
>>> from sympy import Point, Line, Line3D
>>> p1, p2 = Point(0, 0), Point(3, 5)
>>> p3, p4 = Point(-2, -2), Point(0, 2)
>>> l1, l2, l3 = Line(p1, p2), Line(p1, p3), Line(p1, p4)
>>> Line.are_concurrent(l1, l2, l3)
True
>>> l4 = Line(p2, p3)
>>> Line.are_concurrent(l2, l3, l4)
False
coefficients
The coecients (a, b, c) for ax + by + c = 0.
See Also:
sympy.geometry.line.Line.equation (page 518)
Examples
>>> from sympy import Point, Line
>>> from sympy.abc import x, y
>>> p1, p2 = Point(0, 0), Point(5, 3)
>>> l = Line(p1, p2)
>>> l.coefficients
(-3, 5, 0)
>>> p3 = Point(x, y)
>>> l2 = Line(p1, p3)
>>> l2.coefficients
(-y, x, 0)
contains(other)
Subclasses should implement this method and should return True if other is on the
boundaries of self; False if not on the boundaries of self; None if a determination
cannot be made.
intersection(o)
The intersection with another geometrical entity.
Parameters o : Point or LinearEntity
Returns intersection : list of geometrical entities
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy import Point, Line, Segment
>>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(7, 7)
>>> l1 = Line(p1, p2)
>>> l1.intersection(p3)
[Point(7, 7)]
511
is parallel(l1, l2)
Are two linear entities parallel?
Parameters l1 : LinearEntity
l2 : LinearEntity
Returns True : if l1 and l2 are parallel,
False : otherwise.
See Also:
coefficients (page 511)
Examples
>>> from sympy import Point, Line
>>> p1, p2 = Point(0, 0), Point(1, 1)
>>> p3, p4 = Point(3, 4), Point(6, 7)
>>> l1, l2 = Line(p1, p2), Line(p3, p4)
>>> Line.is_parallel(l1, l2)
True
>>> p5 = Point(6, 6)
>>> l3 = Line(p3, p5)
>>> Line.is_parallel(l1, l3)
False
is perpendicular(l1, l2)
Are two linear entities perpendicular?
Parameters l1 : LinearEntity
l2 : LinearEntity
Returns True : if l1 and l2 are perpendicular,
False : otherwise.
See Also:
coefficients (page 511)
Examples
>>> from sympy import Point, Line
>>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(-1, 1)
>>> l1, l2 = Line(p1, p2), Line(p1, p3)
512
>>> l1.is_perpendicular(l2)
True
>>> p4 = Point(5, 3)
>>> l3 = Line(p1, p4)
>>> l1.is_perpendicular(l3)
False
is similar(other)
Return True if self and other are contained in the same line.
Examples
>>> from sympy import Point, Line
>>> p1, p2, p3 = Point(0, 1), Point(3, 4), Point(2, 3)
>>> l1 = Line(p1, p2)
>>> l2 = Line(p1, p3)
>>> l1.is_similar(l2)
True
length
The length of the line.
Examples
>>>
>>>
>>>
>>>
oo
p1
The rst dening point of a linear entity.
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy import Point, Line
>>> p1, p2 = Point(0, 0), Point(5, 3)
>>> l = Line(p1, p2)
>>> l.p1
Point(0, 0)
p2
The second dening point of a linear entity.
See Also:
sympy.geometry.point.Point (page 497)
513
Examples
>>> from sympy import Point, Line
>>> p1, p2 = Point(0, 0), Point(5, 3)
>>> l = Line(p1, p2)
>>> l.p2
Point(5, 3)
parallel line(p)
Create a new Line parallel to this linear entity which passes through the point p.
Parameters p : Point
Returns line : Line
See Also:
is parallel (page 512)
Examples
>>> from sympy import Point, Line
>>> p1, p2, p3 = Point(0, 0), Point(2, 3), Point(-2, 2)
>>> l1 = Line(p1, p2)
>>> l2 = l1.parallel_line(p3)
>>> p3 in l2
True
>>> l1.is_parallel(l2)
True
perpendicular line(p)
Create a new Line perpendicular to this linear entity which passes through the point
p.
Parameters p : Point
Returns line : Line
See Also:
is perpendicular (page 512), perpendicular segment (page 514)
Examples
>>> from sympy import Point, Line
>>> p1, p2, p3 = Point(0, 0), Point(2, 3), Point(-2, 2)
>>> l1 = Line(p1, p2)
>>> l2 = l1.perpendicular_line(p3)
>>> p3 in l2
True
>>> l1.is_perpendicular(l2)
True
perpendicular segment(p)
Create a perpendicular line segment from p to this line.
The enpoints of the segment are p and the closest point in the line containing self.
(If self is not a line, the point might not be in self.)
514
Parameters p : Point
Returns segment : Segment
See Also:
perpendicular line (page 514)
Notes
points
The two points used to dene this linear entity.
Returns points : tuple of Points
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy import Point, Line
>>> p1, p2 = Point(0, 0), Point(5, 11)
>>> l1 = Line(p1, p2)
>>> l1.points
(Point(0, 0), Point(5, 11))
projection(o)
Project a point, line, ray, or segment onto this linear entity.
Parameters other : Point or LinearEntity (Line, Ray, Segment)
Returns projection : Point or LinearEntity (Line, Ray, Segment)
The return type matches the type of the parameter other.
Raises GeometryError :
When method is unable to perform projection.
See Also:
sympy.geometry.point.Point (page 497), perpendicular line (page 514)
515
Notes
A projection involves taking the two points that dene the linear entity and projecting those points onto a Line and then reforming the linear entity using these
projections. A point P is projected onto a line L by nding the point on L that is
closest to P. This point is the intersection of L and the line perpendicular to L that
passes through P.
Examples
>>> from sympy import Point, Line, Segment, Rational
>>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(Rational(1, 2), 0)
>>> l1 = Line(p1, p2)
>>> l1.projection(p3)
Point(1/4, 1/4)
>>> p4, p5 = Point(10, 0), Point(12, 1)
>>> s1 = Segment(p4, p5)
>>> l1.projection(s1)
Segment(Point(5, 5), Point(13/2, 13/2))
random point()
A random point on a LinearEntity.
Returns point : Point
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy import Point, Line
>>> p1, p2 = Point(0, 0), Point(5, 3)
>>> l1 = Line(p1, p2)
>>> p3 = l1.random_point()
>>> # random point - dont know its coords in advance
>>> p3
Point(...)
>>> # point should belong to the line
>>> p3 in l1
True
slope
The slope of this linear entity, or innity if vertical.
Returns slope : number or sympy expression
See Also:
coefficients (page 511)
516
Examples
>>>
>>>
>>>
>>>
5/3
>>> p3 = Point(0, 4)
>>> l2 = Line(p1, p3)
>>> l2.slope
oo
class sympy.geometry.line.Line
An innite line in space.
A line is declared with two distinct points or a point and slope as dened using keyword
slope.
Parameters p1 : Point
pt : Point
slope : sympy expression
See Also:
sympy.geometry.point.Point (page 497)
Notes
At the moment only lines in a 2D space can be declared, because Points can be dened
only for 2D spaces.
Examples
>>> import sympy
>>> from sympy import Point
>>> from sympy.abc import L
>>> from sympy.geometry import Line, Segment
>>> L = Line(Point(2,3), Point(3,5))
>>> L
Line(Point(2, 3), Point(3, 5))
>>> L.points
(Point(2, 3), Point(3, 5))
>>> L.equation()
-2*x + y + 1
>>> L.coefficients
(-2, 1, 1)
517
contains(o)
Return True if o is on this Line, or False otherwise.
Examples
>>> from sympy import Line,Point
>>> p1, p2 = Point(0, 1), Point(3, 4)
>>> l = Line(p1, p2)
>>> l.contains(p1)
True
>>> l.contains((0, 1))
True
>>> l.contains((0, 0))
False
distance(o)
Finds the shortest distance between a line and a point.
Raises NotImplementedError is raised if o is not a Point :
Examples
>>> from sympy import Point, Line
>>> p1, p2 = Point(0, 0), Point(1, 1)
>>> s = Line(p1, p2)
>>> s.distance(Point(-1, 1))
sqrt(2)
>>> s.distance((-1, 2))
3*sqrt(2)/2
equal(other)
Returns True if self and other are the same mathematical entities
equation(x=x, y=y)
The equation of the line: ax + by + c.
Parameters x : str, optional
The name to use for the x-axis, default value is x.
y : str, optional
The name to use for the y-axis, default value is y.
Returns equation : sympy expression
See Also:
LinearEntity.coefficients (page 511)
518
Examples
>>> from sympy import Point, Line
>>> p1, p2 = Point(1, 0), Point(5, 3)
>>> l1 = Line(p1, p2)
>>> l1.equation()
-3*x + 4*y + 3
plot interval(parameter=t)
The plot interval for the default geometric plot of line. Gives values that will produce
a line that is +/- 5 units long (where a unit is the distance between the two points
that dene the line).
Parameters parameter : str, optional
Default value is t.
Returns plot interval : list (plot interval)
[parameter, lower bound, upper bound]
Examples
>>>
>>>
>>>
>>>
[t,
class sympy.geometry.line.Ray
A Ray is a semi-line in the space with a source point and a direction.
Parameters p1 : Point
The source of the Ray
p2 : Point or radian value
This point determines the direction in which the Ray propagates. If
given as an angle it is interpreted in radians with the positive direction being ccw.
See Also:
sympy.geometry.point.Point (page 497), Line (page 517)
Notes
At the moment only rays in a 2D space can be declared, because Points can be dened
only for 2D spaces.
Examples
>>>
>>>
>>>
>>>
import sympy
from sympy import Point, pi
from sympy.abc import r
from sympy.geometry import Ray
519
Attributes
source
xdirection
ydirection
contains(o)
Is other GeometryEntity contained in this Ray?
Examples
>>> from sympy import Ray,Point,Segment
>>> p1, p2 = Point(0, 0), Point(4, 4)
>>> r = Ray(p1, p2)
>>> r.contains(p1)
True
>>> r.contains((1, 1))
True
>>> r.contains((1, 3))
False
>>> s = Segment((1, 1), (2, 2))
>>> r.contains(s)
True
>>> s = Segment((1, 2), (2, 5))
>>> r.contains(s)
False
>>> r1 = Ray((2, 2), (3, 3))
>>> r.contains(r1)
True
>>> r1 = Ray((2, 2), (3, 5))
>>> r.contains(r1)
False
distance(o)
Finds the shortest distance between the ray and a point.
Raises NotImplementedError is raised if o is not a Point :
520
Examples
>>> from sympy import Point, Ray
>>> p1, p2 = Point(0, 0), Point(1, 1)
>>> s = Ray(p1, p2)
>>> s.distance(Point(-1, -1))
sqrt(2)
>>> s.distance((-1, 2))
3*sqrt(2)/2
equals(other)
Returns True if self and other are the same mathematical entities
plot interval(parameter=t)
The plot interval for the default geometric plot of the Ray. Gives values that will
produce a ray that is 10 units long (where a unit is the distance between the two
points that dene the ray).
Parameters parameter : str, optional
Default value is t.
Returns plot interval : list
[parameter, lower bound, upper bound]
Examples
>>>
>>>
>>>
[t,
source
The point from which the ray emanates.
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy import Point, Ray
>>> p1, p2 = Point(0, 0), Point(4, 1)
>>> r1 = Ray(p1, p2)
>>> r1.source
Point(0, 0)
xdirection
The x direction of the ray.
Positive innity if the ray points in the positive x direction, negative innity if the
ray points in the negative x direction, or 0 if the ray is vertical.
See Also:
ydirection (page 522)
521
Examples
>>>
>>>
>>>
>>>
oo
>>>
0
ydirection
The y direction of the ray.
Positive innity if the ray points in the positive y direction, negative innity if the
ray points in the negative y direction, or 0 if the ray is horizontal.
See Also:
xdirection (page 521)
Examples
>>>
>>>
>>>
>>>
-oo
>>>
0
class sympy.geometry.line.Segment
A undirected line segment in space.
Parameters p1 : Point
p2 : Point
See Also:
sympy.geometry.point.Point (page 497), Line (page 517)
Notes
At the moment only segments in a 2D space can be declared, because Points can be
dened only for 2D spaces.
Examples
>>> import sympy
>>> from sympy import Point
>>> from sympy.abc import s
>>> from sympy.geometry import Segment
>>> Segment((1, 0), (1, 1)) # tuples are interpreted as pts
Segment(Point(1, 0), Point(1, 1))
>>> s = Segment(Point(4, 3), Point(1, 1))
>>> s
522
Attributes
length
midpoint
contains(other)
Is the other GeometryEntity contained within this Segment?
Examples
>>> from sympy import Point, Segment
>>> p1, p2 = Point(0, 1), Point(3, 4)
>>> s = Segment(p1, p2)
>>> s2 = Segment(p2, p1)
>>> s.contains(s2)
True
distance(o)
Finds the shortest distance between a line segment and a point.
Raises NotImplementedError is raised if o is not a Point :
Examples
>>> from sympy import Point, Segment
>>> p1, p2 = Point(0, 1), Point(3, 4)
>>> s = Segment(p1, p2)
>>> s.distance(Point(10, 15))
sqrt(170)
>>> s.distance((0, 12))
sqrt(73)
length
The length of the line segment.
See Also:
sympy.geometry.point.Point.distance (page 498)
Examples
523
>>>
>>>
>>>
>>>
5
midpoint
The midpoint of the line segment.
See Also:
sympy.geometry.point.Point.midpoint (page 501)
Examples
>>> from sympy import Point, Segment
>>> p1, p2 = Point(0, 0), Point(4, 3)
>>> s1 = Segment(p1, p2)
>>> s1.midpoint
Point(2, 3/2)
perpendicular bisector(p=None)
The perpendicular bisector of this segment.
If no point is specied or the point specied is not on the bisector then the bisector
is returned as a Line. Otherwise a Segment is returned that joins the point specied
and the intersection of the bisector and the segment.
Parameters p : Point
Returns bisector : Line or Segment
See Also:
LinearEntity.perpendicular segment (page 514)
Examples
>>> from sympy import Point, Segment
>>> p1, p2, p3 = Point(0, 0), Point(6, 6), Point(5, 1)
>>> s1 = Segment(p1, p2)
>>> s1.perpendicular_bisector()
Line(Point(3, 3), Point(9, -3))
>>> s1.perpendicular_bisector(p3)
Segment(Point(3, 3), Point(5, 1))
plot interval(parameter=t)
The plot interval for the default geometric plot of the Segment gives values that will
produce the full segment in a plot.
Parameters parameter : str, optional
Default value is t.
Returns plot interval : list
[parameter, lower bound, upper bound]
524
Examples
>>>
>>>
>>>
>>>
[t,
3D Line
contains(o)
Return True if o is on this Line, or False otherwise.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
525
False
>>> l1 in l2
True
distance(o)
Finds the shortest distance between a line and a point.
Raises NotImplementedError is raised if o is not an instance of
Point3D :
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(1, 1, 1)
>>> s = Line3D(p1, p2)
>>> s.distance(Point3D(-1, 1, 1))
2*sqrt(6)/3
>>> s.distance((-1, 1, 1))
2*sqrt(6)/3
equals(other)
Returns True if self and other are the same mathematical entities
equation(x=x, y=y, z=z, k=k)
The equation of the line in 3D
Parameters x : str, optional
The name to use for the x-axis, default value is x.
y : str, optional
The name to use for the y-axis, default value is y.
z : str, optional
The name to use for the x-axis, default value is z.
Returns equation : tuple
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2 = Point3D(1, 0, 0), Point3D(5, 3, 0)
>>> l1 = Line3D(p1, p2)
>>> l1.equation()
(x/4 - 1/4, y/3, zoo*z, k)
plot interval(parameter=t)
The plot interval for the default geometric plot of line. Gives values that will produce
a line that is +/- 5 units long (where a unit is the distance between the two points
that dene the line).
Parameters parameter : str, optional
Default value is t.
Returns plot interval : list (plot interval)
[parameter, lower bound, upper bound]
526
Examples
>>>
>>>
>>>
>>>
[t,
class sympy.geometry.line3d.LinearEntity3D
An base class for all linear entities (line, ray and segment) in a 3-dimensional Euclidean
space.
Notes
p1
p2
direction ratio
direction cosine
points
angle between(l1, l2)
The angle formed between the two linear entities.
Parameters l1 : LinearEntity
l2 : LinearEntity
Returns angle : angle in radians
See Also:
is perpendicular (page 530)
Notes
527
arbitrary point(parameter=t)
A parameterized point on the Line.
Parameters parameter : str, optional
The name of the parameter which will be used for the parametric
point. The default value is t. When this parameter is 0, the rst
point used to dene the line will be returned, and when it is 1 the
second point will be returned.
Returns point : Point3D
Raises ValueError :
When parameter already appears in the Lines denition.
See Also:
sympy.geometry.point3d.Point3D (page 503)
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2 = Point3D(1, 0, 0), Point3D(5, 3, 1)
>>> l1 = Line3D(p1, p2)
>>> l1.arbitrary_point()
Point3D(4*t + 1, 3*t, t)
Simply take the rst two lines and nd their intersection. If there is no intersection,
then the rst two lines were parallel and had no intersection so concurrency is impossible amongst the whole set. Otherwise, check to see if the intersection point of
the rst two lines is a member on the rest of the lines. If so, the lines are concurrent.
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(3, 5, 2)
>>> p3, p4 = Point3D(-2, -2, -2), Point3D(0, 2, 1)
>>> l1, l2, l3 = Line3D(p1, p2), Line3D(p1, p3), Line3D(p1, p4)
>>> Line3D.are_concurrent(l1, l2, l3)
True
528
contains(other)
Subclasses should implement this method and should return True if other is on the
boundaries of self; False if not on the boundaries of self; None if a determination
cannot be made.
direction cosine
The normalized direction ratio of a given line in 3D.
See Also:
sympy.geometry.line.Line.equation (page 518)
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(5, 3, 1)
>>> l = Line3D(p1, p2)
>>> l.direction_cosine
[sqrt(35)/7, 3*sqrt(35)/35, sqrt(35)/35]
>>> sum(i**2 for i in _)
1
direction ratio
The direction ratio of a given line in 3D.
See Also:
sympy.geometry.line.Line.equation (page 518)
Examples
>>>
>>>
>>>
>>>
[5,
intersection(o)
The intersection with another geometrical entity.
Parameters o : Point or LinearEntity3D
Returns intersection : list of geometrical entities
See Also:
sympy.geometry.point3d.Point3D (page 503)
Examples
>>> from sympy import Point3D, Line3D, Segment3D
>>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(7, 7, 7)
>>> l1 = Line3D(p1, p2)
529
>>> l1.intersection(p3)
[Point3D(7, 7, 7)]
>>> l1 = Line3D(Point3D(4,19,12), Point3D(5,25,17))
>>> l2 = Line3D(Point3D(-3, -15, -19), direction_ratio=[2,8,8])
>>> l1.intersection(l2)
[Point3D(1, 1, -3)]
>>> p6, p7 = Point3D(0, 5, 2), Point3D(2, 6, 3)
>>> s1 = Segment3D(p6, p7)
>>> l1.intersection(s1)
[]
is parallel(l1, l2)
Are two linear entities parallel?
Parameters l1 : LinearEntity
l2 : LinearEntity
Returns True : if l1 and l2 are parallel,
False : otherwise.
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(3, 4, 5)
>>> p3, p4 = Point3D(2, 1, 1), Point3D(8, 9, 11)
>>> l1, l2 = Line3D(p1, p2), Line3D(p3, p4)
>>> Line3D.is_parallel(l1, l2)
True
>>> p5 = Point3D(6, 6, 6)
>>> l3 = Line3D(p3, p5)
>>> Line3D.is_parallel(l1, l3)
False
is perpendicular(l1, l2)
Are two linear entities perpendicular?
Parameters l1 : LinearEntity
l2 : LinearEntity
Returns True : if l1 and l2 are perpendicular,
False : otherwise.
See Also:
direction ratio (page 529)
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(-1, 2, 0)
>>> l1, l2 = Line3D(p1, p2), Line3D(p2, p3)
530
>>> l1.is_perpendicular(l2)
False
>>> p4 = Point3D(5, 3, 7)
>>> l3 = Line3D(p1, p4)
>>> l1.is_perpendicular(l3)
False
is similar(other)
Return True if self and other are contained in the same line.
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(2, 2, 2)
>>> l1 = Line3D(p1, p2)
>>> l2 = Line3D(p1, p3)
>>> l1.is_similar(l2)
True
length
The length of the line.
Examples
>>>
>>>
>>>
>>>
oo
p1
The rst dening point of a linear entity.
See Also:
sympy.geometry.point3d.Point3D (page 503)
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(5, 3, 1)
>>> l = Line3D(p1, p2)
>>> l.p1
Point3D(0, 0, 0)
p2
The second dening point of a linear entity.
See Also:
sympy.geometry.point3d.Point3D (page 503)
531
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(5, 3, 1)
>>> l = Line3D(p1, p2)
>>> l.p2
Point3D(5, 3, 1)
parallel line(p)
Create a new Line parallel to this linear entity which passes through the point p.
Parameters p : Point3D
Returns line : Line3D
See Also:
is parallel (page 530)
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(2, 3, 4), Point3D(-2, 2, 0)
>>> l1 = Line3D(p1, p2)
>>> l2 = l1.parallel_line(p3)
>>> p3 in l2
True
>>> l1.is_parallel(l2)
True
perpendicular line(p)
Create a new Line perpendicular to this linear entity which passes through the point
p.
Parameters p : Point3D
Returns line : Line3D
See Also:
is perpendicular (page 530), perpendicular segment (page 532)
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(2, 3, 4), Point3D(-2, 2, 0)
>>> l1 = Line3D(p1, p2)
>>> l2 = l1.perpendicular_line(p3)
>>> p3 in l2
True
>>> l1.is_perpendicular(l2)
True
perpendicular segment(p)
Create a perpendicular line segment from p to this line.
The enpoints of the segment are p and the closest point in the line containing self.
(If self is not a line, the point might not be in self.)
532
Parameters p : Point3D
Returns segment : Segment3D
See Also:
perpendicular line (page 532)
Notes
points
The two points used to dene this linear entity.
Returns points : tuple of Points
See Also:
sympy.geometry.point3d.Point3D (page 503)
Examples
>>> from sympy import Point3D, Line3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(5, 11, 1)
>>> l1 = Line3D(p1, p2)
>>> l1.points
(Point3D(0, 0, 0), Point3D(5, 11, 1))
projection(o)
Project a point, line, ray, or segment onto this linear entity.
Parameters other : Point or LinearEntity (Line, Ray, Segment)
Returns projection : Point or LinearEntity (Line, Ray, Segment)
The return type matches the type of the parameter other.
Raises GeometryError :
When method is unable to perform projection.
See Also:
sympy.geometry.point3d.Point3D (page 503), perpendicular line (page 532)
533
Notes
A projection involves taking the two points that dene the linear entity and projecting those points onto a Line and then reforming the linear entity using these
projections. A point P is projected onto a line L by nding the point on L that is
closest to P. This point is the intersection of L and the line perpendicular to L that
passes through P.
Examples
>>> from sympy import Point3D, Line3D, Segment3D, Rational
>>> p1, p2, p3 = Point3D(0, 0, 1), Point3D(1, 1, 2), Point3D(2, 0, 1)
>>> l1 = Line3D(p1, p2)
>>> l1.projection(p3)
Point3D(2/3, 2/3, 5/3)
>>> p4, p5 = Point3D(10, 0, 1), Point3D(12, 1, 3)
>>> s1 = Segment3D(p4, p5)
>>> l1.projection(s1)
[Segment3D(Point3D(10/3, 10/3, 13/3), Point3D(5, 5, 6))]
class sympy.geometry.line3d.Ray3D
A Ray is a semi-line in the space with a source point and a direction.
Parameters p1 : Point3D
The source of the Ray
p2 : Point or a direction vector
direction ratio: Determines the direction in which the Ray propagates. :
See Also:
sympy.geometry.point3d.Point3D (page 503), Line3D (page 525)
Examples
>>> import sympy
>>> from sympy import Point3D, pi
>>> from sympy.abc import r
>>> from sympy.geometry import Ray3D
>>> r = Ray3D(Point3D(2, 3, 4), Point3D(3, 5, 0))
>>> r
Ray3D(Point3D(2, 3, 4), Point3D(3, 5, 0))
>>> r.points
(Point3D(2, 3, 4), Point3D(3, 5, 0))
>>> r.source
Point3D(2, 3, 4)
>>> r.xdirection
oo
>>> r.ydirection
oo
>>> r.direction_ratio
[1, 2, -4]
534
Attributes
source
xdirection
ydirection
zdirection
contains(o)
Is other GeometryEntity contained in this Ray?
distance(o)
Finds the shortest distance between the ray and a point.
Raises NotImplementedError is raised if o is not a Point :
Examples
>>> from sympy import Point3D, Ray3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(1, 1, 2)
>>> s = Ray3D(p1, p2)
>>> s.distance(Point3D(-1, -1, 2))
sqrt(6)
>>> s.distance((-1, -1, 2))
sqrt(6)
equals(other)
Returns True if self and other are the same mathematical entities
plot interval(parameter=t)
The plot interval for the default geometric plot of the Ray. Gives values that will
produce a ray that is 10 units long (where a unit is the distance between the two
points that dene the ray).
Parameters parameter : str, optional
Default value is t.
Returns plot interval : list
[parameter, lower bound, upper bound]
Examples
>>>
>>>
>>>
[t,
source
The point from which the ray emanates.
See Also:
sympy.geometry.point3d.Point3D (page 503)
535
Examples
>>> from sympy import Point3D, Ray3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(4, 1, 5)
>>> r1 = Ray3D(p1, p2)
>>> r1.source
Point3D(0, 0, 0)
xdirection
The x direction of the ray.
Positive innity if the ray points in the positive x direction, negative innity if the
ray points in the negative x direction, or 0 if the ray is vertical.
See Also:
ydirection (page 536)
Examples
>>>
>>>
>>>
>>>
oo
>>>
0
ydirection
The y direction of the ray.
Positive innity if the ray points in the positive y direction, negative innity if the
ray points in the negative y direction, or 0 if the ray is horizontal.
See Also:
xdirection (page 536)
Examples
>>>
>>>
>>>
>>>
-oo
>>>
0
zdirection
The z direction of the ray.
Positive innity if the ray points in the positive z direction, negative innity if the
ray points in the negative z direction, or 0 if the ray is horizontal.
See Also:
xdirection (page 536)
536
Examples
>>>
>>>
>>>
>>>
-oo
>>>
0
>>>
0
class sympy.geometry.line3d.Segment3D
A undirected line segment in a 3D space.
Parameters p1 : Point3D
p2 : Point3D
See Also:
sympy.geometry.point.Point3D, Line3D (page 525)
Examples
>>> import sympy
>>> from sympy import Point3D
>>> from sympy.abc import s
>>> from sympy.geometry import Segment3D
>>> Segment3D((1, 0, 0), (1, 1, 1)) # tuples are interpreted as pts
Segment3D(Point3D(1, 0, 0), Point3D(1, 1, 1))
>>> s = Segment3D(Point3D(4, 3, 9), Point3D(1, 1, 7))
>>> s
Segment3D(Point3D(1, 1, 7), Point3D(4, 3, 9))
>>> s.points
(Point3D(1, 1, 7), Point3D(4, 3, 9))
>>> s.length
sqrt(17)
>>> s.midpoint
Point3D(5/2, 2, 8)
Attributes
length
midpoint
contains(other)
Is the other GeometryEntity contained within this Segment?
Examples
>>> from sympy import Point3D, Segment3D
>>> p1, p2 = Point3D(0, 1, 1), Point3D(3, 4, 5)
>>> s = Segment3D(p1, p2)
537
distance(o)
Finds the shortest distance between a line segment and a point.
Raises NotImplementedError is raised if o is not a Point3D :
Examples
>>> from sympy import Point3D, Segment3D
>>> p1, p2 = Point3D(0, 0, 3), Point3D(1, 1, 4)
>>> s = Segment3D(p1, p2)
>>> s.distance(Point3D(10, 15, 12))
sqrt(341)
>>> s.distance((10, 15, 12))
sqrt(341)
length
The length of the line segment.
See Also:
sympy.geometry.point3d.Point3D.distance (page 505)
Examples
>>> from sympy import Point3D, Segment3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(4, 3, 3)
>>> s1 = Segment3D(p1, p2)
>>> s1.length
sqrt(34)
midpoint
The midpoint of the line segment.
See Also:
sympy.geometry.point3d.Point3D.midpoint (page 507)
Examples
>>> from sympy import Point3D, Segment3D
>>> p1, p2 = Point3D(0, 0, 0), Point3D(4, 3, 3)
>>> s1 = Segment3D(p1, p2)
>>> s1.midpoint
Point3D(2, 3/2, 3/2)
plot interval(parameter=t)
The plot interval for the default geometric plot of the Segment gives values that will
produce the full segment in a plot.
Parameters parameter : str, optional
Default value is t.
538
Curves
class sympy.geometry.curve.Curve
A curve in space.
A curve is dened by parametric functions for the coordinates, a parameter and the lower
and upper bounds for the parameter value.
Parameters function : list of functions
limits : 3-tuple
Function parameter and lower and upper bounds.
Raises ValueError :
When f unctions are specied incorrectly. When limits are specied
incorrectly.
See Also:
sympy.core.function.Function (page 169), sympy.polys.polyfuncs.interpolate
(page 1114)
Examples
>>> from sympy import sin, cos, Symbol, interpolate
>>> from sympy.abc import t, a
>>> from sympy.geometry import Curve
>>> C = Curve((sin(t), cos(t)), (t, 0, 2))
>>> C.functions
(sin(t), cos(t))
>>> C.limits
(t, 0, 2)
>>> C.parameter
t
>>> C = Curve((t, interpolate([1, 4, 9, 16], t)), (t, 0, 1)); C
Curve((t, t**2), (t, 0, 1))
>>> C.subs(t, 4)
Point(4, 16)
>>> C.arbitrary_point(a)
Point(a, a**2)
539
Attributes
functions
parameter
limits
arbitrary point(parameter=t)
A parameterized point on the curve.
Parameters parameter : str or Symbol, optional
Default value is t; the Curves parameter is selected with None or
self.parameter otherwise the provided symbol is used.
Returns arbitrary point : Point
Raises ValueError :
When parameter already appears in the functions.
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy import Symbol
>>> from sympy.abc import s
>>> from sympy.geometry import Curve
>>> C = Curve([2*s, s**2], (s, 0, 2))
>>> C.arbitrary_point()
Point(2*t, t**2)
>>> C.arbitrary_point(C.parameter)
Point(2*s, s**2)
>>> C.arbitrary_point(None)
Point(2*s, s**2)
>>> C.arbitrary_point(Symbol(a))
Point(2*a, a**2)
free symbols
Return a set of symbols other than the bound symbols used to parametrically dene
the Curve.
Examples
>>> from sympy.abc import t, a
>>> from sympy.geometry import Curve
>>> Curve((t, t**2), (t, 0, 2)).free_symbols
set()
>>> Curve((t, t**2), (t, a, 2)).free_symbols
set([a])
functions
The functions specifying the curve.
Returns functions : list of parameterized coordinate functions.
540
See Also:
parameter (page 541)
Examples
>>>
>>>
>>>
>>>
(t,
limits
The limits for the curve.
Returns limits : tuple
Contains parameter and lower and upper limits.
See Also:
plot interval (page 541)
Examples
>>>
>>>
>>>
>>>
(t,
parameter
The curve function variable.
Returns parameter : SymPy symbol
See Also:
functions (page 540)
Examples
>>>
>>>
>>>
>>>
t
plot interval(parameter=t)
The plot interval for the default geometric plot of the curve.
Parameters parameter : str or Symbol, optional
Default value is t; otherwise the provided symbol is used.
Returns plot interval : list (plot interval)
[parameter, lower bound, upper bound]
See Also:
5.10. Geometry Module
541
rotate(angle=0, pt=None)
Rotate angle radians counterclockwise about Point pt.
The default pt is the origin, Point(0, 0).
Examples
>>> from sympy.geometry.curve import Curve
>>> from sympy.abc import x
>>> from sympy import pi
>>> Curve((x, x), (x, 0, 1)).rotate(pi/2)
Curve((-x, x), (x, 0, 1))
translate(x=0, y=0)
Translate the Curve by (x, y).
Examples
>>> from sympy.geometry.curve import Curve
>>> from sympy import pi
>>> from sympy.abc import x
>>> Curve((x, x), (x, 0, 1)).translate(1, 2)
Curve((x + 1, x + 2), (x, 0, 1))
Ellipses
class sympy.geometry.ellipse.Ellipse
An elliptical GeometryEntity.
542
Constructed from a center and two radii, the rst being the horizontal radius (along the
x-axis) and the second being the vertical radius (along the y-axis).
When symbolic value for hradius and vradius are used, any calculation that refers to the
foci or the major or minor axis will assume that the ellipse has its major radius on the
x-axis. If this is not true then a manual rotation is necessary.
Examples
>>> from sympy import Ellipse, Point, Rational
>>> e1 = Ellipse(Point(0, 0), 5, 1)
>>> e1.hradius, e1.vradius
(5, 1)
>>> e2 = Ellipse(Point(3, 1), hradius=3, eccentricity=Rational(4, 5))
>>> e2
Ellipse(Point(3, 1), 3, 9/5)
Plotting:
>>> from sympy.plotting.pygletplot import PygletPlot as Plot
>>> from sympy import Circle, Segment
>>> c1 = Circle(Point(0,0), 1)
>>> Plot(c1)
[0]: cos(t), sin(t), mode=parametric
>>> p = Plot()
>>> p[0] = c1
>>> radius = Segment(c1.center, c1.random_point())
>>> p[1] = radius
>>> p
[0]: cos(t), sin(t), mode=parametric
[1]: t*cos(1.546086215036205357975518382),
t*sin(1.546086215036205357975518382), mode=parametric
543
Attributes
center
hradius
vradius
area
circumference
eccentricity
periapsis
apoapsis
focus distance
foci
apoapsis
The apoapsis of the ellipse.
The greatest distance between the focus and the contour.
Returns apoapsis : number
See Also:
periapsis (page 550) Returns shortest distance between foci and contour
Examples
>>> from sympy import Point, Ellipse
>>> p1 = Point(0, 0)
>>> e1 = Ellipse(p1, 3, 1)
>>> e1.apoapsis
2*sqrt(2) + 3
arbitrary point(parameter=t)
A parameterized point on the ellipse.
Parameters parameter : str, optional
Default value is t.
Returns arbitrary point : Point
Raises ValueError :
When parameter already appears in the functions.
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy import Point, Ellipse
>>> e1 = Ellipse(Point(0, 0), 3, 2)
>>> e1.arbitrary_point()
Point(3*cos(t), 2*sin(t))
area
The area of the ellipse.
544
center
The center of the ellipse.
Returns center : number
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy import Point, Ellipse
>>> p1 = Point(0, 0)
>>> e1 = Ellipse(p1, 3, 1)
>>> e1.center
Point(0, 0)
circumference
The circumference of the ellipse.
Examples
>>> from sympy import Point, Ellipse
>>> p1 = Point(0, 0)
>>> e1 = Ellipse(p1, 3, 1)
>>> e1.circumference
12*Integral(sqrt((-8*_x**2/9 + 1)/(-_x**2 + 1)), (_x, 0, 1))
eccentricity
The eccentricity of the ellipse.
Returns eccentricity : number
Examples
>>> from sympy import Point, Ellipse, sqrt
>>> p1 = Point(0, 0)
>>> e1 = Ellipse(p1, 3, sqrt(2))
>>> e1.eccentricity
sqrt(7)/3
encloses point(p)
Return True if p is enclosed by (is inside of) self.
545
Parameters p : Point
Returns encloses point : True, False or None
See Also:
sympy.geometry.point.Point (page 497)
Notes
equation(x=x, y=y)
The equation of the ellipse.
Parameters x : str, optional
Label for the x-axis. Default value is x.
y : str, optional
Label for the y-axis. Default value is y.
Returns equation : sympy expression
See Also:
arbitrary point (page 544) Returns parameterized point on ellipse
Examples
>>> from sympy import Point, Ellipse
>>> e1 = Ellipse(Point(1, 0), 3, 2)
>>> e1.equation()
y**2/4 + (x/3 - 1/3)**2 - 1
evolute(x=x, y=y)
The equation of evolute of the ellipse.
Parameters x : str, optional
Label for the x-axis. Default value is x.
y : str, optional
Label for the y-axis. Default value is y.
Returns equation : sympy expression
546
Examples
>>> from sympy import Point, Ellipse
>>> e1 = Ellipse(Point(1, 0), 3, 2)
>>> e1.evolute()
2**(2/3)*y**(2/3) + (3*x - 3)**(2/3) - 5**(2/3)
foci
The foci of the ellipse.
Raises ValueError :
When the major and minor axis cannot be determined.
See Also:
sympy.geometry.point.Point (page 497)
focus distance (page 547) Returns the distance between focus and center
Notes
The foci can only be calculated if the major/minor axes are known.
Examples
>>> from sympy import Point, Ellipse
>>> p1 = Point(0, 0)
>>> e1 = Ellipse(p1, 3, 1)
>>> e1.foci
(Point(-2*sqrt(2), 0), Point(2*sqrt(2), 0))
focus distance
The focale distance of the ellipse.
The distance between the center and one focus.
Returns focus distance : number
See Also:
foci (page 547)
Examples
>>> from sympy import Point, Ellipse
>>> p1 = Point(0, 0)
>>> e1 = Ellipse(p1, 3, 1)
>>> e1.focus_distance
2*sqrt(2)
hradius
The horizontal radius of the ellipse.
Returns hradius : number
See Also:
vradius (page 553), major (page 549), minor (page 549)
5.10. Geometry Module
547
Examples
>>>
>>>
>>>
>>>
3
intersection(o)
The intersection of this ellipse and another geometrical entity o.
Parameters o : GeometryEntity
Returns intersection : list of GeometryEntity objects
See Also:
sympy.geometry.entity.GeometryEntity (page 493)
Notes
Currently supports intersections with Point, Line, Segment, Ray, Circle and Ellipse
types.
Examples
>>> from sympy import Ellipse, Point, Line, sqrt
>>> e = Ellipse(Point(0, 0), 5, 7)
>>> e.intersection(Point(0, 0))
[]
>>> e.intersection(Point(5, 0))
[Point(5, 0)]
>>> e.intersection(Line(Point(0,0), Point(0, 1)))
[Point(0, -7), Point(0, 7)]
>>> e.intersection(Line(Point(5,0), Point(5, 1)))
[Point(5, 0)]
>>> e.intersection(Line(Point(6,0), Point(6, 1)))
[]
>>> e = Ellipse(Point(-1, 0), 4, 3)
>>> e.intersection(Ellipse(Point(1, 0), 4, 3))
[Point(0, -3*sqrt(15)/4), Point(0, 3*sqrt(15)/4)]
>>> e.intersection(Ellipse(Point(5, 0), 4, 3))
[Point(2, -3*sqrt(7)/4), Point(2, 3*sqrt(7)/4)]
>>> e.intersection(Ellipse(Point(100500, 0), 4, 3))
[]
>>> e.intersection(Ellipse(Point(0, 0), 3, 4))
[Point(-363/175, -48*sqrt(111)/175), Point(-363/175, 48*sqrt(111)/175), Point(3, 0)]
>>> e.intersection(Ellipse(Point(-1, 0), 3, 4))
[Point(-17/5, -12/5), Point(-17/5, 12/5), Point(7/5, -12/5), Point(7/5, 12/5)]
is tangent(o)
Is o tangent to the ellipse?
Parameters o : GeometryEntity
An Ellipse, LinearEntity or Polygon
548
major
Longer axis of the ellipse (if it can be determined) else hradius.
Returns major : number or expression
See Also:
hradius (page 547), vradius (page 553), minor (page 549)
Examples
>>>
>>>
>>>
>>>
3
>>>
>>>
>>>
a
>>>
b
a = Symbol(a)
b = Symbol(b)
Ellipse(p1, a, b).major
>>>
>>>
>>>
m +
m = Symbol(m)
M = m + 1
Ellipse(p1, m, M).major
1
Ellipse(p1, b, a).major
minor
Shorter axis of the ellipse (if it can be determined) else vradius.
Returns minor : number or expression
See Also:
hradius (page 547), vradius (page 553), major (page 549)
549
Examples
>>>
>>>
>>>
>>>
1
>>>
>>>
>>>
b
>>>
a
a = Symbol(a)
b = Symbol(b)
Ellipse(p1, a, b).minor
Ellipse(p1, b, a).minor
>>> m = Symbol(m)
>>> M = m + 1
>>> Ellipse(p1, m, M).minor
m
O-axis points require the solution of a quartic equation. This often leads to very
large expressions that may be of little practical use. An approximate solution of prec
digits can be obtained by passing in the desired value:
>>> e.normal_lines((3, 3), prec=2)
[Line(Point(-38/47, -85/31), Point(9/47, -21/17)),
Line(Point(19/13, -43/21), Point(32/13, -8/3))]
Whereas the above solution has an operation count of 12, the exact solution has an
operation count of 2020.
periapsis
The periapsis of the ellipse.
The shortest distance between the focus and the contour.
Returns periapsis : number
See Also:
apoapsis (page 544) Returns greatest distance between focus and contour
550
Examples
>>> from sympy import Point, Ellipse
>>> p1 = Point(0, 0)
>>> e1 = Ellipse(p1, 3, 1)
>>> e1.periapsis
-2*sqrt(2) + 3
plot interval(parameter=t)
The plot interval for the default geometric plot of the Ellipse.
Parameters parameter : str, optional
Default value is t.
Returns plot interval : list
[parameter, lower bound, upper bound]
Examples
>>>
>>>
>>>
[t,
random point(seed=None)
A random point on the ellipse.
Returns point : Point
See Also:
sympy.geometry.point.Point (page 497)
arbitrary point (page 544) Returns parameterized point on ellipse
Notes
An arbitrary point with a random value of t substituted into it may not test as being
on the ellipse because the expression tested that a point is on the ellipse doesnt
simplify to zero and doesnt evaluate exactly to zero:
>>> from sympy.abc import t
>>> e1.arbitrary_point(t)
Point(3*cos(t), 2*sin(t))
>>> p2 = _.subs(t, 0.1)
>>> p2 in e1
False
Note that arbitrary point routine does not take this approach. A value for cos(t) and
sin(t) (not t) is substituted into the arbitrary point. There is a small chance that this
will give a point that will not test as being in the ellipse, so the process is repeated
(up to 10 times) until a valid point is obtained.
551
Examples
>>> from sympy import Point, Ellipse, Segment
>>> e1 = Ellipse(Point(0, 0), 3, 2)
>>> e1.random_point() # gives some random point
Point(...)
>>> p1 = e1.random_point(seed=0); p1.n(2)
Point(2.1, 1.4)
The random point method assures that the point will test as being in the ellipse:
>>> p1 in e1
True
reflect(line)
Override GeometryEntity.reect since the radius is not a GeometryEntity.
Notes
Until the general ellipse (with no axis parallel to the x-axis) is supported a NotImplemented error is raised and the equation whose zeros dene the rotated ellipse is
given.
Examples
>>> from sympy import Circle, Line
>>> Circle((0, 1), 1).reflect(Line((0, 0), (1, 1)))
Circle(Point(1, 0), -1)
>>> from sympy import Ellipse, Line, Point
>>> Ellipse(Point(3, 4), 1, 3).reflect(Line(Point(0, -4), Point(5, 0)))
Traceback (most recent call last):
...
NotImplementedError:
General Ellipse is not supported but the equation of the reflected
Ellipse is given by the zeros of: f(x, y) = (9*x/41 + 40*y/41 +
37/41)**2 + (40*x/123 - 3*y/41 - 364/123)**2 - 1
Traceback (most recent call last):
...
NotImplementedError:
rotate(angle=0, pt=None)
Rotate angle radians counterclockwise about Point pt.
Note: since the general ellipse is not supported, only rotations that are integer
multiples of pi/2 are allowed.
Examples
>>> from sympy import Ellipse, pi
>>> Ellipse((1, 0), 2, 1).rotate(pi/2)
Ellipse(Point(0, 1), 1, 2)
>>> Ellipse((1, 0), 2, 1).rotate(pi)
Ellipse(Point(-1, 0), 2, 1)
552
tangent lines(p)
Tangent lines between p and the ellipse.
If p is on the ellipse, returns the tangent line through point p. Otherwise, returns
the tangent line(s) from p to the ellipse, or None if no tangent line is possible (e.g.,
p inside ellipse).
Parameters p : Point
Returns tangent lines : list with 1 or 2 Lines
Raises NotImplementedError :
Can only nd tangent lines for a point, p, on the ellipse.
See Also:
sympy.geometry.point.Point (page 497), sympy.geometry.line.Line (page 517)
Examples
>>> from sympy import Point, Ellipse
>>> e1 = Ellipse(Point(0, 0), 3, 2)
>>> e1.tangent_lines(Point(3, 0))
[Line(Point(3, 0), Point(3, -12))]
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
vradius
The vertical radius of the ellipse.
Returns vradius : number
See Also:
hradius (page 547), major (page 549), minor (page 549)
553
Examples
>>>
>>>
>>>
>>>
1
class sympy.geometry.ellipse.Circle
A circle in space.
Constructed simply from a center and a radius, or from three non-collinear points.
Parameters center : Point
radius : number or sympy expression
points : sequence of three Points
Raises GeometryError :
When trying to construct circle from three collinear points. When
trying to construct circle from incorrect parameters.
See Also:
Ellipse (page 542), sympy.geometry.point.Point (page 497)
Examples
>>>
>>>
>>>
>>>
(5,
Attributes
554
equation(x=x, y=y)
The equation of the circle.
Parameters x : str or Symbol, optional
Default value is x.
y : str or Symbol, optional
Default value is y.
Returns equation : SymPy expression
Examples
>>> from sympy import Point, Circle
>>> c1 = Circle(Point(0, 0), 5)
>>> c1.equation()
x**2 + y**2 - 25
intersection(o)
The intersection of this circle with another geometrical entity.
Parameters o : GeometryEntity
Returns intersection : list of GeometryEntities
Examples
>>> from sympy import Point, Circle, Line, Ray
>>> p1, p2, p3 = Point(0, 0), Point(5, 5), Point(6, 0)
>>> p4 = Point(5, 0)
>>> c1 = Circle(p1, 5)
>>> c1.intersection(p2)
[]
>>> c1.intersection(p4)
[Point(5, 0)]
>>> c1.intersection(Ray(p1, p2))
[Point(5*sqrt(2)/2, 5*sqrt(2)/2)]
>>> c1.intersection(Line(p2, p3))
[]
radius
The radius of the circle.
Returns radius : number or sympy expression
See Also:
Ellipse.major (page 549), Ellipse.minor
(page 547), Ellipse.vradius (page 553)
(page
549),
Ellipse.hradius
555
Examples
>>> from sympy import Point, Circle
>>> c1 = Circle(Point(3, 4), 6)
>>> c1.radius
6
reflect(line)
Override GeometryEntity.reect since the radius is not a GeometryEntity.
Examples
>>> from sympy import Circle, Line
>>> Circle((0, 1), 1).reflect(Line((0, 0), (1, 1)))
Circle(Point(1, 0), -1)
vradius
This Ellipse property is an alias for the Circles radius.
Whereas hradius, major and minor can use Ellipses conventions, the vradius does
not exist for a circle. It is always a positive value in order that the Circle, like
Polygons, will have an area that can be positive or negative as determined by the
sign of the hradius.
Examples
>>> from sympy import Point, Circle
>>> c1 = Circle(Point(3, 4), 6)
>>> c1.vradius
6
Polygons
class sympy.geometry.polygon.Polygon
A two-dimensional polygon.
A simple polygon in space. Can be constructed from a sequence of points or from a
center, radius, number of sides and rotation angle.
Parameters vertices : sequence of Points
Raises GeometryError :
556
Polygons are treated as closed paths rather than 2D areas so some calculations can be
be negative or positive (e.g., area) based on the orientation of the points.
Any consecutive identical points are reduced to a single point and any points collinear
and between two points will be removed unless they are needed to dene an explicit
intersection (see examples).
A Triangle, Segment or Point will be returned when there are 3 or fewer points provided.
Examples
>>> from sympy import Point, Polygon, pi
>>> p1, p2, p3, p4, p5 = [(0, 0), (1, 0), (5, 1), (0, 1), (3, 0)]
>>> Polygon(p1, p2, p3, p4)
Polygon(Point(0, 0), Point(1, 0), Point(5, 1), Point(0, 1))
>>> Polygon(p1, p2)
Segment(Point(0, 0), Point(1, 0))
>>> Polygon(p1, p2, p5)
Segment(Point(0, 0), Point(3, 0))
While the sides of a polygon are not allowed to cross implicitly, they can do so explicitly.
For example, a polygon shaped like a Z with the top left connecting to the bottom right
of the Z must have the point in the middle of the Z explicitly given:
>>> mid = Point(1, 1)
>>> Polygon((0, 2), (2, 2), mid, (0, 0), (2, 0), mid).area
0
>>> Polygon((0, 2), (2, 2), mid, (2, 0), (0, 0), mid).area
-2
When the the keyword n is used to dene the number of sides of the Polygon then a
RegularPolygon is created and the other arguments are interpreted as center, radius and
rotation. The unrotated RegularPolygon will always have a vertex at Point(r, 0) where r
is the radius of the circle that circumscribes the RegularPolygon. Its method spin can be
used to increment that angle.
>>> p = Polygon((0,0), 1, n=3)
>>> p
RegularPolygon(Point(0, 0), 1, 3, 0)
>>> p.vertices[0]
Point(1, 0)
>>> p.args[0]
Point(0, 0)
>>> p.spin(pi/2)
>>> p.vertices[0]
Point(0, 1)
557
Attributes
area
angles
perimeter
vertices
centroid
sides
angles
The internal angle at each vertex.
Returns angles : dict
A dictionary where each key is a vertex and each value is the internal
angle at that vertex. The vertices are represented as Points.
See Also:
sympy.geometry.point.Point (page 497), sympy.geometry.line.LinearEntity.angle between
(page 509)
Examples
>>> from sympy import Point, Polygon
>>> p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)])
>>> poly = Polygon(p1, p2, p3, p4)
>>> poly.angles[p1]
pi/2
>>> poly.angles[p2]
acos(-4*sqrt(17)/17)
arbitrary point(parameter=t)
A parameterized point on the polygon.
The parameter, varying from 0 to 1, assigns points to the position on the perimeter
that is that fraction of the total perimeter. So the point evaluated at t=1/2 would
return the point from the rst vertex that is 1/2 way around the polygon.
Parameters parameter : str, optional
Default value is t.
Returns arbitrary point : Point
Raises ValueError :
When parameter already appears in the Polygons denition.
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>>
>>>
>>>
>>>
558
area
The area of the polygon.
See Also:
sympy.geometry.ellipse.Ellipse.area (page 544)
Notes
The area calculation can be positive or negative based on the orientation of the
points.
Examples
>>>
>>>
>>>
>>>
3
centroid
The centroid of the polygon.
Returns centroid : Point
See Also:
sympy.geometry.point.Point
(page 497)
(page
497),
sympy.geometry.util.centroid
Examples
>>> from sympy import Point, Polygon
>>> p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)])
>>> poly = Polygon(p1, p2, p3, p4)
>>> poly.centroid
Point(31/18, 11/18)
distance(o)
Returns the shortest distance between self and o.
If o is a point, then self does not need to be convex. If o is another polygon self and
o must be complex.
Examples
559
encloses point(p)
Return True if p is enclosed by (is inside of) self.
Parameters p : Point
Returns encloses point : True, False or None
See Also:
sympy.geometry.point.Point (page 497), sympy.geometry.ellipse.Ellipse.encloses point
(page 545)
Notes
[1] http://www.ariel.com.au/a/python-point-int-poly.html
Examples
>>> from sympy import Polygon, Point
>>> from sympy.abc import t
>>> p = Polygon((0, 0), (4, 0), (4, 4))
>>> p.encloses_point(Point(2, 1))
True
>>> p.encloses_point(Point(2, 2))
False
>>> p.encloses_point(Point(5, 5))
False
intersection(o)
The intersection of two polygons.
The intersection may be empty and can contain individual Points and complete Line
Segments.
Parameters other: Polygon :
Returns intersection : list
The list of Segments and Points
See Also:
sympy.geometry.point.Point
(page 522)
560
(page
497),
sympy.geometry.line.Segment
Examples
>>> from sympy import Point, Polygon
>>> p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)])
>>> poly1 = Polygon(p1, p2, p3, p4)
>>> p5, p6, p7 = map(Point, [(3, 2), (1, -1), (0, 2)])
>>> poly2 = Polygon(p5, p6, p7)
>>> poly1.intersection(poly2)
[Point(2/3, 0), Point(9/5, 1/5), Point(7/3, 1), Point(1/3, 1)]
is convex()
Is the polygon convex?
A polygon is convex if all its interior angles are less than 180 degrees.
Returns is convex : boolean
True if this polygon is convex, False otherwise.
See Also:
sympy.geometry.util.convex hull (page 495)
Examples
>>> from sympy import Point, Polygon
>>> p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)])
>>> poly = Polygon(p1, p2, p3, p4)
>>> poly.is_convex()
True
perimeter
The perimeter of the polygon.
Returns perimeter : number or Basic instance
See Also:
sympy.geometry.line.Segment.length (page 523)
Examples
>>> from sympy import Point, Polygon
>>> p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)])
>>> poly = Polygon(p1, p2, p3, p4)
>>> poly.perimeter
sqrt(17) + 7
plot interval(parameter=t)
The plot interval for the default geometric plot of the polygon.
Parameters parameter : str, optional
Default value is t.
Returns plot interval : list (plot interval)
[parameter, lower bound, upper bound]
561
Examples
>>>
>>>
>>>
[t,
sides
The line segments that form the sides of the polygon.
Returns sides : list of sides
Each side is a Segment.
See Also:
sympy.geometry.point.Point
(page 522)
(page
497),
sympy.geometry.line.Segment
Notes
The Segments that represent the sides are an undirected line segment so cannot be
used to tell the orientation of the polygon.
Examples
>>> from sympy import Point, Polygon
>>> p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)])
>>> poly = Polygon(p1, p2, p3, p4)
>>> poly.sides
[Segment(Point(0, 0), Point(1, 0)),
Segment(Point(1, 0), Point(5, 1)),
Segment(Point(0, 1), Point(5, 1)), Segment(Point(0, 0), Point(0, 1))]
vertices
The vertices of the polygon.
Returns vertices : tuple of Points
See Also:
sympy.geometry.point.Point (page 497)
Notes
When iterating over the vertices, it is more ecient to index self rather than to
request the vertices and index them. Only use the vertices when you want to process
all of them at once. This is even more important with RegularPolygons that calculate
each vertex.
Examples
562
class sympy.geometry.polygon.RegularPolygon
A regular polygon.
Such a polygon has all internal angles equal and all sides the same length.
Parameters center : Point
radius : number or Basic instance
The distance from the center to a vertex
n : int
The number of sides
Raises GeometryError :
If the center is not a Point, or the radius is not a number or Basic
instance, or the number of sides, n, is less than three.
See Also:
sympy.geometry.point.Point (page 497), Polygon (page 556)
Notes
563
Attributes
vertices
center
radius
rotation
apothem
interior angle
exterior angle
circumcircle
incircle
angles
angles
Returns a dictionary with keys, the vertices of the Polygon, and values, the interior
angle at each vertex.
Examples
>>> from sympy import RegularPolygon, Point
>>> r = RegularPolygon(Point(0, 0), 5, 3)
>>> r.angles
{Point(-5/2, -5*sqrt(3)/2): pi/3,
Point(-5/2, 5*sqrt(3)/2): pi/3,
Point(5, 0): pi/3}
apothem
The inradius of the RegularPolygon.
The apothem/inradius is the radius of the inscribed circle.
Returns apothem : number or instance of Basic
See Also:
sympy.geometry.line.Segment.length (page 523), sympy.geometry.ellipse.Circle.radius
(page 555)
Examples
>>> from sympy import Symbol
>>> from sympy.geometry import RegularPolygon, Point
>>> radius = Symbol(r)
>>> rp = RegularPolygon(Point(0, 0), radius, 4)
>>> rp.apothem
sqrt(2)*r/2
area
Returns the area.
Examples
564
args
Returns the center point, the radius, the number of sides, and the orientation angle.
Examples
>>> from sympy import RegularPolygon, Point
>>> r = RegularPolygon(Point(0, 0), 5, 3)
>>> r.args
(Point(0, 0), 5, 3, 0)
center
The center of the RegularPolygon
This is also the center of the circumscribing circle.
Returns center : Point
See Also:
sympy.geometry.point.Point (page 497), sympy.geometry.ellipse.Ellipse.center
(page 545)
Examples
>>> from sympy.geometry import RegularPolygon, Point
>>> rp = RegularPolygon(Point(0, 0), 5, 4)
>>> rp.center
Point(0, 0)
centroid
The center of the RegularPolygon
This is also the center of the circumscribing circle.
Returns center : Point
See Also:
sympy.geometry.point.Point (page 497), sympy.geometry.ellipse.Ellipse.center
(page 545)
Examples
>>> from sympy.geometry import RegularPolygon, Point
>>> rp = RegularPolygon(Point(0, 0), 5, 4)
>>> rp.center
Point(0, 0)
circumcenter
Alias for center.
5.10. Geometry Module
565
Examples
>>> from sympy.geometry import RegularPolygon, Point
>>> rp = RegularPolygon(Point(0, 0), 5, 4)
>>> rp.circumcenter
Point(0, 0)
circumcircle
The circumcircle of the RegularPolygon.
Returns circumcircle : Circle
See Also:
circumcenter (page 565), sympy.geometry.ellipse.Circle (page 554)
Examples
>>> from sympy.geometry import RegularPolygon, Point
>>> rp = RegularPolygon(Point(0, 0), 4, 8)
>>> rp.circumcircle
Circle(Point(0, 0), 4)
circumradius
Alias for radius.
Examples
>>>
>>>
>>>
>>>
>>>
r
encloses point(p)
Return True if p is enclosed by (is inside of) self.
Parameters p : Point
Returns encloses point : True, False or None
See Also:
sympy.geometry.ellipse.Ellipse.encloses point (page 545)
Notes
566
Examples
>>> from sympy import RegularPolygon, S, Point, Symbol
>>> p = RegularPolygon((0, 0), 3, 4)
>>> p.encloses_point(Point(0, 0))
True
>>> r, R = p.inradius, p.circumradius
>>> p.encloses_point(Point((r + R)/2, 0))
True
>>> p.encloses_point(Point(R/2, R/2 + (R - r)/10))
False
>>> t = Symbol(t, real=True)
>>> p.encloses_point(p.arbitrary_point().subs(t, S.Half))
False
>>> p.encloses_point(Point(5, 5))
False
exterior angle
Measure of the exterior angles.
Returns exterior angle : number
See Also:
sympy.geometry.line.LinearEntity.angle between (page 509)
Examples
>>> from sympy.geometry import RegularPolygon, Point
>>> rp = RegularPolygon(Point(0, 0), 4, 8)
>>> rp.exterior_angle
pi/4
incircle
The incircle of the RegularPolygon.
Returns incircle : Circle
See Also:
inradius (page 567), sympy.geometry.ellipse.Circle (page 554)
Examples
>>> from sympy.geometry import RegularPolygon, Point
>>> rp = RegularPolygon(Point(0, 0), 4, 7)
>>> rp.incircle
Circle(Point(0, 0), 4*cos(pi/7))
inradius
Alias for apothem.
Examples
567
interior angle
Measure of the interior angles.
Returns interior angle : number
See Also:
sympy.geometry.line.LinearEntity.angle between (page 509)
Examples
>>> from sympy.geometry import RegularPolygon, Point
>>> rp = RegularPolygon(Point(0, 0), 4, 8)
>>> rp.interior_angle
3*pi/4
length
Returns the length of the sides.
The half-length of the side and the apothem form two legs of a right triangle whose
hypotenuse is the radius of the regular polygon.
Examples
>>> from sympy.geometry import RegularPolygon
>>> from sympy import sqrt
>>> s = square_in_unit_circle = RegularPolygon((0, 0), 1, 4)
>>> s.length
sqrt(2)
>>> sqrt((_/2)**2 + s.apothem**2) == s.radius
True
radius
Radius of the RegularPolygon
This is also the radius of the circumscribing circle.
Returns radius : number or instance of Basic
See Also:
sympy.geometry.line.Segment.length (page 523), sympy.geometry.ellipse.Circle.radius
(page 555)
Examples
>>> from sympy import Symbol
>>> from sympy.geometry import RegularPolygon, Point
>>> radius = Symbol(r)
568
reflect(line)
Override GeometryEntity.reect since this is not made of only points.
>>> from sympy import RegularPolygon, Line
>>> RegularPolygon((0, 0), 1, 4).reflect(Line((0, 1), slope=-2))
RegularPolygon(Point(4/5, 2/5), -1, 4, acos(3/5))
rotate(angle, pt=None)
Override GeometryEntity.rotate to rst rotate the RegularPolygon about its center.
>>> from sympy import Point, RegularPolygon, Polygon, pi
>>> t = RegularPolygon(Point(1, 0), 1, 3)
>>> t.vertices[0] # vertex on x-axis
Point(2, 0)
>>> t.rotate(pi/2).vertices[0] # vertex on y axis now
Point(0, 2)
See Also:
rotation (page 569)
spin (page 569) Rotates a RegularPolygon in place
rotation
CCW angle by which the RegularPolygon is rotated
Returns rotation : number or instance of Basic
Examples
>>> from sympy import pi
>>> from sympy.geometry import RegularPolygon, Point
>>> RegularPolygon(Point(0, 0), 3, 4, pi).rotation
pi
spin(angle)
Increment in place the virtual Polygons rotation by ccw angle.
See also: rotate method which moves the center.
5.10. Geometry Module
569
See Also:
rotation (page 569)
rotate (page 569) Creates a copy of the RegularPolygon rotated about a Point
vertices
The vertices of the RegularPolygon.
Returns vertices : list
Each vertex is a Point.
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy.geometry import RegularPolygon, Point
>>> rp = RegularPolygon(Point(0, 0), 5, 4)
>>> rp.vertices
[Point(5, 0), Point(0, 5), Point(-5, 0), Point(0, -5)]
class sympy.geometry.polygon.Triangle
A polygon with three vertices and three sides.
Parameters points : sequence of Points
keyword: asa, sas, or sss to specify sides/angles of the triangle :
Raises GeometryError :
If the number of vertices is not equal to three, or one of the vertices
is not a Point, or a valid keyword is not given.
See Also:
sympy.geometry.point.Point (page 497), Polygon (page 556)
Examples
>>> from sympy.geometry import Triangle, Point
>>> Triangle(Point(0, 0), Point(4, 0), Point(4, 3))
Triangle(Point(0, 0), Point(4, 0), Point(4, 3))
Keywords sss, sas, or asa can be used to give the desired side lengths (in order) and
interior angles (in degrees) that dene the triangle:
>>> Triangle(sss=(3, 4, 5))
Triangle(Point(0, 0), Point(3, 0), Point(3, 4))
>>> Triangle(asa=(30, 1, 30))
570
Attributes
vertices
altitudes
orthocenter
circumcenter
circumradius
circumcircle
inradius
incircle
medians
medial
altitudes
The altitudes of the triangle.
An altitude of a triangle is a segment through a vertex, perpendicular to the opposite
side, with length being the height of the vertex measured from the line containing
the side.
Returns altitudes : dict
The dictionary consists of keys which are vertices and values which
are Segments.
See Also:
sympy.geometry.point.Point (page 497), sympy.geometry.line.Segment.length
(page 523)
Examples
>>> from sympy.geometry import Point, Triangle
>>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
>>> t = Triangle(p1, p2, p3)
>>> t.altitudes[p1]
Segment(Point(0, 0), Point(1/2, 1/2))
bisectors()
The angle bisectors of the triangle.
An angle bisector of a triangle is a straight line through a vertex which cuts the
corresponding angle in half.
Returns bisectors : dict
Each key is a vertex (Point) and each value is the corresponding bisector (Segment).
See Also:
sympy.geometry.point.Point
(page 522)
(page
497),
sympy.geometry.line.Segment
571
Examples
>>> from sympy.geometry import Point, Triangle, Segment
>>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
>>> t = Triangle(p1, p2, p3)
>>> from sympy import sqrt
>>> t.bisectors()[p2] == Segment(Point(0, sqrt(2) - 1), Point(1, 0))
True
circumcenter
The circumcenter of the triangle
The circumcenter is the center of the circumcircle.
Returns circumcenter : Point
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy.geometry import Point, Triangle
>>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
>>> t = Triangle(p1, p2, p3)
>>> t.circumcenter
Point(1/2, 1/2)
circumcircle
The circle which passes through the three vertices of the triangle.
Returns circumcircle : Circle
See Also:
sympy.geometry.ellipse.Circle (page 554)
Examples
>>> from sympy.geometry import Point, Triangle
>>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
>>> t = Triangle(p1, p2, p3)
>>> t.circumcircle
Circle(Point(1/2, 1/2), sqrt(2)/2)
circumradius
The radius of the circumcircle of the triangle.
Returns circumradius : number of Basic instance
See Also:
sympy.geometry.ellipse.Circle.radius (page 555)
572
Examples
>>> from sympy import Symbol
>>> from sympy.geometry import Point, Triangle
>>> a = Symbol(a)
>>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, a)
>>> t = Triangle(p1, p2, p3)
>>> t.circumradius
sqrt(a**2/4 + 1/4)
incenter
The center of the incircle.
The incircle is the circle which lies inside the triangle and touches all three sides.
Returns incenter : Point
See Also:
incircle (page 573), sympy.geometry.point.Point (page 497)
Examples
>>> from sympy.geometry import Point, Triangle
>>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
>>> t = Triangle(p1, p2, p3)
>>> t.incenter
Point(-sqrt(2)/2 + 1, -sqrt(2)/2 + 1)
incircle
The incircle of the triangle.
The incircle is the circle which lies inside the triangle and touches all three sides.
Returns incircle : Circle
See Also:
sympy.geometry.ellipse.Circle (page 554)
Examples
>>> from sympy.geometry import Point, Triangle
>>> p1, p2, p3 = Point(0, 0), Point(2, 0), Point(0, 2)
>>> t = Triangle(p1, p2, p3)
>>> t.incircle
Circle(Point(-sqrt(2) + 2, -sqrt(2) + 2), -sqrt(2) + 2)
inradius
The radius of the incircle.
Returns inradius : number of Basic instance
See Also:
incircle (page 573), sympy.geometry.ellipse.Circle.radius (page 555)
573
Examples
>>>
>>>
>>>
>>>
1
is equilateral()
Are all the sides the same length?
Returns is equilateral : boolean
See Also:
sympy.geometry.entity.GeometryEntity.is similar (page 493), RegularPolygon (page 563), is isosceles (page 574), is right (page 574), is scalene
(page 575)
Examples
>>> from sympy.geometry import Triangle, Point
>>> t1 = Triangle(Point(0, 0), Point(4, 0), Point(4, 3))
>>> t1.is_equilateral()
False
>>> from sympy import sqrt
>>> t2 = Triangle(Point(0, 0), Point(10, 0), Point(5, 5*sqrt(3)))
>>> t2.is_equilateral()
True
is isosceles()
Are two or more of the sides the same length?
Returns is isosceles : boolean
See Also:
is equilateral (page 574), is right (page 574), is scalene (page 575)
Examples
>>> from sympy.geometry import Triangle, Point
>>> t1 = Triangle(Point(0, 0), Point(4, 0), Point(2, 4))
>>> t1.is_isosceles()
True
is right()
Is the triangle right-angled.
Returns is right : boolean
See Also:
sympy.geometry.line.LinearEntity.is perpendicular
(page
512),
is equilateral (page 574), is isosceles (page 574), is scalene (page 575)
574
Examples
>>> from sympy.geometry import Triangle, Point
>>> t1 = Triangle(Point(0, 0), Point(4, 0), Point(4, 3))
>>> t1.is_right()
True
is scalene()
Are all the sides of the triangle of dierent lengths?
Returns is scalene : boolean
See Also:
is equilateral (page 574), is isosceles (page 574), is right (page 574)
Examples
>>> from sympy.geometry import Triangle, Point
>>> t1 = Triangle(Point(0, 0), Point(4, 0), Point(1, 4))
>>> t1.is_scalene()
True
is similar(t1, t2)
Is another triangle similar to this one.
Two triangles are similar if one can be uniformly scaled to the other.
Parameters other: Triangle :
Returns is similar : boolean
See Also:
sympy.geometry.entity.GeometryEntity.is similar (page 493)
Examples
>>> from sympy.geometry import Triangle, Point
>>> t1 = Triangle(Point(0, 0), Point(4, 0), Point(4, 3))
>>> t2 = Triangle(Point(0, 0), Point(-4, 0), Point(-4, -3))
>>> t1.is_similar(t2)
True
>>> t2 = Triangle(Point(0, 0), Point(-4, 0), Point(-4, -4))
>>> t1.is_similar(t2)
False
medial
The medial triangle of the triangle.
The triangle which is formed from the midpoints of the three sides.
Returns medial : Triangle
See Also:
sympy.geometry.line.Segment.midpoint (page 524)
575
Examples
>>> from sympy.geometry import Point, Triangle
>>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
>>> t = Triangle(p1, p2, p3)
>>> t.medial
Triangle(Point(1/2, 0), Point(1/2, 1/2), Point(0, 1/2))
medians
The medians of the triangle.
A median of a triangle is a straight line through a vertex and the midpoint of the
opposite side, and divides the triangle into two equal areas.
Returns medians : dict
Each key is a vertex (Point) and each value is the median (Segment)
at that point.
See Also:
sympy.geometry.point.Point.midpoint (page 501), sympy.geometry.line.Segment.midpoint
(page 524)
Examples
>>> from sympy.geometry import Point, Triangle
>>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
>>> t = Triangle(p1, p2, p3)
>>> t.medians[p1]
Segment(Point(0, 0), Point(1/2, 1/2))
orthocenter
The orthocenter of the triangle.
The orthocenter is the intersection of the altitudes of a triangle. It may lie inside,
outside or on the triangle.
Returns orthocenter : Point
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy.geometry import Point, Triangle
>>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
>>> t = Triangle(p1, p2, p3)
>>> t.orthocenter
Point(0, 0)
vertices
The triangles vertices
Returns vertices : tuple
Each element in the tuple is a Point
576
See Also:
sympy.geometry.point.Point (page 497)
Examples
>>> from sympy.geometry import Triangle, Point
>>> t = Triangle(Point(0, 0), Point(4, 0), Point(4, 3))
>>> t.vertices
(Point(0, 0), Point(4, 0), Point(4, 3))
Plane
Geometrical Planes.
Contains Plane
class sympy.geometry.plane.Plane
A plane is a at, two-dimensional surface. A plane is the two-dimensional analogue of a
point (zero-dimensions), a line (one-dimension) and a solid (three-dimensions). A plane
can generally be constructed by two types of inputs. They are three non-collinear points
and a point and the planes normal vector.
Examples
>>> from sympy import Plane, Point3D
>>> from sympy.abc import x
>>> Plane(Point3D(1, 1, 1), Point3D(2, 3, 4), Point3D(2, 2, 2))
Plane(Point3D(1, 1, 1), (-1, 2, -1))
>>> Plane((1, 1, 1), (2, 3, 4), (2, 2, 2))
Plane(Point3D(1, 1, 1), (-1, 2, -1))
>>> Plane(Point3D(1, 1, 1), normal_vector=(1,4,7))
Plane(Point3D(1, 1, 1), (1, 4, 7))
Attributes
p1
normal vector
angle between(o)
Angle between the plane and other geometric entity.
Parameters LinearEntity3D, Plane. :
Returns angle : angle in radians
Notes
This method accepts only 3D entities as its parameter, but if you want to calculate
the angle between a 2D entity and a plane you should rst convert to a 3D entity by
projecting onto a desired plane and then proceed to calculate the angle.
5.10. Geometry Module
577
Examples
>>> from sympy import Point3D, Line3D, Plane
>>> a = Plane(Point3D(1, 2, 2), normal_vector=(1, 2, 3))
>>> b = Line3D(Point3D(1, 3, 4), Point3D(2, 2, 2))
>>> a.angle_between(b)
-asin(sqrt(21)/6)
arbitrary point(t=None)
Returns an arbitrary point on the Plane; varying t from 0 to 2*pi will move the point
in a circle of radius 1 about p1 of the Plane.
Returns Point3D :
Examples
>>> from sympy.geometry.plane import Plane
>>> from sympy.abc import t
>>> p = Plane((0, 0, 0), (0, 0, 1), (0, 1, 0))
>>> p.arbitrary_point(t)
Point3D(0, cos(t), sin(t))
>>> _.distance(p.p1).simplify()
1
distance(o)
Distance beteen the plane and another geometric entity.
Parameters Point3D, LinearEntity3D, Plane. :
Returns distance :
Notes
This method accepts only 3D entities as its parameter, but if you want to calculate
the distance between a 2D entity and a plane you should rst convert to a 3D entity
by projecting onto a desired plane and then proceed to calculate the distance.
578
Examples
>>> from sympy import Point, Point3D, Line, Line3D, Plane
>>> a = Plane(Point3D(1, 1, 1), normal_vector=(1, 1, 1))
>>> b = Point3D(1, 2, 3)
>>> a.distance(b)
sqrt(3)
>>> c = Line3D(Point3D(2, 3, 1), Point3D(1, 2, 2))
>>> a.distance(c)
0
intersection(o)
The intersection with other geometrical entity.
Parameters Point, Point3D, LinearEntity, LinearEntity3D, Plane :
Returns List :
Examples
>>> from sympy import Point, Point3D, Line, Line3D, Plane
>>> a = Plane(Point3D(1, 2, 3), normal_vector=(1, 1, 1))
>>> b = Point3D(1, 2, 3)
>>> a.intersection(b)
[Point3D(1, 2, 3)]
>>> c = Line3D(Point3D(1, 4, 7), Point3D(2, 2, 2))
>>> a.intersection(c)
[Point3D(2, 2, 2)]
>>> d = Plane(Point3D(6, 0, 0), normal_vector=(2, -5, 3))
>>> e = Plane(Point3D(2, 0, 0), normal_vector=(3, 4, -3))
>>> d.intersection(e)
[Line3D(Point3D(78/23, -24/23, 0), Point3D(147/23, 321/23, 23))]
is coplanar(o)
Returns True if o is coplanar with self, else False.
Examples
>>> from sympy import Plane, Point3D
>>> o = (0, 0, 0)
>>> p = Plane(o, (1, 1, 1))
579
is parallel(l)
Is the given geometric entity parallel to the plane?
Parameters LinearEntity3D or Plane :
Returns Boolean :
Examples
>>> from sympy import Plane, Point3D
>>> a = Plane(Point3D(1,4,6), normal_vector=(2, 4, 6))
>>> b = Plane(Point3D(3,1,3), normal_vector=(4, 8, 12))
>>> a.is_parallel(b)
True
is perpendicular(l)
is the given geometric entity perpendicualar to the given plane?
Parameters LinearEntity3D or Plane :
Returns Boolean :
Examples
>>> from sympy import Plane, Point3D
>>> a = Plane(Point3D(1,4,6), normal_vector=(2, 4, 6))
>>> b = Plane(Point3D(2, 2, 2), normal_vector=(-1, 2, -1))
>>> a.is_perpendicular(b)
True
normal vector
Normal vector of the given plane.
Examples
>>> from sympy import Point3D, Plane
>>> a = Plane(Point3D(1, 1, 1), Point3D(2, 3, 4), Point3D(2, 2, 2))
>>> a.normal_vector
(-1, 2, -1)
>>> a = Plane(Point3D(1, 1, 1), normal_vector=(1, 4, 7))
>>> a.normal_vector
(1, 4, 7)
p1
The only dening point of the plane. Others can be obtained from the arbitrary point
method.
See Also:
sympy.geometry.point3d.Point3D (page 503)
580
Examples
>>> from sympy import Point3D, Plane
>>> a = Plane(Point3D(1, 1, 1), Point3D(2, 3, 4), Point3D(2, 2, 2))
>>> a.p1
Point3D(1, 1, 1)
parallel plane(pt)
Plane parallel to the given plane and passing through the point pt.
Parameters pt: Point3D :
Returns Plane :
Examples
>>> from sympy import Plane, Point3D
>>> a = Plane(Point3D(1, 4, 6), normal_vector=(2, 4, 6))
>>> a.parallel_plane(Point3D(2, 3, 5))
Plane(Point3D(2, 3, 5), (2, 4, 6))
perpendicular line(pt)
A line perpendicular to the given plane.
Parameters pt: Point3D :
Returns Line3D :
Examples
>>> from sympy import Plane, Point3D, Line3D
>>> a = Plane(Point3D(1,4,6), normal_vector=(2, 4, 6))
>>> a.perpendicular_line(Point3D(9, 8, 7))
Line3D(Point3D(9, 8, 7), Point3D(11, 12, 13))
perpendicular plane(*pts)
Return a perpendicular passing through the given points. If the direction ratio between the points is the same as the Planes normal vector then, to select from the
innite number of possible planes, a third point will be chosen on the z-axis (or the
y-axis if the normal vector is already parallel to the z-axis). If less than two points
are given they will be supplied as follows: if no point is given then pt1 will be self.p1;
if a second point is not given it will be a point through pt1 on a line parallel to the
z-axis (if the normal is not already the z-axis, otherwise on the line parallel to the
y-axis).
Parameters pts: 0, 1 or 2 Point3D :
Returns Plane :
Examples
>>>
>>>
>>>
>>>
581
>>> p.perpendicular_plane(a, b)
Plane(Point3D(0, 0, 0), (1, 0, 0))
projection(pt)
Project the given point onto the plane along the plane normal.
Parameters Point or Point3D :
Returns Point3D :
Examples
>>> from sympy import Plane, Point, Point3D
>>> A = Plane(Point3D(1, 1, 2), normal_vector=(1, 1, 1))
The projection is along the normal vector direction, not the z axis, so (1, 1) does not
project to (1, 1, 2) on the plane A:
>>> b = Point(1, 1)
>>> A.projection(b)
Point3D(5/3, 5/3, 2/3)
>>> _ in A
True
projection line(line)
Project the given line onto the plane through the normal plane containing the line.
Parameters LinearEntity or LinearEntity3D :
Returns Point3D, Line3D, Ray3D or Segment3D :
Notes
For the interaction between 2D and 3D lines(segments, rays), you should convert the
line to 3D by using this method. For example for nding the intersection between
a 2D and a 3D line, convert the 2D line to a 3D line by projecting it on a required
plane and then proceed to nd the intersection between those lines.
Examples
>>> from sympy import Plane, Line, Line3D, Point, Point3D
>>> a = Plane(Point3D(1, 1, 1), normal_vector=(1, 1, 1))
>>> b = Line(Point(1, 1), Point(2, 2))
>>> a.projection_line(b)
Line3D(Point3D(4/3, 4/3, 1/3), Point3D(5/3, 5/3, -1/3))
>>> c = Line3D(Point3D(1, 1, 1), Point3D(2, 2, 2))
>>> a.projection_line(c)
Point3D(1, 1, 1)
582
random point(seed=None)
Returns a random point on the Plane.
Returns Point3D :
b
a
f dx
5.11.1 Examples
SymPy can integrate a vast array of functions. It can integrate polynomial functions:
>>> from sympy import *
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
>>> x = Symbol(x)
>>> integrate(x**2 + x + 1, x)
3
2
x
x
-- + -- + x
3
2
Rational functions:
>>> integrate(x/(x**2+2*x+1), x)
1
log(x + 1) + ----x + 1
even a few nonelementary integrals (in particular, some integrals involving the error function)
can be evaluated:
>>> integrate(exp(-x**2)*erf(x), x)
____
2
\/ pi *erf (x)
-------------4
583
For all sensible functions, this converges absolutely in a strip a < Re(s) < b.
The Mellin transform is related via change of variables to the Fourier transform, and
also to the (bilateral) Laplace transform.
This function returns (F, (a, b), cond) where F is the Mellin transform of f, (a, b)
is the fundamental strip (as above), and cond are auxiliary convergence conditions.
If the integral cannot be computed in closed form, this function returns an unevaluated
MellinTransform object.
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). If noconds=False, then
only F will be returned (i.e. not cond, and also not the strip (a, b)).
>>> from sympy.integrals.transforms import mellin_transform
>>> from sympy import exp
>>> from sympy.abc import x, s
>>> mellin_transform(exp(-x), x, s)
(gamma(s), (0, oo), True)
See Also:
inverse mellin transform
(page
fourier transform
(page
586),
verse hankel transform (page 590)
584),
laplace transform
hankel transform
(page
(page
589),
585),
in-
c+i
f (x) =
xs F (s)ds,
ci
for any c in the fundamental strip. Under certain regularity conditions on F and/or f ,
this recovers f from its Mellin transform F (and vice versa), for positive real x.
One of a or b may be passed as None; a suitable c will be inferred.
If the integral cannot be computed in closed form, this function returns an unevaluated
InverseMellinTransform object.
Note that this function will assume x to be positive and real, regardless of the sympy
assumptions!
For
a
description
of
possible
hints,
refer
to
sympy.integrals.transforms.IntegralTransform.doit().
584
the
docstring
of
See Also:
mellin transform
(page
584),
verse hankel transform (page 590)
hankel transform
(page
589),
in-
For all sensible functions, this converges absolutely in a half plane a < Re(s).
This function returns (F, a, cond) where F is the Laplace transform of f, Re(s) > a is
the half-plane of convergence, and cond are auxiliary convergence conditions.
If the integral cannot be computed in closed form, this function returns an unevaluated
LaplaceTransform object.
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). If noconds=True, only F
will be returned (i.e. not cond, and also not the plane a).
>>> from sympy.integrals import laplace_transform
>>> from sympy.abc import t, s, a
>>> laplace_transform(t**a, t, s)
(s**(-a)*gamma(a + 1)/s, 0, -re(a) < 1)
See Also:
inverse laplace transform
(page
fourier transform
(page
586),
verse hankel transform (page 590)
585),
mellin transform
hankel transform
(page
(page
589),
584),
in-
plane=None,
c+i
est F (s)ds,
f (t) =
ci
for c so large that F (s) has no singularites in the half-plane Re(s) > c .
5.11. Symbolic Integrals
585
The plane can be specied by argument plane, but will be inferred if passed as None.
Under certain regularity conditions, this recovers f (t) from its Laplace Transform F (s),
for non-negative t, and vice versa.
If the integral cannot be computed in closed form, this function returns an unevaluated
InverseLaplaceTransform object.
Note that this function will always assume t to be real, regardless of the sympy assumption on t.
For
a
description
of
possible
hints,
refer
to
sympy.integrals.transforms.IntegralTransform.doit().
the
docstring
of
See Also:
laplace transform
(page
585),
verse hankel transform (page 590)
hankel transform
(page
589),
in-
If the transform cannot be computed in closed form, this function returns an unevaluated
FourierTransform object.
For
other
Fourier
transform
conventions,
sympy.integrals.transforms. fourier transform().
see
the
function
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import fourier_transform, exp
>>> from sympy.abc import x, k
>>> fourier_transform(exp(-x**2), x, k)
sqrt(pi)*exp(-pi**2*k**2)
>>> fourier_transform(exp(-x**2), x, k, noconds=False)
(sqrt(pi)*exp(-pi**2*k**2), True)
See Also:
inverse fourier transform (page 586),
sine transform (page 587),
in(page
587),
cosine transform
(page
588),
inverse sine transform
verse cosine transform (page 588),
hankel transform (page 589),
inverse hankel transform (page 590), mellin transform (page 584), laplace transform
(page 585)
sympy.integrals.transforms.inverse fourier transform(F, k, x, **hints)
586
If the transform cannot be computed in closed form, this function returns an unevaluated
InverseFourierTransform object.
For
other
Fourier
transform
conventions,
sympy.integrals.transforms. fourier transform().
see
the
function
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import inverse_fourier_transform, exp, sqrt, pi
>>> from sympy.abc import x, k
>>> inverse_fourier_transform(sqrt(pi)*exp(-(pi*k)**2), k, x)
exp(-x**2)
>>> inverse_fourier_transform(sqrt(pi)*exp(-(pi*k)**2), k, x, noconds=False)
(exp(-x**2), True)
See Also:
fourier transform (page 586), sine transform (page 587), inverse sine transform
(page 587), cosine transform (page 588), inverse cosine transform (page 588), hankel transform (page 589), inverse hankel transform (page 590), mellin transform
(page 584), laplace transform (page 585)
sympy.integrals.transforms.sine transform(f, x, k, **hints)
Compute the unitary, ordinary-frequency sine transform of f , dened as
2
F (k) =
f (x) sin(2xk)dx.
0
If the transform cannot be computed in closed form, this function returns an unevaluated
SineTransform object.
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import sine_transform, exp
>>> from sympy.abc import x, k, a
>>> sine_transform(x*exp(-a*x**2), x, k)
sqrt(2)*k*exp(-k**2/(4*a))/(4*a**(3/2))
>>> sine_transform(x**(-a), x, k)
2**(-a + 1/2)*k**(a - 1)*gamma(-a/2 + 1)/gamma(a/2 + 1/2)
See Also:
fourier transform
(page
586),
inverse fourier transform
(page
586),
inverse sine transform (page 587),
cosine transform (page 588),
inhankel transform (page 589),
inverse cosine transform (page 588),
verse hankel transform (page 590), mellin transform (page 584), laplace transform
(page 585)
587
If the transform cannot be computed in closed form, this function returns an unevaluated
InverseSineTransform object.
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import inverse_sine_transform, exp, sqrt, gamma, pi
>>> from sympy.abc import x, k, a
>>> inverse_sine_transform(2**((1-2*a)/2)*k**(a - 1)*
...
gamma(-a/2 + 1)/gamma((a+1)/2), k, x)
x**(-a)
>>> inverse_sine_transform(sqrt(2)*k*exp(-k**2/(4*a))/(4*sqrt(a)**3), k, x)
x*exp(-a*x**2)
See Also:
fourier transform
(page
586),
inverse fourier transform
(page
586),
sine transform (page 587), cosine transform (page 588), inverse cosine transform
(page 588), hankel transform (page 589), inverse hankel transform (page 590),
mellin transform (page 584), laplace transform (page 585)
sympy.integrals.transforms.cosine transform(f, x, k, **hints)
Compute the unitary, ordinary-frequency cosine transform of f , dened as
2
F (k) =
f (x) cos(2xk)dx.
0
If the transform cannot be computed in closed form, this function returns an unevaluated
CosineTransform object.
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import cosine_transform, exp, sqrt, cos
>>> from sympy.abc import x, k, a
>>> cosine_transform(exp(-a*x), x, k)
sqrt(2)*a/(sqrt(pi)*(a**2 + k**2))
>>> cosine_transform(exp(-a*sqrt(x))*cos(a*sqrt(x)), x, k)
a*exp(-a**2/(2*k))/(2*k**(3/2))
See Also:
fourier transform
(page
586),
inverse fourier transform
(page
586),
sine transform
(page
587),
inverse sine transform
(page
587),
inverse cosine transform (page 588),
hankel transform (page 589),
inverse hankel transform (page 590), mellin transform (page 584), laplace transform
(page 585)
588
If the transform cannot be computed in closed form, this function returns an unevaluated
InverseCosineTransform object.
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import inverse_cosine_transform, exp, sqrt, pi
>>> from sympy.abc import x, k, a
>>> inverse_cosine_transform(sqrt(2)*a/(sqrt(pi)*(a**2 + k**2)), k, x)
exp(-a*x)
>>> inverse_cosine_transform(1/sqrt(k), k, x)
1/sqrt(x)
See Also:
fourier transform
(page
586),
inverse fourier transform
(page
586),
sine transform (page 587), inverse sine transform (page 587), cosine transform
(page 588), hankel transform (page 589), inverse hankel transform (page 590),
mellin transform (page 584), laplace transform (page 585)
sympy.integrals.transforms.hankel transform(f, r, k, nu, **hints)
Compute the Hankel transform of f , dened as
F (k) =
f (r)J (kr)rdr.
0
If the transform cannot be computed in closed form, this function returns an unevaluated
HankelTransform object.
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import hankel_transform, inverse_hankel_transform
>>> from sympy import gamma, exp, sinh, cosh
>>> from sympy.abc import r, k, m, nu, a
>>> ht = hankel_transform(1/r**m, r, k, nu)
>>> ht
2*2**(-m)*k**(m - 2)*gamma(-m/2 + nu/2 + 1)/gamma(m/2 + nu/2)
>>> inverse_hankel_transform(ht, k, r, nu)
r**(-m)
>>> ht = hankel_transform(exp(-a*r), r, k, 0)
>>> ht
a/(k**3*(a**2/k**2 + 1)**(3/2))
589
>>> inverse_hankel_transform(ht, k, r, 0)
exp(-a*r)
See Also:
fourier transform
(page
586),
inverse fourier transform
(page
586),
sine transform (page 587), inverse sine transform (page 587), cosine transform
(page 588), inverse cosine transform (page 588), inverse hankel transform
(page 590), mellin transform (page 584), laplace transform (page 585)
sympy.integrals.transforms.inverse hankel transform(F, k, r, nu, **hints)
Compute the inverse Hankel transform of F dened as
F (k)J (kr)kdk.
f (r) =
0
If the transform cannot be computed in closed form, this function returns an unevaluated
InverseHankelTransform object.
For
a
description
of
possible
hints,
refer
to
the
docstring
of
sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import hankel_transform, inverse_hankel_transform, gamma
>>> from sympy import gamma, exp, sinh, cosh
>>> from sympy.abc import r, k, m, nu, a
>>> ht = hankel_transform(1/r**m, r, k, nu)
>>> ht
2*2**(-m)*k**(m - 2)*gamma(-m/2 + nu/2 + 1)/gamma(m/2 + nu/2)
>>> inverse_hankel_transform(ht, k, r, nu)
r**(-m)
>>> ht = hankel_transform(exp(-a*r), r, k, 0)
>>> ht
a/(k**3*(a**2/k**2 + 1)**(3/2))
>>> inverse_hankel_transform(ht, k, r, 0)
exp(-a*r)
See Also:
fourier transform
(page
586),
inverse fourier transform
(page
586),
sine transform (page 587), inverse sine transform (page 587), cosine transform
(page 588), inverse cosine transform (page 588), hankel transform (page 589),
mellin transform (page 584), laplace transform (page 585)
5.11.3 Internals
There is a general method for calculating antiderivatives of elementary functions, called the
Risch algorithm. The Risch algorithm is a decision procedure that can determine whether an
elementary solution exists, and in that case calculate it. It can be extended to handle many
nonelementary functions in addition to the elementary ones.
SymPy currently uses a simplied version of the Risch algorithm, called the Risch-Norman
algorithm. This algorithm is much faster, but may fail to nd an antiderivative, although it is
590
still very powerful. SymPy also uses pattern matching and heuristics to speed up evaluation
of some types of integrals, e.g. polynomials.
For non-elementary denite integrals, SymPy uses so-called Meijer G-functions. Details are
described here:
Computing Integrals using Meijer G-Functions
This text aims do describe in some detail the steps (and subtleties) involved in using Meijer
G-functions for computing denite and indenite integrals. We shall ignore proofs completely.
Overview
f (x)dx or
Some other integrals (e.g. ) can also be computed by rst recasting them into one of the
above forms. There is a lot of choice involved here, and the algorithm is heuristic at best.
Polar Numbers and Branched Functions
Both Meijer G-Functions and Hypergeometric functions are typically branched (possible
branchpoints being 0, 1, ). This is not very important when e.g. expanding a single hypergeometric function into named special functions, since sorting out the branches can be left
to the human user. However this algorithm manipulates and transforms G-functions, and to
do this correctly it needs at least some crude understanding of the branchings involved.
To begin, we consider the set S = {(r, ) : r > 0, R}. We have a map p : S : C {0}, (r, ) 7
rei . Decreeing this to be a local biholomorphism gives S both a topology and a complex
structure. This Riemann Surface is usually referred to as the Riemann Surface of the logarithm, for the following reason: We can dene maps Exp : C S, (x + iy) 7 (exp(x), y) and
Log : S C, (ex , y) 7 x + iy. These can both be shown to be holomorphic, and are indeed
mutual inverses.
We also sometimes formally attach a point zero (0) to S and denote the resulting object
S0 . Notably there is no complex structure dened near 0. A fundamental system of neighbourhoods is given by {Exp(z) : <(z) < k}, which at least denes a topology. Elements of
S0 shall be called polar numbers. We further dene functions Arg : S R, (r, ) 7 and
|.| : S0 R>0 , (r, ) 7 r. These have evident meaning and are both continuous everywhere.
Using these maps many operations can be extended from C to S. We dene Exp(a) Exp(b) =
Exp(a + b) for a, b C, also for a S and b C we dene ab = Exp(b Log(a)). It can be checked
easily that using these denitions, many algebraic properties holding for positive reals (e.g.
(ab)c = ac bc ) which hold in C only for some numbers (because of branch cuts) hold indeed for
all polar numbers.
591
As one peculiarity it should be mentioned that addition of polar numbers is not usually dened.
However, formal sums of polar numbers
can be used to express
branching behaviour. For
example, consider the functions F (z) = 1 + z and G(a, b) = a + b, where a, b, z are polar
numbers. The general rule is that functions of a single polar variable are dened in such a
way that they are continuous on circles, and agree with the usual denition for positive reals.
Thus if S(z) denotes the standard branch of the square root function on C, we are forced to
dene
: |z| < 1
S(p(z))
F (z) = S(p(z))
: < Arg(z) + 4n for some n Z .
S(p(z)) : else
(We
are omitting |z| = 1 here, this does not matter for integration.) Finally we dene G(a, b) =
aF (b/a).
Representing Branched Functions on the Argand Plane
Suppose we are given an integrand f (x) and are trying to rewrite it as a single G-function.
To do this, we rst split f (x) into the form xs g(x) (where g(x) is supposed to be simpler than
f (x)). This is because multiplicative powers can be absorbed into the G-function later. This
splitting is done by split mul(f, x). Then we assemble a tuple of functions that occur in f
(e.g. if f (x) = ex cos x, we would assemble the tuple (cos, exp)). This is done by the function
mytype(f, x). Next we index a lookup table (created using create lookup table()) with
this tuple. This (hopefully) yields a list of Meijer G-function formulae involving these functions, we then pattern-match all of them. If one ts, we were successful, otherwise not and
we have to try something else.
Suppose now we want to rewrite as a product of two G-functions. To do this, we (try to)
nd all inequivalent ways of splitting f (x) into a product f1 (x)f2 (x). We could try these splittings in any order, but it is often a good idea to minimise (a) the number of powers occuring in fi (x) and (b) the number of dierent functions occuring in fi (x). Thus given e.g.
f (x) = sin x ex sin 2x we should try f1 (x) = sin x sin 2x, f2 (x) = ex rst. All of this is done by the
function mul as two parts(f).
Finally, we can try a recursive Mellin transform technique. Since the Meijer G-function is
dened essentially as a certain inverse mellin transform, if we want to write a function f (x)
as a G-function, we can compute its mellin transform F (s). If F (s) is in the right form, the
G-function expression can be read o. This technique generalises many standard rewritings,
e.g. eax ebx = e(a+b)x .
One twist is that some functions dont have mellin transforms, even though they can be written
as G-functions. This is true for example for f (x) = ex sin x (the function grows too rapidly to
have a mellin transform). However if the function is recognised to be analytic, then we can
592
try to compute the mellin-transform of f (ax) for a parameter a, and deduce the G-function
expression by analytic continuation. (Checking for analyticity is easy. Since we can only
deal with a certain subset of functions anyway, we only have to lter out those which are not
analyitc.)
The function rewrite single does the table lookup and recursive mellin transform.
The functions rewrite1 and rewrite2 respectively use above-mentioned helpers and
rewrite single to rewrite their argument as respectively one or two G-functions.
Applying the Integral Theorems
If the integrand has been recast into G-functions, evaluating the integral is relatively easy. We
rst do some substitutions to reduce e.g. the exponent of the argument of the G-function to
unity (see rewrite saxena 1 and rewrite saxena, respectively, for one or two G-functions).
Next we go through a list of conditions under which the integral theorem applies. It can fail
for basically two reasons: either the integral does not exist, or the manipulations in deriving
the theorem may not be allowed (for more details, see this [BlogPost] (page 1909)).
Sometimes this can be remedied by reducing the argument of the G-functions involved. For
example it is clear that the G-function representing ez is satises G(Exp(2i)z) = G(z) for all
z S. The function meijerg.get period() can be used to discover this, and the function
principal branch(z, period) in functions/elementary/complexes.py can be used to exploit the information. This is done transparently by the integration code.
The G-Function Integration Theorems
This section intends to display in detail the denite integration theorems used in the code.
The following two formulae go back to Meijer (In fact he proved more general formulae;
indeed in the literature formulae are usually staded in more general form. However it is very
easy to deduce the general formulae from the ones we give here. It seemed best to keep the
theorems as simple as possible, since they are very complicated anyway.):
1.
(
Gm,n
p,q
2.
n
m
)
(aj )
a1 , . . . , ap
j=1 (bj + 1)
p j=1
x dx = q
b1 , . . . , bq
j=m+1 (bj ) j=n+1 (aj + 1)
)
)
)
(
(
c1 , . . . , cu
a1 , . . . , ap
a1 , . . . , an , d1 , . . . , dv , an+1 , . . . , ap
m+t,n+s
m,n
x Gp,q
x dx = Gv+p,u+q
d1 , . . . , dv
b1 , . . . , b q
b1 , . . . , bm , c1 , . . . , cu , bm+1 , . . . , bq
(
Gs,t
u,v
The more interesting question is under what conditions these formulae are valid. Below we
detail the conditions implemented in SymPy. They are an amalgamation of conditions found
in [Prudnikov1990] (page 1912) and [Luke1969] (page 1912); please let us know if you nd
any errors.
Conditions of Convergence for Integral (1)
We can without loss of generality assume p q, since the G-functions of indices m, n, p, q and
of indices n, m, q, p can be related easily (see e.g. [Luke1969] (page 1912), section 5.3). We
5.11. Symbolic Integrals
593
C4 : <() +
q+1p
>qp
2
The convergence conditions will be detailed in several cases, numbered one to ve. For
later use it will be helpful to separate conditions at innity from conditions at zero. By
conditions at innity we mean conditions that only depend on the behaviour of the integrand
for large, positive values of x, whereas by conditions at zero we mean conditions that only
depend on the behaviour of the integrand on (0, ) for any > 0. Since all our conditions are
specied in terms of parameters of the G-functions, this distinction is not immediately visible.
They are, however, of very distinct character mathematically; the conditions at innity being
in particular much harder to control.
In order for the integral theorem to be valid, conditions n at zero and at innity both have
to be fullled, for some n.
These are the conditions at innity:
1.
> 0 | arg()| < (A B C),
where
A=1np<q1m
B = 1 p 1 m q = p + 1 (n = 0 m = p + 1)
594
.
2
2.
n = 0 p + 1 m | arg()| <
3.
(p < q 1 m > 0 | arg()| = ) (p q 2 = 0 arg() = 0)
4.
p = q = 0 arg() = 0 =
6 0 <
bj aj < 0
j=1
5.
> 0 | arg()| <
2.
C3
3.
C3 C4
4.
C3
5.
C3
595
u+v
2
c = m + n
dj
j=1
j=1
p+q
2
cj +
uv
+1
2
aj +
pq
+1
2
j=1
bj
j=1
=qp
uv
+1
2
= 1 (v u)
(q m n) + | arg()|
qp
(v s t) + | arg()|)
vu
s0 (1, 1) s0 (1, 1)
596
z0 =
i(b +c )
e
z1 =
i(b +c )
e
3
for i = 1, . . . , t
2
3
for i = 1, . . . , s
2
3
for i = 1, . . . , n
2
3
for i = 1, . . . , m
2
597
C13 : | arg()| = c
1
C14
: (z0 6= 1 | arg(1 z0 )| < ) (z0 = 1 <( + u + v) < 1)
2
C14
: (z1 6= 1 | arg(1 z1 )| < ) (z1 = 1 <( + p + q) < 1)
1
2
C14 : = 0 b + c 1 (C14
C14
)
C16 :
Gs,t
u,v (x)dx converges at innity
C17 :
Gm,n
p,q (x)dx converges at innity
Note that C16 and C17 are the reason we split the convergence conditions for integral (1).
With this notation established, the implemented convergence conditions can be enumerated
as follows:
1.
mnst 6= 0 0 < b 0 < c C1 C2 C3 C10 C12
2.
u = v b = 0 0 < c 0 < < < 1 C1 C2 C3 C12
3.
p = q u = v b = 0 c = 0 0 < 0 < < < 1 < < 1 6= C1 C2 C3
4.
p = q u = v b = 0 c = 0 0 < 0 < < ( + ) < 1 6= C1 C2 C3
598
5.
p = q u = v b = 0 c = 0 0 < 0 < < ( + ) < 1 6= C1 C2 C3
6.
q < p 0 < s 0 < b 0 c C1 C2 C3 C5 C10 C13
7.
p < q 0 < t 0 < b 0 c C1 C2 C3 C4 C10 C13
8.
v < u 0 < m 0 < c 0 b C1 C2 C3 C7 C11 C12
9.
u < v 0 < n 0 < c 0 b C1 C2 C3 C6 C11 C12
10.
q < p u = v b = 0 0 c 0 < < < 1 C1 C2 C3 C5 C13
11.
p < q u = v b = 0 0 c 0 < < < 1 C1 C2 C3 C4 C13
12.
p = q v < u 0 b c = 0 0 < < < 1 C1 C2 C3 C7 C11
13.
p = q u < v 0 b c = 0 0 < < < 1 C1 C2 C3 C6 C11
14.
p < q v < u 0 b 0 c C1 C2 C3 C4 C7 C11 C13
15.
q < p u < v 0 b 0 c C1 C2 C3 C5 C6 C11 C13
599
16.
q < p v < u 0 b 0 c C1 C2 C3 C5 C7 C8 C11 C13 C14
17.
p < q u < v 0 b 0 c C1 C2 C3 C4 C6 C9 C11 C13 C14
18.
t = 0 0 < s 0 < b 0 < C1 C2 C10
19.
s = 0 0 < t 0 < b < 0 C1 C3 C10
20.
n = 0 0 < m 0 < c < 0 C1 C2 C12
21.
m = 0 0 < n 0 < c 0 < C1 C3 C12
22.
st = 0 0 < b 0 < c C1 C2 C3 C10 C12
23.
mn = 0 0 < b 0 < c C1 C2 C3 C10 C12
24.
p < m + n t = 0 = 0 0 < s 0 < b c < 0 |arg ()| < (m + n p + 1) C1 C2 C10 C14 C15
25.
q < m + n s = 0 = 0 0 < t 0 < b c < 0 |arg ()| < (m + n q + 1) C1 C3 C10 C14 C15
26.
p = q 1 t = 0 = 0 0 < s 0 < b 0 c c < |arg ()| C1 C2 C10 C14 C15
600
27.
p = q + 1 s = 0 = 0 0 < t 0 < b 0 c c < |arg ()| C1 C3 C10 C14 C15
28.
p < q 1 t = 0 = 0 0 < s 0 < b 0 c c < |arg ()| |arg ()| < (m + n p + 1) C1 C2 C10
29.
q + 1 < p s = 0 = 0 0 < t 0 < b 0 c c < |arg ()| |arg ()| < (m + n q + 1) C1 C3 C10
30.
n = 0 = 0 0 < s + t 0 < m 0 < c b < 0 |arg ()| < (s + t u + 1) C1 C2 C12 C14 C15
31.
m = 0 = 0 v < s + t 0 < n 0 < c b < 0 |arg ()| < (s + t v + 1) C1 C3 C12 C14 C15
32.
n = 0 = 0 u = v 1 0 < m 0 < c 0 b b < |arg ()| |arg ()| < (b + 1) C1 C2 C12 C14
33.
m = 0 = 0 u = v + 1 0 < n 0 < c 0 b b < |arg ()| |arg ()| < (b + 1) C1 C3 C12 C14
34.
n = 0 = 0 u < v 1 0 < m 0 < c 0 b b < |arg ()| |arg ()| < (s + t u + 1) C1 C2 C12
35.
m = 0 = 0 v + 1 < u 0 < n 0 < c 0 b b < |arg ()| |arg ()| < (s + t v + 1) C1 C3 C12
36.
C17 t = 0 u < s 0 < b C10 C1 C2 C3
37.
C17 s = 0 v < t 0 < b C10 C1 C2 C3
601
38.
C16 n = 0 p < m 0 < c C12 C1 C2 C3
39.
C16 m = 0 q < n 0 < c C12 C1 C2 C3
1
2i
c+i
We shall work formally for now. Denote by (s) the product of gamma functions appearing in
the denition of G, so that
1
G(z) =
(s)z s ds.
2i L
Thus
1
f (t) =
(2i)2
c+i
ci
602
1
2i
c+i
ezt z as
bs (s)
L
ci
dz
ds.
2i
1
1
The inner integral is easily seen to be (as)
t1+as . (Using Cauchys theorem and Jordans
lemma deform the contour to run from to , encircling 0 once in the negative sense.
For as real and greater than one, this contour can be pushed onto the negative real axis
and the integral is recognised as a product of a sine and a gamma function. The formula is
then proved using the functional equation of the gamma function, and extended to the entire
domain of convergence of the original integral by appealing to analytic continuation.) Hence
we nd
( )s
1 1
1
b
f (t) =
(s)
ds,
t 2i L
(as) ta
which is a so-called Fox H function (of argument tba ). For rational a, this can be expressed as
a Meijer G-function using the gamma function multiplication theorem.
When this computation is valid
There are a number of obstacles in this computation. Interchange of integrals is only valid
if all integrals involved are absolutely convergent. In particular the inner integral has to
converge. Also, for our identication of the nal integral as a Fox H / Meijer G-function to be
correct, the poles of the newly obtained gamma function must be separated properly.
It is easy to check that the inner integal converges absolutely for <(as) < 1. Thus the contour
L has to run left of the line <(as) = 1. Under this condition, the poles of the newly-introduced
gamma function are separated properly.
It remains to observe that the Meijer G-function is an analytic, unbranched function of its
parameters, and of the coecient b. Hence so is f (t). Thus the nal computation remains
valid as long as the initial integral converges, and if there exists a changed set of parameters
where the computation is valid. If we assume w.l.o.g. that a > 0, then the latter condition is
fullled if G converges along contours (2) or (3) of [Luke1969] (page 1912), section 5.2, i.e.
either >= a2 or p 1, p q.
When the integral exists
Using [Luke1969] (page 1912), section 5.10, for any given meijer G-function we can nd a
c
dominant term of the form z a ebz (although this expression might not be the best possible,
because of cancellation).
We must thus investigate
c+iT
lim
ciT
(This principal value integral is the exact statement used in the Laplace inversion theorem.)
We write z = c + i . Then arg(z) 2 , and so ezt eit (where shall always mean asymptot
ically equivalent up to a positive real multiplicative constant). Also z x+iy | |x eiy log | | exi 2 .
Set = bei<(c) 2 . We have three cases:
603
(z p + b)
q )
z p
sin (a)
b
(
a
1 a1 2,2 0, a
ba + (z q p)
=
b
G
2,2 0, a
zq p b
+ 12 , 2b + 1
0
q )
z p
b a2
(
)b
ab b 1,2 2b + 12 , 2b + 1
q
2
a + z p + a
= G2,2
b
2
q )
z p
0 a2
(
a+
604
zq p
a2
)b
ab b
= G1,2
2 2,2
)b
z q p + a2
z q p + a2
1
= ab1 G1,2
2,2
)b
a2 b
p + z q p + a = G2,1
2 2,2
b
(b
)b
(
a + z q p + a2
1 b1 1,2 2b + 12 , 2b
=
a G2,2
0
z q p + a2
a +
z2
q )
z p
b
(
ba 1,1 a + 1
=
G1,1
0
(a)
(b
2
+ 12 , 2b
b
(b
+1
0, 12
( b
b
)b
a2 b
2 + 1
z
p + z q p + a = G2,1
0, 21
2 2,2
q
2
q )
z p
b a2
q )
z p
0 a2
)
2b + 1 z q p
a
b
2
)
+ 1 z q p
a
z2
)b
(b 1
p + zq p + a
1 b 1
2 + 2
q
= a 2 2 G2,1
2,2
0, 21
z p+a
( q
)b
(
z 2 p + z q p + a
1 b 1 2,1 2b +
q
= a 2 2 G2,2
0, 21
z p+a
)
2b + 12 z q p
a
1
2
b
2
)
+ 12 z q p
a
(
a
|b|
1,1 a + 1
( )
=
G2,2
0
cos a
2 (a)
)
a2 + 12 z q p
, if <a < 1
a2 + 12 b
1
p2 2q
2 , 1
z
1 1
2, 2 4
2,0
G1,3
0, 0
2
)
1 p2 2q
z
1
2 4
Ei (z p) =
iG1,0
1,1
)
)
(
)
(
1
1 q i
2,0
0,1 1
z
z G1,2
z pe
iG1,1
0
0, 0
0
a1
a1
(z p b)
(
(z p b) = b
q
a1
G0,1
1,1
(
(z p + b)
a1
(z p + b) = b
G1,0
1,1
q )
z p
(a), if b > 0
0 b
)
a z q p
b (a), if b > 0
0
a1
(
( ) q1 )
b
a
= ba1 G0,1
z
1,1
p
a1
(
)
( ) q1 )
b
a z q p
= ba1 G1,0
z +
1,1 0
b (a), if b > 0
p
(z p b)
q )
z p
(a), if b > 0
0 b
(z p + b)
605
log (z q p) (z q p + 1) = generated
log (z q p) (z q p 1) = generated
Functions involving Shi (z q p):
2
)
p 2q i
z e
21 , 12 4
p q 1,1 21
z G1,3
Shi (z p) =
0
4
q
1,1
G
2 1,3
Si (z q p) =
2
)
p 2q
z
0, 0 4
1
1
2
(
q
Ia (z p) =
G1,0
1,3
1
a
p2 2q
2 + 2
z
a a
1
2, 2 + 2 4
a
2
(
q
Ja (z p) =
G1,0
0,2
a
2
1 2,0
G
2 0,2
2
)
p 2q
z
4
(
a
a
2,2
(
q
Ya (z p) =
G2,0
1,3
a
a
2,2
cos (z p) = G1,0
0,2
2
)
p 2q
z
1
2 4
606
2
)
p 2q
z
1 1
2, 2 4
1
2
cosh (z q p) = 2 G1,0
1,3
(1
3
2, 2
1
E (z p) = G1,2
4 2,2
q
)
q
z p
0
(1
1
2, 2
)
2q 2
z p
0
1
1
2
(
1 2,0
erfc (z p) = G1,2
0, 12
Functions involving ez
pei
)
2q 2
1 z p
(1
2
:
ez
pei
(
= G1,0
0,1
)
q
z p
Ea (z p) =
G2,0
1,2
a 1, 0
)
a q
z p
1
1
4
2 4
)
p 4q
z
0, 34 16
1
3
4
2 4
)
p 4q
z
0, 14 16
607
log (z q p) = generated
(
q
log (z p + a) =
G1,0
1,1
(
log (|z q p a|) = G1,0
1,1
)
)
(
(
1
0,1 1
1,2 1, 1
z log (a) + G1,1
z log (a) + G2,2
0
0
1
q )
z p
0 a
)
)
(
(
)
1 zq p
1
0,1 1
2
z log (|a|) + G1,2 1, 1
z
log
(|a|)
+
G
3,3
1,1
0
0
1 0, 12 a
1,0
G0,2
(
1
2
2
)
p 2q
z
0 4
sinh (z q p) = 2 G1,0
1,3
1
2
)
1 p2 2q
z
1, 0 4
Several variables can be specied, in which case the result is multiple integration. (If
var is omitted and the integrand is univariate, the indenite integral in that variable will
be performed.)
Indenite integrals are returned without terms that are independent of the integration
variables. (see examples)
Denite improper integrals often entail delicate convergence conditions.
Pass
conds=piecewise, separate or none to have these returned, respectively, as a Piecewise function, as a separate result (i.e. result will be a tuple), or not at all (default is
piecewise).
Strategy
608
SymPy uses various approaches to denite integration. One method is to nd an antiderivative for the integrand, and then use the fundamental theorem of calculus. Various
functions are implemented to integrate polynomial, rational and trigonometric functions,
and integrands containing DiracDelta terms.
SymPy also implements the part of the Risch algorithm, which is a decision procedure
for integrating elementary functions, i.e., the algorithm can either nd an elementary
antiderivative, or prove that one does not exist. There is also a (very successful, albeit
somewhat slow) general implementation of the heuristic Risch algorithm. This algorithm
will eventually be phased out as more of the full Risch algorithm is implemented. See
the docstring of Integral. eval integral() for more details on computing the antiderivative
using algebraic methods.
The option risch=True can be used to use only the (full) Risch algorithm. This is useful
if you want to know if an elementary function has an elementary antiderivative. If the
indenite Integral returned by this function is an instance of NonElementaryIntegral,
that means that the Risch algorithm has proven that integral to be non-elementary. Note
that by default, additional methods (such as the Meijer G method outlined below) are
tried on these integrals, as they may be expressible in terms of special functions, so if
you only care about elementary answers, use risch=True. Also note that an unevaluated
Integral returned by this function is not necessarily a NonElementaryIntegral, even with
risch=True, as it may just be an indication that the particular part of the Risch algorithm
needed to integrate that function is not yet implemented.
Another family of strategies comes from re-writing the integrand in terms of so-called
Meijer G-functions. Indenite integrals of a single G-function can always be computed,
and the denite integral of a product of two G-functions can be computed from zero to
innity. Various strategies are implemented to rewrite integrands as G-functions, and
use this information to compute integrals (see the meijerint module).
The option manual=True can be used to use only an algorithm that tries to mimic integration by hand. This algorithm does not handle as many integrands as the other
algorithms implemented but may return results in a more familiar form. The manualintegrate module has functions that return the steps used (see the module docstring for
more information).
In general, the algebraic methods work best for computing antiderivatives of (possibly
complicated) combinations of elementary functions. The G-function methods work best
for computing denite integrals from zero to innity of moderately complicated combinations of special functions, or indenite integrals of very simple combinations of special
functions.
The strategy employed by the integration code is as follows:
If computing a denite integral, and both limits are real, and at least one limit is +oo, try the G-function method of denite integration rst.
Try to nd an antiderivative, using all available methods, ordered by performance
(that is try fastest method rst, slowest last; in particular polynomial integration is
tried rst, meijer g-functions second to last, and heuristic risch last).
If still not successful, try G-functions irrespective of the limits.
The option meijerg=True, False, None can be used to, respectively: always use Gfunction methods and no others, never use G-function methods, or use all available methods (in order as described above). It defaults to None.
See Also:
Integral, Integral.doit
609
Examples
>>> from sympy import integrate, log, exp, oo
>>> from sympy.abc import a, x, y
>>> integrate(x*y, x)
x**2*y/2
>>> integrate(log(x), x)
x*log(x) - x
>>> integrate(log(x), (x, 1, a))
a*log(a) - a + 1
>>> integrate(x)
x**2/2
Note that integrate(x) syntax is meant only for convenience in interactive sessions and
should be avoided in library code.
>>> integrate(x**a*exp(-x), (x, 0, oo)) # same as conds=piecewise
Piecewise((gamma(a + 1), -re(a) < 1),
(Integral(x**a*exp(-x), (x, 0, oo)), True))
>>> integrate(x**a*exp(-x), (x, 0, oo), conds=none)
gamma(a + 1)
>>> integrate(x**a*exp(-x), (x, 0, oo), conds=separate)
(gamma(a + 1), -re(a) < 1)
610
Examples
>>> from sympy import Curve, line_integrate, E, ln
>>> from sympy.abc import x, y, t
>>> C = Curve([E**t + 1, E**t - 1], (t, 0, ln(2)))
>>> line_integrate(x + y, C, [x, y])
3*sqrt(2)
static integrals.deltaintegrate(f, x)
The idea for integration is the following:
If we are dealing with a DiracDelta expression, i.e. DiracDelta(g(x)), we try to simplify it.
If we could simplify it, then we integrate the resulting expression. We already know
we can integrate a simplied expression, because only simple DiracDelta expressions are involved.
If we couldnt simplify it, there are two cases:
1.The expression is a simple expression: we return the integral, taking care if we
are dealing with a Derivative or with a proper DiracDelta.
2.The expression is not simple (i.e. DiracDelta(cos(x))): we can do nothing at all.
If the node is a multiplication node having a DiracDelta term:
(page
377),
Examples
>>> from sympy.abc import x, y, z
>>> from sympy.integrals.deltafunctions import deltaintegrate
>>> from sympy import sin, cos, DiracDelta, Heaviside
>>> deltaintegrate(x*sin(x)*cos(x)*DiracDelta(x - 1), x)
sin(1)*cos(1)*Heaviside(x - 1)
>>> deltaintegrate(y**2*DiracDelta(x - z)*DiracDelta(y - z), y)
z**2*DiracDelta(x - z)*Heaviside(y - z)
611
See Also:
sympy.integrals.integrals.Integral.doit, ratint logpart, ratint ratpart
References
612
of
Tangents,
(II),
ACM
Specication
613
>>> trigintegrate(sin(x)*tan(x), x)
-log(sin(x) - 1)/2 + log(sin(x) + 1)/2 - sin(x)
http://en.wikibooks.org/wiki/Calculus/Integration techniques
See Also:
sympy.integrals.integrals.Integral.doit, sympy.integrals.integrals.Integral
static integrals.manualintegrate(f, var)
Compute indenite integral of a single variable using an algorithm that resembles what
a student would do by hand.
Unlike integrate, var can only be a single symbol.
See Also:
sympy.integrals.integrals.integrate, sympy.integrals.integrals.Integral.doit,
sympy.integrals.integrals.Integral
Examples
>>> from sympy import sin, cos, tan, exp, log, integrate
>>> from sympy.integrals.manualintegrate import manualintegrate
>>> from sympy.abc import x
>>> manualintegrate(1 / x, x)
log(x)
>>> integrate(1/x)
log(x)
>>> manualintegrate(log(x), x)
x*log(x) - x
>>> integrate(log(x))
x*log(x) - x
>>> manualintegrate(exp(x) / (1 + exp(2 * x)), x)
atan(exp(x))
>>> integrate(exp(x) / (1 + exp(2 * x)))
RootSum(4*_z**2 + 1, Lambda(_i, _i*log(2*_i + exp(x))))
>>> manualintegrate(cos(x)**4 * sin(x), x)
-cos(x)**5/5
>>> integrate(cos(x)**4 * sin(x), x)
-cos(x)**5/5
>>> manualintegrate(cos(x)**4 * sin(x)**3, x)
cos(x)**7/7 - cos(x)**5/5
>>> integrate(cos(x)**4 * sin(x)**3, x)
cos(x)**7/7 - cos(x)**5/5
>>> manualintegrate(tan(x), x)
-log(cos(x))
>>> integrate(tan(x), x)
-log(sin(x)**2 - 1)/2
614
The rst step; most rules have substeps that must also be considered.
These substeps can be evaluated using manualintegrate to obtain a
result.
Examples
>>> from sympy import exp, sin, cos
>>> from sympy.integrals.manualintegrate import integral_steps
>>> from sympy.abc import x
>>> print(repr(integral_steps(exp(x) / (1 + exp(2 * x)), x)))
URule(u_var=_u, u_func=exp(x), constant=1,
substep=ArctanRule(context=1/(_u**2 + 1), symbol=_u),
context=exp(x)/(exp(2*x) + 1), symbol=x)
>>> print(repr(integral_steps(sin(x), x)))
TrigRule(func=sin, arg=x, context=sin(x), symbol=x)
>>> print(repr(integral_steps((x**2 + 3)**2 , x)))
RewriteRule(rewritten=x**4 + 6*x**2 + 9,
substep=AddRule(substeps=[PowerRule(base=x, exp=4, context=x**4, symbol=x),
ConstantTimesRule(constant=6, other=x**2,
substep=PowerRule(base=x, exp=2, context=x**2, symbol=x),
context=6*x**2, symbol=x),
ConstantRule(constant=9, context=9, symbol=x)],
context=x**4 + 6*x**2 + 9, symbol=x), context=(x**2 + 3)**2, symbol=x)
The class Integral represents an unevaluated integral and has some methods that help in the
integration of an expression.
class sympy.integrals.Integral
Represents unevaluated integral.
is commutative
Returns whether all the free symbols in the integral are commutative.
as sum(n, method=midpoint)
Approximates the denite integral by a sum.
method ... one of: left, right, midpoint, trapezoid
These are all basically the rectangle method [1], the only dierence is where the
function value is taken in each interval to dene the rectangle.
[1] http://en.wikipedia.org/wiki/Rectangle method
See Also:
Integral.doit Perform the integration using any hints
Examples
>>> from sympy import sin, sqrt
>>> from sympy.abc import x
>>> from sympy.integrals import Integral
>>> e = Integral(sin(x), (x, 3, 7))
>>> e
Integral(sin(x), (x, 3, 7))
For demonstration purposes, this interval will only be split into 2 regions, bounded
by [3, 5] and [5, 7].
5.11. Symbolic Integrals
615
The left-hand rule uses function evaluations at the left of each interval:
>>> e.as_sum(2, left)
2*sin(5) + 2*sin(3)
The right-hand rule uses function evaluations at the right of each interval:
>>> e.as_sum(2, right)
2*sin(5) + 2*sin(7)
The trapezoid rule uses function evaluations on both sides of the intervals. This is
equivalent to taking the average of the left and right hand rule results:
>>> e.as_sum(2, trapezoid)
2*sin(5) + sin(3) + sin(7)
>>> (e.as_sum(2, left) + e.as_sum(2, right))/2 == _
True
All but the trapexoid method may be used when dealing with a function with a discontinuity. Here, the discontinuity at x = 0 can be avoided by using the midpoint or
right-hand method:
>>> e = Integral(1/sqrt(x), (x, 0, 1))
>>> e.as_sum(5).n(4)
1.730
>>> e.as_sum(10).n(4)
1.809
>>> e.doit().n(4) # the actual value is 2
2.000
The left- or trapezoid method will encounter the discontinuity and return oo:
>>> e.as_sum(5, left)
oo
>>> e.as_sum(5, trapezoid)
oo
doit(**hints)
Perform the integration using any hints given.
See Also:
sympy.integrals.trigonometry.trigintegrate, sympy.integrals.risch.heurisch,
sympy.integrals.rationaltools.ratint
as sum Approximate the integral using a sum
Examples
>>> from sympy import Integral
>>> from sympy.abc import x, i
>>> Integral(x**i, (i, 1, 3)).doit()
Piecewise((2, log(x) == 0), (x**3/log(x) - x/log(x), True))
616
free symbols
This method returns the symbols that will exist when the integral is evaluated. This
is useful if one is trying to determine whether an integral depends on a certain
symbol or not.
See Also:
function, limits, variables
Examples
>>> from sympy import Integral
>>> from sympy.abc import x, y
>>> Integral(x, (x, y, 1)).free_symbols
set([y])
transform(x, u)
Performs a change of variables from x to u using the relationship given by x and u
which will dene the transformations f and F (which are inverses of each other) as
follows:
1.If x is a Symbol (which is a variable of integration) then u will be interpreted as
some function, f(u), with inverse F(u). This, in eect, just makes the substitution
of x with f(x).
2.If u is a Symbol then x will be interpreted as some function, F(x), with inverse
f(u). This is commonly referred to as u-substitution.
Once f and F have been identied, the transformation is made as follows:
F (b)
xdx
a
f (x)
F (a)
d
dx
where F (x) is the inverse of f (x) and the limits and integrand have been corrected
so as to retain the same value after integration.
See Also:
variables Lists the integration variables
as dummy Replace integration variables with dummy ones
Notes
The mappings, F(x) or f(u), must lead to a unique integral. Linear or rational linear
expression, 2 x, 1/x and sqrt(x), will always work; quadratic expressions like x 2 1
are acceptable as long as the resulting integrand does not depend on the sign of the
solutions (see examples).
The integral will be returned unchanged if x is not a variable of integration.
x must be (or contain) only one of of the integration variables. If u has more than
one free symbol then it should be sent as a tuple (u, uvar) where uvar identies which
variable is replacing the integration variable. XXX can it contain another integration
variable?
617
Examples
>>> from sympy.abc import a, b, c, d, x, u, y
>>> from sympy import Integral, S, cos, sqrt
>>> i = Integral(x*cos(x**2 - 1), (x, 0, 1))
This attempt fails because x = +/-sqrt(u + 1) and the sign does not cancel out of the
integrand:
>>> Integral(cos(x**2 - 1), (x, 0, 1)).transform(x**2 - 1, u)
Traceback (most recent call last):
...
ValueError:
The mapping between F(x) and f(u) did not give a unique integrand.
Traceback (most recent call last):
...
ValueError:
transform can do a substitution. Here, the previous result is transformed back into
the original expression using u-substitution:
>>> ui = _
>>> _.transform(sqrt(u + 1), x) == i
True
If the x does not contain a symbol of integration then the integral will be returned
unchanged. Integral i does not have an integration variable a so no change is made:
>>> i.transform(a, x) == i
True
When u has more than one free symbol the symbol that is replacing x must be identied by passing u as a tuple:
>>> Integral(x,
Integral(a + u,
>>> Integral(x,
Integral(a + u,
618
(x,
(u,
(x,
(a,
0, 1)).transform(x, (u + a, u))
-a, -a + 1))
0, 1)).transform(x, (u + a, a))
-u, -u + 1))
1
1
f (x) dx
wi f (xi )
i=1
The nodes xi of an order n quadrature rule are the roots of Pn and the weights wi are
given by:
wi =
2
2
gauss hermite,
gauss chebyshev t,
References
619
>>> w
[0.34786, 0.65215, 0.65215, 0.34786]
ex f (x) dx
wi f (xi )
0
i=1
The nodes xi of an order n quadrature rule are the roots of Ln and the weights wi are
given by:
xi
wi =
2
(n + 1)2 (Ln+1 (xi ))
Parameters n : the order of quadrature
n digits : number of signicant digits of the points and weights to return
Returns (x, w) : the x and w are lists of points and weights as Floats.
The points xi and weights wi are returned as (x, w) tuple of lists.
See Also:
gauss legendre,
gauss gen laguerre,
gauss chebyshev u, gauss jacobi
gauss hermite,
gauss chebyshev t,
References
2
ex f (x) dx
wi f (xi )
620
i=1
The nodes xi of an order n quadrature rule are the roots of Hn and the weights wi are
given by:
2n1 n!
wi =
2
n2 (Hn1 (xi ))
gauss chebyshev t,
References
x e
0
f (x) dx
wi f (xi )
i=1
( + n)
+1
n(n)L
n1 (xi )Ln1 (xi )
621
gauss hermite,
gauss chebyshev t,
References
1
f (x) dx
wi f (xi )
1 x2
i=1
n
The nodes xi of an order n quadrature rule are the roots of Tn and the weights wi are
given by:
wi =
See Also:
gauss legendre,
gauss laguerre,
gauss chebyshev u, gauss jacobi
gauss hermite,
References
1
1
1 x2 f (x) dx
wi f (xi )
i=1
The nodes xi of an order n quadrature rule are the roots of Un and the weights wi are
given by:
(
)
i
2
sin
wi =
n+1
n+1
gauss hermite,
623
References
(1 x) (1 + x) f (x) dx
wi f (xi )
i=1
(,)
2n + + + 2 (n + + 1)(n + + 1)
2+
n + + + 1 (n + + + 1)(n + 1)! Pn0 (xi )P (,) (xi )
n+1
gauss hermite,
References
624
Examples
>>> from sympy import S
>>> from sympy.integrals.quadrature import gauss_jacobi
>>> x, w = gauss_jacobi(3, S.Half, -S.Half, 5)
>>> x
[-0.90097, -0.22252, 0.62349]
>>> w
[1.7063, 1.0973, 0.33795]
>>> x, w = gauss_jacobi(6, 1, 1, 5)
>>> x
[-0.87174, -0.5917, -0.2093, 0.2093, 0.5917, 0.87174]
>>> w
[0.050584, 0.22169, 0.39439, 0.39439, 0.22169, 0.050584]
The logic module also includes the following functions to derive boolean expressions from
their truth tables-
625
626
class sympy.logic.boolalg.BooleanFalse
SymPy version of False.
The instances of this class are singletonized and can be accessed via S.false.
This is the SymPy version of False, for use in the logic module. The primary advantage
of using false instead of False is that shorthand boolean operations like and >> will
work as expected on this class, whereas with False they act bitwise on 0. Functions in
the logic module will return this class when they evaluate to false.
See Also:
sympy.logic.boolalg.BooleanTrue (page 627)
Examples
>>> from sympy import sympify, false, Or, true
>>> sympify(False)
False
>>> false >> false
True
>>> False >> False
0
>>> Or(True, False)
True
class sympy.logic.boolalg.And
Logical AND function.
It evaluates its arguments in order, giving False immediately if any of them are False,
and True if they are all True.
5.13. Logic Module
627
Notes
The & operator is provided as a convenience, but note that its use here is dierent from
its normal use in Python, which is bitwise and. Hence, And(a, b) and a & b will return
dierent things if a and b are integers.
>>> And(x, y).subs(x, 1)
y
Examples
>>> from sympy.core import symbols
>>> from sympy.abc import x, y
>>> from sympy.logic.boolalg import And
>>> x & y
And(x, y)
class sympy.logic.boolalg.Or
Logical OR function
It evaluates its arguments in order, giving True immediately if any of them are True, and
False if they are all False.
Notes
The | operator is provided as a convenience, but note that its use here is dierent from
its normal use in Python, which is bitwise or. Hence, Or(a, b) and a | b will return
dierent things if a and b are integers.
>>> Or(x, y).subs(x, 0)
y
Examples
>>> from sympy.core import symbols
>>> from sympy.abc import x, y
>>> from sympy.logic.boolalg import Or
>>> x | y
Or(x, y)
class sympy.logic.boolalg.Not
Logical Not function (negation)
Returns True if the statement is False Returns False if the statement is True
Notes
The operator is provided as a convenience, but note that its use here is dierent
from its normal use in Python, which is bitwise not. In particular, a and Not(a) will
be dierent if a is an integer. Furthermore, since bools in Python subclass from int,
True is the same as 1 which is -2, which has a boolean value of True. To avoid this
issue, use the SymPy boolean types true and false.
628
Examples
>>> from sympy.logic.boolalg import Not, And, Or
>>> from sympy.abc import x, A, B
>>> Not(True)
False
>>> Not(False)
True
>>> Not(And(True, False))
True
>>> Not(Or(True, False))
False
>>> Not(And(And(True, x), Or(x, False)))
Not(x)
>>> ~x
Not(x)
>>> Not(And(Or(A, B), Or(~A, ~B)))
Not(And(Or(A, B), Or(Not(A), Not(B))))
class sympy.logic.boolalg.Xor
Logical XOR (exclusive OR) function.
Returns True if an odd number of the arguments are True and the rest are False.
Returns False if an even number of the arguments are True and the rest are False.
Notes
The operator is provided as a convenience, but note that its use here is dierent from
its normal use in Python, which is bitwise xor. In particular, a b and Xor(a, b) will
be dierent if a and b are integers.
>>> Xor(x, y).subs(y, 0)
x
Examples
>>> from sympy.logic.boolalg import Xor
>>> from sympy import symbols
>>> x, y = symbols(x y)
>>> Xor(True, False)
True
>>> Xor(True, True)
False
>>> Xor(True, False, True, True, False)
True
>>> Xor(True, False, True, False)
False
629
>>> x ^ y
Xor(x, y)
class sympy.logic.boolalg.Nand
Logical NAND function.
It evaluates its arguments in order, giving True immediately if any of them are False, and
False if they are all True.
Returns True if any of the arguments are False Returns False if all arguments are True
Examples
>>> from sympy.logic.boolalg import Nand
>>> from sympy import symbols
>>> x, y = symbols(x y)
>>> Nand(False, True)
True
>>> Nand(True, True)
False
>>> Nand(x, y)
Not(And(x, y))
class sympy.logic.boolalg.Nor
Logical NOR function.
It evaluates its arguments in order, giving False immediately if any of them are True, and
True if they are all False.
Returns False if any argument is True Returns True if all arguments are False
Examples
>>> from sympy.logic.boolalg import Nor
>>> from sympy import symbols
>>> x, y = symbols(x y)
>>> Nor(True, False)
False
>>> Nor(True, True)
False
>>> Nor(False, True)
False
>>> Nor(False, False)
True
>>> Nor(x, y)
Not(Or(x, y))
class sympy.logic.boolalg.Implies
Logical implication.
A implies B is equivalent to !A v B
Accepts two Boolean arguments; A and B. Returns False if A is True and B is False Returns
True otherwise.
630
Notes
The >> and << operators are provided as a convenience, but note that their use here is
dierent from their normal use in Python, which is bit shifts. Hence, Implies(a, b) and
a >> b will return dierent things if a and b are integers. In particular, since Python
considers True and False to be integers, True >> True will be the same as 1 >> 1,
i.e., 0, which has a truth value of False. To avoid this issue, use the SymPy objects true
and false.
>>> from sympy import true, false
>>> True >> False
1
>>> true >> false
False
Examples
>>> from sympy.logic.boolalg import Implies
>>> from sympy import symbols
>>> x, y = symbols(x y)
>>> Implies(True, False)
False
>>> Implies(False, False)
True
>>> Implies(True, True)
True
>>> Implies(False, True)
True
>>> x >> y
Implies(x, y)
>>> y << x
Implies(x, y)
class sympy.logic.boolalg.Equivalent
Equivalence relation.
Equivalent(A, B) is True i A and B are both True or both False
Returns True if all of the arguments are logically equivalent. Returns False otherwise.
Examples
>>> from sympy.logic.boolalg import Equivalent, And
>>> from sympy.abc import x, y
>>> Equivalent(False, False, False)
True
>>> Equivalent(True, False, False)
False
>>> Equivalent(x, And(x, True))
True
class sympy.logic.boolalg.ITE
If then else clause.
631
ITE(A, B, C) evaluates and returns the result of B if A is true else it returns the result of
C
Examples
>>> from sympy.logic.boolalg import ITE, And, Xor, Or
>>> from sympy.abc import x, y, z
>>> ITE(True, False, True)
False
>>> ITE(Or(True, False), And(True, True), Xor(True, True))
True
>>> ITE(x, y, z)
ITE(x, y, z)
>>> ITE(True, x, y)
x
>>> ITE(False, x, y)
y
>>> ITE(x, y, y)
y
The following functions can be used to handle Conjunctive and Disjunctive Normal formssympy.logic.boolalg.to cnf(expr, simplify=False)
Convert a propositional logical sentence s to conjunctive normal form. That is, of the
form ((A | B | ...) & (B | C | ...) & ...) If simplify is True, the expr is evaluated to its
simplest CNF form.
Examples
>>> from sympy.logic.boolalg import to_cnf
>>> from sympy.abc import A, B, D
>>> to_cnf(~(A | B) | D)
And(Or(D, Not(A)), Or(D, Not(B)))
>>> to_cnf((A | B) & (A | ~A), True)
Or(A, B)
sympy.logic.boolalg.is cnf(expr)
Test whether or not an expression is in conjunctive normal form.
632
Examples
>>> from sympy.logic.boolalg import is_cnf
>>> from sympy.abc import A, B, C
>>> is_cnf(A | B | C)
True
>>> is_cnf(A & B & C)
True
>>> is_cnf((A & B) | C)
False
sympy.logic.boolalg.is dnf(expr)
Test whether or not an expression is in disjunctive normal form.
Examples
>>> from sympy.logic.boolalg import is_dnf
>>> from sympy.abc import A, B, C
>>> is_dnf(A | B | C)
True
>>> is_dnf(A & B & C)
True
>>> is_dnf((A & B) | C)
True
>>> is_dnf(A & (B | C))
False
633
>>> S(b)
Or(And(Not(x), Not(y), Not(z)), And(Not(x), Not(y), z))
>>> simplify_logic(_)
And(Not(x), Not(y))
SymPys simplify() function can also be used to simplify logic expressions to their simplest
forms.
sympy.logic.boolalg.bool map(bool1, bool2)
Return the simplied version of bool1, and the mapping of variables that makes the two
expressions bool1 and bool2 represent the same logical behaviour for some correspondence between the variables of each. If more than one mappings of this sort exist, one
of them is returned. For example, And(x, y) is logically equivalent to And(a, b) for the
mapping {x: a, y:b} or {x: b, y:a}. If no such mapping exists, return False.
Examples
>>> from sympy import SOPform, bool_map, Or, And, Not, Xor
>>> from sympy.abc import w, x, y, z, a, b, c, d
>>> function1 = SOPform([x,z,y],[[1, 0, 1], [0, 0, 1]])
>>> function2 = SOPform([a,b,c],[[1, 0, 1], [1, 0, 0]])
>>> bool_map(function1, function2)
(And(Not(z), y), {y: a, z: b})
The results are not necessarily unique, but they are canonical. Here, (w, z) could be
(a, d) or (d, a):
>>> eq = Or(And(Not(y), w), And(Not(y), z), And(x,
>>> eq2 = Or(And(Not(c), a), And(Not(c), d), And(b,
>>> bool_map(eq, eq2)
(Or(And(Not(y), w), And(Not(y), z), And(x, y)), {w:
>>> eq = And(Xor(a, b), c, And(c,d))
>>> bool_map(eq, eq.subs(c, x))
(And(Or(Not(a), Not(b)), Or(a, b), c, d), {a: a, b:
y))
c))
a, x: b, y: c, z: d})
b, c: d, d: x})
5.13.5 Inference
This module implements some inference routines in propositional logic.
The function satisable will test that a given Boolean expression is satisable, that is, you can
assign values to the variables to make the sentence T rue.
For example, the expression x & x is not satisable, since there are no values for x that
make this sentence True. On the other hand, (x | y) & (x | y) & (x | y) is satisable
with both x and y being True.
>>> from sympy.logic.inference import satisfiable
>>> from sympy import Symbol
>>> x = Symbol(x)
>>> y = Symbol(y)
>>> satisfiable(x & ~x)
False
>>> satisfiable((x | y) & (x | ~y) & (~x | y))
{x: True, y: True}
634
As you see, when a sentence is satisable, it returns a model that makes that sentence True.
If it is not satisable it will return False.
sympy.logic.inference.satisfiable(expr, algorithm=dpll2, all models=False)
Check satisability of a propositional sentence. Returns a model when it succeeds. Returns {true: true} for trivially true expressions.
On setting all models to True, if given expr is satisable then returns a generator of
models. However, if expr is unsatisable then returns a generator containing the single
element False.
Examples
>>> from sympy.abc import A, B
>>> from sympy.logic.inference import satisfiable
>>> satisfiable(A & ~B)
{A: True, B: False}
>>> satisfiable(A & ~A)
False
>>> satisfiable(True)
{True: True}
>>> next(satisfiable(A & ~A, all_models=True))
False
>>> models = satisfiable((A >> B) & B, all_models=True)
>>> next(models)
{A: False, B: True}
>>> next(models)
{A: True, B: True}
>>> def use_models(models):
...
for model in models:
...
if model:
...
# Do something with the model.
...
print(model)
...
else:
...
# Given expr is unsatisfiable.
...
print(UNSAT)
>>> use_models(satisfiable(A >> ~A, all_models=True))
{A: False}
>>> use_models(satisfiable(A ^ A, all_models=True))
UNSAT
5.14 Matrices
A module that handles matrices.
Includes functions for fast creating matrices like zero, one/eye, random matrix, etc.
Contents:
5.14. Matrices
635
In addition to creating a matrix from a list of appropriately-sized lists and/or matrices, SymPy
also supports more advanced methods of matrix creation including a single list of values and
dimension inputs:
>>> Matrix(2, 3, [1, 2, 3, 4, 5, 6])
[1 2 3]
[
]
[4 5 6]
More interesting (and useful), is the ability to use a 2-variable function (or lambda) to create
a matrix. Here we create an indicator function which is 1 on the diagonal and then use it to
make the identity matrix:
>>>
...
...
...
...
...
>>>
[1
[
[0
[
[0
[
[0
def f(i,j):
if i == j:
return 1
else:
return 0
Matrix(4, 4, f)
0 0 0]
]
1 0 0]
]
0 1 0]
]
0 0 1]
Finally lets use lambda to create a 1-line matrix with 1s in the even permutation entries:
636
>>>
[1
[
[0
[
[1
There are also a couple of special constructors for quick matrix construction: eye is the
identity matrix, zeros and ones for matrices of all zeros and ones, respectively, and diag to
put matrices or elements along the diagonal:
>>>
[1
[
[0
[
[0
[
[0
>>>
[0
[
[0
>>>
[0
[
[0
>>>
[1
[
[1
[
[1
>>>
[1
>>>
[1
[
[0
[
[0
eye(4)
0 0 0]
]
1 0 0]
]
0 1 0]
]
0 0 1]
zeros(2)
0]
]
0]
zeros(2, 5)
0 0 0 0]
]
0 0 0 0]
ones(3)
1 1]
]
1 1]
]
1 1]
ones(1, 3)
1 1]
diag(1, Matrix([[1, 2], [3, 4]]))
0 0]
]
1 2]
]
3 4]
Basic Manipulation
While learning to work with matrices, lets choose one where the entries are readily identiable. One useful thing to know is that while matrices are 2-dimensional, the storage is not
and so it is allowable - though one should be careful - to access the entries as if they were a
1-d list.
>>> M = Matrix(2, 3, [1, 2, 3, 4, 5, 6])
>>> M[4]
5
Now, the more standard entry access is a pair of indices which will always return the value
at the corresponding row and column of the matrix:
5.14. Matrices
637
>>> M[1, 2]
6
>>> M[0, 0]
1
>>> M[1, 1]
5
Since this is Python were also able to slice submatrices; slices always give a matrix in return,
even if the dimension is 1 x 1:
>>>
[1
[
[4
>>>
[]
>>>
[3]
[ ]
[6]
>>>
[3]
M[0:2, 0:2]
2]
]
5]
M[2:2, 2]
M[:, 2]
M[:1, 2]
In the second example above notice that the slice 2:2 gives an empty range. Note also (in
keeping with 0-based indexing of Python) the rst row/column is 0.
You cannot access rows or columns that are not present unless they are in a slice:
>>> M[:, 10] # the 10-th column (not there)
Traceback (most recent call last):
...
IndexError: Index out of range: a[[0, 10]]
>>> M[:, 10:11] # the 10-th column (if there)
[]
>>> M[:, :10] # all columns up to the 10-th
[1 2 3]
[
]
[4 5 6]
Traceback (most recent call last):
...
IndexError: Index out of range: a[[0, 10]]
Slicing an empty matrix works as long as you use a slice for the coordinate that has no size:
>>> Matrix(0, 3, [])[:, 1]
[]
Slicing gives a copy of what is sliced, so modications of one object do not aect the other:
>>> M2 = M[:, :]
>>> M2[0, 0] = 100
>>> M[0, 0] == 100
False
Notice that changing M2 didnt change M. Since we can slice, we can also assign entries:
>>> M = Matrix(([1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]))
>>> M
[1
2
3
4 ]
[
]
638
[5
6
7
[
[9
10 11
[
[13 14 15
>>> M[2,2] =
>>> M
[1
2
3
[
[5
6
7
[
[9
10 0
[
[13 14 15
8 ]
]
12]
]
16]
M[0,3] = 0
0 ]
]
8 ]
]
12]
]
16]
5.14. Matrices
639
[66
[
[102
81
126
96 ]
]
150]
M.row_del(0)
M
5 6]
]
8 9]
M.col_del(1)
M
6]
]
9]
v1 = Matrix([1,2,3])
v2 = Matrix([4,5,6])
v3 = v1.cross(v2)
v1.dot(v2)
v2.dot(v3)
v1.dot(v3)
Recall that the row del() and col del() operations dont return a value - they simply change
the matrix object. We can also glue together matrices of the appropriate size:
>>>
>>>
>>>
[1
[
[0
[
[0
>>>
>>>
[1
[
[0
[
[0
[
[0
[
[0
[
[0
[
[0
M1 = eye(3)
M2 = zeros(3, 4)
M1.row_join(M2)
0 0 0 0 0 0]
]
1 0 0 0 0 0]
]
0 1 0 0 0 0]
M3 = zeros(4, 3)
M1.col_join(M3)
0 0]
]
1 0]
]
0 1]
]
0 0]
]
0 0]
]
0 0]
]
0 0]
Operations on entries
We are not restricted to having multiplication between two matrices:
640
>>>
>>>
[2
[
[0
[
[0
>>>
[3
[
[0
[
[0
M = eye(3)
2*M
0 0]
]
2 0]
]
0 2]
3*M
0 0]
]
3 0]
]
0 3]
but we can also apply functions to our matrix entries using applyfunc(). Here well declare
a function that double any input number. Then we apply it to the 3x3 identity matrix:
>>>
>>>
[2
[
[0
[
[0
f = lambda x: 2*x
eye(3).applyfunc(f)
0 0]
]
2 0]
]
0 2]
One more useful matrix-wide entry application function is the substitution function. Lets
declare a matrix with symbolic entries then substitute a value. Remember we can substitute
anything - even another symbol!:
>>>
>>>
>>>
>>>
[x
[
[0
[
[0
>>>
[4
[
[0
[
[0
>>>
>>>
[y
[
[0
[
[0
Linear algebra
Now that we have the basics out of the way, lets see what we can do with the actual matrices.
Of course, one of the rst things that comes to mind is the determinant:
5.14. Matrices
641
>>>
>>>
-28
>>>
>>>
1
>>>
>>>
0
Another common operation is the inverse: In SymPy, this is computed by Gaussian elimination
by default (for dense matrices) but we can specify it be done by LU decomposition as well:
>>> M2.inv()
[1 0 0]
[
]
[0 1 0]
[
]
[0 0 1]
>>> M2.inv(method=LU)
[1 0 0]
[
]
[0 1 0]
[
]
[0 0 1]
>>> M.inv(method=LU)
[-3/14 1/14 1/2 ]
[
]
[-1/28 5/28 -1/4]
[
]
[ 3/7
-1/7
0 ]
>>> M * M.inv(method=LU)
[1 0 0]
[
]
[0 1 0]
[
]
[0 0 1]
642
[ ___ 4*\/ 6
[\/ 6
------[
3
[
[
___
[
\/ 3
[ 0
----[
3
[
[
[ 0
0
>>> Q*R
[1 1 1]
[
]
[1 1 3]
[
]
[2 3 4]
___]
2*\/ 6 ]
]
]
]
]
0
]
]
]
___ ]
\/ 2 ]
In addition to the solvers in the solver.py le, we can solve the system Ax=b by passing
the b vector to the matrix As LUsolve function. Here well cheat a little choose A and x then
multiply to get b. Then we can solve for x and check that its correct:
>>>
>>>
>>>
>>>
>>>
[3]
[ ]
[7]
[ ]
[5]
Theres also a nice Gram-Schmidt orthogonalizer which will take a set of vectors and orthogonalize then with respect to another another. There is an optional argument which species
whether or not the output should also be normalized, it defaults to False. Lets take some
vectors and orthogonalize them - one normalized and one not:
>>> L = [Matrix([2,3,5]), Matrix([3,6,2]), Matrix([8,3,6])]
>>> out1 = GramSchmidt(L)
>>> out2 = GramSchmidt(L, True)
We can spot-check their orthogonality with dot() and their normality with norm():
5.14. Matrices
643
>>>
0
>>>
0
>>>
0
>>>
1
>>>
1
>>>
1
out1[0].dot(out1[1])
out1[0].dot(out1[2])
out1[1].dot(out1[2])
out2[0].norm()
out2[1].norm()
out2[2].norm()
So there is quite a bit that can be done with the module including eigenvalues, eigenvectors,
nullspace calculation, cofactor expansion tools, and so on. From here one might want to look
over the matrices.py le for all functionality.
MatrixBase Class Reference
class sympy.matrices.matrices.MatrixBase
Attributes
is Identity
C
By-element conjugation.
D
Return Dirac conjugate (if self.rows == 4).
See Also:
conjugate By-element conjugation
H (page 645) Hermite conjugation
Examples
>>> from sympy import Matrix, I, eye
>>> m = Matrix((0, 1 + I, 2, 3))
>>> m.D
Matrix([[0, 1 - I, -2, -3]])
>>> m = (eye(4) + I*eye(4))
>>> m[0, 3] = 2
>>> m.D
Matrix([
[1 - I,
0,
0,
0],
[
0, 1 - I,
0,
0],
[
0,
0, -1 + I,
0],
[
2,
0,
0, -1 + I]])
If the matrix does not have 4 rows an AttributeError will be raised because this
property is only dened for matrices with 4 rows.
644
>>> Matrix(eye(2)).D
Traceback (most recent
...
AttributeError: Matrix
Traceback (most recent
...
AttributeError: Matrix
call last):
has no attribute D.
call last):
has no attribute D.
H
Return Hermite conjugate.
See Also:
conjugate By-element conjugation
D (page 644) Dirac conjugation
Examples
>>> from sympy import Matrix, I
>>> m = Matrix((0, 1 + I, 2, 3))
>>> m
Matrix([
[
0],
[1 + I],
[
2],
[
3]])
>>> m.H
Matrix([[0, 1 - I, 2, 3]])
LDLdecomposition()
Returns the LDL Decomposition (L, D) of matrix A, such that L * D * L.T == A This
method eliminates the use of square root. Further this ensures that all the diagonal
entries of L are 1. A must be a square, symmetric, positive-denite and non-singular
matrix.
See Also:
cholesky (page 651), LUdecomposition (page 646), QRdecomposition (page 647)
Examples
>>> from sympy.matrices import Matrix, eye
>>> A = Matrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11)))
>>> L, D = A.LDLdecomposition()
>>> L
Matrix([
[
1,
0, 0],
[ 3/5,
1, 0],
[-1/5, 1/3, 1]])
>>> D
Matrix([
[25, 0, 0],
[ 0, 9, 0],
[ 0, 0, 9]])
5.14. Matrices
645
LDLsolve(rhs)
Solves Ax = B using LDL decomposition, for a general square and non-singular matrix.
For a non-square matrix with rows > cols, the least squares solution is returned.
See Also:
LDLdecomposition (page 645), lower triangular solve (page 668), upper triangular solve (page 677), cholesky solve (page 651), diagonal solve
(page 653), LUsolve (page 647), QRsolve (page 648), pinv solve (page 671)
Examples
>>> from sympy.matrices import Matrix, eye
>>> A = eye(2)*2
>>> B = Matrix([[1, 2], [3, 4]])
>>> A.LDLsolve(B) == B/2
True
LUdecompositionFF()
Compute a fraction-free LU decomposition.
Returns 4 matrices P, L, D, U such that PA = L D**-1 U. If the elements of the matrix
belong to some integral domain I, then all elements of L, D and U are guaranteed to
belong to I.
Reference
W. Zhou & D.J. Jerey, Fraction-free matrix factors: new forms for LU and
QR factors. Frontiers in Computer Science in China, Vol 2, no. 1, pp. 67-80,
2008.
646
See Also:
LUdecomposition (page 646), LUdecomposition Simple (page 647), LUsolve
(page 647)
LUdecomposition Simple(iszerofunc=<function iszero at 0xa2e4aac>)
Returns A comprised of L, U (Ls diag entries are 1) and p which is the list of the row
swaps (in order).
See Also:
LUdecomposition (page 646), LUdecompositionFF (page 646), LUsolve (page 647)
LUsolve(rhs, iszerofunc=<function iszero at 0xa2e4aac>)
Solve the linear system Ax = rhs for x where A = self.
This is for symbolic matrices, for real or complex ones use sympy.mpmath.lu solve
or sympy.mpmath.qr solve.
See Also:
lower triangular solve (page 668), upper triangular solve (page 677),
cholesky solve (page 651), diagonal solve (page 653), LDLsolve (page 646),
QRsolve (page 648), pinv solve (page 671), LUdecomposition (page 646)
QRdecomposition()
Return Q, R where A = Q*R, Q is orthogonal and R is upper triangular.
See Also:
cholesky (page 651), LDLdecomposition (page 645), LUdecomposition (page 646),
QRsolve (page 648)
Examples
5.14. Matrices
647
>>> R
Matrix([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
QRsolve(b)
Solve the linear system Ax = b.
self is the matrix A, the method argument is the vector b. The method returns
the solution vector x. If b is a matrix, the system is solved for each column of b
and the return value is a matrix of the same shape as b.
This method is slower (approximately by a factor of 2) but more stable for oatingpoint arithmetic than the LUsolve method. However, LUsolve usually uses an exact
arithmetic, so you dont need to use QRsolve.
This is mainly for educational purposes and symbolic matrices, for real (or complex)
matrices use sympy.mpmath.qr solve.
See Also:
lower triangular solve (page 668), upper triangular solve (page 677),
cholesky solve (page 651), diagonal solve (page 653), LDLsolve (page 646),
LUsolve (page 647), pinv solve (page 671), QRdecomposition (page 647)
T
Matrix transposition.
add(b)
Return self + b
adjoint()
Conjugate transpose or Hermitian conjugation.
adjugate(method=berkowitz)
Returns the adjugate matrix.
Adjugate matrix is the transpose of the cofactor matrix.
http://en.wikipedia.org/wiki/Adjugate
See Also:
cofactorMatrix (page 651), transpose, berkowitz (page 648)
atoms(*types)
Returns the atoms that form the current object.
Examples
>>> from sympy.abc import x, y
>>> from sympy.matrices import Matrix
>>> Matrix([[x]])
Matrix([[x]])
>>> _.atoms()
set([x])
berkowitz()
The Berkowitz algorithm.
648
5.14. Matrices
649
Examples
>>> from sympy import Matrix
>>> from sympy.abc import x, y
>>> A = Matrix([[1, 3], [2, 0]])
>>> A.berkowitz_charpoly(x) == A.berkowitz_charpoly(y)
True
Specifying x is optional; a Dummy with name lambda is used by default (which looks
good when pretty-printed in unicode):
>>> A.berkowitz_charpoly().as_expr()
_lambda**2 - _lambda - 6
No test is done to see that x doesnt clash with an existing symbol, so using the
default (lambda) or your own Dummy symbol is the safest option:
>>> A = Matrix([[1, 2], [x, 0]])
>>> A.charpoly().as_expr()
_lambda**2 - _lambda - 2*x
>>> A.charpoly(x).as_expr()
x**2 - 3*x
berkowitz det()
Computes determinant using Berkowitz method.
See Also:
det (page 653), berkowitz (page 648)
berkowitz eigenvals(**ags)
Computes eigenvalues of a Matrix using Berkowitz method.
See Also:
berkowitz (page 648)
berkowitz minors()
Computes principal minors using Berkowitz method.
See Also:
berkowitz (page 648)
charpoly(x= lambda, simplify=<function simplify at 0xa29b8ec>)
Computes characteristic polynomial minors using Berkowitz method.
A PurePoly is returned so using dierent variables for x does not aect the comparison or the polynomials:
See Also:
berkowitz (page 648)
Examples
>>> from sympy import Matrix
>>> from sympy.abc import x, y
>>> A = Matrix([[1, 3], [2, 0]])
>>> A.berkowitz_charpoly(x) == A.berkowitz_charpoly(y)
True
650
Specifying x is optional; a Dummy with name lambda is used by default (which looks
good when pretty-printed in unicode):
>>> A.berkowitz_charpoly().as_expr()
_lambda**2 - _lambda - 6
No test is done to see that x doesnt clash with an existing symbol, so using the
default (lambda) or your own Dummy symbol is the safest option:
>>> A = Matrix([[1, 2], [x, 0]])
>>> A.charpoly().as_expr()
_lambda**2 - _lambda - 2*x
>>> A.charpoly(x).as_expr()
x**2 - 3*x
cholesky()
Returns the Cholesky decomposition L of a matrix A such that L * L.T = A
A must be a square, symmetric, positive-denite and non-singular matrix.
See Also:
LDLdecomposition (page 645), LUdecomposition (page 646), QRdecomposition
(page 647)
Examples
>>> from sympy.matrices import Matrix
>>> A = Matrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11)))
>>> A.cholesky()
Matrix([
[ 5, 0, 0],
[ 3, 3, 0],
[-1, 1, 3]])
>>> A.cholesky() * A.cholesky().T
Matrix([
[25, 15, -5],
[15, 18, 0],
[-5, 0, 11]])
cholesky solve(rhs)
Solves Ax = B using Cholesky decomposition, for a general square non-singular matrix. For a non-square matrix with rows > cols, the least squares solution is returned.
See Also:
lower triangular solve (page 668), upper triangular solve (page 677), diagonal solve (page 653), LDLsolve (page 646), LUsolve (page 647), QRsolve
(page 648), pinv solve (page 671)
cofactor(i, j, method=berkowitz)
Calculate the cofactor of an element.
See Also:
cofactorMatrix (page 651), minorEntry (page 668), minorMatrix (page 668)
cofactorMatrix(method=berkowitz)
Return a matrix containing the cofactor of each element.
See Also:
5.14. Matrices
651
cofactor (page 651), minorEntry (page 668), minorMatrix (page 668), adjugate
(page 648)
col insert(pos, mti)
Insert one or more columns at the given column position.
See Also:
col, row insert (page 673)
Examples
>>> from sympy import zeros, ones
>>> M = zeros(3)
>>> V = ones(3, 1)
>>> M.col_insert(1, V)
Matrix([
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0]])
col join(bott)
Concatenates two matrices along selfs last and botts rst row
See Also:
col, row join (page 673)
Examples
>>> from sympy import zeros, ones
>>> M = zeros(3)
>>> V = ones(1, 3)
>>> M.col_join(V)
Matrix([
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[1, 1, 1]])
condition number()
Returns the condition number of a matrix.
This is the maximum singular value divided by the minimum singular value
See Also:
singular values (page 674)
Examples
>>> from sympy import Matrix, S
>>> A = Matrix([[1, 0, 0], [0, 10, 0], [0, 0, S.One/10]])
>>> A.condition_number()
100
652
cross(b)
Return the cross product of self and b relaxing the condition of compatible dimensions: if each has 3 elements, a matrix of the same type and shape as self will be
returned. If b has the same shape as self then common identities for the cross product (like axb = bxa) will hold.
See Also:
dot (page 654), multiply (page 668), multiply elementwise (page 668)
det(method=bareis)
Computes the matrix determinant using the method method.
Possible values for method: bareis ... det bareis berkowitz ... berkowitz det
det LU ... det LU decomposition
See Also:
det bareis (page 653), berkowitz det (page 650), det LU
det LU decomposition()
Compute matrix determinant using LU decomposition
Note that this method fails if the LU decomposition itself fails. In particular, if the
matrix has no inverse this method will fail.
TODO:
Implement
algorithm
for
sparse
http://www.eecis.udel.edu/saunders/papers/sge/it5.ps.
matrices
(SFF),
See Also:
det (page 653), det bareis (page 653), berkowitz det (page 650)
det bareis()
Compute matrix determinant using Bareis fraction-free algorithm which is an extension of the well known Gaussian elimination method. This approach is best suited
for dense symbolic matrices and will result in a determinant with minimal number
of fractions. It means that less term rewriting is needed on resulting formulae.
TODO:
Implement
algorithm
for
sparse
http://www.eecis.udel.edu/saunders/papers/sge/it5.ps.
matrices
(SFF),
See Also:
det (page 653), berkowitz det (page 650)
diagonal solve(rhs)
Solves Ax = B eciently, where A is a diagonal Matrix, with non-zero diagonal entries.
See Also:
lower triangular solve (page 668), upper triangular solve (page 677),
cholesky solve (page 651), LDLsolve (page 646), LUsolve (page 647), QRsolve
(page 648), pinv solve (page 671)
Examples
>>> from sympy.matrices import Matrix, eye
>>> A = eye(2)*2
>>> B = Matrix([[1, 2], [3, 4]])
>>> A.diagonal_solve(B) == B/2
True
5.14. Matrices
653
diff(*args)
Calculate the derivative of each element in the matrix.
See Also:
integrate (page 657), limit (page 668)
Examples
>>> from sympy.matrices import Matrix
>>> from sympy.abc import x, y
>>> M = Matrix([[x, y], [1, 0]])
>>> M.diff(x)
Matrix([
[1, 0],
[0, 0]])
dot(b)
Return the dot product of Matrix self and b relaxing the condition of compatible
dimensions: if either the number of rows or columns are the same as the length
of b then the dot product is returned. If self is a row or column vector, a scalar is
654
returned. Otherwise, a list of results is returned (and in that case the number of
columns in self must match the length of b).
See Also:
cross (page 652), multiply (page 668), multiply elementwise (page 668)
Examples
>>>
>>>
>>>
>>>
6
>>>
12
>>>
[6,
dual()
Returns the dual of a matrix, which is:
(1/2) levicivita(i, j, k, l) M (k, l) summed over indices k and l
Since the levicivita method is anti symmetric for any pairwise exchange of indices,
the dual of a symmetric matrix is the zero matrix. Strictly speaking the dual dened
here assumes that the matrix M is a contravariant anti symmetric second rank
tensor, so that the dual is a covariant second rank tensor.
eigenvals(**ags)
Return eigen values using the berkowitz eigenvals routine.
Since the roots routine doesnt always work well with Floats, they will be replaced
with Rationals before calling that routine. If this is not desired, set ag rational to
False.
eigenvects(**ags)
Return list of triples (eigenval, multiplicity, basis).
The ag simplify has two eects: 1)
if
bool(simplify)
is
True,
as content primitive() will be used to tidy up normalization artifacts; 2) if
nullspace needs simplication to compute the basis, the simplify ag will be
passed on to the nullspace routine which will interpret it there.
If the matrix contains any Floats, they will be changed to Rationals for computation
purposes, but the answers will be returned after being evaluated with evalf. If it is
desired to removed small imaginary portions during the evalf step, pass a value for
the chop ag.
evalf(prec=None, **options)
Apply evalf() to each element of self.
exp()
Return the exponentiation of a square matrix.
expand(deep=True,
modulus=None,
power base=True,
power exp=True,
mul=True, log=True, multinomial=True, basic=True, **hints)
Apply core.function.expand to each entry of the matrix.
5.14. Matrices
655
Examples
>>> from sympy.abc import x
>>> from sympy.matrices import Matrix
>>> Matrix(1, 1, [x*(x+1)])
Matrix([[x*(x + 1)]])
>>> _.expand()
Matrix([[x**2 + x]])
extract(rowsList, colsList)
Return a submatrix by specifying a list of rows and columns. Negative indices can
be given. All indices must be in the range -n <= i < n where n is the number of rows
or columns.
Examples
>>> from sympy import Matrix
>>> m = Matrix(4, 3, range(12))
>>> m
Matrix([
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10, 11]])
>>> m.extract([0, 1, 3], [0, 1])
Matrix([
[0, 1],
[3, 4],
[9, 10]])
Every other row can be taken by using range to provide the indices:
>>> m.extract(range(0, m.rows, 2), [-1])
Matrix([
[2],
[8]])
free symbols
Returns the free symbols within the matrix.
Examples
>>> from sympy.abc import x
>>> from sympy.matrices import Matrix
>>> Matrix([[x], [1]]).free_symbols
set([x])
656
has(*patterns)
Test whether any subexpression matches any of the patterns.
Examples
>>> from sympy import Matrix, Float
>>> from sympy.abc import x, y
>>> A = Matrix(((1, x), (0.2, 3)))
>>> A.has(x)
True
>>> A.has(y)
False
>>> A.has(Float)
True
classmethod hstack(*args)
Return a matrix formed by joining args horizontally (i.e. by repeated application of
row join).
Examples
>>> from sympy.matrices import Matrix, eye
>>> Matrix.hstack(eye(2), 2*eye(2))
Matrix([
[1, 0, 2, 0],
[0, 1, 0, 2]])
integrate(*args)
Integrate each element of the matrix.
See Also:
limit (page 668), diff (page 654)
5.14. Matrices
657
Examples
>>> from sympy.matrices import Matrix
>>> from sympy.abc import x, y
>>> M = Matrix([[x, y], [1, 0]])
>>> M.integrate((x, ))
Matrix([
[x**2/2, x*y],
[
x,
0]])
>>> M.integrate((x, 0, 2))
Matrix([
[2, 2*y],
[2,
0]])
inv mod(m)
Returns the inverse of the matrix K (mod m), if it exists.
Method to nd the matrix inverse of K (mod m) implemented in this function:
Compute adj(K) = cof(K)t , the adjoint matrix of K.
Compute r = 1/det(K) (mod m).
K 1 = r adj(K) (mod m).
Examples
>>> from sympy import Matrix
>>> A = Matrix(2, 2, [1, 2, 3, 4])
>>> A.inv_mod(5)
Matrix([
[3, 1],
[4, 2]])
>>> A.inv_mod(3)
Matrix([
[1, 1],
[0, 1]])
When simplify=True (default), the sum M[i, j] + M[j, i] is simplied before testing
to see if it is zero. By default, the SymPy simplify function is used. To use a custom
function set simplify to a function that accepts a single argument which returns
a simplied expression. To skip simplication, set simplify to False but note that
although this will be faster, it may induce false negatives.
Examples
>>> from sympy import Matrix, symbols
>>> m = Matrix(2, 2, [0, 1, -1, 0])
>>> m
Matrix([
[ 0, 1],
[-1, 0]])
>>> m.is_anti_symmetric()
True
>>> x, y = symbols(x y)
>>> m = Matrix(2, 3, [0, 0, x, -y, 0, 0])
>>> m
Matrix([
[ 0, 0, x],
[-y, 0, 0]])
>>> m.is_anti_symmetric()
False
>>> from sympy.abc import x, y
>>> m = Matrix(3, 3, [0, x**2 + 2*x + 1, y,
...
-(x + 1)**2 , 0, x*y,
...
-y, -x*y, 0])
If simplify=False is used for the case when a Matrix is already simplied, this will
speed things up. Here, we see that without simplication the matrix does not appear
anti-symmetric:
>>> m.is_anti_symmetric(simplify=False)
False
But if the matrix were already expanded, then it would appear anti-symmetric and
simplication in the is anti symmetric routine is not needed:
>>> m = m.expand()
>>> m.is_anti_symmetric(simplify=False)
True
is diagonal()
Check if matrix is diagonal, that is matrix in which the entries outside the main
diagonal are all zero.
See Also:
5.14. Matrices
659
is lower (page 661), is upper (page 664), is diagonalizable (page 660), diagonalize (page 653)
Examples
>>> from sympy import Matrix, diag
>>> m = Matrix(2, 2, [1, 0, 0, 2])
>>> m
Matrix([
[1, 0],
[0, 2]])
>>> m.is_diagonal()
True
>>> m = Matrix(2, 2, [1, 1, 0, 2])
>>> m
Matrix([
[1, 1],
[0, 2]])
>>> m.is_diagonal()
False
>>> m = diag(1, 2, 3)
>>> m
Matrix([
[1, 0, 0],
[0, 2, 0],
[0, 0, 3]])
>>> m.is_diagonal()
True
660
Matrix([
[0, 1],
[0, 0]])
>>> m.is_diagonalizable()
False
>>> m = Matrix(2, 2, [0, 1, -1, 0])
>>> m
Matrix([
[ 0, 1],
[-1, 0]])
>>> m.is_diagonalizable()
True
>>> m.is_diagonalizable(True)
False
is hermitian
Checks if the matrix is Hermitian.
In a Hermitian matrix element i,j is the complex conjugate of element j,i.
Examples
>>> from sympy.matrices import Matrix
>>> from sympy import I
>>> from sympy.abc import x
>>> a = Matrix([[1, I], [-I, 1]])
>>> a
Matrix([
[ 1, I],
[-I, 1]])
>>> a.is_hermitian
True
>>> a[0, 0] = 2*I
>>> a.is_hermitian
False
>>> a[0, 0] = x
>>> a.is_hermitian
>>> a[0, 1] = a[1, 0]*I
>>> a.is_hermitian
False
is lower
Check if matrix is a lower triangular matrix. True can be returned even if the matrix
is not square.
See Also:
is upper (page 664), is diagonal (page 659), is lower hessenberg (page 662)
Examples
>>> from sympy import Matrix
>>> m = Matrix(2, 2, [1, 0, 0, 1])
>>> m
Matrix([
[1, 0],
5.14. Matrices
661
[0, 1]])
>>> m.is_lower
True
>>> m = Matrix(4, 3, [0, 0, 0, 2, 0, 0, 1, 4 , 0, 6, 6, 5])
>>> m
Matrix([
[0, 0, 0],
[2, 0, 0],
[1, 4, 0],
[6, 6, 5]])
>>> m.is_lower
True
>>> from sympy.abc import x, y
>>> m = Matrix(2, 2, [x**2 + y, y**2 + x, 0, x + y])
>>> m
Matrix([
[x**2 + y, x + y**2],
[
0,
x + y]])
>>> m.is_lower
False
is lower hessenberg
Checks if the matrix is in the lower-Hessenberg form.
The lower hessenberg matrix has zero entries above the rst superdiagonal.
See Also:
is upper hessenberg (page 665), is lower (page 661)
Examples
>>> from sympy.matrices import Matrix
>>> a = Matrix([[1, 2, 0, 0], [5, 2, 3, 0], [3, 4, 3, 7], [5, 6, 1, 1]])
>>> a
Matrix([
[1, 2, 0, 0],
[5, 2, 3, 0],
[3, 4, 3, 7],
[5, 6, 1, 1]])
>>> a.is_lower_hessenberg
True
is nilpotent()
Checks if a matrix is nilpotent.
A matrix B is nilpotent if for some integer k, B**k is a zero matrix.
Examples
>>> from sympy import Matrix
>>> a = Matrix([[0, 0, 0], [1, 0, 0], [1, 1, 0]])
>>> a.is_nilpotent()
True
662
is square
Checks if a matrix is square.
A matrix is square if the number of rows equals the number of columns. The empty
matrix is square by denition, since the number of rows and the number of columns
are both zero.
Examples
>>> from sympy import Matrix
>>> a = Matrix([[1, 2, 3], [4, 5, 6]])
>>> b = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> c = Matrix([])
>>> a.is_square
False
>>> b.is_square
True
>>> c.is_square
True
is symbolic()
Checks if any elements contain Symbols.
Examples
>>> from sympy.matrices import Matrix
>>> from sympy.abc import x, y
>>> M = Matrix([[x, y], [1, 0]])
>>> M.is_symbolic()
True
is symmetric(simplify=True)
Check if matrix is symmetric matrix, that is square matrix and is equal to its transpose.
By default, simplications occur before testing symmetry. They can be skipped using simplify=False; while speeding things a bit, this may however induce false
negatives.
Examples
>>> from sympy import Matrix
>>> m = Matrix(2, 2, [0, 1, 1, 2])
>>> m
Matrix([
[0, 1],
[1, 2]])
>>> m.is_symmetric()
True
5.14. Matrices
663
If the matrix is already simplied, you may speed-up is symmetric() test by using
simplify=False.
>>> m.is_symmetric(simplify=False)
False
>>> m1 = m.expand()
>>> m1.is_symmetric(simplify=False)
True
is upper
Check if matrix is an upper triangular matrix. True can be returned even if the
matrix is not square.
See Also:
is lower (page 661), is diagonal (page 659), is upper hessenberg (page 665)
Examples
>>> from sympy import Matrix
>>> m = Matrix(2, 2, [1, 0, 0, 1])
>>> m
Matrix([
[1, 0],
[0, 1]])
>>> m.is_upper
True
>>> m = Matrix(4, 3, [5, 1, 9, 0, 4 , 6, 0, 0, 5, 0, 0, 0])
>>> m
Matrix([
664
[5, 1, 9],
[0, 4, 6],
[0, 0, 5],
[0, 0, 0]])
>>> m.is_upper
True
>>> m = Matrix(2, 3, [4, 2, 5, 6, 1, 1])
>>> m
Matrix([
[4, 2, 5],
[6, 1, 1]])
>>> m.is_upper
False
is upper hessenberg
Checks if the matrix is the upper-Hessenberg form.
The upper hessenberg matrix has zero entries below the rst subdiagonal.
See Also:
is lower hessenberg (page 662), is upper (page 664)
Examples
>>> from sympy.matrices import Matrix
>>> a = Matrix([[1, 4, 2, 3], [3, 4, 1, 7], [0, 2, 3, 4], [0, 0, 1, 3]])
>>> a
Matrix([
[1, 4, 2, 3],
[3, 4, 1, 7],
[0, 2, 3, 4],
[0, 0, 1, 3]])
>>> a.is_upper_hessenberg
True
is zero
Checks if a matrix is a zero matrix.
A matrix is zero if every element is zero. A matrix need not be square to be considered zero. The empty matrix is zero by the principle of vacuous truth. For a matrix
that may or may not be zero (e.g. contains a symbol), this will be None
Examples
>>> from sympy import Matrix, zeros
>>> from sympy.abc import x
>>> a = Matrix([[0, 0], [0, 0]])
>>> b = zeros(3, 4)
>>> c = Matrix([[0, 1], [0, 0]])
>>> d = Matrix([])
>>> e = Matrix([[x, 0], [0, 0]])
>>> a.is_zero
True
>>> b.is_zero
5.14. Matrices
665
True
>>> c.is_zero
False
>>> d.is_zero
True
>>> e.is_zero
jacobian(X)
Calculates the Jacobian matrix (derivative of a vectorial function).
Parameters self : vector of expressions representing functions f i(x 1, ...,
x n).
X : set of x is in order, it can be a list or a Matrix
Both self and X can be a row or a column matrix in any order :
(i.e., jacobian() should always work). :
See Also:
hessian, wronskian
Examples
>>> from sympy import sin, cos, Matrix
>>> from sympy.abc import rho, phi
>>> X = Matrix([rho*cos(phi), rho*sin(phi), rho**2])
>>> Y = Matrix([rho, phi])
>>> X.jacobian(Y)
Matrix([
[cos(phi), -rho*sin(phi)],
[sin(phi), rho*cos(phi)],
[
2*rho,
0]])
>>> X = Matrix([rho*cos(phi), rho*sin(phi)])
>>> X.jacobian(Y)
Matrix([
[cos(phi), -rho*sin(phi)],
[sin(phi), rho*cos(phi)]])
666
Examples
>>>
>>>
...
...
...
...
key2bounds(keys)
Converts a key with potentially mixed types of keys (integer and slice) into a tuple
of ranges and raises an error if any index is out of selfs range.
See Also:
key2ij (page 667)
key2ij(key)
Converts key into canonical form, converting integers or indexable items into valid
integers for selfs range or returning slices unchanged.
5.14. Matrices
667
See Also:
key2bounds (page 667)
limit(*args)
Calculate the limit of each element in the matrix.
See Also:
integrate (page 657), diff (page 654)
Examples
>>> from sympy.matrices import Matrix
>>> from sympy.abc import x, y
>>> M = Matrix([[x, y], [1, 0]])
>>> M.limit(x, 2)
Matrix([
[2, y],
[1, 0]])
668
n(prec=None, **options)
Apply evalf() to each element of self.
norm(ord=None)
Return the Norm of a Matrix or Vector. In the simplest case this is the geometric
size of the vector Other norms can be specied by the ord parameter
ord
None
fro
inf
-inf
1
-1
2
-2
other
2-norm
(largest
sing.
value)
smallest singular value
max(abs(x))
min(abs(x))
as below
as below
as below
as below
sum(abs(x)**ord)**(1./ord)
See Also:
normalized (page 669)
Examples
>>> from sympy import Matrix, Symbol, trigsimp, cos, sin, oo
>>> x = Symbol(x, real=True)
>>> v = Matrix([cos(x), sin(x)])
>>> trigsimp( v.norm() )
1
>>> v.norm(10)
(sin(x)**10 + cos(x)**10)**(1/10)
>>> A = Matrix([[1, 1], [1, 1]])
>>> A.norm(2)# Spectral norm (max of |Ax|/|x| under 2-vector-norm)
2
>>> A.norm(-2) # Inverse spectral norm (smallest singular value)
0
>>> A.norm() # Frobenius Norm
2
>>> Matrix([1, -2]).norm(oo)
2
>>> Matrix([-1, 2]).norm(-oo)
1
5.14. Matrices
669
normalized()
Return the normalized version of self.
See Also:
norm (page 669)
nullspace(simplify=False)
Returns list of vectors (Matrix objects) that span nullspace of self
permuteBkwd(perm)
Permute the rows of the matrix with the given permutation in reverse.
See Also:
permuteFwd (page 670)
Examples
>>> from sympy.matrices import eye
>>> M = eye(3)
>>> M.permuteBkwd([[0, 1], [0, 2]])
Matrix([
[0, 1, 0],
[0, 0, 1],
[1, 0, 0]])
permuteFwd(perm)
Permute the rows of the matrix with the given permutation.
See Also:
permuteBkwd (page 670)
Examples
>>> from sympy.matrices import eye
>>> M = eye(3)
>>> M.permuteFwd([[0, 1], [0, 2]])
Matrix([
[0, 0, 1],
[1, 0, 0],
[0, 1, 0]])
pinv()
Calculate the Moore-Penrose pseudoinverse of the matrix.
The Moore-Penrose pseudoinverse exists and is unique for any matrix. If the matrix
is invertible, the pseudoinverse is the same as the inverse.
See Also:
inv, pinv solve (page 671)
References
670
Examples
>>> from sympy import Matrix
>>> Matrix([[1, 2, 3], [4, 5, 6]]).pinv()
Matrix([
[-17/18, 4/9],
[ -1/9, 1/9],
[ 13/18, -2/9]])
This may return either exact solutions or least squares solutions. To determine
which, check A * A.pinv() * B == B. It will be True if exact solutions exist,
and False if only a least-squares solution exists. Be aware that the left hand side of
that equation may need to be simplied to correctly compare to the right hand side.
References
5.14. Matrices
671
Examples
>>> from sympy import Matrix
>>> A = Matrix([[1, 2, 3], [4, 5, 6]])
>>> B = Matrix([7, 8])
>>> A.pinv_solve(B)
Matrix([
[ _w0_0/6 - _w1_0/3 + _w2_0/6 - 55/18],
[-_w0_0/3 + 2*_w1_0/3 - _w2_0/3 + 1/9],
[ _w0_0/6 - _w1_0/3 + _w2_0/6 + 59/18]])
>>> A.pinv_solve(B, arbitrary_matrix=Matrix([0, 0, 0]))
Matrix([
[-55/18],
[
1/9],
[ 59/18]])
print nonzero(symb=X)
Shows location of non-zero entries for fast shape lookup.
Examples
>>> from sympy.matrices import Matrix, eye
>>> m = Matrix(2, 3, lambda i, j: i*3+j)
>>> m
Matrix([
[0, 1, 2],
[3, 4, 5]])
>>> m.print_nonzero()
[ XX]
[XXX]
>>> m = eye(4)
>>> m.print_nonzero(x)
[x
]
[ x ]
[ x ]
[
x]
project(v)
Return the projection of self onto the line containing v.
Examples
>>> from sympy import Matrix, S, sqrt
>>> V = Matrix([sqrt(3)/2, S.Half])
>>> x = Matrix([[1, 0]])
>>> V.project(x)
Matrix([[sqrt(3)/2, 0]])
>>> V.project(-x)
Matrix([[sqrt(3)/2, 0]])
672
>>>
>>>
>>>
>>>
2
>>>
>>>
2
replace(F, G, map=False)
Replaces Function F in Matrix entries with Function G.
Examples
>>> from sympy import symbols, Function, Matrix
>>> F, G = symbols(F, G, cls=Function)
>>> M = Matrix(2, 2, lambda i, j: F(i+j)) ; M
Matrix([
[F(0), F(1)],
[F(1), F(2)]])
>>> N = M.replace(F,G)
>>> N
Matrix([
[G(0), G(1)],
[G(1), G(2)]])
row join(rhs)
Concatenates two matrices along selfs last and rhss rst column
See Also:
row, col join (page 652)
5.14. Matrices
673
Examples
>>> from sympy import zeros, ones
>>> M = zeros(3)
>>> V = ones(3, 1)
>>> M.row_join(V)
Matrix([
[0, 0, 0, 1],
[0, 0, 0, 1],
[0, 0, 0, 1]])
shape
The shape (dimensions) of the matrix as the 2-tuple (rows, cols).
Examples
>>>
>>>
>>>
(2,
>>>
2
>>>
3
674
singular values()
Compute the singular values of a Matrix
See Also:
condition number (page 652)
Examples
>>> from sympy import Matrix, Symbol
>>> x = Symbol(x, real=True)
>>> A = Matrix([[0, 1, 0], [0, x, 0], [-1, 0, 0]])
>>> A.singular_values()
[sqrt(x**2 + 1), 1, 0]
solve(rhs, method=GE)
Return solution to self*soln = rhs using given inversion method.
For a list of possible inversion methods, see the .inv() docstring.
solve least squares(rhs, method=CH)
Return the least-square t to the data.
By default the cholesky solve routine is used (method=CH); other methods of matrix inversion can be used. To nd out which are available, see the docstring of the
.inv() method.
Examples
>>> from sympy.matrices import Matrix, ones
>>> A = Matrix([1, 2, 3])
>>> B = Matrix([2, 3, 4])
>>> S = Matrix(A.row_join(B))
>>> S
Matrix([
[1, 2],
[2, 3],
[3, 4]])
If each line of S represent coecients of Ax + By and x and y are [2, 3] then S*xy is:
>>> r = S*Matrix([2, 3]); r
Matrix([
[ 8],
[13],
[18]])
But lets add 1 to the middle value and then solve for the least-squares value of xy:
>>> xy = S.solve_least_squares(Matrix([8, 14, 18])); xy
Matrix([
[ 5/3],
[10/3]])
5.14. Matrices
675
>>> S*xy - r
Matrix([
[1/3],
[1/3],
[1/3]])
>>> _.norm().n(2)
0.58
subs(*args, **kwargs)
Return a new matrix with subs applied to each entry.
Examples
>>> from sympy.abc import x, y
>>> from sympy.matrices import SparseMatrix, Matrix
>>> SparseMatrix(1, 1, [x])
Matrix([[x]])
>>> _.subs(x, y)
Matrix([[y]])
>>> Matrix(_).subs(y, x)
Matrix([[x]])
676
5.14. Matrices
677
Examples
>>> from sympy import Matrix
>>> m=Matrix([[1, 2], [2, 3]])
>>> m
Matrix([
[1, 2],
[2, 3]])
>>> m.vech()
Matrix([
[1],
[2],
[3]])
>>> m.vech(diagonal=False)
Matrix([[2]])
classmethod vstack(*args)
Return a matrix formed by joining args vertically (i.e. by repeated application of
col join).
Examples
>>> from sympy.matrices import Matrix, eye
>>> Matrix.vstack(eye(2), 2*eye(2))
Matrix([
[1, 0],
[0, 1],
[2, 0],
[0, 2]])
678
See Also:
mul
sympy.matrices.dense.zeros(r, c=None, cls=None)
Returns a matrix of zeros with r rows and c columns; if c is omitted a square matrix will
be returned.
See Also:
ones, eye, diag
sympy.matrices.dense.ones(r, c=None)
Returns a matrix of ones with r rows and c columns; if c is omitted a square matrix will
be returned.
See Also:
zeros, eye, diag
sympy.matrices.dense.eye(n, cls=None)
Create square identity matrix n x n
See Also:
diag, zeros, ones
sympy.matrices.dense.diag(*values, **kwargs)
Create a sparse, diagonal matrix from a list of diagonal values.
See Also:
eye
Notes
5.14. Matrices
679
The diagonal elements can be matrices; diagonal lling will continue on the diagonal
from the last element of the matrix:
>>> from sympy.abc import x, y, z
>>> a = Matrix([x, y, z])
>>> b = Matrix([[1, 2], [3, 4]])
>>> c = Matrix([[5, 6]])
>>> diag(a, 7, b, c)
Matrix([
[x, 0, 0, 0, 0, 0],
[y, 0, 0, 0, 0, 0],
[z, 0, 0, 0, 0, 0],
[0, 7, 0, 0, 0, 0],
[0, 0, 1, 2, 0, 0],
[0, 0, 3, 4, 0, 0],
[0, 0, 0, 0, 5, 6]])
When diagonal elements are lists, they will be treated as arguments to Matrix:
>>> diag([1, 2, 3], 4)
Matrix([
[1, 0],
[2, 0],
[3, 0],
[0, 4]])
>>> diag([[1, 2, 3]], 4)
Matrix([
[1, 2, 3, 0],
[0, 0, 0, 4]])
A given band o the diagonal can be made by padding with a vertical or horizontal kerning vector:
>>> hpad = ones(0, 2)
>>> vpad = ones(2, 0)
>>> diag(vpad, 1, 2, 3, hpad) + diag(hpad, 4, 5, 6, vpad)
Matrix([
[0, 0, 4, 0, 0],
[0, 0, 0, 5, 0],
[1, 0, 0, 0, 6],
[0, 2, 0, 0, 0],
[0, 0, 3, 0, 0]])
The type is mutable by default but can be made immutable by setting the mutable ag
to False:
680
>>> type(diag(1))
<class sympy.matrices.dense.MutableDenseMatrix>
>>> from sympy.matrices import ImmutableMatrix
>>> type(diag(1, cls=ImmutableMatrix))
<class sympy.matrices.immutable.ImmutableMatrix>
sympy.matrices.dense.jordan cell(eigenval, n)
Create matrix of Jordan cell kind:
Examples
>>> from sympy.matrices import jordan_cell
>>> from sympy.abc import x
>>> jordan_cell(x, 4)
Matrix([
[x, 1, 0, 0],
[0, x, 1, 0],
[0, 0, x, 1],
[0, 0, 0, x]])
http://en.wikipedia.org/wiki/Hessian matrix
Examples
>>> from sympy import Function, hessian, pprint
>>> from sympy.abc import x, y
>>> f = Function(f)(x, y)
>>> g1 = Function(g)(x, y)
>>> g2 = x**2 + 3*y
>>> pprint(hessian(f, (x, y), [g1, g2]))
[
d
d
]
[
0
0
--(g(x, y))
--(g(x, y)) ]
[
dx
dy
]
[
]
[
0
0
2*x
3
]
[
]
[
2
2
]
[d
d
d
]
[--(g(x, y)) 2*x
---(f(x, y))
-----(f(x, y))]
[dx
2
dy dx
]
[
dx
]
[
]
[
2
2
]
[d
d
d
]
5.14. Matrices
681
[--(g(x, y))
[dy
[
-----(f(x, y))
dy dx
---(f(x, y)) ]
2
]
dy
]
sympy.matrices.dense.GramSchmidt(vlist, orthog=False)
Apply the Gram-Schmidt process to a set of vectors.
see: http://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt process
sympy.matrices.dense.wronskian(functions, var, method=bareis)
Compute Wronskian for [] of functions
| f1
f2
| f1
f2
| .
.
W(f1, ..., fn) = | .
.
| .
.
| (n)
(n)
| D
(f1) D
(f2)
...
...
.
.
.
...
fn
fn
.
.
.
(n)
D
(fn)
|
|
|
|
|
|
|
see: http://en.wikipedia.org/wiki/Wronskian
See Also:
sympy.matrices.mutable.Matrix.jacobian, hessian
sympy.matrices.dense.casoratian(seqs, n, zero=True)
Given linear dierence operator L of order k and homogeneous equation Ly = 0 we
want to compute kernel of L, which is a set of k sequences: a(n), b(n), ... z(n).
Solutions of L are linearly independent i their Casoratian, denoted as C(a, b, ..., z), do
not vanish for n = 0.
Casoratian is dened by k x k determinant:
+ a(n)
b(n)
. . . z(n)
+
| a(n+1)
b(n+1)
. . . z(n+1)
|
|
.
.
.
.
|
|
.
.
.
.
|
|
.
.
.
.
|
+ a(n+k-1) b(n+k-1) . . . z(n+k-1) +
It proves very useful in rsolve hyper() where it is applied to a generating set of a recurrence to factor out linearly dependent solutions and return a basis:
>>> from sympy import Symbol, casoratian, factorial
>>> n = Symbol(n, integer=True)
682
Examples
>>> from sympy.matrices import randMatrix
>>> randMatrix(3)
[25, 45, 27]
[44, 54, 9]
[23, 96, 46]
>>> randMatrix(3, 2)
[87, 29]
[23, 37]
[90, 26]
>>> randMatrix(3, 3, 0, 2)
[0, 2, 0]
[2, 0, 1]
[0, 0, 1]
>>> randMatrix(3, symmetric=True)
[85, 26, 29]
[26, 71, 43]
[29, 43, 57]
>>> A = randMatrix(3, seed=1)
>>> B = randMatrix(3, seed=2)
>>> A == B
False
>>> A == randMatrix(3, seed=1)
True
>>> randMatrix(3, symmetric=True, percent=50)
[0, 68, 43]
[0, 68, 0]
[0, 91, 34]
683
Examples
If you want multiple symarrays to contain distinct symbols, you must provide unique
prexes:
>>> a = symarray(, 3)
>>> b = symarray(, 3)
>>> a[0] == b[0]
True
>>> a = symarray(a, 3)
>>> b = symarray(b, 3)
>>> a[0] == b[0]
False
For more than one dimension, the shape must be given as a tuple:
>>> symarray(a, (2, 3))
[[a_0_0 a_0_1 a_0_2]
[a_1_0 a_1_1 a_1_2]]
>>> symarray(a, (2, 3, 2))
[[[a_0_0_0 a_0_0_1]
[a_0_1_0 a_0_1_1]
[a_0_2_0 a_0_2_1]]
[[a_1_0_0 a_1_0_1]
[a_1_1_0 a_1_1_1]
[a_1_2_0 a_1_2_1]]]
sympy.matrices.dense.rot axis1(theta)
Returns a rotation matrix for a rotation of theta (in radians) about the 1-axis.
See Also:
rot axis2 Returns a rotation matrix for a rotation of theta (in radians) about the 2-axis
rot axis3 Returns a rotation matrix for a rotation of theta (in radians) about the 3-axis
Examples
>>> from sympy import pi
>>> from sympy.matrices import rot_axis1
684
[1,
0,
0],
[0,
1/2, sqrt(3)/2],
[0, -sqrt(3)/2,
1/2]])
sympy.matrices.dense.rot axis2(theta)
Returns a rotation matrix for a rotation of theta (in radians) about the 2-axis.
See Also:
rot axis1 Returns a rotation matrix for a rotation of theta (in radians) about the 1-axis
rot axis3 Returns a rotation matrix for a rotation of theta (in radians) about the 3-axis
Examples
>>> from sympy import pi
>>> from sympy.matrices import rot_axis2
sympy.matrices.dense.rot axis3(theta)
Returns a rotation matrix for a rotation of theta (in radians) about the 3-axis.
See Also:
rot axis1 Returns a rotation matrix for a rotation of theta (in radians) about the 1-axis
rot axis2 Returns a rotation matrix for a rotation of theta (in radians) about the 2-axis
Examples
>>> from sympy import pi
>>> from sympy.matrices import rot_axis3
5.14. Matrices
685
sympy.matrices.matrices.a2idx(j, n=None)
Return integer after making positive and validating against n.
col op(j, f)
In-place operation on col j using two-arg functor whose args are interpreted as
(self[i, j], i).
See Also:
col, row op
686
Examples
>>> from sympy.matrices import eye
>>> M = eye(3)
>>> M.col_op(1, lambda v, i: v + 2*M[i, 0]); M
Matrix([
[1, 2, 0],
[0, 1, 0],
[0, 0, 1]])
col swap(i, j)
Swap the two given columns of the matrix in-place.
See Also:
col, row swap
Examples
>>> from sympy.matrices import Matrix
>>> M = Matrix([[1, 0], [1, 0]])
>>> M
Matrix([
[1, 0],
[1, 0]])
>>> M.col_swap(0, 1)
>>> M
Matrix([
[0, 1],
[0, 1]])
5.14. Matrices
687
Matrix([
[1, 0, 0],
[3, 4, 0],
[0, 0, 1]])
fill(value)
Fill the matrix with the scalar value.
See Also:
zeros, ones
row del(i)
Delete the given row.
See Also:
row, col del
Examples
>>> from sympy.matrices import eye
>>> M = eye(3)
>>> M.row_del(1)
>>> M
Matrix([
688
[1, 0, 0],
[0, 0, 1]])
row op(i, f)
In-place operation on row i using two-arg functor whose args are interpreted as
(self[i, j], j).
See Also:
row, zip row op, col op
Examples
>>> from sympy.matrices import eye
>>> M = eye(3)
>>> M.row_op(1, lambda v, j: v + 2*M[0, j]); M
Matrix([
[1, 0, 0],
[2, 1, 0],
[0, 0, 1]])
row swap(i, j)
Swap the two given rows of the matrix in-place.
See Also:
row, col swap
Examples
>>> from sympy.matrices import Matrix
>>> M = Matrix([[0, 1], [1, 0]])
>>> M
Matrix([
[0, 1],
[1, 0]])
>>> M.row_swap(0, 1)
>>> M
Matrix([
[1, 0],
[0, 1]])
5.14. Matrices
689
Examples
>>> from sympy.matrices import eye
>>> M = eye(3)
>>> M.zip_row_op(1, 0, lambda v, u: v + 2*u); M
Matrix([
[1, 0, 0],
[2, 1, 0],
[0, 0, 1]])
ImmutableMatrix.C
By-element conjugation.
ImmutableMatrix.adjoint()
Conjugate transpose or Hermitian conjugation.
ImmutableMatrix.as mutable()
Returns a mutable version of this matrix
Examples
>>> from sympy import ImmutableMatrix
>>> X = ImmutableMatrix([[1, 2], [3, 4]])
>>> Y = X.as_mutable()
>>> Y[1, 1] = 5 # Can set values in Y
>>> Y
Matrix([
[1, 2],
[3, 5]])
elements are equivalent, returning True if they are, False if any pair is not, and None
(or the rst failing expression if failing expression is True) if it cannot be decided if
the expressions are equivalent or not. This is, in general, an expensive operation.
See Also:
sympy.core.expr.equals
Examples
>>> from sympy.matrices import Matrix
>>> from sympy.abc import x
>>> from sympy import cos
>>> A = Matrix([x*(x - 1), 0])
>>> B = Matrix([x**2 - x, 0])
>>> A == B
False
>>> A.simplify() == B.simplify()
True
>>> A.equals(B)
True
>>> A.equals(2)
False
ImmutableMatrix.is zero
Checks if a matrix is a zero matrix.
A matrix is zero if every element is zero. A matrix need not be square to be considered zero. The empty matrix is zero by the principle of vacuous truth. For a matrix
that may or may not be zero (e.g. contains a symbol), this will be None
Examples
>>> from sympy import Matrix, zeros
>>> from sympy.abc import x
>>> a = Matrix([[0, 0], [0, 0]])
>>> b = zeros(3, 4)
>>> c = Matrix([[0, 1], [0, 0]])
>>> d = Matrix([])
>>> e = Matrix([[x, 0], [0, 0]])
>>> a.is_zero
True
>>> b.is_zero
True
>>> c.is_zero
False
>>> d.is_zero
True
>>> e.is_zero
5.14. Matrices
691
CL
Alternate faster representation
LDLdecomposition()
Returns the LDL Decomposition (matrices L and D) of matrix A, such that L * D *
L.T == A. A must be a square, symmetric, positive-denite and non-singular.
This method eliminates the use of square root and ensures that all the diagonal
entries of L are 1.
Examples
>>> from sympy.matrices import SparseMatrix
>>> A = SparseMatrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11)))
>>> L, D = A.LDLdecomposition()
>>> L
Matrix([
[
1,
0, 0],
[ 3/5,
1, 0],
[-1/5, 1/3, 1]])
>>> D
Matrix([
[25, 0, 0],
[ 0, 9, 0],
[ 0, 0, 9]])
>>> L * D * L.T == A
True
RL
Alternate faster representation
add(other)
Add two sparse matrices with dictionary representation.
692
See Also:
multiply (page 696)
Examples
>>> from sympy.matrices import SparseMatrix, eye, ones
>>> SparseMatrix(eye(3)).add(SparseMatrix(ones(3)))
Matrix([
[2, 1, 1],
[1, 2, 1],
[1, 1, 2]])
>>> SparseMatrix(eye(3)).add(-SparseMatrix(eye(3)))
Matrix([
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
Only the non-zero elements are stored, so the resulting dictionary that is used to
represent the sparse matrix is empty: >>> . smat {}
applyfunc(f)
Apply a function to each element of the matrix.
Examples
>>> from sympy.matrices import SparseMatrix
>>> m = SparseMatrix(2, 2, lambda i, j: i*2+j)
>>> m
Matrix([
[0, 1],
[2, 3]])
>>> m.applyfunc(lambda i: 2*i)
Matrix([
[0, 2],
[4, 6]])
as immutable()
Returns an Immutable version of this Matrix.
as mutable()
Returns a mutable version of this matrix.
Examples
>>> from sympy import ImmutableMatrix
>>> X = ImmutableMatrix([[1, 2], [3, 4]])
>>> Y = X.as_mutable()
>>> Y[1, 1] = 5 # Can set values in Y
>>> Y
Matrix([
[1, 2],
[3, 5]])
5.14. Matrices
693
cholesky()
Returns the Cholesky decomposition L of a matrix A such that L * L.T = A
A must be a square, symmetric, positive-denite and non-singular matrix
Examples
>>> from sympy.matrices import SparseMatrix
>>> A = SparseMatrix(((25,15,-5),(15,18,0),(-5,0,11)))
>>> A.cholesky()
Matrix([
[ 5, 0, 0],
[ 3, 3, 0],
[-1, 1, 3]])
>>> A.cholesky() * A.cholesky().T == A
True
col(j)
Returns column j from self as a column vector.
See Also:
row (page 697), col list (page 694)
Examples
>>> from sympy.matrices import SparseMatrix
>>> a = SparseMatrix(((1, 2), (3, 4)))
>>> a.col(0)
Matrix([
[1],
[3]])
col list()
Returns a column-sorted list of non-zero elements of the matrix.
See Also:
col op, row list (page 697)
Examples
>>> from sympy.matrices import SparseMatrix
>>> a=SparseMatrix(((1, 2), (3, 4)))
>>> a
Matrix([
[1, 2],
[3, 4]])
>>> a.CL
[(0, 0, 1), (1, 0, 3), (0, 1, 2), (1, 1, 4)]
extract(rowsList, colsList)
Return a submatrix by specifying a list of rows and columns. Negative indices can
be given. All indices must be in the range -n <= i < n where n is the number of rows
or columns.
694
Examples
>>> from sympy import Matrix
>>> m = Matrix(4, 3, range(12))
>>> m
Matrix([
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10, 11]])
>>> m.extract([0, 1, 3], [0, 1])
Matrix([
[0, 1],
[3, 4],
[9, 10]])
Every other row can be taken by using range to provide the indices:
>>> m.extract(range(0, m.rows, 2), [-1])
Matrix([
[2],
[8]])
classmethod eye(n)
Return an n x n identity matrix.
has(*patterns)
Test whether any subexpression matches any of the patterns.
Examples
>>> from sympy import SparseMatrix, Float
>>> from sympy.abc import x, y
>>> A = SparseMatrix(((1, x), (0.2, 3)))
>>> A.has(x)
True
>>> A.has(y)
False
>>> A.has(Float)
True
is hermitian
Checks if the matrix is Hermitian.
In a Hermitian matrix element i,j is the complex conjugate of element j,i.
5.14. Matrices
695
Examples
>>> from sympy.matrices import SparseMatrix
>>> from sympy import I
>>> from sympy.abc import x
>>> a = SparseMatrix([[1, I], [-I, 1]])
>>> a
Matrix([
[ 1, I],
[-I, 1]])
>>> a.is_hermitian
True
>>> a[0, 0] = 2*I
>>> a.is_hermitian
False
>>> a[0, 0] = x
>>> a.is_hermitian
>>> a[0, 1] = a[1, 0]*I
>>> a.is_hermitian
False
is symmetric(simplify=True)
Return True if self is symmetric.
Examples
>>> from sympy.matrices import SparseMatrix, eye
>>> M = SparseMatrix(eye(3))
>>> M.is_symmetric()
True
>>> M[0, 2] = 1
>>> M.is_symmetric()
False
liupc()
Lius algorithm, for pre-determination of the Elimination Tree of the given matrix,
used in row-based symbolic Cholesky factorization.
References
Symbolic Sparse Cholesky Factorization using Elimination Trees, Jeroen Van Grondelle (1999) http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.7582
Examples
>>> from sympy.matrices import SparseMatrix
>>> S = SparseMatrix([
... [1, 0, 3, 2],
... [0, 0, 1, 0],
... [4, 0, 0, 5],
... [0, 6, 7, 0]])
>>> S.liupc()
([[0], [], [0], [1, 2]], [4, 3, 4, 4])
696
multiply(other)
Fast multiplication exploiting the sparsity of the matrix.
See Also:
add (page 692)
Examples
>>> from sympy.matrices import SparseMatrix, ones
>>> A, B = SparseMatrix(ones(4, 3)), SparseMatrix(ones(3, 4))
>>> A.multiply(B) == 3*ones(4)
True
nnz()
Returns the number of non-zero elements in Matrix.
reshape(rows, cols)
Reshape matrix while retaining original size.
Examples
>>> from sympy.matrices import SparseMatrix
>>> S = SparseMatrix(4, 2, range(8))
>>> S.reshape(2, 4)
Matrix([
[0, 1, 2, 3],
[4, 5, 6, 7]])
row(i)
Returns column i from self as a row vector.
See Also:
col (page 694), row list (page 697)
Examples
>>> from sympy.matrices import SparseMatrix
>>> a = SparseMatrix(((1, 2), (3, 4)))
>>> a.row(0)
Matrix([[1, 2]])
row list()
Returns a row-sorted list of non-zero elements of the matrix.
See Also:
row op, col list (page 694)
Examples
5.14. Matrices
697
Symbolic Sparse Cholesky Factorization using Elimination Trees, Jeroen Van Grondelle (1999) http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.7582
Examples
>>> from sympy.matrices import SparseMatrix
>>> S = SparseMatrix([
... [1, 0, 3, 2],
... [0, 0, 1, 0],
... [4, 0, 0, 5],
... [0, 6, 7, 0]])
>>> S.row_structure_symbolic_cholesky()
[[0], [], [0], [1, 2]]
scalar multiply(scalar)
Scalar element-wise multiplication
solve(rhs, method=LDL)
Return solution to self*soln = rhs using given inversion method.
For a list of possible inversion methods, see the .inv() docstring.
solve least squares(rhs, method=LDL)
Return the least-square t to the data.
By default the cholesky solve routine is used (method=CH); other methods of matrix inversion can be used. To nd out which are available, see the docstring of the
.inv() method.
Examples
>>> from sympy.matrices import SparseMatrix, Matrix, ones
>>> A = Matrix([1, 2, 3])
>>> B = Matrix([2, 3, 4])
>>> S = SparseMatrix(A.row_join(B))
>>> S
Matrix([
[1, 2],
[2, 3],
[3, 4]])
698
If each line of S represent coecients of Ax + By and x and y are [2, 3] then S*xy is:
>>> r = S*Matrix([2, 3]); r
Matrix([
[ 8],
[13],
[18]])
But lets add 1 to the middle value and then solve for the least-squares value of xy:
>>> xy = S.solve_least_squares(Matrix([8, 14, 18])); xy
Matrix([
[ 5/3],
[10/3]])
tolist()
Convert this sparse matrix into a list of nested Python lists.
Examples
>>> from sympy.matrices import SparseMatrix, ones
>>> a = SparseMatrix(((1, 2), (3, 4)))
>>> a.tolist()
[[1, 2], [3, 4]]
When there are no rows then it will not be possible to tell how many columns were
in the original matrix:
>>> SparseMatrix(ones(0, 3)).tolist()
[]
5.14. Matrices
699
Examples
>>> from sympy.matrices import SparseMatrix
>>> M = SparseMatrix([[0, 0], [0, 1]])
>>> M
Matrix([
[0, 0],
[0, 1]])
>>> M.col_del(0)
>>> M
Matrix([
[0],
[1]])
col join(other)
Returns B augmented beneath A (row-wise joining):
[A]
[B]
Examples
>>> from sympy import SparseMatrix, Matrix, ones
>>> A = SparseMatrix(ones(3))
>>> A
Matrix([
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
>>> B = SparseMatrix.eye(3)
>>> B
Matrix([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
>>> C = A.col_join(B); C
Matrix([
[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
>>> C == A.col_join(Matrix(B))
True
Joining along columns is the same as appending rows at the end of the matrix:
>>> C == A.row_insert(A.rows, Matrix(B))
True
col op(j, f)
In-place operation on col j using two-arg functor whose args are interpreted as
(self[i, j], i) for i in range(self.rows).
700
Examples
>>> from sympy.matrices import SparseMatrix
>>> M = SparseMatrix.eye(3)*2
>>> M[1, 0] = -1
>>> M.col_op(1, lambda v, i: v + 2*M[i, 0]); M
Matrix([
[ 2, 4, 0],
[-1, 0, 0],
[ 0, 0, 2]])
col swap(i, j)
Swap, in place, columns i and j.
Examples
>>> from sympy.matrices import SparseMatrix
>>> S = SparseMatrix.eye(3); S[2, 1] = 2
>>> S.col_swap(1, 0); S
Matrix([
[0, 1, 0],
[1, 0, 0],
[2, 0, 1]])
fill(value)
Fill self with the given value.
Notes
Unless many values are going to be deleted (i.e. set to zero) this will create a matrix
that is slower than a dense matrix in operations.
Examples
>>> from sympy.matrices import SparseMatrix
>>> M = SparseMatrix.zeros(3); M
Matrix([
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
>>> M.fill(1); M
Matrix([
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
row del(k)
Delete the given row of the matrix.
See Also:
col del (page 699)
5.14. Matrices
701
Examples
>>> from sympy.matrices import SparseMatrix
>>> M = SparseMatrix([[0, 0], [0, 1]])
>>> M
Matrix([
[0, 0],
[0, 1]])
>>> M.row_del(0)
>>> M
Matrix([[0, 1]])
row join(other)
Returns B appended after A (column-wise augmenting):
[A B]
Examples
>>> from sympy import SparseMatrix, Matrix
>>> A = SparseMatrix(((1, 0, 1), (0, 1, 0), (1, 1, 0)))
>>> A
Matrix([
[1, 0, 1],
[0, 1, 0],
[1, 1, 0]])
>>> B = SparseMatrix(((1, 0, 0), (0, 1, 0), (0, 0, 1)))
>>> B
Matrix([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
>>> C = A.row_join(B); C
Matrix([
[1, 0, 1, 1, 0, 0],
[0, 1, 0, 0, 1, 0],
[1, 1, 0, 0, 0, 1]])
>>> C == A.row_join(Matrix(B))
True
Joining at row ends is the same as appending columns at the end of the matrix:
>>> C == A.col_insert(A.cols, B)
True
row op(i, f)
In-place operation on row i using two-arg functor whose args are interpreted as
(self[i, j], j).
See Also:
row, zip row op (page 703), col op (page 700)
702
Examples
>>> from sympy.matrices import SparseMatrix
>>> M = SparseMatrix.eye(3)*2
>>> M[0, 1] = -1
>>> M.row_op(1, lambda v, j: v + 2*M[0, j]); M
Matrix([
[2, -1, 0],
[4, 0, 0],
[0, 0, 2]])
row swap(i, j)
Swap, in place, columns i and j.
Examples
>>> from sympy.matrices import SparseMatrix
>>> S = SparseMatrix.eye(3); S[2, 1] = 2
>>> S.row_swap(1, 0); S
Matrix([
[0, 1, 0],
[1, 0, 0],
[0, 2, 1]])
5.14. Matrices
703
subs(*args, **kwargs)
Return a new matrix with subs applied to each entry.
Examples
>>> from sympy.abc import x, y
>>> from sympy.matrices import SparseMatrix, Matrix
>>> SparseMatrix(1, 1, [x])
Matrix([[x]])
>>> _.subs(x, y)
Matrix([[y]])
>>> Matrix(_).subs(y, x)
Matrix([[x]])
704
[7, 8, 9]])
>>> IM[1, 1] = 5
Traceback (most recent
...
TypeError: Can not set
Traceback (most recent
...
TypeError: Can not set
call last):
values in Immutable Matrix. Use Matrix instead.
call last):
values in Immutable Matrix. Use Matrix instead.
C
By-element conjugation.
adjoint()
Conjugate transpose or Hermitian conjugation.
as mutable()
Returns a mutable version of this matrix
Examples
>>> from sympy import ImmutableMatrix
>>> X = ImmutableMatrix([[1, 2], [3, 4]])
>>> Y = X.as_mutable()
>>> Y[1, 1] = 5 # Can set values in Y
>>> Y
Matrix([
[1, 2],
[3, 5]])
705
(or the rst failing expression if failing expression is True) if it cannot be decided if
the expressions are equivalent or not. This is, in general, an expensive operation.
See Also:
sympy.core.expr.equals
Examples
>>> from sympy.matrices import Matrix
>>> from sympy.abc import x
>>> from sympy import cos
>>> A = Matrix([x*(x - 1), 0])
>>> B = Matrix([x**2 - x, 0])
>>> A == B
False
>>> A.simplify() == B.simplify()
True
>>> A.equals(B)
True
>>> A.equals(2)
False
is zero
Checks if a matrix is a zero matrix.
A matrix is zero if every element is zero. A matrix need not be square to be considered zero. The empty matrix is zero by the principle of vacuous truth. For a matrix
that may or may not be zero (e.g. contains a symbol), this will be None
Examples
>>> from sympy import Matrix, zeros
>>> from sympy.abc import x
>>> a = Matrix([[0, 0], [0, 0]])
>>> b = zeros(3, 4)
>>> c = Matrix([[0, 1], [0, 0]])
>>> d = Matrix([])
>>> e = Matrix([[x, 0], [0, 0]])
>>> a.is_zero
True
>>> b.is_zero
True
>>> c.is_zero
False
>>> d.is_zero
True
>>> e.is_zero
706
where X and Y are MatrixSymbol (page 708)s rather than scalar symbols.
Matrix Expressions Core Reference
class sympy.matrices.expressions.MatrixExpr
Superclass for Matrix Expressions
MatrixExprs represent abstract matrices, linear transformations represented within a
particular basis.
Examples
>>>
>>>
>>>
>>>
Attributes
is Identity
T
Matrix transposition.
as explicit()
Returns a dense Matrix with elements represented explicitly
Returns an object of type ImmutableMatrix.
See Also:
as mutable (page 708) returns mutable Matrix type
Examples
5.14. Matrices
707
as mutable()
Returns a dense, mutable matrix with elements represented explicitly
See Also:
as explicit (page 707) returns ImmutableMatrix
Examples
>>> from sympy import Identity
>>> I = Identity(3)
>>> I
I
>>> I.shape
(3, 3)
>>> I.as_mutable()
Matrix([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
equals(other)
Test elementwise equality between matrices, potentially of dierent types
>>> from sympy import Identity, eye
>>> Identity(3).equals(eye(3))
True
class sympy.matrices.expressions.MatrixSymbol
Symbolic representation of a Matrix object
Creates a SymPy Symbol to represent a Matrix. This matrix has a shape and can be
included in Matrix Expressions
>>>
>>>
>>>
>>>
(3,
>>>
I +
Attributes
is Identity
708
class sympy.matrices.expressions.MatAdd
A Sum of Matrix Expressions
MatAdd inherits from and operates like SymPy Add
>>>
>>>
>>>
>>>
>>>
A +
Attributes
is Identity
class sympy.matrices.expressions.MatMul
A product of matrix expressions
Examples
>>> from sympy import MatMul, MatrixSymbol
>>> A = MatrixSymbol(A, 5, 4)
>>> B = MatrixSymbol(B, 4, 3)
>>> C = MatrixSymbol(C, 3, 6)
>>> MatMul(A, B, C)
A*B*C
Attributes
is Identity
class sympy.matrices.expressions.MatPow
Attributes
is Identity
class sympy.matrices.expressions.Inverse
The multiplicative inverse of a matrix expression
This is a symbolic object that simply stores its argument without evaluating it. To actually
compute the inverse, use the .inverse() method of matrices.
Examples
>>> from sympy import MatrixSymbol, Inverse
>>> A = MatrixSymbol(A, 3, 3)
>>> B = MatrixSymbol(B, 3, 3)
>>> Inverse(A)
A^-1
>>> A.inverse() == Inverse(A)
5.14. Matrices
709
True
>>> (A*B).inverse()
B^-1*A^-1
>>> Inverse(A*B)
(A*B)^-1
Attributes
is Identity
class sympy.matrices.expressions.Transpose
The transpose of a matrix expression.
This is a symbolic object that simply stores its argument without evaluating it. To actually
compute the transpose, use the transpose() function, or the .T attribute of matrices.
Examples
>>> from sympy.matrices import MatrixSymbol, Transpose
>>> from sympy.functions import transpose
>>> A = MatrixSymbol(A, 3, 5)
>>> B = MatrixSymbol(B, 5, 3)
>>> Transpose(A)
A
>>> A.T == transpose(A) == Transpose(A)
True
>>> Transpose(A*B)
(A*B)
>>> transpose(A*B)
B*A
Attributes
is Identity
class sympy.matrices.expressions.Trace
Matrix Trace
Represents the trace of a matrix expression.
>>> from sympy import MatrixSymbol, Trace, eye
>>> A = MatrixSymbol(A, 3, 3)
>>> Trace(A)
Trace(A)
710
Attributes
is Identity
class sympy.matrices.expressions.Identity
The Matrix Identity I - multiplicative identity
>>>
>>>
>>>
>>>
A
class sympy.matrices.expressions.ZeroMatrix
The Matrix Zero 0 - additive identity
>>>
>>>
>>>
>>>
A
>>>
0
Attributes
is Identity
Block Matrices
Block matrices allow you to construct larger matrices out of smaller sub-blocks. They can
work with MatrixExpr (page 707) or ImmutableMatrix objects.
class sympy.matrices.expressions.blockmatrix.BlockMatrix
A BlockMatrix is a Matrix composed of other smaller, submatrices
5.14. Matrices
711
The submatrices are stored in a SymPy Matrix object but accessed as part of a Matrix
Expression
>>> from sympy import (MatrixSymbol, BlockMatrix, symbols,
...
Identity, ZeroMatrix, block_collapse)
>>> n,m,l = symbols(n m l)
>>> X = MatrixSymbol(X, n, n)
>>> Y = MatrixSymbol(Y, m ,m)
>>> Z = MatrixSymbol(Z, n, m)
>>> B = BlockMatrix([[X, Z], [ZeroMatrix(m,n), Y]])
>>> print(B)
Matrix([
[X, Z],
[0, Y]])
>>> C = BlockMatrix([[Identity(n), Z]])
>>> print(C)
Matrix([[I, Z]])
>>> print(block_collapse(C*B))
Matrix([[X, Z*Y + Z]])
transpose()
Return transpose of matrix.
Examples
>>> from sympy import MatrixSymbol, BlockMatrix, ZeroMatrix
>>> from sympy.abc import l, m, n
>>> X = MatrixSymbol(X, n, n)
>>> Y = MatrixSymbol(Y, m ,m)
>>> Z = MatrixSymbol(Z, n, m)
>>> B = BlockMatrix([[X, Z], [ZeroMatrix(m,n), Y]])
>>> B.transpose()
Matrix([
[X, 0],
[Z, Y]])
>>> _.transpose()
Matrix([
[X, Z],
[0, Y]])
class sympy.matrices.expressions.blockmatrix.BlockDiagMatrix
A BlockDiagMatrix is a BlockMatrix with matrices only along the diagonal
>>> from sympy import MatrixSymbol, BlockDiagMatrix, symbols, Identity
>>> n,m,l = symbols(n m l)
>>> X = MatrixSymbol(X, n, n)
>>> Y = MatrixSymbol(Y, m ,m)
>>> BlockDiagMatrix(X, Y)
Matrix([
[X, 0],
[0, Y]])
sympy.matrices.expressions.blockmatrix.block collapse(expr)
Evaluates a block matrix expression
712
Identity, Ma
5.15.1 Introduction
Setting up mpmath
Download and installation
Installer The mpmath setup les can be downloaded from the mpmath download page or
the Python Package Index. Download the source package (available as both .zip and .tar.gz),
extract it, open the extracted directory, and run
python setup.py install
If you are using Windows, you can download the binary installer
mpmath-(version).win32.exe
from the mpmath website or the Python Package Index. Run the installer and follow the
instructions.
Using setuptools If you have setuptools installed, you can download and install mpmath in
one step by running:
easy install mpmath
or
python -m easy install mpmath
5.15. Welcome to mpmaths documentation!
713
If you have an old version of mpmath installed already, you may have to pass easy install
the -U ag to force an upgrade.
Debian/Ubuntu
Note: if you have are upgrading mpmath from an earlier version, you may have to manually
uninstall the old version or remove the old les.
Using gmpy (optional)
By default, mpmath uses Python integers internally. If gmpy version 1.03 or later is installed
on your system, mpmath will automatically detect it and transparently use gmpy integers
intead. This makes mpmath much faster, especially at high precision (approximately above
100 digits).
To verify that mpmath uses gmpy, check the internal variable BACKEND is not equal to python:
>>> import mpmath.libmp
>>> mpmath.libmp.BACKEND
gmpy
The gmpy mode can be disabled by setting the MPMATH NOGMPY environment variable.
Note that the mode cannot be switched during runtime; mpmath must be re-imported for this
change to take eect.
714
Running tests
It is recommended that you run mpmaths full set of unit tests to make sure everything works.
The tests are located in the tests subdirectory of the main mpmath directory. They can be
run in the interactive interpreter using the runtests() function:
import mpmath
mpmath.runtests()
If you downloaded the source package, the text source for these documentation pages is
included in the doc directory. The documentation can be compiled to pretty HTML using
Sphinx. Go to the doc directory and run
python build.py
You can also test that all the interactive examples in the documentation work by running
python run doctest.py
and by running the individual .py les in the mpmath source.
(The doctests may take several minutes.)
Finally, some additional demo scripts are available in the demo directory included in the source
package.
Mpmath under SymPy
Mpmath is available as a subpackage of SymPy. With SymPy installed, you can just do
import sympy.mpmath as mpmath
instead of import mpmath. Note that the SymPy version of mpmath might not be the most
recent. You can make a separate mpmath installation even if SymPy is installed; the two
mpmath packages will not interfere with each other.
715
Mpmath is a standard package in Sage, in version 4.1 or later of Sage. Mpmath is preinstalled
a regular Python module, and can be imported as usual within Sage:
---------------------------------------------------------------------| Sage Version 4.1, Release Date: 2009-07-09
|
| Type notebook() for the GUI, and license() for information.
|
---------------------------------------------------------------------sage: import mpmath
sage: mpmath.mp.dps = 50
sage: print mpmath.mpf(2) ** 0.5
1.4142135623730950488016887242096980785696718753769
The mpmath installation under Sage automatically use Sage integers for asymptotically fast
arithmetic, so there is no need to install GMPY:
sage: mpmath.libmp.BACKEND
sage
In Sage,
mpmath can alternatively
sage.libs.mpmath.all. For example:
be
imported
via
the
interface
library
This module provides a few extra conversion functions, including call() which permits calling any mpmath function with Sage numbers as input, and getting Sage RealNumber or ComplexNumber instances with the appropriate precision back:
sage: w = mpmath.call(mpmath.erf, 2+3*I, prec=100)
sage: w
-20.829461427614568389103088452 + 8.6873182714701631444280787545*I
sage: type(w)
<type sage.rings.complex number.ComplexNumber>
sage: w.prec()
100
Importing everything can be convenient, especially when using mpmath interactively, but be
careful when mixing mpmath with other libraries! To avoid inadvertently overriding other
functions or objects, explicitly import only the needed objects, or use the mpmath. or mp.
namespaces:
from mpmath import sin, cos
sin(1), cos(1)
import mpmath
mpmath.sin(1), mpmath.cos(1)
716
Number types
Description
Real oat
Complex oat
Matrix
The following section will provide a very short introduction to the types mpf and mpc. Intervals
and matrices are described further in the documentation chapters on interval arithmetic and
matrices / linear algebra.
The mpf type is analogous to Pythons built-in float. It holds a real number or one of the
special values inf (positive innity), -inf (negative innity) and nan (not-a-number, indicating
an indeterminate result). You can create mpf instances from strings, integers, oats, and other
mpf instances:
>>> mpf(4)
mpf(4.0)
>>> mpf(2.5)
mpf(2.5)
>>> mpf(1.25e6)
mpf(1250000.0)
>>> mpf(mpf(2))
mpf(2.0)
>>> mpf(inf)
mpf(+inf)
The mpc type represents a complex number in rectangular form as a pair of mpf instances. It
can be constructed from a Python complex, a real number, or a pair of real numbers:
>>> mpc(2,3)
mpc(real=2.0, imag=3.0)
>>> mpc(complex(2,3)).imag
mpf(3.0)
You can mix mpf and mpc instances with each other and with Python numbers:
>>> mpf(3) + 2*mpf(2.5) + 1.0
mpf(9.0)
>>> mp.dps = 15
# Set precision (see below)
>>> mpc(1j)**0.5
mpc(real=0.70710678118654757, imag=0.70710678118654757)
Mpmath uses a global working precision; it does not keep track of the precision or accuracy of
individual numbers. Performing an arithmetic operation or calling mpf() rounds the result to
the current working precision. The working precision is controlled by a context object called
mp, which has the following default state:
717
>>> print mp
Mpmath settings:
mp.prec = 53
mp.dps = 15
mp.trap_complex = False
[default: 53]
[default: 15]
[default: False]
The term prec denotes the binary precision (measured in bits) while dps (short for decimal
places) is the decimal precision. Binary and decimal precision are related roughly according
to the formula prec = 3.33*dps. For example, it takes a precision of roughly 333 bits to hold
an approximation of pi that is accurate to 100 decimal places (actually slightly more than 333
bits is used).
Changing either precision property of the mp object automatically updates the other; usually
you just want to change the dps value:
>>> mp.dps = 100
>>> mp.dps
100
>>> mp.prec
336
When the precision has been set, all mpf operations are carried out at that precision:
>>> mp.dps = 50
>>> mpf(1) / 6
mpf(0.16666666666666666666666666666666666666666666666666656)
>>> mp.dps = 25
>>> mpf(2) ** mpf(0.5)
mpf(1.414213562373095048801688713)
There is no restriction on the magnitude of numbers. An mpf can for example hold an approximation of a large Mersenne prime:
>>> mp.dps = 15
>>> print mpf(2)**32582657 - 1
1.24575026015369e+9808357
718
In Python 2.5, the with statement along with the mpmath functions workprec, workdps, extraprec and extradps can be used to temporarily change precision in a more safe manner:
>>> from __future__ import with_statement
>>> with workdps(20):
...
print mpf(1)/7
...
with extradps(10):
...
print mpf(1)/7
...
0.14285714285714285714
0.142857142857142857142857142857
>>> mp.dps
15
The with statement ensures that the precision gets reset when exiting the block, even in the
case that an exception is raised. (The eect of the with statement can be emulated in Python
2.4 by using a try/finally block.)
The workprec family of functions can also be used as function decorators:
>>> @workdps(6)
... def f():
...
return mpf(1)/3
...
>>> f()
mpf(0.33333331346511841)
Some functions accept the prec and dps keyword arguments and this will override the global
working precision. Note that this will not aect the precision at which the result is printed,
so to get all digits, you must either use increase precision afterward when printing or use
nstr/nprint:
>>> mp.dps = 15
>>> print exp(1)
2.71828182845905
>>> print exp(1, dps=50)
# Extra digits wont be printed
2.71828182845905
>>> nprint(exp(1, dps=50), 50)
2.7182818284590452353602874713526624977572470937
Finally, instead of using the global context object mp, you can create custom contexts and
work with methods of those instances instead of global functions. The working precision will
be local to each context object:
>>> mp2 = mp.clone()
>>> mp.dps = 10
>>> mp2.dps = 20
>>> print mp.mpf(1) / 3
0.3333333333
>>> print mp2.mpf(1) / 3
0.33333333333333333333
Note: the ability to create multiple contexts is a new feature that is only partially implemented. Not all mpmath functions are yet available as context-local methods. In the present
version, you are likely to encounter bugs if you try mixing dierent contexts.
719
Note that when creating a new mpf, the value will at most be as accurate as the input. Be
careful when mixing mpmath numbers with Python oats. When working at high precision,
fractional mpf values should be created from strings or integers:
>>> mp.dps = 30
>>> mpf(10.9)
# bad
mpf(10.9000000000000003552713678800501)
>>> mpf(10.9) # good
mpf(10.8999999999999999999999999999997)
>>> mpf(109) / mpf(10)
# also good
mpf(10.8999999999999999999999999999997)
>>> mp.dps = 15
(Binary fractions such as 0.5, 1.5, 0.75, 0.125, etc, are generally safe as input, however, since
those can be represented exactly by Python oats.)
Printing
By default, the repr() of a number includes its type signature. This way eval can be used to
recreate a number from its string representation:
>>> eval(repr(mpf(2.5)))
mpf(2.5)
Prettier output can be obtained by using str() or print, which hide the mpf and mpc signatures and also suppress rounding artifacts in the last few digits:
>>> mpf(3.14159)
mpf(3.1415899999999999)
>>> print mpf(3.14159)
3.14159
>>> print mpc(1j)**0.5
(0.707106781186548 + 0.707106781186548j)
Setting the mp.pretty option will use the str()-style output for repr() as well:
>>> mp.pretty = True
>>> mpf(0.6)
0.6
>>> mp.pretty = False
>>> mpf(0.6)
mpf(0.59999999999999998)
The number of digits with which numbers are printed by default is determined by the working
precision. To specify the number of digits to show without changing the working precision,
use mpmath.nstr() (page 727) and mpmath.nprint() (page 727):
>>> a = mpf(1) / 6
>>> a
mpf(0.16666666666666666)
>>> nstr(a, 8)
0.16666667
>>> nprint(a, 8)
0.16666667
720
Most global functions in the global mpmath namespace are actually methods of the mp context.
This fact is usually transparent to the user, but sometimes shows up in the form of an initial
parameter called ctx visible in the help for the function:
>>> import mpmath
>>> help(mpmath.fsum)
Help on method fsum in module mpmath.ctx_mp_python:
fsum(ctx, terms, absolute=False, squared=False) method of mpmath.ctx_mp.MPContext instance
Calculates a sum containing a finite number of terms (for infinite
series, see :func:~mpmath.nsum). The terms will be converted to
...
Common interface
721
>>> fp.mpf(3)
3.0
722
The mp context is what most users probably want to use most of the time, as it supports the
most functions, is most well-tested, and is implemented with a high level of optimization.
Nearly all examples in this documentation use mp functions.
See Basic usage (page 716) for a description of basic usage.
Arbitrary-precision interval arithmetic (iv)
The iv.mpf type represents a closed interval [a, b]; that is, the set {x : a x b}, where a
and b are arbitrary-precision oating-point values, possibly . The iv.mpc type represents
a rectangular complex interval [a, b] + [c, d]i; that is, the set {z = x + iy : a x b c y d}.
Interval arithmetic provides rigorous error tracking. If f is a mathematical function and f is its
interval arithmetic version, then the basic guarantee of interval arithmetic is that f (v) f(v)
for any input interval v. Put dierently, if an interval represents the known uncertainty for a
xed number, any sequence of interval operations will produce an interval that contains what
would be the result of applying the same sequence of operations to the exact number. The
principal drawbacks of interval arithmetic are speed (iv arithmetic is typically at least two
times slower than mp arithmetic) and that it sometimes provides far too pessimistic bounds.
Note: The support for interval arithmetic in mpmath is still experimental, and many functions do not yet properly support intervals. Please use this feature with caution.
Intervals can be created from single numbers (treated as zero-width intervals) or pairs of
endpoint numbers. Strings are treated as exact decimal numbers. Note that a Python oat
like 0.1 generally does not represent the same number as its literal; use 0.1 instead:
>>> from mpmath import iv
>>> iv.dps = 15; iv.pretty = False
>>> iv.mpf(3)
mpi(3.0, 3.0)
>>> print iv.mpf(3)
[3.0, 3.0]
>>> iv.pretty = True
>>> iv.mpf([2,3])
[2.0, 3.0]
>>> iv.mpf(0.1)
# probably not intended
[0.10000000000000000555, 0.10000000000000000555]
>>> iv.mpf(0.1)
# good, gives a containing interval
[0.099999999999999991673, 0.10000000000000000555]
>>> iv.mpf([0.1, 0.2])
[0.099999999999999991673, 0.2000000000000000111]
The fact that 0.1 results in an interval of nonzero width indicates that 1/10 cannot be
represented using binary oating-point numbers at this precision level (in fact, it cannot be
represented exactly at any precision).
Intervals may be innite or half-innite:
723
The equality testing operators == and != check whether their operands are identical as intervals; that is, have the same endpoints. The ordering operators < <= > >= permit inequality
testing using triple-valued logic: a guaranteed inequality returns True or False while an
indeterminate inequality returns None:
>>> iv.mpf([1,2])
True
>>> iv.mpf([1,2])
False
>>> iv.mpf([1,2])
True
>>> iv.mpf([1,2])
True
>>> iv.mpf([1,2])
False
>>> iv.mpf([1,2])
>>> iv.mpf([2,2])
False
>>> iv.mpf([1,2])
True
>>> iv.mpf([1,2])
>>> iv.mpf([1,2])
False
== iv.mpf([1,2])
!= iv.mpf([1,2])
<= 2
> 0
< 1
< 2
< 2
# returns None
<= iv.mpf([2,3])
< iv.mpf([2,3]) # returns None
< iv.mpf([-1,0])
Intervals have the properties .a, .b (endpoints), .mid, and .delta (width):
>>> x = iv.mpf([2, 5])
>>> x.a
[2.0, 2.0]
>>> x.b
[5.0, 5.0]
>>> x.mid
[3.5, 3.5]
>>> x.delta
[3.0, 3.0]
724
>>> iv.exp([0,inf])
[1.0, +inf]
>>> iv.exp([0,1])
[1.0, 2.7182818284590455349]
>>>
>>> iv.log(1)
[0.0, 0.0]
>>> iv.log([0,1])
[-inf, 0.0]
>>> iv.log([0,inf])
[-inf, +inf]
>>> iv.log(2)
[0.69314718055994528623, 0.69314718055994539725]
>>>
>>> iv.sin([100,inf])
[-1.0, 1.0]
>>> iv.cos([-0.1,0.1])
[0.99500416527802570954, 1.0]
Interval arithmetic is useful for proving inequalities involving irrational numbers. Naive use
of mp arithmetic may result in wrong conclusions, such as the following:
>>> mp.dps = 25
>>> x = mp.exp(mp.pi*mp.sqrt(163))
>>> y = mp.mpf(640320**3+744)
>>> print x
262537412640768744.0000001
>>> print y
262537412640768744.0
>>> x > y
True
163
>>> mp.dps = 50
>>> print mp.exp(mp.pi*mp.sqrt(163))
262537412640768743.99999999999925007259719818568888
With interval arithmetic, the comparison returns None until the precision is large enough for
x y to have a denite sign:
>>> iv.dps = 15
>>> iv.exp(iv.pi*iv.sqrt(163)) > (640320**3+744)
>>> iv.dps = 30
>>> iv.exp(iv.pi*iv.sqrt(163)) > (640320**3+744)
>>> iv.dps = 60
>>> iv.exp(iv.pi*iv.sqrt(163)) > (640320**3+744)
False
>>> iv.dps = 15
Although mpmath is generally designed for arbitrary-precision arithmetic, many of the highlevel algorithms work perfectly well with ordinary Python float and complex numbers, which
use hardware double precision (on most systems, this corresponds to 53 bits of precision).
Whereas the global functions (which are methods of the mp object) always convert inputs to
mpmath numbers, the fp object instead converts them to float or complex, and in some
5.15. Welcome to mpmaths documentation!
725
cases employs basic functions optimized for double precision. When large amounts of function evaluations (numerical integration, plotting, etc) are required, and when fp arithmetic
provides sucient accuracy, this can give a signicant speedup over mp arithmetic.
To take advantage of this feature, simply use the fp prex, i.e. write fp.func instead of func
or mp.func:
>>> u = fp.erfc(2.5)
>>> print u
0.000406952017445
>>> type(u)
<type float>
>>> mp.dps = 15
>>> print mp.erfc(2.5)
0.000406952017444959
>>> fp.matrix([[1,2],[3,4]]) ** 2
matrix(
[[7.0, 10.0],
[15.0, 22.0]])
>>>
>>> type(_[0,0])
<type float>
>>> print fp.quad(fp.sin, [0, fp.pi])
2.0
# numerical integration
The fp context wraps Pythons math and cmath modules for elementary functions. It supports
both real and complex numbers and automatically generates complex results for real inputs
(math raises an exception):
>>> fp.sqrt(5)
2.23606797749979
>>> fp.sqrt(-5)
2.23606797749979j
>>> fp.sin(10)
-0.5440211108893698
>>> fp.power(-1, 0.25)
(0.7071067811865476+0.7071067811865475j)
>>> (-1) ** 0.25
Traceback (most recent call last):
...
ValueError: negative number cannot be raised to a fractional power
Traceback (most recent call last):
...
ValueError: negative number cannot be raised to a fractional power
The prec and dps attributes can be changed (for interface compatibility with the mp context)
but this has no eect:
>>>
53
>>>
15
>>>
>>>
53
>>>
15
fp.prec
fp.dps
fp.prec = 80
fp.prec
fp.dps
Due to intermediate rounding and cancellation errors, results computed with fp arithmetic
may be much less accurate than those computed with mp using an equivalent precision
726
(mp.prec = 53), since the latter often uses increased internal precision. The accuracy is
highly problem-dependent: for some functions, fp almost always gives 14-15 correct digits;
for others, results can be accurate to only 2-3 digits or even completely wrong. The recommended use for fp is therefore to speed up large-scale computations where accuracy can be
veried in advance on a subset of the input set, or where results can be veried afterwards.
Utility functions
This page lists functions that perform basic operations on numbers or aid general programming.
Conversion and printing
mpmathify() / convert()
mpmath.mpmathify(x, strings=True)
Converts x to an mpf or mpc. If x is of type mpf, mpc, int, float, complex, the conversion
will be performed losslessly.
If x is a string, the result will be rounded to the present working precision. Strings
representing fractions or complex numbers are permitted.
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> mpmathify(3.5)
mpf(3.5)
>>> mpmathify(2.1)
mpf(2.1000000000000001)
>>> mpmathify(3/4)
mpf(0.75)
>>> mpmathify(2+3j)
mpc(real=2.0, imag=3.0)
nstr()
mpmath.nstr(x, n=6, **kwargs)
Convert an mpf or mpc to a decimal string literal with n signicant digits. The small default value for n is chosen to make this function useful for printing collections of numbers
(lists, matrices, etc).
If x is a list or tuple, nstr() (page 727) is applied recursively to each element. For
unrecognized classes, nstr() (page 727) simply returns str(x).
The companion function nprint() (page 727) prints the result instead of returning it.
>>> from sympy.mpmath import *
>>> nstr([+pi, ldexp(1,-500)])
[3.14159, 3.05494e-151]
>>> nprint([+pi, ldexp(1,-500)])
[3.14159, 3.05494e-151]
nprint()
mpmath.nprint(x, n=6, **kwargs)
Equivalent to print(nstr(x, n)).
727
Arithmetic operations
See also mpmath.sqrt() (page 752), mpmath.exp() (page 756) etc., listed in Powers and logarithms (page 751)
fadd()
mpmath.fadd(ctx, x, y, **kwargs)
Adds the numbers x and y, giving a oating-point result, optionally using a custom precision and rounding mode.
The default precision is the working precision of the context. You can specify a custom
precision in bits by passing the prec keyword argument, or by providing an equivalent
decimal precision with the dps keyword argument. If the precision is set to +inf, or if
the ag exact=True is passed, an exact addition with no rounding is performed.
When the precision is nite, the optional rounding keyword argument species the direction of rounding. Valid options are n for nearest (default), f for oor, c for
ceiling, d for down, u for up.
Examples
Using fadd() (page 728) with precision and rounding control:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> fadd(2, 1e-20)
mpf(2.0)
>>> fadd(2, 1e-20, rounding=u)
mpf(2.0000000000000004)
>>> nprint(fadd(2, 1e-20, prec=100), 25)
2.00000000000000000001
>>> nprint(fadd(2, 1e-20, dps=15), 25)
2.0
>>> nprint(fadd(2, 1e-20, dps=25), 25)
2.00000000000000000001
>>> nprint(fadd(2, 1e-20, exact=True), 25)
2.00000000000000000001
Exact addition avoids cancellation errors, enforcing familiar laws of numbers such as
x + y x = y, which dont hold in oating-point arithmetic with nite precision:
>>> x, y = mpf(2), mpf(1e-1000)
>>> print(x + y - x)
0.0
>>> print(fadd(x, y, prec=inf) - x)
1.0e-1000
>>> print(fadd(x, y, exact=True) - x)
1.0e-1000
Exact addition can be inecient and may be impossible to perform with large magnitude
dierences:
>>> fadd(1, 1e-100000000000000000000, prec=inf)
Traceback (most recent call last):
...
OverflowError: the exact result does not fit in memory
Traceback (most recent call last):
...
OverflowError: the exact result does not fit in memory
728
fsub()
mpmath.fsub(ctx, x, y, **kwargs)
Subtracts the numbers x and y, giving a oating-point result, optionally using a custom
precision and rounding mode.
See the documentation of fadd() (page 728) for a detailed description of how to specify
precision and rounding.
Examples
Using fsub() (page 729) with precision and rounding control:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> fsub(2, 1e-20)
mpf(2.0)
>>> fsub(2, 1e-20, rounding=d)
mpf(1.9999999999999998)
>>> nprint(fsub(2, 1e-20, prec=100), 25)
1.99999999999999999999
>>> nprint(fsub(2, 1e-20, dps=15), 25)
2.0
>>> nprint(fsub(2, 1e-20, dps=25), 25)
1.99999999999999999999
>>> nprint(fsub(2, 1e-20, exact=True), 25)
1.99999999999999999999
Exact subtraction avoids cancellation errors, enforcing familiar laws of numbers such as
x y + y = x, which dont hold in oating-point arithmetic with nite precision:
>>>
>>>
0.0
>>>
2.0
>>>
2.0
x, y = mpf(2), mpf(1e1000)
print(x - y + y)
print(fsub(x, y, prec=inf) + y)
print(fsub(x, y, exact=True) + y)
Exact addition can be inecient and may be impossible to perform with large magnitude
dierences:
>>> fsub(1, 1e-100000000000000000000, prec=inf)
Traceback (most recent call last):
...
OverflowError: the exact result does not fit in memory
Traceback (most recent call last):
...
OverflowError: the exact result does not fit in memory
fneg()
mpmath.fneg(ctx, x, **kwargs)
Negates the number x, giving a oating-point result, optionally using a custom precision
and rounding mode.
See the documentation of fadd() (page 728) for a detailed description of how to specify
precision and rounding.
Examples
An mpmath number is returned:
729
fmul()
mpmath.fmul(ctx, x, y, **kwargs)
Multiplies the numbers x and y, giving a oating-point result, optionally using a custom
precision and rounding mode.
See the documentation of fadd() (page 728) for a detailed description of how to specify
precision and rounding.
Examples
The result is an mpmath number:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> fmul(2, 5.0)
mpf(10.0)
>>> fmul(0.5j, 0.5)
mpc(real=0.0, imag=0.25)
Avoiding roundo:
>>> x, y = 10**10+1, 10**15+1
>>> print(x*y)
10000000001000010000000001
>>> print(mpf(x) * mpf(y))
1.0000000001e+25
730
Exact multiplication with complex numbers can be inecient and may be impossible to
perform with large magnitude dierences between real and imaginary parts:
>>> x = 1+2j
>>> y = mpc(2, 1e-100000000000000000000)
>>> fmul(x, y)
mpc(real=2.0, imag=4.0)
>>> fmul(x, y, rounding=u)
mpc(real=2.0, imag=4.0000000000000009)
>>> fmul(x, y, exact=True)
Traceback (most recent call last):
...
OverflowError: the exact result does not fit in memory
Traceback (most recent call last):
...
OverflowError: the exact result does not fit in memory
fdiv()
mpmath.fdiv(ctx, x, y, **kwargs)
Divides the numbers x and y, giving a oating-point result, optionally using a custom
precision and rounding mode.
See the documentation of fadd() (page 728) for a detailed description of how to specify
precision and rounding.
Examples
The result is an mpmath number:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> fdiv(3, 2)
mpf(1.5)
>>> fdiv(2, 3)
mpf(0.66666666666666663)
>>> fdiv(2+4j, 0.5)
mpc(real=4.0, imag=8.0)
731
Unlike fadd() (page 728), fmul() (page 730), etc., exact division is not allowed since the
quotient of two oating-point numbers generally does not have an exact oating-point
representation. (In the future this might be changed to allow the case where the division
is actually exact.)
>>> fdiv(2, 3, exact=True)
Traceback (most recent call
...
ValueError: division is not
Traceback (most recent call
...
ValueError: division is not
last):
an exact operation
last):
an exact operation
fmod()
mpmath.fmod(x, y)
Converts x and y to mpmath numbers and returns x mod y. For mpmath numbers, this
is equivalent to x % y.
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> fmod(100, pi)
2.61062773871641
You can use fmod() (page 732) to compute fractional parts of numbers:
>>> fmod(10.25, 1)
0.25
fsum()
mpmath.fsum(terms, absolute=False, squared=False)
Calculates a sum containing a nite number of terms (for innite series, see nsum()
(page 979)). The terms will be converted to mpmath numbers. For len(terms) > 2, this
function is generally faster and produces more accurate results than the builtin Python
function sum().
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> fsum([1, 2, 0.5, 7])
mpf(10.5)
With squared=True each term is squared, and with absolute=True the absolute value of
each term is used.
fprod()
mpmath.fprod(factors)
Calculates a product containing a nite number of factors (for innite products, see
nprod() (page 988)). The factors will be converted to mpmath numbers.
732
fdot()
mpmath.fdot(A, B=None, conjugate=False)
Computes the dot product of the iterables A and B,
Ak Bk .
k=0
Alternatively, fdot() (page 733) accepts a single iterable of pairs. In other words,
fdot(A,B) and fdot(zip(A,B)) are equivalent. The elements are automatically converted to mpmath numbers.
With conjugate=True, the elements in the second vector will be conjugated:
Ak Bk
k=0
Examples
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> A = [2, 1.5, 3]
>>> B = [1, -1, 2]
>>> fdot(A, B)
mpf(6.5)
>>> list(zip(A, B))
[(2, 1), (1.5, -1), (3, 2)]
>>> fdot(_)
mpf(6.5)
>>> A = [2, 1.5, 3j]
>>> B = [1+j, 3, -1-j]
>>> fdot(A, B)
mpc(real=9.5, imag=-1.0)
>>> fdot(A, B, conjugate=True)
mpc(real=3.5, imag=-5.0)
Complex components
fabs()
mpmath.fabs(x)
Returns the absolute value of x, |x|. Unlike abs(), fabs() (page 733) converts nonmpmath numbers (such as int) into mpmath numbers:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> fabs(3)
mpf(3.0)
>>> fabs(-3)
mpf(3.0)
>>> fabs(3+4j)
mpf(5.0)
733
sign()
mpmath.sign(x)
Returns the sign of x, dened as sign(x) = x/|x| (with the special case sign(0) = 0):
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> sign(10)
mpf(1.0)
>>> sign(-10)
mpf(-1.0)
>>> sign(0)
mpf(0.0)
Note that the sign function is also dened for complex numbers, for which it gives the
projection onto the unit circle:
>>> mp.dps = 15; mp.pretty = True
>>> sign(1+j)
(0.707106781186547 + 0.707106781186547j)
re()
mpmath.re(x)
Returns the real part of x, <(x). Unlike x.real, re() (page 734) converts x to a mpmath
number:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> re(3)
mpf(3.0)
>>> re(-1+4j)
mpf(-1.0)
im()
mpmath.im(x)
Returns the imaginary part of x, =(x). Unlike x.imag, im() (page 734) converts x to a
mpmath number:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> im(3)
mpf(0.0)
>>> im(-1+4j)
mpf(4.0)
arg()
mpmath.arg(x)
Computes the complex argument (phase) of x, dened as the signed angle between the
positive real axis and x in the complex plane:
>>>
>>>
>>>
0.0
>>>
734
0.785398163397448
>>> arg(3j)
1.5707963267949
>>> arg(-3)
3.14159265358979
>>> arg(-3j)
-1.5707963267949
The angle is dened to satisfy < arg(x) and with the sign convention that a
nonnegative imaginary part results in a nonnegative argument.
The value returned by arg() (page 734) is an mpf instance.
conj()
mpmath.conj(x)
Returns the complex conjugate of x, x. Unlike x.conjugate(), im() (page 734) converts
x to a mpmath number:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> conj(3)
mpf(3.0)
>>> conj(-1+4j)
mpc(real=-1.0, imag=-4.0)
polar()
mpmath.polar(x)
Returns the polar representation of the complex number z as a pair (r, ) such that z =
rei :
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> polar(-2)
(2.0, 3.14159265358979)
>>> polar(3-4j)
(5.0, -0.927295218001612)
rect()
mpmath.rect(x)
Returns the complex number represented by polar coordinates (r, ):
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> chop(rect(2, pi))
-2.0
>>> rect(sqrt(2), -pi/4)
(1.0 - 1.0j)
floor()
735
mpmath.floor(x)
Computes the oor of x, bxc, dened as the largest integer less than or equal to x:
>>> from sympy.mpmath import *
>>> mp.pretty = False
>>> floor(3.5)
mpf(3.0)
Note: floor() (page 735), ceil() (page 736) and nint() (page 736) return a oatingpoint number, not a Python int. If bxc is too large to be represented exactly at the present
working precision, the result will be rounded, not necessarily in the direction implied by
the mathematical denition of the function.
To avoid rounding, use prec=0:
>>> mp.dps = 15
>>> print(int(floor(10**30+1)))
1000000000000000019884624838656
>>> print(int(floor(10**30+1, prec=0)))
1000000000000000000000000000001
The oor function is dened for complex numbers and acts on the real and imaginary
parts separately:
>>> floor(3.25+4.75j)
mpc(real=3.0, imag=4.0)
ceil()
mpmath.ceil(x)
Computes the ceiling of x, dxe, dened as the smallest integer greater than or equal to
x:
>>> from sympy.mpmath import *
>>> mp.pretty = False
>>> ceil(3.5)
mpf(4.0)
The ceiling function is dened for complex numbers and acts on the real and imaginary
parts separately:
>>> ceil(3.25+4.75j)
mpc(real=4.0, imag=5.0)
736
mpf(4.0)
>>> nint(3.5)
mpf(4.0)
>>> nint(4.5)
mpf(4.0)
The nearest integer function is dened for complex numbers and acts on the real and
imaginary parts separately:
>>> nint(3.25+4.75j)
mpc(real=3.0, imag=5.0)
For a complex number, the fractional part function applies to the real and imaginary
parts separately:
>>> frac(2.25+3.75j)
mpc(real=0.25, imag=0.75)
Plotted, the fractional part function gives a sawtooth wave. The Fourier series coecients have a simple form:
>>> mp.dps = 15
>>> nprint(fourier(lambda x: frac(x)-0.5, [0,1], 4))
([0.0, 0.0, 0.0, 0.0, 0.0], [0.0, -0.31831, -0.159155, -0.106103, -0.0795775])
>>> nprint([-1/(pi*k) for k in range(1,5)])
[-0.31831, -0.159155, -0.106103, -0.0795775]
Note: The fractional part is sometimes dened as a symmetric function, i.e. returning
frac(x) if x < 0. This convention is used, for instance, by Mathematicas FractionalPart.
chop()
mpmath.chop(x, tol=None)
Chops o small real or imaginary parts, or converts numbers close to zero to exact zeros.
The input can be a single number or an iterable:
737
Properties of numbers
isinf()
mpmath.isinf(x)
Return True if the absolute value of x is innite; otherwise return False:
>>> from sympy.mpmath import *
>>> isinf(inf)
True
>>> isinf(-inf)
True
>>> isinf(3)
False
>>> isinf(3+4j)
False
>>> isinf(mpc(3,inf))
True
738
>>> isinf(mpc(inf,3))
True
isnan()
mpmath.isnan(x)
Return True if x is a NaN (not-a-number), or for a complex number, whether either the
real or complex part is NaN; otherwise return False:
>>> from sympy.mpmath import *
>>> isnan(3.14)
False
>>> isnan(nan)
True
>>> isnan(mpc(3.14,2.72))
False
>>> isnan(mpc(3.14,nan))
True
isnormal()
mpmath.isnormal(x)
Determine whether x is normal in the sense of oating-point representation; that is,
return False if x is zero, an innity or NaN; otherwise return True. By extension, a
complex number x is considered normal if its magnitude is normal:
>>> from sympy.mpmath import *
>>> isnormal(3)
True
>>> isnormal(0)
False
>>> isnormal(inf); isnormal(-inf); isnormal(nan)
False
False
False
>>> isnormal(0+0j)
False
>>> isnormal(0+3j)
True
>>> isnormal(mpc(2,nan))
False
isfinite()
mpmath.isfinite(x)
Return True if x is a nite number, i.e. neither an innity or a NaN.
>>> from sympy.mpmath import *
>>> isfinite(inf)
False
>>> isfinite(-inf)
False
>>> isfinite(3)
True
>>> isfinite(nan)
False
>>> isfinite(3+4j)
739
True
>>> isfinite(mpc(3,inf))
False
>>> isfinite(mpc(nan,3))
False
isint()
mpmath.isint(x, gaussian=False)
Return True if x is integer-valued; otherwise return False:
>>> from sympy.mpmath import *
>>> isint(3)
True
>>> isint(mpf(3))
True
>>> isint(3.2)
False
>>> isint(inf)
False
ldexp()
mpmath.ldexp(x, n)
Computes x2n eciently. No rounding is performed. The argument x must be a real
oating-point number (or possible to convert into one) and n must be a Python int.
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> ldexp(1, 10)
mpf(1024.0)
>>> ldexp(1, -3)
mpf(0.125)
frexp()
mpmath.frexp(x, n)
Given a real number x, returns (y, n) with y [0.5, 1), n a Python integer, and such that
x = y2n . No rounding is performed.
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> frexp(7.5)
(mpf(0.9375), 3)
mag()
740
mpmath.mag(x)
Quick logarithmic magnitude estimate of a number. Returns an integer or innity m such
that |x| <= 2m . It is not guaranteed that m is an optimal bound, but it will never be too
large by more than 2 (and probably not more than 1).
Examples
>>> from sympy.mpmath import *
>>> mp.pretty = True
>>> mag(10), mag(10.0), mag(mpf(10)), int(ceil(log(10,2)))
(4, 4, 4, 4)
>>> mag(10j), mag(10+10j)
(4, 5)
>>> mag(0.01), int(ceil(log(0.01,2)))
(-6, -6)
>>> mag(0), mag(inf), mag(-inf), mag(nan)
(-inf, +inf, +inf, nan)
nint distance()
mpmath.nint distance(x)
Return (n, d) where n is the nearest integer to x and d is an estimate of log2 (|x n|). If
d < 0, d gives the precision (measured in bits) lost to cancellation when computing xn.
>>> from sympy.mpmath import *
>>> n, d = nint_distance(5)
>>> print(n); print(d)
5
-inf
>>> n, d = nint_distance(mpf(5))
>>> print(n); print(d)
5
-inf
>>> n, d = nint_distance(mpf(5.00000001))
>>> print(n); print(d)
5
-26
>>> n, d = nint_distance(mpf(4.99999999))
>>> print(n); print(d)
5
-26
>>> n, d = nint_distance(mpc(5,10))
>>> print(n); print(d)
5
4
>>> n, d = nint_distance(mpc(5,0.000001))
>>> print(n); print(d)
5
-19
Number generation
fraction()
mpmath.fraction(p, q)
Given Python integers (p, q), returns a lazy mpf representing the fraction p/q. The value
is updated with the precision.
741
rand()
mpmath.rand()
Returns an mpf with value chosen randomly from [0, 1). The number of randomly generated bits in the mantissa is equal to the working precision.
arange()
mpmath.arange(*args)
This is a generalized version of Pythons range() function that accepts fractional endpoints and step sizes and returns a list of mpf instances. Like range(), arange()
(page 742) can be called with 1, 2 or 3 arguments:
arange(b) [0, 1, 2, . . . , x]
arange(a, b) [a, a + 1, a + 2, . . . , x]
arange(a, b, h) [a, a + h, a + h, . . . , x]
where b 1 x < b (in the third case, b h x < b).
Like Pythons range(), the endpoint is not included. To produce ranges where the endpoint is included, linspace() (page 742) is more convenient.
Examples
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> arange(4)
[mpf(0.0), mpf(1.0), mpf(2.0), mpf(3.0)]
>>> arange(1, 2, 0.25)
[mpf(1.0), mpf(1.25), mpf(1.5), mpf(1.75)]
>>> arange(1, -1, -0.75)
[mpf(1.0), mpf(0.25), mpf(-0.5)]
linspace()
mpmath.linspace(*args, **kwargs)
linspace(a, b, n) returns a list of n evenly spaced samples from a to b. The syntax
linspace(mpi(a,b), n) is also valid.
This function is often more convenient than arange() (page 742) for partitioning an
interval into subintervals, since the endpoint is included:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
742
>>> linspace(1, 4, 4)
[mpf(1.0), mpf(2.0), mpf(3.0), mpf(4.0)]
Precision management
autoprec()
mpmath.autoprec(ctx, f, maxprec=None, catch=(), verbose=False)
Return a wrapped copy of f that repeatedly evaluates f with increasing precision until
the result converges to the full precision used at the point of the call.
This heuristically protects against rounding errors, at the cost of roughly a 2x slowdown
compared to manually setting the optimal precision. This method can, however, easily
be fooled if the results from f depend discontinuously on the precision, for instance if
catastrophic cancellation can occur. Therefore, autoprec() (page 743) should be used
judiciously.
Examples
Many functions are sensitive to perturbations of the input arguments. If the arguments
are decimal numbers, they may have to be converted to binary at a much higher precision. If the amount of required extra precision is unknown, autoprec() (page 743) is
convenient:
>>> from sympy.mpmath import *
>>> mp.dps = 15
>>> mp.pretty = True
>>> besselj(5, 125 * 10**28)
# Exact input
-8.03284785591801e-17
>>> besselj(5, 1.25e30)
# Bad
7.12954868316652e-16
>>> autoprec(besselj)(5, 1.25e30)
# Good
-8.03284785591801e-17
The following fails to converge because sin() = 0 whereas all nite-precision approximations of give nonzero values:
>>> autoprec(sin)(pi)
Traceback (most recent call last):
...
NoConvergence: autoprec: prec increased to 2910 without convergence
Traceback (most recent call last):
...
NoConvergence: autoprec: prec increased to 2910 without convergence
As the following example shows, autoprec() (page 743) can protect against cancellation,
but is fooled by too severe cancellation:
>>> x = 1e-10
>>> exp(x)-1; expm1(x); autoprec(lambda t: exp(t)-1)(x)
1.00000008274037e-10
1.00000000005e-10
1.00000000005e-10
>>> x = 1e-50
743
With catch, an exception or list of exceptions to intercept may be specied. The raised
exception is interpreted as signaling insucient precision. This permits, for example,
evaluating a function where a too low precision results in a division by zero:
>>> f = lambda x: 1/(exp(x)-1)
>>> f(1e-30)
Traceback (most recent call last):
...
ZeroDivisionError
>>> autoprec(f, catch=ZeroDivisionError)(1e-30)
1.0e+30
Traceback (most recent call last):
...
ZeroDivisionError
workprec()
mpmath.workprec(ctx, n, normalize output=False)
The block
with workprec(n): <code>
sets the precision to n bits, executes <code>, and then restores the precision.
workprec(n)(f) returns a decorated version of the function f that sets the precision
to n bits before execution, and restores the precision afterwards. With normalize output=True, it rounds the return value to the parent precision.
workdps()
mpmath.workdps(ctx, n, normalize output=False)
This function is analogous to workprec (see documentation) but changes the decimal
precision instead of the number of bits.
extraprec()
mpmath.extraprec(ctx, n, normalize output=False)
The block
with extraprec(n): <code>
increases the precision n bits, executes <code>, and then restores the precision.
extraprec(n)(f) returns a decorated version of the function f that increases the working
precision by n bits before execution, and restores the parent precision afterwards. With
normalize output=True, it rounds the return value to the parent precision.
extradps()
mpmath.extradps(ctx, n, normalize output=False)
This function is analogous to extraprec (see documentation) but changes the decimal
precision instead of the number of bits.
744
memoize()
mpmath.memoize(ctx, f)
Return a wrapped copy of f that caches computed values, i.e. a memoized copy of f.
Values are only reused if the cached precision is equal to or higher than the working
precision:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> f = memoize(maxcalls(sin, 1))
>>> f(2)
0.909297426825682
>>> f(2)
0.909297426825682
>>> mp.dps = 25
>>> f(2)
Traceback (most recent call last):
...
NoConvergence: maxcalls: function evaluated 1 times
Traceback (most recent call last):
...
NoConvergence: maxcalls: function evaluated 1 times
maxcalls()
mpmath.maxcalls(ctx, f, N)
Return a wrapped copy of f that raises NoConvergence when f has been called more than
N times:
>>> from sympy.mpmath import *
>>> mp.dps = 15
>>> f = maxcalls(sin, 10)
>>> print(sum(f(n) for n in range(10)))
1.95520948210738
>>> f(10)
Traceback (most recent call last):
...
NoConvergence: maxcalls: function evaluated 10 times
Traceback (most recent call last):
...
NoConvergence: maxcalls: function evaluated 10 times
monitor()
mpmath.monitor(f, input=print, output=print)
Returns a wrapped copy of f that monitors evaluation by calling input with every input
(args, kwargs) passed to f and output with every value returned from f. The default
action (specify using the special string value print) is to print inputs and outputs to
stdout, along with the total evaluation count:
>>>
>>>
>>>
in
out
in
745
out 1 mpf(2.7182818309906424675501024)
mpf(2.7182808)
To disable either the input or the output handler, you may pass None as argument.
Custom input and output handlers may be used e.g. to store results for later analysis:
>>> mp.dps = 15
>>> input = []
>>> output = []
>>> findroot(monitor(sin, input.append, output.append), 3.0)
mpf(3.1415926535897932)
>>> len(input) # Count number of evaluations
9
>>> print(input[3]); print(output[3])
((mpf(3.1415076583334066),), {})
8.49952562843408e-5
>>> print(input[4]); print(output[4])
((mpf(3.1415928201669122),), {})
-1.66577118985331e-7
timing()
mpmath.timing(f, *args, **kwargs)
Returns time elapsed for evaluating f(). Optionally arguments may be passed to time
the execution of f(*args, **kwargs).
If the rst call is very quick, f is called repeatedly and the best time is returned.
Plotting
If matplotlib is available, the functions plot and cplot in mpmath can be used to plot functions
respectively as x-y graphs and in the complex plane. Also, splot can be used to produce 3D
surface plots.
746
Points where the function raises a numerical exception or returns an innite value are
removed from the graph. Singularities can also be excluded explicitly as follows (useful
for removing erroneous vertical lines):
plot(cot, ylim=[-5, 5])
# bad
plot(cot, ylim=[-5, 5], singularities=[-pi, 0, pi])
# good
For parts where the function assumes complex values, the real part is plotted with dashes
and the imaginary part is plotted with dots.
747
By default, the complex argument (phase) is shown as color (hue) and the magnitude is
show as brightness. You can also supply a custom color function (color). This function
should take a complex number as input and return an RGB 3-tuple containing oats in
the range 0.0-1.0.
To obtain a sharp image, the number of points may need to be increased to 100,000
or thereabout. Since evaluating the function that many times is likely to be slow, the
verbose option is useful to display progress.
748
3D surface plots
Plotting a donut:
749
>>> r, R = 1, 2.5
>>> f = lambda u, v: [r*cos(u), (R+r*sin(u))*cos(v), (R+r*sin(u))*sin(v)]
>>> splot(f, [0, 2*pi], [0, 2*pi])
750
Exact constants The predened objects j (imaginary unit), inf (positive innity) and nan
(not-a-number) are shortcuts to mpc and mpf instances with these xed values.
Pi (pi)
mp.pi = <pi: 3.14159>
Degree (degree)
mp.degree = <1 deg = pi / 180: 0.0174533>
Base of the natural logarithm (e)
mp.e = <e = exp(1): 2.71828>
Golden ratio (phi)
mp.phi = <Golden ratio phi: 1.61803>
Eulers constant (euler)
mp.euler = <Eulers constant: 0.577216>
Catalans constant (catalan)
mp.catalan = <Catalans constant: 0.915966>
Aperys constant (apery)
mp.apery = <Aperys constant: 1.20206>
Khinchins constant (khinchin)
mp.khinchin = <Khinchins constant: 2.68545>
Glaishers constant (glaisher)
mp.glaisher = <Glaishers constant: 1.28243>
Mertens constant (mertens)
mp.mertens = <Mertens constant: 0.261497>
Twin prime constant (twinprime)
mp.twinprime = <Twin prime constant: 0.660162>
Powers and logarithms
Nth roots
751
sqrt()
mpmath.sqrt(x, **kwargs)
sqrt(x) gives the principal square root of x, x. For positive real numbers, the principal
root is simply the positive square
root. For arbitrary complex numbers, the principal
square root is dened to satisfy x = exp(log(x)/2). The function thus has a branch cut
along the negative half real axis.
For all mpmath numbers x, calling sqrt(x) is equivalent to performing x**0.5.
Examples
Basic examples and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> sqrt(10)
3.16227766016838
>>> sqrt(100)
10.0
>>> sqrt(-4)
(0.0 + 2.0j)
>>> sqrt(1+1j)
(1.09868411346781 + 0.455089860562227j)
>>> sqrt(inf)
+inf
hypot()
mpmath.hypot(x, y)
Computes the Euclidean norm of the vector (x, y), equal to x2 + y 2 . Both x and y must
be real.
cbrt()
mpmath.cbrt(x, **kwargs)
cbrt(x) computes the cube root of x, x1/3 . This function is faster and more accurate
than raising to a oating-point fraction:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> 125**(mpf(1)/3)
mpf(4.9999999999999991)
752
>>> cbrt(125)
mpf(5.0)
Every nonzero complex number has three cube roots. This function returns the cube
root dened by exp(log(x)/3) where the principal branch of the natural logarithm is used.
Note that this does not give a real cube root for negative real numbers:
>>> mp.pretty = True
>>> cbrt(-1)
(0.5 + 0.866025403784439j)
root()
mpmath.root(z, n, k=0)
root(z, n, k=0) computes an n-th root of z, i.e. returns a number r that (up to possible
approximation error) satises rn = z. (nthroot is available as an alias for root.)
Every complex number z 6= 0 has n distinct n-th roots, which are equidistant points on
a circle with radius |z|1/n , centered around the origin. A specic root may be selected
using the optional index k. The roots are indexed counterclockwise, starting with k = 0
for the root closest to the positive real half-axis.
The k = 0 root is the so-called principal n-th root, often denoted by n z or z 1/n , and also
given by exp(log(z)/n). If z is a positive real number, the principal root is just the unique
positive n-th root of z. Under some circumstances, non-principal real roots exist: for
positive real z, n even, there is a negative root given by k = n/2; for negative real z, n
odd, there is a negative root given by k = (n 1)/2.
To obtain all roots with a simple expression, use [root(z,n,k) for k in range(n)].
An important special case, root(1, n, k) returns the k-th n-th root of unity, k = e2ik/n .
Alternatively, unitroots() (page 754) provides a slightly more convenient way to obtain
the roots of unity, including the option to compute only the primitive roots of unity.
Both k and n should be integers; k outside of range(n) will be reduced modulo n. If n is
negative, x1/n = 1/x1/n (or the equivalent reciprocal for a non-principal root with k 6= 0)
is computed.
root() (page 753) is implemented to use Newtons method for small n. At high precision,
this makes x1/n not much more expensive than the regular exponentiation, xn . For very
large n, nthroot() falls back to use the exponential function.
Examples
nthroot()/root() (page 753) is faster and more accurate than raising to a oating-point
fraction:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> 16807 ** (mpf(1)/5)
mpf(7.0000000000000009)
>>> root(16807, 5)
mpf(7.0)
>>> nthroot(16807, 5)
# Alias
mpf(7.0)
A high-precision root:
>>> mp.dps = 50; mp.pretty = True
>>> nthroot(10, 5)
753
1.584893192461113485202101373391507013269442133825
>>> nthroot(10, 5) ** 5
10.0
unitroots()
mpmath.unitroots(n, primitive=False)
unitroots(n) returns 0 , 1 , . . . , n1 , all the distinct n-th roots of unity, as a list. If the
option primitive=True is passed, only the primitive roots are returned.
Every n-th root of unity satises (k )n = 1. There are n distinct roots for each n (k and
j are the same when k = j (mod n)), which form a regular polygon with vertices on the
unit circle. They are ordered counterclockwise with increasing k, starting with 0 = 1.
Examples
754
Primitive roots up to n = 4:
>>> mp.dps = 15
>>> nprint(unitroots(1, primitive=True))
[1.0]
>>> nprint(unitroots(2, primitive=True))
[-1.0]
>>> nprint(unitroots(3, primitive=True))
[(-0.5 + 0.866025j), (-0.5 - 0.866025j)]
>>> nprint(unitroots(4, primitive=True))
[(0.0 + 1.0j), (0.0 - 1.0j)]
The n-th roots of unity form a group, the cyclic group of order n. Any primitive root r is
a generator for this group, meaning that r0 , r1 , . . . , rn1 gives the whole set of unit roots
(in some permuted order):
>>> for r in unitroots(6): print(r)
...
1.0
(0.5 + 0.866025403784439j)
(-0.5 + 0.866025403784439j)
-1.0
(-0.5 - 0.866025403784439j)
(0.5 - 0.866025403784439j)
>>> r = unitroots(6, primitive=True)[1]
>>> for k in range(6): print(chop(r**k))
...
1.0
(0.5 - 0.866025403784439j)
(-0.5 - 0.866025403784439j)
-1.0
(-0.5 + 0.866025403784438j)
(0.5 + 0.866025403784438j)
The number of primitive roots equals the Euler totient function (n):
755
Exponentiation
exp()
mpmath.exp(x, **kwargs)
Computes the exponential function,
exp(x) = ex =
xk
k=0
k!
Functional properties
Numerical verication of Eulers identity for the complex exponential function:
756
>>> mp.dps = 15
>>> exp(j*pi)+1
(0.0 + 1.22464679914735e-16j)
>>> chop(exp(j*pi)+1)
0.0
This recovers the coecients (reciprocal factorials) in the Maclaurin series expansion
of exp:
>>> nprint(taylor(exp, 0, 5))
[1.0, 1.0, 0.5, 0.166667, 0.0416667, 0.00833333]
The exponential function can be evaluated using various methods, including direct summation of the series, limits, and solving the dening dierential equation:
>>> nsum(lambda k: pi**k/fac(k), [0,inf])
23.1406926327793
>>> limit(lambda k: (1+pi/k)**k, inf)
23.1406926327793
>>> odefun(lambda t, x: x, 0, 1)(pi)
23.1406926327793
power()
mpmath.power(x, y)
Converts x and y to mpmath numbers and evaluates xy = exp(y log(x)):
>>> from sympy.mpmath import *
>>> mp.dps = 30; mp.pretty = True
>>> power(2, 0.5)
1.41421356237309504880168872421
This shows the leading few digits of a large Mersenne prime (performing the exact calculation 2**43112609-1 and displaying the result in Python would be very slow):
>>> power(2, 43112609)-1
3.16470269330255923143453723949e+12978188
expj()
mpmath.expj(x, **kwargs)
Convenience function for computing eix :
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> expj(0)
(1.0 + 0.0j)
>>> expj(-1)
(0.5403023058681397174009366 - 0.8414709848078965066525023j)
>>> expj(j)
757
(0.3678794411714423215955238 + 0.0j)
>>> expj(1+j)
(0.1987661103464129406288032 + 0.3095598756531121984439128j)
expjpi()
mpmath.expjpi(x, **kwargs)
Convenience function for computing eix . Evaluation is accurate near zeros (see also
cospi() (page 770), sinpi() (page 770)):
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> expjpi(0)
(1.0 + 0.0j)
>>> expjpi(1)
(-1.0 + 0.0j)
>>> expjpi(0.5)
(0.0 + 1.0j)
>>> expjpi(-1)
(-1.0 + 0.0j)
>>> expjpi(j)
(0.04321391826377224977441774 + 0.0j)
>>> expjpi(1+j)
(-0.04321391826377224977441774 + 0.0j)
expm1()
mpmath.expm1(x)
Computes ex 1, accurately for small x.
Unlike the expression exp(x) - 1, expm1(x) does not suer from potentially catastrophic
cancellation:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> exp(1e-10)-1; print(expm1(1e-10))
1.00000008274037e-10
1.00000000005e-10
>>> exp(1e-20)-1; print(expm1(1e-20))
0.0
1.0e-20
>>> 1/(exp(1e-20)-1)
Traceback (most recent call last):
...
ZeroDivisionError
>>> 1/expm1(1e-20)
1.0e+20
Traceback (most recent call last):
...
ZeroDivisionError
758
powm1()
mpmath.powm1(x, y)
Computes xy 1, accurately when xy is very close to 1.
This avoids potentially catastrophic cancellation:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> power(0.99999995, 1e-10) - 1
0.0
>>> powm1(0.99999995, 1e-10)
-5.00000012791934e-18
Logarithms
log()
mpmath.log(x, b=None)
Computes the base-b logarithm of x, logb (x). If b is unspecied, log() (page 759) computes the natural (base e) logarithm and is equivalent to ln() (page 760). In general,
the base b logarithm is dened in terms of the natural logarithm as logb (x) = ln(x)/ ln(b).
By convention, we take log(0) = .
The natural logarithm is real if x > 0 and complex if x < 0 or if x is complex. The principal
branch of the complex logarithm is used, meaning that =(ln(x)) = < arg(x) .
Examples
Some basic values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> log(1)
0.0
>>> log(2)
0.693147180559945
>>> log(1000,10)
3.0
>>> log(4, 16)
0.5
>>> log(j)
(0.0 + 1.5707963267949j)
>>> log(-1)
759
(0.0 + 3.14159265358979j)
>>> log(0)
-inf
>>> log(inf)
+inf
The Taylor series expansion of the natural logarithm around x = 1 has coecients
(1)n+1 /n:
>>> nprint(taylor(log, 1, 7))
[0.0, 1.0, -0.5, 0.333333, -0.25, 0.2, -0.166667, 0.142857]
ln()
mpmath.ln(x, **kwargs)
Computes the base-b logarithm of x, logb (x). If b is unspecied, log() (page 759) computes the natural (base e) logarithm and is equivalent to ln() (page 760). In general,
the base b logarithm is dened in terms of the natural logarithm as logb (x) = ln(x)/ ln(b).
By convention, we take log(0) = .
The natural logarithm is real if x > 0 and complex if x < 0 or if x is complex. The principal
branch of the complex logarithm is used, meaning that =(ln(x)) = < arg(x) .
Examples
Some basic values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> log(1)
0.0
>>> log(2)
0.693147180559945
>>> log(1000,10)
3.0
>>> log(4, 16)
0.5
>>> log(j)
(0.0 + 1.5707963267949j)
760
>>> log(-1)
(0.0 + 3.14159265358979j)
>>> log(0)
-inf
>>> log(inf)
+inf
The Taylor series expansion of the natural logarithm around x = 1 has coecients
(1)n+1 /n:
>>> nprint(taylor(log, 1, 7))
[0.0, 1.0, -0.5, 0.333333, -0.25, 0.2, -0.166667, 0.142857]
log10()
mpmath.log10(x)
Computes the base-10 logarithm of x, log10 (x). log10(x) is equivalent to log(x, 10).
Lambert W function
lambertw()
mpmath.lambertw(z, k=0)
The Lambert W function W (z) is dened as the inverse function of w exp(w). In other
words, the value of W (z) is such that z = W (z) exp(W (z)) for any complex number z.
The Lambert W function is a multivalued function with innitely many branches Wk (z),
indexed by k Z. Each branch gives a dierent solution w of the equation z = w exp(w).
All branches are supported by lambertw() (page 761):
lambertw(z) gives the principal solution (branch 0)
lambertw(z, k) gives the solution on branch k
The Lambert W function has two partially real branches: the principal branch (k = 0) is
real for real z > 1/e, and the k = 1 branch is real for 1/e < z < 0. All branches except
k = 0 have a logarithmic singularity at z = 0.
The denition, implementation and choice of branches is based on [Corless] (page 1910).
761
Plots
# Branches 0 and -1 of the Lambert W function
plot([lambertw, lambda x: lambertw(x,-1)], [-2,2], [-5,2], points=2000)
762
Basic examples
The Lambert W function is the inverse of w exp(w):
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> w = lambertw(1)
>>> w
0.5671432904097838729999687
>>> w*exp(w)
1.0
Applications to equation-solving
The Lambert W function may be used to ...
solve various kinds of equations, such as nding
z
the value of the innite power tower z z :
763
Properties
The Lambert W function grows roughly like the natural logarithm for large arguments:
>>> lambertw(1000); log(1000)
5.249602852401596227126056
6.907755278982137052053974
>>> lambertw(10**100); log(10**100)
224.8431064451185015393731
230.2585092994045684017991
The principal branch of the Lambert W function has a rational Taylor series expansion
around z = 0:
>>> nprint(taylor(lambertw, 0, 6), 10)
[0.0, 1.0, -1.0, 1.5, -2.666666667, 5.208333333, -10.8]
The k = 0 and k = 1 branches join at z = 1/e where W (z) = 1 for both branches.
Since 1/e can only be represented approximately with binary oating-point numbers,
evaluating the Lambert W function at this point only gives 1 approximately:
>>> lambertw(-1/e, 0)
-0.9999999999998371330228251
>>> lambertw(-1/e, -1)
-1.000000000000162866977175
If 1/e happens to round in the negative direction, there might be a small imaginary
part:
764
>>> mp.dps = 15
>>> lambertw(-1/e)
(-1.0 + 8.22007971483662e-9j)
>>> lambertw(-1/e+eps)
-0.999999966242188
References
1.[Corless] (page 1910)
Arithmetic-geometric mean
agm()
mpmath.agm(a, b=1)
agm(a, b) computes the arithmetic-geometric mean of a and b, dened as the limit of
the following iteration:
a0 = a
b0 = b
an + bn
an+1 =
2
bn+1 = an bn
This function can be called with a single argument, computing agm(a, 1) = agm(1, a).
Examples
It is a well-known theorem that the geometric mean of two distinct positive numbers
is less than the arithmetic mean. It follows that the arithmetic-geometric mean lies
between the two means:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> a = mpf(3)
>>> b = mpf(4)
>>> sqrt(a*b)
3.46410161513775
>>> agm(a,b)
3.48202767635957
>>> (a+b)/2
3.5
765
>>> agm(0.01)
0.262166887202249
>>> -pi/2/log(0.0025)
0.262172347753122
The AGM iteration converges very quickly (each step doubles the number of correct
digits), so agm() (page 765) supports ecient high-precision evaluation:
>>> mp.dps = 10000
>>> a = agm(1,2)
>>> str(a)[-10:]
1679581912
Mathematical relations
The arithmetic-geometric mean may be used to evaluate the following two parametric
denite integrals:
1
I1 =
dx
2
2
(x + a )(x2 + b2 )
0
/2
1
I2 =
dx
0
a2 cos2 (x) + b2 sin2 (x)
We have:
>>> mp.dps = 15
>>> a = 3
>>> b = 4
>>> f1 = lambda x: ((x**2+a**2)*(x**2+b**2))**-0.5
>>> f2 = lambda x: ((a*cos(x))**2 + (b*sin(x))**2)**-0.5
>>> quad(f1, [0, inf])
0.451115405388492
>>> quad(f2, [0, pi/2])
0.451115405388492
>>> pi/(2*agm(a,b))
0.451115405388492
Possible issues
The branch cut chosen for complex a and b is somewhat arbitrary.
Trigonometric functions
Except where otherwise noted, the trigonometric functions take a radian angle as input and
the inverse trigonometric functions return radian angles.
766
The ordinary trigonometric functions are single-valued functions dened everywhere in the
complex plane (except at the poles of tan, sec, csc, and cot). They are dened generally via
the exponential function, e.g.
cos(x) =
eix + eix
.
2
The inverse trigonometric functions are multivalued, thus requiring branch cuts, and are generally real-valued only on a part of the real line. Denitions and branch cuts are given in the
documentation of each function. The branch cut conventions used by mpmath are essentially
the same as those found in most standard mathematical software, such as Mathematica and
Pythons own cmath libary (as of Python 2.6; earlier Python versions implement some functions erroneously).
Degree-radian conversion
degrees()
mpmath.degrees(x)
Converts the radian angle x to a degree angle:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> degrees(pi/3)
60.0
radians()
mpmath.radians(x)
Converts the degree angle x to radians:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> radians(60)
1.0471975511966
Trigonometric functions
cos()
mpmath.cos(x, **kwargs)
Computes the cosine of x, cos(x).
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> cos(pi/3)
0.5
>>> cos(100000001)
-0.9802850113244713353133243
>>> cos(2+3j)
(-4.189625690968807230132555 - 9.109227893755336597979197j)
>>> cos(inf)
nan
>>> nprint(chop(taylor(cos, 0, 6)))
[1.0, 0.0, -0.5, 0.0, 0.0416667, 0.0, -0.00138889]
767
sin()
mpmath.sin(x, **kwargs)
Computes the sine of x, sin(x).
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> sin(pi/3)
0.8660254037844386467637232
>>> sin(100000001)
0.1975887055794968911438743
>>> sin(2+3j)
(9.1544991469114295734673 - 4.168906959966564350754813j)
>>> sin(inf)
nan
>>> nprint(chop(taylor(sin, 0, 6)))
[0.0, 1.0, 0.0, -0.166667, 0.0, 0.00833333, 0.0]
tan()
mpmath.tan(x, **kwargs)
sin(x)
. The tangent function is singular at x = (n +
Computes the tangent of x, tan(x) = cos(x)
1/2), but tan(x) always returns a nite result since (n + 1/2) cannot be represented
exactly using oating-point arithmetic.
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> tan(pi/3)
1.732050807568877293527446
>>> tan(100000001)
-0.2015625081449864533091058
>>> tan(2+3j)
(-0.003764025641504248292751221 + 1.003238627353609801446359j)
>>> tan(inf)
nan
>>> nprint(chop(taylor(tan, 0, 6)))
[0.0, 1.0, 0.0, 0.333333, 0.0, 0.133333, 0.0]
768
[0.0, 1.55740772465490223050697482944]
>>> iv.tan([0,2]) # Interval includes a singularity
[-inf, +inf]
sec()
mpmath.sec(x)
1
Computes the secant of x, sec(x) = cos(x)
. The secant function is singular at x = (n + 1/2),
but sec(x) always returns a nite result since (n + 1/2) cannot be represented exactly
using oating-point arithmetic.
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> sec(pi/3)
2.0
>>> sec(10000001)
-1.184723164360392819100265
>>> sec(2+3j)
(-0.04167496441114427004834991 + 0.0906111371962375965296612j)
>>> sec(inf)
nan
>>> nprint(chop(taylor(sec, 0, 6)))
[1.0, 0.0, 0.5, 0.0, 0.208333, 0.0, 0.0847222]
csc()
mpmath.csc(x)
1
Computes the cosecant of x, csc(x) = sin(x)
. This cosecant function is singular at x = n,
but with the exception of the point x = 0, csc(x) returns a nite result since n cannot
be represented exactly using oating-point arithmetic.
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> csc(pi/3)
1.154700538379251529018298
>>> csc(10000001)
-1.864910497503629858938891
>>> csc(2+3j)
(0.09047320975320743980579048 + 0.04120098628857412646300981j)
>>> csc(inf)
nan
769
cot()
mpmath.cot(x)
1
Computes the cotangent of x, cot(x) = tan(x)
= cos(x)
sin(x) . This cotangent function is singular
at x = n, but with the exception of the point x = 0, cot(x) returns a nite result since
n cannot be represented exactly using oating-point arithmetic.
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> cot(pi/3)
0.5773502691896257645091488
>>> cot(10000001)
1.574131876209625656003562
>>> cot(2+3j)
(-0.003739710376336956660117409 - 0.9967577965693583104609688j)
>>> cot(inf)
nan
sinpi()
mpmath.sinpi(x, **kwargs)
Computes sin(x), more accurately than the expression sin(pi*x):
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> sinpi(10**10), sin(pi*(10**10))
(0.0, -2.23936276195592e-6)
>>> sinpi(10**10+0.5), sin(pi*(10**10+0.5))
(1.0, 0.999999999998721)
770
acos()
mpmath.acos(x, **kwargs)
Computes the inverse cosine or arccosine of x, cos1 (x). Since 1 cos(x) 1 for real x,
the inverse cosine is real-valued only for 1 x 1. On this interval, acos() (page 771)
is dened to be a monotonically decreasing function assuming values between + and 0.
Basic values are:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> acos(-1)
3.141592653589793238462643
>>> acos(0)
1.570796326794896619231322
>>> acos(1)
0.0
>>> nprint(chop(taylor(acos, 0, 6)))
[1.5708, -1.0, 0.0, -0.166667, 0.0, -0.075, 0.0]
acos() (page 771) is dened so as to be a proper inverse function of cos() for 0 < .
We have cos(cos1 (x)) = x for all x, but cos1 (cos(x)) = x only for 0 <[x] < :
>>> for x in [1, 10, -1, 2+3j, 10+3j]:
...
print(%s %s % (cos(acos(x)), acos(cos(x))))
...
1.0 1.0
(10.0 + 0.0j) 2.566370614359172953850574
-1.0 1.0
(2.0 + 3.0j) (2.0 + 3.0j)
(10.0 + 3.0j) (2.566370614359172953850574 - 3.0j)
The inverse cosine has two branch points: x = 1. acos() (page 771) places the branch
cuts along the line segments (, 1) and (+1, +). In general,
)
(
771
asin() (page 771) is dened so as to be a proper inverse function of sin() for /2 < <
/2. We have sin(sin1 (x)) = x for all x, but sin1 (sin(x)) = x only for /2 < <[x] < /2:
>>> for x in [1, 10, -1, 1+3j, -2+3j]:
...
print(%s %s % (chop(sin(asin(x))), asin(sin(x))))
...
1.0 1.0
10.0 -0.5752220392306202846120698
-1.0 -1.0
(1.0 + 3.0j) (1.0 + 3.0j)
(-2.0 + 3.0j) (-1.141592653589793238462643 - 3.0j)
The inverse sine has two branch points: x = 1. asin() (page 771) places the branch
cuts along the line segments (, 1) and (+1, +). In general,
)
(
The inverse tangent is often used to compute angles. However, the atan2 function is
often better for this as it preserves sign (see atan2() (page 773)).
atan() (page 772) is dened so as to be a proper inverse function of tan() for /2 < <
/2. We have tan(tan1 (x)) = x for all x, but tan1 (tan(x)) = x only for /2 < <[x] < /2:
>>> mp.dps = 25
>>> for x in [1, 10, -1, 1+3j, -2+3j]:
...
print(%s %s % (tan(atan(x)), atan(tan(x))))
...
1.0 1.0
10.0 0.5752220392306202846120698
-1.0 -1.0
(1.0 + 3.0j) (1.000000000000000000000001 + 3.0j)
(-2.0 + 3.0j) (1.141592653589793238462644 + 3.0j)
772
The inverse tangent has two branch points: x = i. atan() (page 772) places the branch
cuts along the line segments (i, i) and (+i, +i). In general,
tan1 (x) =
i
(log(1 ix) log(1 + ix))
2
The angle convention is the same as that used for the complex argument; see arg()
(page 734).
asec()
mpmath.asec(x)
Computes the inverse secant of x, sec1 (x) = cos1 (1/x).
acsc()
mpmath.acsc(x)
Computes the inverse cosecant of x, csc1 (x) = sin1 (1/x).
acot()
mpmath.acot(x)
Computes the inverse cotangent of x, cot1 (x) = tan1 (1/x).
Sinc function
sinc()
mpmath.sinc(x)
sinc(x) computes the unnormalized sinc function, dened as
{
sin(x)/x, if x 6= 0
sinc(x) =
1,
if x = 0.
5.15. Welcome to mpmaths documentation!
773
sincpi()
mpmath.sincpi(x)
sincpi(x) computes the normalized sinc function, dened as
{
sin(x)/(x), if x 6= 0
sinc (x) =
1,
if x = 0.
Equivalently, we have sinc (x) = sinc(x).
The normalization entails that the function integrates to unity over the entire real line:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> quadosc(sincpi, [-inf, inf], period=2.0)
1.0
Like, sinpi() (page 770), sincpi() (page 774) is evaluated accurately at its roots:
>>> sincpi(10)
0.0
Hyperbolic functions
Hyperbolic functions
cosh()
mpmath.cosh(x, **kwargs)
Computes the hyperbolic cosine of x, cosh(x) = (ex + ex )/2. Values and limits include:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> cosh(0)
1.0
>>> cosh(1)
1.543080634815243778477906
>>> cosh(-inf), cosh(+inf)
(+inf, +inf)
774
The hyperbolic cosine is an even, convex function with a global minimum at x = 0, having
a Maclaurin series that starts:
>>> nprint(chop(taylor(cosh, 0, 5)))
[1.0, 0.0, 0.5, 0.0, 0.0416667, 0.0]
sinh()
mpmath.sinh(x, **kwargs)
Computes the hyperbolic sine of x, sinh(x) = (ex ex )/2. Values and limits include:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> sinh(0)
0.0
>>> sinh(1)
1.175201193643801456882382
>>> sinh(-inf), sinh(+inf)
(-inf, +inf)
The hyperbolic sine is an odd function, with a Maclaurin series that starts:
>>> nprint(chop(taylor(sinh, 0, 5)))
[0.0, 1.0, 0.0, 0.166667, 0.0, 0.00833333]
Generalized to complex numbers, the hyperbolic sine is essentially a sine with a rotation
i applied to the argument; more precisely, sinh x = i sin ix:
>>> sinh(2+3j)
(-3.590564589985779952012565 + 0.5309210862485198052670401j)
>>> j*sin(3-2j)
(-3.590564589985779952012565 + 0.5309210862485198052670401j)
tanh()
mpmath.tanh(x, **kwargs)
Computes the hyperbolic tangent of x, tanh(x) = sinh(x)/ cosh(x). Values and limits include:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> tanh(0)
0.0
>>> tanh(1)
0.7615941559557648881194583
>>> tanh(-inf), tanh(inf)
(-1.0, 1.0)
The hyperbolic tangent is an odd, sigmoidal function, similar to the inverse tangent and
error function. Its Maclaurin series is:
775
sech()
mpmath.sech(x)
Computes the hyperbolic secant of x, sech(x) =
1
cosh(x) .
csch()
mpmath.csch(x)
Computes the hyperbolic cosecant of x, csch(x) =
1
sinh(x) .
coth()
mpmath.coth(x)
Computes the hyperbolic cotangent of x, coth(x) =
cosh(x)
sinh(x) .
1
Computes the inverse hyperbolic cosine of x, cosh (x) = log(x + x + 1 x 1).
asinh()
mpmath.asinh(x, **kwargs)
1
Computes the inverse hyperbolic sine of x, sinh (x) = log(x + 1 + x2 ).
atanh()
mpmath.atanh(x, **kwargs)
1
Computes the inverse hyperbolic tangent of x, tanh (x) =
1
2
asech()
mpmath.asech(x)
1
1
Computes the inverse hyperbolic secant of x, sech (x) = cosh (1/x).
acsch()
mpmath.acsch(x)
1
1
Computes the inverse hyperbolic cosecant of x, csch (x) = sinh (1/x).
776
acoth()
mpmath.acoth(x)
1
1
Computes the inverse hyperbolic cotangent of x, coth (x) = tanh (1/x).
Factorials and gamma functions
Factorials and factorial-like sums and products are basic tools of combinatorics and number theory. Much like the exponential function is fundamental to dierential equations and
analysis in general, the factorial function (and its extension to complex numbers, the gamma
function) is fundamental to dierence equations and functional equations.
A large selection of factorial-like functions is implemented in mpmath. All functions support
complex arguments, and arguments may be arbitrarily large. Results are numerical approximations, so to compute exact values a high enough precision must be set manually:
>>> mp.dps = 15; mp.pretty = True
>>> fac(100)
9.33262154439442e+157
>>> print int(_)
# most digits are wrong
93326215443944150965646704795953882578400970373184098831012889540582227238570431
295066113089288327277825849664006524270554535976289719382852181865895959724032
>>> mp.dps = 160
>>> fac(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915
608941463976156518286253697920827223758251185210916864000000000000000000000000.0
The gamma and polygamma functions are closely related to Zeta functions, L-series and polylogarithms (page 931). See also q-functions (page 968) for q-analogs of factorial-like functions.
Factorials
factorial()/fac()
mpmath.factorial(x, **kwargs)
Computes the factorial, x!. For integers n 0, we have n! = 1 2 (n 1) n and more
generally the factorial is dened for real or complex x by x! = (x + 1).
Examples
Basic values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> for k in range(6):
...
print(%s %s % (k, fac(k)))
...
0 1.0
1 1.0
2 2.0
3 6.0
4 24.0
5 120.0
>>> fac(inf)
+inf
>>> fac(0.5), sqrt(pi)/2
(0.886226925452758, 0.886226925452758)
777
Reciprocal factorials appear in the Taylor series of the exponential function (among many
other contexts):
>>> nsum(lambda k:
(2.71828182845905,
>>> nsum(lambda k:
(23.1406926327793,
fac2()
mpmath.fac2(x)
Computes the double factorial x!!, dened for integers x > 0 by
{
1 3 (x 2) x x odd
x!! =
2 4 (x 2) x x even
and more generally by [1]
x!! = 2x/2
( )(cos(x)1)/4
2
(x
2
)
+1 .
Examples
The integer sequence of double factorials begins:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> nprint([fac2(n) for n in range(10)])
[1.0, 1.0, 2.0, 3.0, 8.0, 15.0, 48.0, 105.0, 384.0, 945.0]
The recurrence formula x!! = x(x 2)!! can be reversed to dene the double factorial of
negative odd integers (but not negative even integers):
>>> fac2(-1), fac2(-3), fac2(-5), fac2(-7)
(1.0, -1.0, 0.333333333333333, -0.0666666666666667)
>>> fac2(-2)
Traceback (most recent call last):
...
ValueError: gamma function pole
778
With the exception of the poles at negative even integers, fac2() (page 778) supports
evaluation for arbitrary complex arguments. The recurrence formula is valid generally:
>>> fac2(pi+2j)
(-1.3697207890154e-12 + 3.93665300979176e-12j)
>>> (pi+2j)*fac2(pi-2+2j)
(-1.3697207890154e-12 + 3.93665300979176e-12j)
Double factorials should not be confused with nested factorials, which are immensely
larger:
>>> fac(fac(20))
5.13805976125208e+43675043585825292774
>>> fac2(20)
3715891200.0
Double factorials appear, among other things, in series expansions of Gaussian functions
and the error function. Innite series include:
>>> nsum(lambda k: 1/fac2(k), [0, inf])
3.05940740534258
>>> sqrt(e)*(1+sqrt(pi/2)*erf(sqrt(2)/2))
3.05940740534258
>>> nsum(lambda k: 2**k/fac2(2*k-1), [1, inf])
4.06015693855741
>>> e * erf(1) * sqrt(pi)
4.06015693855741
References
1.http://functions.wolfram.com/GammaBetaErf/Factorial2/27/01/0002/
2.http://mathworld.wolfram.com/DoubleFactorial.html
Binomial coecients
binomial()
mpmath.binomial(n, k)
Computes the binomial coecient
( )
n
n!
=
.
k
k!(n k)!
The binomial coecient gives the number of ways that k items can be chosen from a set
of n items. More generally, the binomial coecient is a well-dened function of arbitrary
real or complex n and k, via the gamma function.
Examples
5.15. Welcome to mpmaths documentation!
779
There is 1 way to select 0 items from the empty set, and 0 ways to select 1 item from the
empty set:
>>> binomial(0, 0)
1.0
>>> binomial(0, 1)
0.0
An integral representation:
>>> n, k = 5, 3
>>> f = lambda t: exp(-j*k*t)*(1+exp(j*t))**n
>>> chop(quad(f, [-pi,pi])/(2*pi))
10.0
>>> binomial(n,k)
10.0
Gamma function
gamma()
mpmath.gamma(x, **kwargs)
Computes the gamma function, (x). The gamma function is a shifted version of the
ordinary factorial, satisfying (n) = (n 1)! for integers n > 0. More generally, it is
dened by
(x) =
tx1 et dt
0
for any real or complex x with <(x) > 0 and for <(x) < 0 by analytic continuation.
Examples
780
Arguments can also be large. Note that the gamma function grows very quickly:
>>> mp.dps = 15
>>> gamma(10**20)
1.9328495143101e+1956570551809674817225
rgamma()
mpmath.rgamma(x, **kwargs)
Computes the reciprocal of the gamma function, 1/(z). This function evaluates to zero
at the poles of the gamma function, z = 0, 1, 2, . . ..
Examples
Basic examples:
781
gammaprod()
mpmath.gammaprod(a, b)
Given iterables a and b, gammaprod(a, b) computes the product / quotient of gamma
functions:
(a0 )(a1 ) (ap )
(b0 )(b1 ) (bq )
Unlike direct calls to gamma() (page 780), gammaprod() (page 782) considers the entire
product as a limit and evaluates this limit properly if any of the numerator or denominator arguments are nonpositive integers such that poles of the gamma function are
encountered. That is, gammaprod() (page 782) evaluates
lim
0
In particular:
If there are equally many poles in the numerator and the denominator, the limit is a
rational number times the remaining, regular part of the product.
If there are more poles in the numerator, gammaprod() (page 782) returns +inf.
If there are more poles in the denominator, gammaprod() (page 782) returns 0.
Examples
The reciprocal gamma function 1/(x) evaluated at x = 0:
>>> from sympy.mpmath import *
>>> mp.dps = 15
>>> gammaprod([], [0])
0.0
A limit:
>>> gammaprod([-4], [-3])
-0.25
>>> limit(lambda x: gamma(x-1)/gamma(x), -3, direction=1)
782
-0.25
>>> limit(lambda x: gamma(x-1)/gamma(x), -3, direction=-1)
-0.25
loggamma()
mpmath.loggamma(x)
Computes the principal branch of the log-gamma function, ln (z). Unlike ln((z)), which
has innitely many complex branch cuts, the principal log-gamma function only has a single branch cut along the negative half-axis. The principal branch continuously matches
the asymptotic Stirling expansion
(
)
ln(2)
1
ln (z)
+ z
ln(z) z + O(z 1 ).
2
2
The real parts of both functions agree, but their imaginary parts generally dier by 2n
for some n Z. They coincide for z R, z > 0.
Computationally, it is advantageous to use loggamma() (page 783) instead of gamma()
(page 780) for extremely large arguments.
Examples
Comparing with ln((z)):
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> loggamma(13.2); log(gamma(13.2))
20.49400419456603678498394
20.49400419456603678498394
>>> loggamma(3+4j)
(-1.756626784603784110530604 + 4.742664438034657928194889j)
>>> log(gamma(3+4j))
(-1.756626784603784110530604 - 1.540520869144928548730397j)
>>> log(gamma(3+4j)) + 2*pi*j
(-1.756626784603784110530604 + 4.742664438034657928194889j)
783
>>> loggamma(1e30)
6.807755278982137052053974e+31
>>> loggamma(1e300)
6.897755278982137052053974e+302
>>> loggamma(1e3000)
6.906755278982137052053974e+3003
>>> loggamma(1e100000000000000000000)
2.302585092994045684007991e+100000000000000000020
>>> loggamma(1e30j)
(-1.570796326794896619231322e+30 + 6.807755278982137052053974e+31j)
>>> loggamma(1e300j)
(-1.570796326794896619231322e+300 + 6.897755278982137052053974e+302j)
>>> loggamma(1e3000j)
(-1.570796326794896619231322e+3000 + 6.906755278982137052053974e+3003j)
The log-gamma function can be integrated analytically on any interval of unit length:
>>> z = 0
>>> quad(loggamma, [z,z+1]); log(2*pi)/2
0.9189385332046727417803297
0.9189385332046727417803297
>>> z = 3+4j
>>> quad(loggamma, [z,z+1]); (log(z)-1)*z + log(2*pi)/2
(-0.9619286014994750641314421 + 5.219637303741238195688575j)
(-0.9619286014994750641314421 + 5.219637303741238195688575j)
The derivatives of the log-gamma function are given by the polygamma function (psi()
(page 792)):
>>> diff(loggamma, -4+3j); psi(0, -4+3j)
(1.688493531222971393607153 + 2.554898911356806978892748j)
(1.688493531222971393607153 + 2.554898911356806978892748j)
>>> diff(loggamma, -4+3j, 2); psi(1, -4+3j)
(-0.1539414829219882371561038 - 0.1020485197430267719746479j)
(-0.1539414829219882371561038 - 0.1020485197430267719746479j)
The log-gamma function satises an additive form of the recurrence relation for the
ordinary gamma function:
>>> z = 2+3j
>>> loggamma(z); loggamma(z+1) - log(z)
(-2.092851753092733349564189 + 2.302396543466867626153708j)
(-2.092851753092733349564189 + 2.302396543466867626153708j)
(x + n)
(x)
ff()
mpmath.ff(x, n)
Computes the falling factorial,
(x)n = x(x 1) (x n + 1) =
(x + 1)
(x n + 1)
Beta function
beta()
mpmath.beta(x, y)
Computes the beta function, B(x, y) = (x)(y)/(x + y). The beta function is also commonly dened by the integral representation
1
B(x, y) =
tx1 (1 t)y1 dt
0
Examples
5.15. Welcome to mpmaths documentation!
785
For integer and half-integer arguments where all three gamma functions are nite, the
beta function becomes either rational number or a rational multiple of :
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> beta(5, 2)
0.0333333333333333
>>> beta(1.5, 2)
0.266666666666667
>>> 16*beta(2.5, 1.5)
3.14159265358979
Where appropriate, beta() (page 785) evaluates limits. A pole of the beta function is
taken to result in +inf:
>>> beta(-0.5, 0.5)
0.0
>>> beta(-3, 3)
-0.333333333333333
>>> beta(-2, 3)
+inf
>>> beta(inf, 1)
0.0
>>> beta(inf, 0)
nan
beta() (page 785) supports complex numbers and arbitrary precision evaluation:
>>> beta(1, 2+j)
(0.4 - 0.2j)
>>> mp.dps = 25
>>> beta(j,0.5)
(1.079424249270925780135675 - 1.410032405664160838288752j)
>>> mp.dps = 50
>>> beta(pi, e)
0.037890298781212201348153837138927165984170287886464
betainc()
mpmath.betainc(a, b, x1=0, x2=1, regularized=False)
betainc(a, b, x1=0, x2=1, regularized=False) gives the generalized incomplete
beta function,
x2
x2
Ix1 (a, b) =
ta1 (1 t)b1 dt.
x1
When x1 = 0, x2 = 1, this reduces to the ordinary (complete) beta function B(a, b); see
beta() (page 785).
786
With the keyword argument regularized=True, betainc() (page 786) computes the
regularized incomplete beta function Ixx12 (a, b)/B(a, b). This is the cumulative distribution
of the beta distribution with parameters a, b.
Examples
Verifying that betainc() (page 786) computes the integral in the denition:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> x,y,a,b = 3, 4, 0, 6
>>> betainc(x, y, a, b)
-4010.4
>>> quad(lambda t: t**(x-1) * (1-t)**(y-1), [a, b])
-4010.4
With regularization:
>>> betainc(1, 2, 0, 0.25, regularized=True)
0.4375
>>> betainc(pi, e, 0, 1, regularized=True)
# Complete
1.0
The beta integral can often be evaluated analytically. For integer and rational arguments, the incomplete beta function typically reduces to a simple algebraic-logarithmic
expression:
>>> mp.dps = 25
>>> identify(chop(betainc(0, 0, 3, 4)))
-(log((9/8)))
>>> identify(betainc(2, 3, 4, 5))
(673/12)
>>> identify(betainc(1.5, 1, 1, 2))
((-12+sqrt(1152))/18)
k!
k=1
For general complex z, sf(z) is dened in terms of the Barnes G-function (see barnesg()
(page 790)).
787
Examples
The rst few superfactorials are (OEIS A000178):
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> for n in range(10):
...
print(%s %s % (n, superfac(n)))
...
0 1.0
1 1.0
2 2.0
3 12.0
4 288.0
5 34560.0
6 24883200.0
7 125411328000.0
8 5.05658474496e+15
9 1.83493347225108e+21
References
1.http://oeis.org/A000178
hyperfac()
mpmath.hyperfac(z)
Computes the hyperfactorial, dened for integers as the product
H(n) =
kk .
k=1
The hyperfactorial satises the recurrence formula H(z) = z z H(z 1). It can be dened
more generally in terms of the Barnes G-function (see barnesg() (page 790)) and the
gamma function by the formula
H(z) =
(z + 1)z
.
G(z)
The extension to complex numbers can also be done via the integral representation
]
[(
) z
z+1
log(t!) dt .
H(z) = (2)z/2 exp
+
2
0
788
Examples
The rapidly-growing sequence of hyperfactorials begins (OEIS A002109):
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> for n in range(10):
...
print(%s %s % (n, hyperfac(n)))
...
0 1.0
1 1.0
2 4.0
3 108.0
4 27648.0
5 86400000.0
6 4031078400000.0
7 3.3197663987712e+18
8 5.56964379417266e+25
9 2.15779412229419e+34
789
>>> mp.dps = 50
>>> hyperfac(10)
215779412229418562091680268288000000000000000.0
>>> hyperfac(1/sqrt(2))
0.89404818005227001975423476035729076375705084390942
References
1.http://oeis.org/A002109
2.http://mathworld.wolfram.com/Hyperfactorial.html
barnesg()
mpmath.barnesg(z)
Evaluates the Barnes G-function, which generalizes the superfactorial (superfac()
(page 787)) and by extension also the hyperfactorial (hyperfac() (page 788)) to the
complex numbers in an analogous way to how the gamma function generalizes the ordinary factorial.
The Barnes G-function may be dened in terms of a Weierstrass product:
z/2 [z(z+1)+z 2 ]/2
G(z + 1) = (2)
[(
z )n z+z2 /(2n) ]
e
1+
n
n=1
790
...
gamma(0.25)**3/sqrt(glaisher)**9, 4)
0.29375596533861
The asymptotic growth rate of the Barnes G-function is related to the Glaisher-Kinkelin
constant:
>>> limit(lambda n: barnesg(n+1)/(n**(n**2/2-mpf(1)/12)*
...
(2*pi)**(n/2)*exp(-3*n**2/4)), inf)
0.847536694177301
>>> exp(1/12)/glaisher
0.847536694177301
References
791
1.Whittaker & Watson, A Course of Modern Analysis, Cambridge University Press, 4th
edition (1927), p.264
2.http://en.wikipedia.org/wiki/Barnes G-function
3.http://mathworld.wolfram.com/BarnesG-Function.html
Polygamma functions and harmonic numbers
psi()/digamma()
mpmath.psi(m, z)
Gives the polygamma function of order m of z, (m) (z). Special cases are known as the
digamma function ( (0) (z)), the trigamma function ( (1) (z)), etc. The polygamma functions are dened as the logarithmic derivatives of the gamma function:
(
(m)
(z) =
d
dz
)m+1
log (z)
In particular, (0) (z) = 0 (z)/(z). In the present implementation of psi() (page 792),
the order m must be a nonnegative integer, while the argument z may be an arbitrary
complex number (with exception for the polygamma functions poles at z = 0, 1, 2, . . .).
Examples
For various rational arguments, the polygamma function reduces to a combination of
standard mathematical constants:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> psi(0, 1), -euler
(-0.5772156649015328606065121, -0.5772156649015328606065121)
>>> psi(1, 1/4), pi**2+8*catalan
(17.19732915450711073927132, 17.19732915450711073927132)
>>> psi(2, 1/2), -14*apery
(-16.82879664423431999559633, -16.82879664423431999559633)
792
k=0
1
.
(z + k)m+1
Since the roots of a polynomial may be complex, it is sometimes necessary to use the
complex polygamma function to evaluate an entirely real-valued sum:
>>> nsum(lambda k: 1/(k**2-2*k+3), [0, inf])
1.694361433907061256154665
>>> nprint(polyroots([1,-2,3]))
[(1.0 - 1.41421j), (1.0 + 1.41421j)]
>>> r1 = 1-sqrt(2)*j
>>> r2 = r1.conjugate()
>>> (psi(0,-r2)-psi(0,-r1))/(r1-r2)
(1.694361433907061256154665 + 0.0j)
mpmath.digamma(z)
Shortcut for psi(0,z).
harmonic()
mpmath.harmonic(z)
If n is an integer, harmonic(n) gives a oating-point approximation of the n-th harmonic
number H(n), dened as
H(n) = 1 +
1 1
1
+ + ... +
2 3
n
793
5 2.28333333333333
6 2.45
7 2.59285714285714
harmonic() (page 793) is evaluated using the digamma function rather than by summing
the harmonic series term by term. It can therefore be computed quickly for arbitrarily
large n, and even for nonintegral arguments:
>>> harmonic(10**100)
230.835724964306
>>> harmonic(0.5)
0.613705638880109
>>> harmonic(3+4j)
(2.24757548223494 + 0.850502209186044j)
The harmonic series diverges, but at a glacial pace. It is possible to calculate the exact
number of terms required before the sum exceeds a given amount, say 100:
>>> mp.dps = 50
>>> v = 10**findroot(lambda x: harmonic(10**x) - 100, 10)
>>> v
15092688622113788323693563264538101449859496.864101
>>> v = int(ceil(v))
>>> print(v)
15092688622113788323693563264538101449859497
>>> harmonic(v-1)
99.999999999999999999999999999999999999999999942747
>>> harmonic(v)
100.000000000000000000000000000000000000000000009
Exponential integrals give closed-form solutions to a large class of commonly occurring transcendental integrals that cannot be evaluated using elementary functions. Integrals of this
2
type include those with an integrand of the form ta et or ex , the latter giving rise to the
Gaussian (or normal) probability distribution.
The most general function in this section is the incomplete gamma function, to which all
others can be reduced. The incomplete gamma function, in turn, can be expressed using
hypergeometric functions (see Hypergeometric functions (page 888)).
Incomplete gamma functions
794
gammainc()
mpmath.gammainc(z, a=0, b=inf, regularized=False)
gammainc(z, a=0, b=inf) computes the (generalized) incomplete gamma function with
integration limits [a, b]:
(z, a, b) =
tz1 et dt
The generalized incomplete gamma function reduces to the following special cases when
one or both endpoints are xed:
(z, 0, ) is the standard (complete) gamma function, (z) (available directly as the
mpmath function gamma() (page 780))
(z, a, ) is the upper incomplete gamma function, (z, a)
(z, 0, b) is the lower incomplete gamma function, (z, b).
(z, a, b)
.
(z)
Examples
We can compare with numerical quadrature to verify that gammainc() (page 795) computes the integral in the denition:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> gammainc(2+3j, 4, 10)
(0.00977212668627705160602312 - 0.0770637306312989892451977j)
>>> quad(lambda t: t**(2+3j-1) * exp(-t), [4, 10])
(0.00977212668627705160602312 - 0.0770637306312989892451977j)
795
Evaluation of a generalized incomplete gamma function automatically chooses the representation that gives a more accurate result, depending on which parameter is larger:
>>> gammainc(10000000, 3) - gammainc(10000000, 2)
# Bad
0.0
>>> gammainc(10000000, 2, 3)
# Good
1.755146243738946045873491e+4771204
>>> gammainc(2, 0, 100000001) - gammainc(2, 0, 100000000)
0.0
>>> gammainc(2, 100000000, 100000001)
# Good
4.078258353474186729184421e-43429441
# Bad
If z is an integer, the recurrence reduces the incomplete gamma function to P (a) exp(a)+
Q(b) exp(b) where P and Q are polynomials:
>>> gammainc(1, 2); exp(-2)
0.1353352832366126918939995
0.1353352832366126918939995
>>> mp.dps = 50
>>> identify(gammainc(6, 1, 2), [exp(-1), exp(-2)])
(326*exp(-1) + (-872)*exp(-2))
The incomplete gamma functions reduce to functions such as the exponential integral Ei
and the error function for special arguments:
>>> mp.dps = 25
>>> gammainc(0, 4); -ei(-4)
0.00377935240984890647887486
0.00377935240984890647887486
>>> gammainc(0.5, 0, 2); sqrt(pi)*erf(sqrt(2))
1.691806732945198336509541
1.691806732945198336509541
Exponential integrals
ei()
mpmath.ei(x, **kwargs)
Computes the exponential integral or Ei-function, Ei(x). The exponential integral is de-
796
ned as
Ei(x) =
et
dt.
t
ei() (page 796) supports complex arguments and arbitrary precision evaluation:
>>> mp.dps = 50
>>> ei(pi)
10.928374389331410348638445906907535171566338835056
>>> mp.dps = 25
>>> ei(3+4j)
(-4.154091651642689822535359 + 4.294418620024357476985535j)
Related functions
The exponential integral is closely related to the logarithmic integral.
(page 799) for additional information.
See li()
The exponential integral is related to the hyperbolic and trigonometric integrals (see
chi() (page 803), shi() (page 803), ci() (page 801), si() (page 802)) similarly to
how the ordinary exponential function is related to the hyperbolic and trigonometric
functions:
>>> mp.dps = 15
>>> ei(3)
9.93383257062542
>>> chi(3) + shi(3)
9.93383257062542
>>> chop(ci(3j) - j*si(3j) - pi*j/2)
9.93383257062542
797
Beware that logarithmic corrections, as in the last example above, are required to obtain
the correct branch in general. For details, see [1].
The exponential integral is also a special case of the hypergeometric function 2 F2 :
>>> z = 0.6
>>> z*hyper([1,1],[2,2],z) + (ln(z)-ln(1/z))/2 + euler
0.769881289937359
>>> ei(z)
0.769881289937359
References
The E1-function is essentially the same as the Ei-function (ei() (page 796)) with negated
argument, except for an imaginary branch cut term:
>>> e1(2.5)
0.02491491787026973549562801
>>> -ei(-2.5)
0.02491491787026973549562801
>>> e1(-2.5)
(-7.073765894578600711923552 - 3.141592653589793238462643j)
>>> -ei(2.5)
-7.073765894578600711923552
expint()
mpmath.expint(*args)
expint(n,z)() gives the generalized exponential integral or En-function,
zt
e
En (z) =
dt,
tn
1
where n and z may both be complex numbers. The case with n = 1 is also given by e1()
(page 798).
798
Examples
Evaluation at real and complex arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> expint(1, 6.25)
0.0002704758872637179088496194
>>> expint(-3, 2+3j)
(0.00299658467335472929656159 + 0.06100816202125885450319632j)
>>> expint(2+3j, 4-5j)
(0.001803529474663565056945248 - 0.002235061547756185403349091j)
Logarithmic integral
li()
mpmath.li(x, **kwargs)
Computes the logarithmic integral or li-function li(x), dened by
x
1
li(x) =
dt
0 log t
The logarithmic integral has a singularity at x = 1.
Alternatively, li(x, offset=True) computes the oset logarithmic integral (used in
number theory)
x
1
Li(x) =
dt.
2 log t
These two functions are related via the simple identity Li(x) = li(x) li(2).
The logarithmic integral should also not be confused with the polylogarithm (also denoted by Li), which is implemented as polylog() (page 944).
Examples
Some basic values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 30; mp.pretty = True
>>> li(0)
0.0
799
>>> li(1)
-inf
>>> li(1)
-inf
>>> li(2)
1.04516378011749278484458888919
>>> findroot(li, 2)
1.45136923488338105028396848589
>>> li(inf)
+inf
>>> li(2, offset=True)
0.0
>>> li(1, offset=True)
-inf
>>> li(0, offset=True)
-1.04516378011749278484458888919
>>> li(10, offset=True)
5.12043572466980515267839286347
The prime number theorem states that the number of primes less than x is asymptotic to Li(x) (equivalently li(x)). For example, it is known that there are exactly
1,925,320,391,606,803,968,923 prime numbers less than 1023 [1]. The logarithmic integral provides a very accurate estimate:
>>> li(10**23, offset=True)
1.92532039161405e+21
References
1.http://mathworld.wolfram.com/PrimeCountingFunction.html
2.http://mathworld.wolfram.com/LogarithmicIntegral.html
800
Trigonometric integrals
ci()
mpmath.ci(x, **kwargs)
Computes the cosine integral,
Ci(x) =
cos t
dt = + log x +
t
x
0
cos t 1
dt
t
Examples
Some values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> ci(0)
-inf
>>> ci(1)
0.3374039229009681346626462
>>> ci(pi)
0.07366791204642548599010096
>>> ci(inf)
0.0
>>> ci(-inf)
(0.0 + 3.141592653589793238462643j)
>>> ci(2+3j)
(1.408292501520849518759125 - 2.983617742029605093121118j)
The cosine integral behaves roughly like the sinc function (see sinc() (page 773)) for
large real x:
>>> ci(10**10)
-4.875060251748226537857298e-11
>>> sinc(10**10)
-4.875060250875106915277943e-11
>>> chop(limit(ci, inf))
0.0
801
si()
mpmath.si(x, **kwargs)
Computes the sine integral,
Si(x) =
0
sin t
dt.
t
The sine integral is thus the antiderivative of the sinc function (see sinc() (page 773)).
Examples
Some values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> si(0)
0.0
>>> si(1)
0.9460830703671830149413533
>>> si(-1)
-0.9460830703671830149413533
>>> si(pi)
1.851937051982466170361053
>>> si(inf)
1.570796326794896619231322
>>> si(-inf)
-1.570796326794896619231322
>>> si(2+3j)
(4.547513889562289219853204 + 1.399196580646054789459839j)
802
>>> si(1)
0.946083070367183
Hyperbolic integrals
chi()
mpmath.chi(x, **kwargs)
Computes the hyperbolic cosine integral, dened in analogy with the cosine integral (see
ci() (page 801)) as
x
cosh t
cosh t 1
dt = + log x +
dt
Chi(x) =
t
t
x
0
Some values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> chi(0)
-inf
>>> chi(1)
0.8378669409802082408946786
>>> chi(inf)
+inf
>>> findroot(chi, 0.5)
0.5238225713898644064509583
>>> chi(2+3j)
(-0.1683628683277204662429321 + 2.625115880451325002151688j)
shi()
mpmath.shi(x, **kwargs)
Computes the hyperbolic sine integral, dened in analogy with the sine integral (see
si() (page 802)) as
x
sinh t
Shi(x) =
dt.
t
0
Some values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> shi(0)
0.0
>>> shi(1)
1.057250875375728514571842
>>> shi(-1)
-1.057250875375728514571842
>>> shi(inf)
+inf
>>> shi(2+3j)
(-0.1931890762719198291678095 + 2.645432555362369624818525j)
803
Error functions
erf()
mpmath.erf(x, **kwargs)
Computes the error function, erf(x). The error function is the normalized antiderivative
of the Gaussian function exp(t2 ). More precisely,
x
2
erf(x) =
exp(t2 ) dt
0
Basic examples
Simple values and limits include:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> erf(0)
0.0
>>> erf(1)
0.842700792949715
>>> erf(-1)
-0.842700792949715
>>> erf(inf)
1.0
>>> erf(-inf)
-1.0
erf() (page 804) implements arbitrary-precision evaluation and supports complex numbers:
>>> mp.dps = 50
>>> erf(0.5)
0.52049987781304653768274665389196452873645157575796
>>> mp.dps = 25
>>> erf(1+j)
(1.316151281697947644880271 + 0.1904534692378346862841089j)
804
>>> mp.dps = 25
>>> erf(1e1000)
1.0
>>> erf(-1e1000)
-1.0
>>> erf(1e-1000)
1.128379167095512573896159e-1000
>>> erf(1e7j)
(0.0 + 8.593897639029319267398803e+43429448190317j)
>>> erf(1e7+1e7j)
(0.9999999858172446172631323 + 3.728805278735270407053139e-8j)
Related functions
See also erfc() (page 805), which is more accurate for large x, and erfi() (page 805)
which gives the antiderivative of exp(t2 ).
The Fresnel integrals fresnels() (page 808) and fresnelc() (page 809) are also related
to the error function.
erfc()
mpmath.erfc(x, **kwargs)
Computes the complementary error function, erfc(x) = 1 erf(x). This function avoids
cancellation that occurs when naively computing the complementary error function as
1-erf(x):
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> 1 - erf(10)
0.0
>>> erfc(10)
2.08848758376254e-45
erfc() (page 805) works accurately even for ludicrously large arguments:
>>> erfc(10**10)
4.3504398860243e-43429448190325182776
erfi()
mpmath.erfi(x)
Computes the imaginary error function, erfi(x). The imaginary error function is dened
in analogy with the error function, but with a positive sign in the integrand:
x
2
erfi(x) =
exp(t2 ) dt
0
Whereas the error function rapidly converges to 1 as x grows, the imaginary error function rapidly diverges to innity. The functions are related as erfi(x) = i erf(ix) for all
complex numbers x.
Examples
Basic values and limits:
5.15. Welcome to mpmaths documentation!
805
erfinv()
mpmath.erfinv(x)
Computes the inverse error function, satisfying
erf(erfinv(x)) = erfinv(erf(x)) = x.
This function is dened only for 1 x 1.
Examples
Special values include:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> erfinv(0)
0.0
>>> erfinv(1)
+inf
>>> erfinv(-1)
-inf
806
It is simple to check that erfinv() (page 806) computes inverse values of erf()
(page 804) as promised:
>>> erf(erfinv(0.75))
0.75
>>> erf(erfinv(-0.995))
-0.995
The inverse error function can be used to generate random numbers with a Gaussian
distribution (although this is a relatively inecient algorithm):
>>> nprint([erfinv(2*rand()-1) for n in range(6)])
[-0.586747, 1.10233, -0.376796, 0.926037, -0.708142, -0.732012]
807
See also ncdf() (page 808), which gives the cumulative distribution.
ncdf()
mpmath.ncdf(x, mu=0, sigma=1)
ncdf(x, mu=0, sigma=1) evaluates the cumulative distribution function of a normal
distribution with mean value and variance 2 .
See also npdf() (page 807), which gives the probability density.
Elementary properties include:
>>>
>>>
>>>
0.5
>>>
0.0
>>>
1.0
The cumulative distribution is the integral of the density function having identical mu
and sigma:
>>> mp.dps = 15
>>> diff(ncdf, 2)
0.053990966513188
>>> npdf(2)
0.053990966513188
>>> diff(lambda x: ncdf(x, 1, 0.5), 0)
0.107981933026376
>>> npdf(0, 1, 0.5)
0.107981933026376
Fresnel integrals
fresnels()
mpmath.fresnels(x)
Computes the Fresnel sine integral
sin
S(x) =
0
t2
2
)
dt
Note that some sources dene this function without the normalization factor /2.
Examples
Some basic values and limits:
>>>
>>>
>>>
0.0
>>>
0.5
808
>>> fresnels(-inf)
-0.5
>>> fresnels(1)
0.4382591473903547660767567
>>> fresnels(1+2j)
(36.72546488399143842838788 + 15.58775110440458732748279j)
fresnelc()
mpmath.fresnelc(x)
Computes the Fresnel cosine integral
cos
C(x) =
0
t2
2
)
dt
Note that some sources dene this function without the normalization factor /2.
Examples
Some basic values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> fresnelc(0)
0.0
>>> fresnelc(inf)
0.5
>>> fresnelc(-inf)
-0.5
>>> fresnelc(1)
0.7798934003768228294742064
>>> fresnelc(1+2j)
(16.08787137412548041729489 - 36.22568799288165021578758j)
The functions in this section arise as solutions to various dierential equations in physics, typically describing wavelike oscillatory behavior or a combination of oscillation and exponential
decay or growth. Mathematically, they are special cases of the conuent hypergeometric
functions 0 F1 , 1 F1 and 1 F2 (see Hypergeometric functions (page 888)).
Bessel functions
809
besselj()
mpmath.besselj(n, x, derivative=0)
besselj(n, x, derivative=0) gives the Bessel function of the rst kind Jn (x). Bessel
functions of the rst kind are dened as solutions of the dierential equation
x2 y 00 + xy 0 + (x2 n2 )y = 0
which appears, among other things, when solving the radial part of Laplaces equation
in cylindrical coordinates. This equation has two solutions for given n, where the Jn function is the solution that is nonsingular at x = 0. For positive integer n, Jn (x) behaves
roughly like a sine (odd n) or cosine (even n) multiplied by a magnitude factor that decays
slowly as x .
Generally, Jn is a special case of the hypergeometric function 0 F1 :
(
)
xn
x2
Jn (x) = n
0 F1 n + 1,
2 (n + 1)
4
With derivative = m 6= 0, the m-th derivative
dm
Jn (x)
dxm
is computed.
Plots
# Bessel function J_n(x) on the real line for n=0,1,2,3
j0 = lambda x: besselj(0,x)
j1 = lambda x: besselj(1,x)
j2 = lambda x: besselj(2,x)
j3 = lambda x: besselj(3,x)
plot([j0,j1,j2,j3],[0,14])
810
811
Examples
Evaluation is supported for arbitrary arguments, and at arbitrary precision:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> besselj(2, 1000)
-0.024777229528606
>>> besselj(4, 0.75)
0.000801070086542314
>>> besselj(2, 1000j)
(-2.48071721019185e+432 + 6.41567059811949e-437j)
>>> mp.dps = 25
>>> besselj(0.75j, 3+4j)
(-2.778118364828153309919653 - 1.5863603889018621585533j)
>>> mp.dps = 50
>>> besselj(1, pi)
0.28461534317975275734531059968613140570981118184947
812
(-3.540725411970948860173735e+43426 + 4.4949812409615803110051e-43433j)
The Bessel functions of the rst kind satisfy simple symmetries around x = 0:
>>> mp.dps = 15
>>> nprint([besselj(n,0) for n in range(5)])
[1.0, 0.0, 0.0, 0.0, 0.0]
>>> nprint([besselj(n,pi) for n in range(5)])
[-0.304242, 0.284615, 0.485434, 0.333458, 0.151425]
>>> nprint([besselj(n,-pi) for n in range(5)])
[-0.304242, -0.284615, 0.485434, -0.333458, 0.151425]
for k in
11.7915,
for k in
13.3237,
The roots are not periodic, but the distance between successive roots asymptotically
approaches 2. Bessel functions of the rst kind have the following normalization:
>>> quadosc(j0, [0, inf], period=2*pi)
1.0
>>> quadosc(j1, [0, inf], period=2*pi)
1.0
Dierentiation with a noninteger order gives the fractional derivative in the sense of the
Riemann-Liouville dierintegral, as computed by differint() (page 1002):
>>> mp.dps = 15
>>> besselj(1, 3.5, 0.75)
-0.385977722939384
>>> differint(lambda x: besselj(1, x), 3.5, 0.75)
-0.385977722939384
813
mpmath.j0(x)
Computes the Bessel function J0 (x). See besselj() (page 810).
mpmath.j1(x)
Computes the Bessel function J1 (x). See besselj() (page 810).
bessely()
mpmath.bessely(n, x, derivative=0)
bessely(n, x, derivative=0) gives the Bessel function of the second kind,
Yn (x) =
814
Examples
Some values of Yn (x):
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> bessely(0,0), bessely(1,0), bessely(2,0)
(-inf, -inf, -inf)
>>> bessely(1, pi)
0.3588729167767189594679827
>>> bessely(0.5, 3+4j)
(9.242861436961450520325216 - 3.085042824915332562522402j)
815
besseli()
mpmath.besseli(n, x, derivative=0)
besseli(n, x, derivative=0) gives the modied Bessel function of the rst kind,
In (x) = in Jn (ix).
With derivative = m 6= 0, the m-th derivative
dm
In (x)
dxm
is computed.
Plots
# Modified Bessel function I_n(x) on the real line for n=0,1,2,3
i0 = lambda x: besseli(0,x)
i1 = lambda x: besseli(1,x)
i2 = lambda x: besseli(2,x)
i3 = lambda x: besseli(3,x)
plot([i0,i1,i2,i3],[0,5],[0,5])
816
817
Examples
Some values of In (x):
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> besseli(0,0)
1.0
>>> besseli(1,0)
0.0
>>> besseli(0,1)
1.266065877752008335598245
>>> besseli(3.5, 2+3j)
(-0.2904369752642538144289025 - 0.4469098397654815837307006j)
818
besselk()
mpmath.besselk(n, x)
besselk(n, x) gives the modied Bessel function of the second kind,
Kn (x) =
In (x) In (x)
2
sin(n)
819
820
Examples
Evaluation is supported for arbitrary complex arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> besselk(0,1)
0.4210244382407083333356274
>>> besselk(0, -1)
(0.4210244382407083333356274 - 3.97746326050642263725661j)
>>> besselk(3.5, 2+3j)
(-0.02090732889633760668464128 + 0.2464022641351420167819697j)
>>> besselk(2+3j, 0.5)
(0.9615816021726349402626083 + 0.1918250181801757416908224j)
821
>>> besselk(0,0)
+inf
>>> besselk(1,0)
+inf
>>> for n in range(-4, 5):
...
print(besselk(n, 1e-1000))
...
4.8e+4001
8.0e+3000
2.0e+2000
1.0e+1000
2302.701024509704096466802
1.0e+1000
2.0e+2000
8.0e+3000
4.8e+4001
j,1 < j+1,2 < j,2 < j+1,2 < j,3 <
Examples
Initial zeros of the Bessel functions J0 (z), J1 (z), J2 (z):
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> besseljzero(0,1); besseljzero(0,2); besseljzero(0,3)
2.404825557695772768621632
5.520078110286310649596604
8.653727912911012216954199
>>> besseljzero(1,1); besseljzero(1,2); besseljzero(1,3)
3.831705970207512315614436
7.01558666981561875353705
10.17346813506272207718571
>>> besseljzero(2,1); besseljzero(2,2); besseljzero(2,3)
5.135622301840682556301402
8.417244140399864857783614
11.61984117214905942709415
822
0.0
3.831705970207512315614436
7.01558666981561875353705
>>> besseljzero(1,1,1); besseljzero(1,2,1); besseljzero(1,3,1)
1.84118378134065930264363
5.331442773525032636884016
8.536316366346285834358961
>>> besseljzero(2,1,1); besseljzero(2,2,1); besseljzero(2,3,1)
3.054236928227140322755932
6.706133194158459146634394
9.969467823087595793179143
Both J (z) and J0 (z) can be expressed as innite products over their zeros:
>>> v,z = 2, mpf(1)
>>> (z/2)**v/gamma(v+1) * \
...
nprod(lambda k: 1-(z/besseljzero(v,k))**2, [1,inf])
...
0.1149034849319004804696469
>>> besselj(v,z)
0.1149034849319004804696469
>>> (z/2)**(v-1)/2/gamma(v) * \
...
nprod(lambda k: 1-(z/besseljzero(v,k,1))**2, [1,inf])
823
...
0.2102436158811325550203884
>>> besselj(v,z,1)
0.2102436158811325550203884
besselyzero()
mpmath.besselyzero(v, m, derivative=0)
For a real order 0 and a positive integer m, returns y,m , the m-th positive zero of the
Bessel function of the second kind Y (z) (see bessely() (page 814)). Alternatively, with
0
derivative=1, gives the rst positive zero y,m
of Y0 (z).
The zeros are interlaced according to the inequalities
0
< y,k+1
y,k < y,k
y,1 < y+1,2 < y,2 < y+1,2 < y,3 <
Examples
Initial zeros of the Bessel functions Y0 (z), Y1 (z), Y2 (z):
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> besselyzero(0,1); besselyzero(0,2); besselyzero(0,3)
0.8935769662791675215848871
3.957678419314857868375677
7.086051060301772697623625
>>> besselyzero(1,1); besselyzero(1,2); besselyzero(1,3)
2.197141326031017035149034
5.429681040794135132772005
8.596005868331168926429606
>>> besselyzero(2,1); besselyzero(2,2); besselyzero(2,3)
3.384241767149593472701426
6.793807513268267538291167
10.02347797936003797850539
824
3147.086508524556404473186
31421.42392920214673402828
>>> besselyzero(0,100,1); besselyzero(0,1000,1); besselyzero(0,10000,1)
313.3726705426359345050449
3140.807136030340213610065
31415.14112579761578220175
Hankel functions
hankel1()
mpmath.hankel1(n, x)
hankel1(n,x) computes the Hankel function of the rst kind, which is the complex combination of Bessel functions given by
Hn(1) (x) = Jn (x) + iYn (x).
Plots
# Hankel function H1_n(x) on the real line for n=0,1,2,3
h0 = lambda x: hankel1(0,x)
h1 = lambda x: hankel1(1,x)
h2 = lambda x: hankel1(2,x)
h3 = lambda x: hankel1(3,x)
plot([h0,h1,h2,h3],[0,6],[-2,1])
825
826
Examples
The Hankel function is generally complex-valued:
>>> from sympy.mpmath import
>>> mp.dps = 25; mp.pretty =
>>> hankel1(2, pi)
(0.4854339326315091097054957
>>> hankel1(3.5, pi)
(0.2340002029630507922628888
*
True
- 0.0999007139290278787734903j)
- 0.6419643823412927142424049j)
hankel2()
mpmath.hankel2(n, x)
hankel2(n,x) computes the Hankel function of the second kind, which is the complex
combination of Bessel functions given by
Hn(2) (x) = Jn (x) iYn (x).
Plots
# Hankel function H2_n(x) on the real line for n=0,1,2,3
h0 = lambda x: hankel2(0,x)
h1 = lambda x: hankel2(1,x)
h2 = lambda x: hankel2(2,x)
h3 = lambda x: hankel2(3,x)
plot([h0,h1,h2,h3],[0,6],[-1,2])
827
828
Examples
The Hankel function is generally complex-valued:
>>> from sympy.mpmath import
>>> mp.dps = 25; mp.pretty =
>>> hankel2(2, pi)
(0.4854339326315091097054957
>>> hankel2(3.5, pi)
(0.2340002029630507922628888
*
True
+ 0.0999007139290278787734903j)
+ 0.6419643823412927142424049j)
Kelvin functions
ber()
mpmath.ber(ctx, n, z, **kwargs)
Computes the Kelvin function ber, which for real arguments gives the real part of the
Bessel J function of a rotated argument
)
(
Jn xe3i/4 = bern (x) + ibein (x).
The imaginary part is given by bei() (page 831).
Plots
829
# Kelvin functions ber_n(x) and bei_n(x) on the real line for n=0,2
f0 = lambda x: ber(0,x)
f1 = lambda x: bei(0,x)
f2 = lambda x: ber(2,x)
f3 = lambda x: bei(2,x)
plot([f0,f1,f2,f3],[0,10],[-10,10])
Examples
Verifying the dening relation:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> n, x = 2, 3.5
>>> ber(n,x)
1.442338852571888752631129
>>> bei(n,x)
-0.948359035324558320217678
>>> besselj(n, x*root(1,8,3))
(1.442338852571888752631129 - 0.948359035324558320217678j)
The ber and bei functions are also dened by analytic continuation for complex arguments:
>>> ber(1+j, 2+3j)
(4.675445984756614424069563 - 15.84901771719130765656316j)
>>> bei(1+j, 2+3j)
(15.83886679193707699364398 + 4.684053288183046528703611j)
830
bei()
mpmath.bei(ctx, n, z, **kwargs)
Computes the Kelvin function bei, which for real arguments gives the imaginary part of
the Bessel J function of a rotated argument. See ber() (page 829).
ker()
mpmath.ker(ctx, n, z, **kwargs)
Computes the Kelvin function ker, which for real arguments gives the real part of the
(rescaled) Bessel K function of a rotated argument
(
)
ei/2 Kn xe3i/4 = kern (x) + ikein (x).
The imaginary part is given by kei() (page 832).
Plots
# Kelvin functions ker_n(x) and kei_n(x) on the real line for n=0,2
f0 = lambda x: ker(0,x)
f1 = lambda x: kei(0,x)
f2 = lambda x: ker(2,x)
f3 = lambda x: kei(2,x)
plot([f0,f1,f2,f3],[0,5],[-1,4])
Examples
Verifying the dening relation:
831
The ker and kei functions are also dened by analytic continuation for complex arguments:
>>> ker(1+j, 3+4j)
(1.586084268115490421090533 - 2.939717517906339193598719j)
>>> kei(1+j, 3+4j)
(-2.940403256319453402690132 - 1.585621643835618941044855j)
kei()
mpmath.kei(ctx, n, z, **kwargs)
Computes the Kelvin function kei, which for real arguments gives the imaginary part of
the (rescaled) Bessel K function of a rotated argument. See ker() (page 831).
Struve functions
struveh()
mpmath.struveh(ctx, n, z, **kwargs)
Gives the Struve function
Hn (z) =
( z )2k+n+1
(1)k
3
(k +
+ n + 2) 2
k=0
3
2 )(k
2z n+1
.
(2n 1)!!
Examples
Evaluation for arbitrary real and complex arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> struveh(0, 3.5)
0.3608207733778295024977797
>>> struveh(-1, 10)
-0.255212719726956768034732
>>> struveh(1, -100.5)
0.5819566816797362287502246
>>> struveh(2.5, 10000000000000)
3153915652525200060.308937
>>> struveh(2.5, -10000000000000)
(0.0 - 3153915652525200060.308937j)
>>> struveh(1+j, 1000000+4000000j)
(-3.066421087689197632388731e+1737173 - 1.596619701076529803290973e+1737173j)
832
struvel()
mpmath.struvel(ctx, n, z, **kwargs)
Gives the modied Struve function
Ln (z) = ieni/2 Hn (iz)
which solves to the modied Struve dierential equation
z 2 f 00 (z) + zf 0 (z) (z 2 + n2 )f (z) =
2z n+1
.
(2n 1)!!
Examples
Evaluation for arbitrary real and complex arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> struvel(0, 3.5)
7.180846515103737996249972
>>> struvel(-1, 10)
2670.994904980850550721511
>>> struvel(1, -100.5)
1.757089288053346261497686e+42
>>> struvel(2.5, 10000000000000)
4.160893281017115450519948e+4342944819025
>>> struvel(2.5, -10000000000000)
(0.0 - 4.160893281017115450519948e+4342944819025j)
>>> struvel(1+j, 700j)
(-0.1721150049480079451246076 + 0.1240770953126831093464055j)
>>> struvel(1+j, 1000000+4000000j)
(-2.973341637511505389128708e+434290 - 5.164633059729968297147448e+434290j)
z =
n =
f =
lhs
rhs
mpf(3.5)
3
lambda z: struvel(n,z)
= z**2*diff(f,z,2) + z*diff(f,z) - (z**2+n**2)*f(z)
= 2*z**(n+1)/fac2(2*n-1)/pi
833
>>> lhs
6.368850306060678353018165
>>> rhs
6.368850306060678353018165
Anger-Weber functions
angerj()
mpmath.angerj(ctx, v, z, **kwargs)
Gives the Anger function
1
J (z) =
which is an entire function of both the parameter and the argument z. It solves the
inhomogeneous Bessel dierential equation
(
)
2
(z )
1 0
00
f (z) + f (z) + 1 2 f (z) =
sin().
z
z
z 2
Examples
Evaluation for real and complex parameter and argument:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> angerj(2,3)
0.4860912605858910769078311
>>> angerj(-3+4j, 2+5j)
(-5033.358320403384472395612 + 585.8011892476145118551756j)
>>> angerj(3.25, 1e6j)
(4.630743639715893346570743e+434290 - 1.117960409887505906848456e+434291j)
>>> angerj(-1.5, 1e6)
0.0002795719747073879393087011
The Anger function coincides with the Bessel J-function when is an integer:
>>> angerj(1,3); besselj(1,3)
0.3390589585259364589255146
0.3390589585259364589255146
>>> angerj(1.5,3); besselj(1.5,3)
0.4088969848691080859328847
0.4777182150870917715515015
834
References
1.[DLMF] (page 1910) section 11.10: Anger-Weber Functions
webere()
mpmath.webere(ctx, v, z, **kwargs)
Gives the Weber function
1
E (z) =
which is an entire function of both the parameter and the argument z. It solves the
inhomogeneous Bessel dierential equation
(
)
1 0
2
1
00
f (z) + f (z) + 1 2 f (z) = 2 (z + + (z ) cos()).
z
z
z
Examples
Evaluation for real and complex parameter and argument:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> webere(2,3)
-0.1057668973099018425662646
>>> webere(-3+4j, 2+5j)
(-585.8081418209852019290498 - 5033.314488899926921597203j)
>>> webere(3.25, 1e6j)
(-1.117960409887505906848456e+434291 - 4.630743639715893346570743e+434290j)
>>> webere(3.25, 1e6)
-0.00002812518265894315604914453
Up to addition of a rational function of z, the Weber function coincides with the Struve
H-function when is an integer:
>>> webere(1,3); 2/pi-struveh(1,3)
-0.3834897968188690177372881
-0.3834897968188690177372881
>>> webere(5,3); 26/(35*pi)-struveh(5,3)
0.2009680659308154011878075
0.2009680659308154011878075
References
1.[DLMF] (page 1910) section 11.10: Anger-Weber Functions
5.15. Welcome to mpmaths documentation!
835
Lommel functions
lommels1()
mpmath.lommels1(ctx, u, v, z, **kwargs)
(1)
Gives the Lommel function s, or s,
(
)
z +1
+ 3 + + 3 z2
s, (z) =
,
;
1 F2 1;
( + 1)( + + 1)
2
2
4
which solves the inhomogeneous Bessel equation
z 2 f 00 (z) + zf 0 (z) + (z 2 2 )f (z) = z +1 .
A second solution is given by lommels2() (page 837).
Plots
# Lommel function s_(u,v)(x) on the real line for a few different u,v
f1 = lambda x: lommels1(-1,2.5,x)
f2 = lambda x: lommels1(0,0.5,x)
f3 = lambda x: lommels1(0,6,x)
f4 = lambda x: lommels1(0.5,3,x)
plot([f1,f2,f3,f4], [0,20])
Examples
An integral representation:
836
A special value:
>>> lommels1(v,v,z)
0.5461221367746048054932553
>>> gamma(v+0.5)*sqrt(pi)*power(2,v-1)*struveh(v,z)
0.5461221367746048054932553
References
1.[GradshteynRyzhik] (page 1910)
2.[Weisstein] (page 1910) http://mathworld.wolfram.com/LommelFunction.html
lommels2()
mpmath.lommels2(ctx, u, v, z, **kwargs)
(2)
Gives the second Lommel function S, or s,
(
) (
)
S, (z) = s, (z) + 21 12 ( + 1) 12 ( + + 1)
[
]
sin( 21 ( ))J (z) cos( 21 ( ))Y (z)
which solves the same dierential equation as lommels1() (page 836).
Plots
# Lommel function S_(u,v)(x) on the real line for a few different u,v
f1 = lambda x: lommels2(-1,2.5,x)
f2 = lambda x: lommels2(1.5,2,x)
f3 = lambda x: lommels2(2.5,1,x)
f4 = lambda x: lommels2(3.5,-0.5,x)
plot([f1,f2,f3,f4], [0,8], [-8,8])
837
Examples
For large |z|, S, z 1 :
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> lommels2(10,2,30000)
1.968299831601008419949804e+40
>>> power(30000,9)
1.9683e+40
A special value:
>>> u,v,z = 0.5, 0.125, mpf(0.75)
>>> lommels2(v,v,z)
0.9589683199624672099969765
>>> (struveh(v,z)-bessely(v,z))*power(2,v-1)*sqrt(pi)*gamma(v+0.5)
0.9589683199624672099969765
References
1.[GradshteynRyzhik] (page 1910)
838
1
1 3
Ai(x) =
cos
t + xt dt
xR
0
3
( 3
)
t
z3
3
Ai(z) =
exp 3 dt.
2 0
3
3t
The Ai-function is an entire function with a turning point, behaving roughly like a slowly
decaying sine wave for z < 0 and like a rapidly decreasing exponential for z > 0. A second
solution of the Airy dierential equation is given by Bi(z) (see airybi() (page 844)).
Optionally, with derivative=alpha, airyai() can compute the -th order fractional
derivative with respect to z. For = n = 1, 2, 3, . . . this gives the derivative Ai(n) (z), and
for = n = 1, 2, 3, . . . this gives the n-fold iterated integral
f0 (z) = Ai(z)
z
fn (z) =
fn1 (t)dt.
0
The Ai-function has innitely many zeros, all located along the negative half of the real
axis. They can be computed with airyaizero() (page 848).
Plots
# Airy function Ai(x), Ai(x) and int_0^x Ai(t) dt on the real line
f = airyai
f_diff = lambda z: airyai(z, derivative=1)
f_int = lambda z: airyai(z, derivative=-1)
plot([f, f_diff, f_int], [-10,5])
839
840
Basic examples
Limits and values include:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> airyai(0); 1/(power(3,2/3)*gamma(2/3))
0.3550280538878172392600632
0.3550280538878172392600632
>>> airyai(1)
0.1352924163128814155241474
>>> airyai(-1)
0.5355608832923521187995166
>>> airyai(inf); airyai(-inf)
0.0
0.0
841
>>> airyai(10**10)
1.162235978298741779953693e-289529654602171
>>> airyai(-10**10)
0.0001736206448152818510510181
>>> w = airyai(10**10*(1+j))
>>> w.real
5.711508683721355528322567e-186339621747698
>>> w.imag
1.867245506962312577848166e-186339621747697
The rst few terms of the Taylor series expansion around z = 0 (every third term is zero):
>>> nprint(taylor(airyai, 0, 5))
[0.355028, -0.258819, 0.0, 0.0591713, -0.0215683, 0.0]
The Airy functions satisfy the Wronskian relation Ai(z) Bi0 (z) Ai0 (z) Bi(z) = 1/:
>>> z = -0.5
>>> airyai(z)*airybi(z,1) - airyai(z,1)*airybi(z)
0.3183098861837906715377675
>>> 1/pi
0.3183098861837906715377675
The Airy functions can be expressed in terms of Bessel functions of order 1/3. For
<[z] 0, we have:
>>> z = -3
>>> airyai(z)
-0.3788142936776580743472439
>>> y = 2*power(-z,3/2)/3
>>> (sqrt(-z) * (besselj(1/3,y) + besselj(-1/3,y)))/3
-0.3788142936776580743472439
842
1.136442881032974223041732
>>> airyai(1000,1); diff(airyai,1000)
-2.943133917910336090459748e-9156
-2.943133917910336090459748e-9156
Several derivatives at z = 0:
>>> airyai(0,0); airyai(0,1); airyai(0,2)
0.3550280538878172392600632
-0.2588194037928067984051836
0.0
>>> airyai(0,3); airyai(0,4); airyai(0,5)
0.3550280538878172392600632
-0.5176388075856135968103671
0.0
>>> airyai(0,15); airyai(0,16); airyai(0,17)
1292.30211615165475090663
-3188.655054727379756351861
0.0
843
References
1.[DLMF] (page 1910) Chapter 9: Airy and Related Functions
2.[WolframFunctions] (page 1910) section: Bessel-Type Functions
airybi()
mpmath.airybi(z, derivative=0, **kwargs)
Computes the Airy function Bi(z), which is the solution of the Airy dierential equation
f 00 (z) zf (z) = 0 with initial conditions
Bi(0) =
1
( )
31/6 23
Bi0 (0) =
31/6
( ).
13
Like the Ai-function (see airyai() (page 839)), the Bi-function is oscillatory for z < 0,
but it grows rather than decreases for z > 0.
Optionally, as for airyai() (page 839), derivatives, integrals and fractional derivatives
can be computed with the derivative parameter.
The Bi-function has innitely many zeros along the negative half-axis, as well as complex
zeros, which can all be computed with airybizero() (page 849).
Plots
# Airy function Bi(x), Bi(x) and int_0^x Bi(t) dt on the real line
f = airybi
f_diff = lambda z: airybi(z, derivative=1)
f_int = lambda z: airybi(z, derivative=-1)
plot([f, f_diff, f_int], [-10,2], [-1,2])
844
845
Basic examples
Limits and values include:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> airybi(0); 1/(power(3,1/6)*gamma(2/3))
0.6149266274460007351509224
0.6149266274460007351509224
>>> airybi(1)
1.207423594952871259436379
>>> airybi(-1)
0.10399738949694461188869
>>> airybi(inf); airybi(-inf)
+inf
0.0
Huge arguments:
846
>>> airybi(10**10)
1.369385787943539818688433e+289529654602165
>>> airybi(-10**10)
0.001775656141692932747610973
>>> w = airybi(10**10*(1+j))
>>> w.real
-6.559955931096196875845858e+186339621747689
>>> w.imag
-6.822462726981357180929024e+186339621747690
The rst few terms of the Taylor series expansion around z = 0 (every third term is zero):
>>> nprint(taylor(airybi, 0, 5))
[0.614927, 0.448288, 0.0, 0.102488, 0.0373574, 0.0]
The Airy functions can be expressed in terms of Bessel functions of order 1/3. For
<[z] 0, we have:
>>> z = -3
>>> airybi(z)
-0.1982896263749265432206449
>>> p = 2*power(-z,3/2)/3
>>> sqrt(-mpf(z)/3)*(besselj(-1/3,p) - besselj(1/3,p))
-0.1982896263749265432206449
Several derivatives at z = 0:
>>> airybi(0,0); airybi(0,1); airybi(0,2)
0.6149266274460007351509224
847
0.4482883573538263579148237
0.0
>>> airybi(0,3); airybi(0,4); airybi(0,5)
0.6149266274460007351509224
0.8965767147076527158296474
0.0
>>> airybi(0,15); airybi(0,16); airybi(0,17)
2238.332923903442675949357
5522.912562599140729510628
0.0
airyaizero()
848
mpmath.airyaizero(k, derivative=0)
Gives the k-th zero of the Airy Ai-function, i.e. the k-th number ak ordered by magnitude
for which Ai(ak ) = 0.
Optionally, with derivative=1, the corresponding zero a0k of the derivative function, i.e.
Ai0 (a0k ) = 0, is computed.
Examples
Some values of ak :
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> airyaizero(1)
-2.338107410459767038489197
>>> airyaizero(2)
-4.087949444130970616636989
>>> airyaizero(3)
-5.520559828095551059129856
>>> airyaizero(1000)
-281.0315196125215528353364
Verication:
>>> chop(airyai(airyaizero(1)))
0.0
>>> chop(airyai(airyaizero(1,1),1))
0.0
airybizero()
mpmath.airybizero(k, derivative=0, complex=0)
With complex=False, gives the k-th real zero of the Airy Bi-function, i.e. the k-th number
bk ordered by magnitude for which Bi(bk ) = 0.
With complex=True, gives the k-th complex zero in the upper half plane k . Also the
conjugate k is a zero.
Optionally, with derivative=1, the corresponding zero b0k or k0 of the derivative function,
i.e. Bi0 (b0k ) = 0 or Bi0 (k0 ) = 0, is computed.
Examples
Some values of bk :
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> airybizero(1)
-1.17371322270912792491998
>>> airybizero(2)
-3.271093302836352715680228
849
>>> airybizero(3)
-4.830737841662015932667709
>>> airybizero(1000)
-280.9378112034152401578834
Some values of bk :
>>> airybizero(1,1)
-2.294439682614123246622459
>>> airybizero(2,1)
-4.073155089071828215552369
>>> airybizero(3,1)
-5.512395729663599496259593
>>> airybizero(1000,1)
-281.0315164471118527161362
Some values of k :
>>> airybizero(1,complex=True)
(0.9775448867316206859469927 + 2.141290706038744575749139j)
>>> airybizero(2,complex=True)
(1.896775013895336346627217 + 3.627291764358919410440499j)
>>> airybizero(3,complex=True)
(2.633157739354946595708019 + 4.855468179979844983174628j)
>>> airybizero(1000,complex=True)
(140.4978560578493018899793 + 243.3907724215792121244867j)
Some values of k0 :
>>> airybizero(1,1,complex=True)
(0.2149470745374305676088329 + 1.100600143302797880647194j)
>>> airybizero(2,1,complex=True)
(1.458168309223507392028211 + 2.912249367458445419235083j)
>>> airybizero(3,1,complex=True)
(2.273760763013482299792362 + 4.254528549217097862167015j)
>>> airybizero(1000,1,complex=True)
(140.4509972835270559730423 + 243.3096175398562811896208j)
Verication:
>>>
0.0
>>>
0.0
>>>
>>>
0.0
>>>
0.0
chop(airybi(airybizero(1)))
chop(airybi(airybizero(1,1),1))
u = airybizero(1,complex=True)
chop(airybi(u))
chop(airybi(conj(u)))
The complex zeros (in the upper and lower half-planes respectively) asymptotically approach the rays z = R exp(i/3):
>>> arg(airybizero(1,complex=True))
1.142532510286334022305364
>>> arg(airybizero(1000,complex=True))
1.047271114786212061583917
>>> arg(airybizero(1000000,complex=True))
1.047197624741816183341355
850
>>> pi/3
1.047197551196597746154214
scorergi()
mpmath.scorergi(z, **kwargs)
Evaluates the Scorer function
Gi(z) = Ai(z)
Bi(t)dt + Bi(z)
0
Ai(t)dt
z
which gives a particular solution to the inhomogeneous Airy dierential equation f 00 (z)
zf (z) = 1/. Another particular solution is given by the Scorer Hi-function (scorerhi()
(page 853)). The two functions are related as Gi(z) + Hi(z) = Bi(z).
Plots
# Scorer function Gi(x) and Gi(x) on the real line
plot([scorergi, diffun(scorergi)], [-10,10])
851
Examples
Some values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> scorergi(0); 1/(power(3,7/6)*gamma(2/3))
0.2049755424820002450503075
0.2049755424820002450503075
>>> diff(scorergi, 0); 1/(power(3,5/6)*gamma(1/3))
0.1494294524512754526382746
0.1494294524512754526382746
>>> scorergi(+inf); scorergi(-inf)
0.0
0.0
>>> scorergi(1)
0.2352184398104379375986902
>>> scorergi(-1)
-0.1166722172960152826494198
852
0.0000003183098861837906715377675
>>> scorergi(-1000)
-0.08358288400262780392338014
>>> scorergi(-100000)
0.02886866118619660226809581
>>> scorergi(50+10j)
(0.0061214102799778578790984 - 0.001224335676457532180747917j)
>>> scorergi(-50-10j)
(5.236047850352252236372551e+29 - 3.08254224233701381482228e+29j)
>>> scorergi(100000j)
(-8.806659285336231052679025e+6474077 + 8.684731303500835514850962e+6474077j)
References
1.[DLMF] (page 1910) section 9.12: Scorer Functions
scorerhi()
mpmath.scorerhi(z, **kwargs)
Evaluates the second Scorer function
z
Hi(z) = Bi(z)
Ai(t)dt Ai(z)
Bi(t)dt
which gives a particular solution to the inhomogeneous Airy dierential equation f 00 (z)
zf (z) = 1/. See also scorergi() (page 851).
Plots
# Scorer function Hi(x) and Hi(x) on the real line
plot([scorerhi, diffun(scorerhi)], [-10,2], [0,2])
853
854
Examples
Some values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> scorerhi(0); 2/(power(3,7/6)*gamma(2/3))
0.4099510849640004901006149
0.4099510849640004901006149
>>> diff(scorerhi,0); 2/(power(3,5/6)*gamma(1/3))
0.2988589049025509052765491
0.2988589049025509052765491
>>> scorerhi(+inf); scorerhi(-inf)
+inf
0.0
>>> scorerhi(1)
0.9722051551424333218376886
>>> scorerhi(-1)
0.2206696067929598945381098
855
0.0317685352825022727415011
>>> scorerhi(-100)
0.003183092495767499864680483
>>> scorerhi(100j)
(-6.366197716545672122983857e-9 + 0.003183098861710582761688475j)
>>> scorerhi(50+50j)
(-5.322076267321435669290334e+63 + 1.478450291165243789749427e+65j)
>>> scorerhi(-1000-1000j)
(0.0001591549432510502796565538 - 0.000159154943091895334973109j)
f (z) = 0.
z
z2
A second linearly independent solution is given by the irregular Coulomb wave function
Gl (, z) (see coulombg() (page 860)) and thus the general solution is f (z) = C1 Fl (, z) +
C2 Gl (, z) for arbitrary constants C1 , C2 . Physically, the Coulomb wave functions give the
radial solution to the Schrodinger equation for a point particle in a 1/z potential; z is
then the radius and l, are quantum numbers.
The Coulomb wave functions with real parameters are dened in Abramowitz & Stegun,
section 14. However, all parameters are permitted to be complex in this implementation
(see references).
Plots
856
857
Examples
Evaluation is supported for arbitrary magnitudes of z:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> coulombf(2, 1.5, 3.5)
0.4080998961088761187426445
>>> coulombf(-2, 1.5, 3.5)
0.7103040849492536747533465
>>> coulombf(2, 1.5, 1e-10)
4.143324917492256448770769e-33
>>> coulombf(2, 1.5, 1000)
0.4482623140325567050716179
>>> coulombf(2, 1.5, 10**10)
-0.066804196437694360046619
l, eta, z = 2, 3, mpf(2.75)
A, B = 1, 2
f = lambda z: A*coulombf(l,eta,z) + B*coulombg(l,eta,z)
chop(diff(f,z,2) + (1-2*eta/z - l*(l+1)/z**2)*f(z))
858
Some test case with complex parameters, taken from Michel [2]:
>>> mp.dps = 15
>>> coulombf(1+0.1j, 50+50j, 100.156)
(-1.02107292320897e+15 - 2.83675545731519e+15j)
>>> coulombg(1+0.1j, 50+50j, 100.156)
(2.83675545731519e+15 - 1.02107292320897e+15j)
>>> coulombf(1e-5j, 10+1e-5j, 0.1+1e-6j)
(4.30566371247811e-14 - 9.03347835361657e-19j)
>>> coulombg(1e-5j, 10+1e-5j, 0.1+1e-6j)
(778709182061.134 + 18418936.2660553j)
The following reproduces a table in Abramowitz & Stegun, at twice the precision:
>>> mp.dps = 10
>>> eta = 2; z = 5
>>> for l in [5, 4, 3, 2, 1, 0]:
...
print(%s %s %s % (l, coulombf(l,eta,z),
...
diff(lambda z: coulombf(l,eta,z), z)))
...
5 0.09079533488 0.1042553261
4 0.2148205331 0.2029591779
3 0.4313159311 0.320534053
2 0.7212774133 0.3952408216
1 0.9935056752 0.3708676452
0 1.143337392 0.2937960375
References
1.I.J. Thompson & A.R. Barnett, Coulomb and Bessel Functions of Complex Arguments and Order, J. Comp. Phys., vol 64, no. 2, June 1986.
859
2.N. Michel, Precise Coulomb wave functions for a wide range of complex l, and z,
http://arxiv.org/abs/physics/0702051v1
coulombg()
mpmath.coulombg(l, eta, z)
Calculates the irregular Coulomb wave function
Gl (, z) =
Fl (, z) cos() Fl1 (, z)
sin()
860
Examples
Evaluation is supported for arbitrary magnitudes of z:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> coulombg(-2, 1.5, 3.5)
1.380011900612186346255524
>>> coulombg(2, 1.5, 3.5)
1.919153700722748795245926
>>> coulombg(-2, 1.5, 1e-10)
201126715824.7329115106793
>>> coulombg(-2, 1.5, 1000)
0.1802071520691149410425512
>>> coulombg(-2, 1.5, 10**10)
0.652103020061678070929794
The following reproduces a table in Abramowitz & Stegun, at twice the precision:
>>> mp.dps = 10
>>> eta = 2; z = 5
>>> for l in [1, 2, 3, 4, 5]:
...
print(%s %s %s % (l, coulombg(l,eta,z),
...
-diff(lambda z: coulombg(l,eta,z), z)))
...
1 1.08148276 0.6028279961
2 1.496877075 0.5661803178
3 2.048694714 0.7959909551
4 3.09408669 1.731802374
861
5 5.629840456 4.549343289
coulombc()
mpmath.coulombc(l, eta)
Gives the normalizing Gamow constant for Coulomb wave functions,
Cl () = 2l exp (/2 + [ln (1 + l + i) + ln (1 + l i)]/2 ln (2l + 2)) ,
where the log gamma function with continuous imaginary part away from the negative
half axis (see loggamma() (page 783)) is implied.
This function is used internally for the calculation of Coulomb wave functions, and automatically cached to make multiple evaluations with xed l, fast.
Conuent U and Whittaker functions
hyperu()
mpmath.hyperu(a, b, z)
Gives the Tricomi conuent hypergeometric function U , also known as the Kummer or
conuent hypergeometric function of the second kind. This function gives a second linearly independent solution to the conuent hypergeometric dierential equation (the
rst is provided by 1 F1 see hyp1f1() (page 889)).
Examples
Evaluation for arbitrary complex arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> hyperu(2,3,4)
0.0625
>>> hyperu(0.25, 5, 1000)
0.1779949416140579573763523
>>> hyperu(0.25, 5, -1000)
(0.1256256609322773150118907 - 0.1256256609322773150118907j)
862
An integral representation:
>>> a,b,z = 2, 3.5, 4.25
>>> hyperu(a,b,z)
0.06674960718150520648014567
>>> quad(lambda t: exp(-z*t)*t**(a-1)*(1+t)**(b-a-1),[0,inf]) / gamma(a)
0.06674960718150520648014567
Examples
Evaluation for arbitrary real and complex arguments is supported:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> whitm(1, 1, 1)
0.7302596799460411820509668
>>> whitm(1, 1, -1)
(0.0 - 1.417977827655098025684246j)
>>> whitm(j, j/2, 2+3j)
(3.245477713363581112736478 - 0.822879187542699127327782j)
>>> whitm(2, 3, 100000)
4.303985255686378497193063e+21707
Evaluation at zero:
>>> whitm(1,-1,0); whitm(1,-0.5,0); whitm(1,0,0)
+inf
nan
0.0
863
We can verify that whitm() (page 863) numerically satises the dierential equation for
arbitrarily chosen values:
>>>
>>>
>>>
>>>
...
...
0.0
0.0
0.0
0.0
k =
m =
f =
for
mpf(0.25)
mpf(1.5)
lambda z: whitm(k,m,z)
z in [-1, 2.5, 3, 1+2j]:
chop(diff(f,z,2) + (-0.25 + k/z + (0.25-m**2)/z**2)*f(z))
An integral involving both whitm() (page 863) and whitw() (page 864), verifying evaluation along the real axis:
>>> quad(lambda x: exp(-x)*whitm(3,2,x)*whitw(1,-2,x), [0,inf])
3.438869842576800225207341
>>> 128/(21*sqrt(pi))
3.438869842576800225207341
whitw()
mpmath.whitw(k, m, z)
Evaluates the Whittaker function W (k, m, z), which gives a second solution to the Whittaker dierential equation. (See whitm() (page 863).)
Examples
Evaluation for arbitrary real and complex arguments is supported:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> whitw(1, 1, 1)
1.19532063107581155661012
>>> whitw(1, 1, -1)
(-0.9424875979222187313924639 - 0.2607738054097702293308689j)
>>> whitw(j, j/2, 2+3j)
(0.1782899315111033879430369 - 0.01609578360403649340169406j)
>>> whitw(2, 3, 100000)
1.887705114889527446891274e-21705
>>> whitw(-1, -1, 100)
1.905250692824046162462058e-24
Evaluation at zero:
>>> for m in [-1, -0.5, 0, 0.5, 1]:
...
whitw(1, m, 0)
...
+inf
nan
0.0
nan
+inf
We can verify that whitw() (page 864) numerically satises the dierential equation for
arbitrarily chosen values:
864
>>>
>>>
>>>
>>>
...
...
0.0
0.0
0.0
0.0
k =
m =
f =
for
mpf(0.25)
mpf(1.5)
lambda z: whitw(k,m,z)
z in [-1, 2.5, 3, 1+2j]:
chop(diff(f,z,2) + (-0.25 + k/z + (0.25-m**2)/z**2)*f(z))
865
Examples
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> pcfd(0,0); pcfd(1,0); pcfd(2,0); pcfd(3,0)
1.0
0.0
-1.0
0.0
>>> pcfd(4,0); pcfd(-3,0)
3.0
0.6266570686577501256039413
>>> pcfd(1/2, 2+3j)
(-5.363331161232920734849056 - 3.858877821790010714163487j)
>>> pcfd(2, -10)
1.374906442631438038871515e-9
n = mpf(2.5)
y = lambda z: pcfd(n,z)
z = 1.75
chop(diff(y,z,2) + (n+0.5-0.25*z**2)*y(z))
866
pcfu()
mpmath.pcfu(a, z, **kwargs)
Gives the parabolic cylinder function U (a, z), which may be dened for <(z) > 0 in terms
of the conuent U-function (see hyperu() (page 862)) by
(
)
a
1 2
1
a 1 1 1 2
U (a, z) = 2 4 2 e 4 z U
+ , , z
2 4 2 2
or, for arbitrary z,
(
)
)
(
1 2
e 4 z U (a, z) = U (a, 0) 1 F1 a2 + 14 ; 12 ; 12 z 2 + U 0 (a, 0)z 1 F1 a2 + 34 ; 23 ; 12 z 2 .
Examples
Connection to other functions:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> z = mpf(3)
>>> pcfu(0.5,z)
0.03210358129311151450551963
>>> sqrt(pi/2)*exp(z**2/4)*erfc(z/sqrt(2))
0.03210358129311151450551963
>>> pcfu(0.5,-z)
23.75012332835297233711255
>>> sqrt(pi/2)*exp(z**2/4)*erfc(-z/sqrt(2))
23.75012332835297233711255
>>> pcfu(0.5,-z)
23.75012332835297233711255
>>> sqrt(pi/2)*exp(z**2/4)*erfc(-z/sqrt(2))
23.75012332835297233711255
pcfv()
mpmath.pcfv(a, z, **kwargs)
Gives the parabolic cylinder function V (a, z), which can be represented in terms of pcfu()
(page 867) as
V (a, z) =
Examples
Wronskian relation between U and V :
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> a, z = 2, 3
>>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)
0.7978845608028653558798921
>>> sqrt(2/pi)
0.7978845608028653558798921
>>> a, z = 2.5, 3
>>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)
867
0.7978845608028653558798921
>>> a, z = 0.25, -1
>>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)
0.7978845608028653558798921
>>> a, z = 2+1j, 2+3j
>>> chop(pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z))
0.7978845608028653558798921
pcfw()
mpmath.pcfw(a, z, **kwargs)
Gives the parabolic cylinder function W (a, z) dened in (DLMF 12.14).
Examples
Value at the origin:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> a = mpf(0.25)
>>> pcfw(a,0)
0.9722833245718180765617104
>>> power(2,-0.75)*sqrt(abs(gamma(0.25+0.5j*a)/gamma(0.75+0.5j*a)))
0.9722833245718180765617104
>>> diff(pcfw,(a,0),(0,1))
-0.5142533944210078966003624
>>> -power(2,-0.25)*sqrt(abs(gamma(0.75+0.5j*a)/gamma(0.25+0.5j*a)))
-0.5142533944210078966003624
Orthogonal polynomials
cn 6= 0 if m = n
Pn (x)Pm (x)w(x)dx =
0
if m 6= n
S
where S is some domain (e.g. an interval [a, b] R) and w(x) is a xed weight function. A
sequence of orthogonal polynomials is determined completely by w, S, and a normalization
convention (e.g. cn = 1). Applications of orthogonal polynomials include function approximation and solution of dierential equations.
Orthogonal polynomials are sometimes dened using the dierential equations they satisfy
(as functions of x) or the recurrence relations they satisfy with respect to the order n. Other
ways of dening orthogonal polynomials include dierentiation formulas and generating functions. The standard orthogonal polynomials can also be represented as hypergeometric series
(see Hypergeometric functions (page 888)), more specically using the Gauss hypergeometric function 2 F1 in most cases. The following functions are generally implemented using
hypergeometric functions since this is computationally ecient and easily generalizes.
For more information, see the Wikipedia article on orthogonal polynomials.
Legendre functions
868
legendre()
mpmath.legendre(n, x)
legendre(n, x) evaluates the Legendre polynomial Pn (x). The Legendre polynomials
are given by the formula
Pn (x) =
1 dn 2
(x 1)n .
2n n! dxn
869
Basic evaluation
The Legendre polynomials assume xed values at the points x = 1 and x = 1:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> nprint([legendre(n, 1) for n in range(6)])
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
>>> nprint([legendre(n, -1) for n in range(6)])
[1.0, -1.0, 1.0, -1.0, 1.0, -1.0]
The coecients of Legendre polynomials can be recovered using degree-n Taylor expansion:
>>> for n in range(5):
...
nprint(chop(taylor(lambda x: legendre(n, x), 0, n)))
...
[1.0]
[0.0, 1.0]
[-0.5, 0.0, 1.5]
[0.0, -1.5, 0.0, 2.5]
[0.375, 0.0, -3.75, 0.0, 4.375]
The roots of Legendre polynomials are located symmetrically on the interval [1, 1]:
>>> for n in range(5):
...
nprint(polyroots(taylor(lambda x: legendre(n, x), 0, n)[::-1]))
...
[]
[0.0]
[-0.57735, 0.57735]
[-0.774597, 0.0, 0.774597]
[-0.861136, -0.339981, 0.339981, 0.861136]
Orthogonality
The Legendre polynomials are orthogonal on [1, 1] with respect to the trivial weight
w(x) = 1. That is, Pm (x)Pn (x) integrates to zero if m 6= n and to 2/(2n + 1) if m = n:
>>> m, n = 3, 4
>>> quad(lambda x: legendre(m,x)*legendre(n,x), [-1, 1])
0.0
>>> m, n = 4, 4
>>> quad(lambda x: legendre(m,x)*legendre(n,x), [-1, 1])
0.222222222222222
Dierential equation
The Legendre polynomials satisfy the dierential equation
((1 x2 )y 0 )0 + n(n + 1)y 0 = 0.
We can verify this numerically:
>>> n = 3.6
>>> x = 0.73
>>> P = legendre
870
legenp()
mpmath.legenp(n, m, z, type=2)
Calculates the (associated) Legendre function of the rst kind of degree n and order m,
Pnm (z). Taking m = 0 gives the ordinary Legendre function of the rst kind, Pn (z). The
parameters may be complex numbers.
In terms of the Gauss hypergeometric function, the (associated) Legendre function is
dened as
)
(
1
(1 + z)m/2
1z
Pnm (z) =
F
n,
n
+
1,
1
m,
.
2 1
(1 m) (1 z)m/2
2
With type=3 instead of type=2, the alternative denition
(
)
1
(z + 1)m/2
1z
m
Pn (z) =
.
2 F1 n, n + 1, 1 m,
(1 m) (z 1)m/2
2
is used. These functions correspond respectively to LegendreP[n,m,2,z] and LegendreP[n,m,3,z] in Mathematica.
The general solution of the (associated) Legendre dierential equation
(
)
m2
2 00
0
(1 z )f (z) 2zf (z) + n(n + 1)
f (z) = 0
1 z2
m
is given by C1 Pnm (z) + C2 Qm
n (z) for arbitrary constants C1 , C2 , where Qn (z) is a Legendre
function of the second kind as implemented by legenq() (page 872).
Examples
Evaluation for arbitrary parameters and arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> legenp(2, 0, 10); legendre(2, 10)
149.5
149.5
>>> legenp(-2, 0.5, 2.5)
(1.972260393822275434196053 - 1.972260393822275434196053j)
>>> legenp(2+3j, 1-j, -0.5+4j)
(-3.335677248386698208736542 - 5.663270217461022307645625j)
>>> chop(legenp(3, 2, -1.5, type=2))
28.125
>>> chop(legenp(3, 2, -1.5, type=3))
-28.125
n, m = 2, -0.5
C1, C2 = 1, -3
f = lambda z: C1*legenp(n,m,z) + C2*legenq(n,m,z)
deq = lambda z: (1-z**2)*diff(f,z,2) - 2*z*diff(f,z) + \
(n*(n+1)-m**2/(1-z**2))*f(z)
for z in [0, 2, -1.5, 0.5+2j]:
871
...
...
0.0
0.0
0.0
0.0
chop(deq(mpmathify(z)))
legenq()
mpmath.legenq(n, m, z, type=2)
Calculates the (associated) Legendre function of the second kind of degree n and order
m, Qm
n (z). Taking m = 0 gives the ordinary Legendre function of the second kind, Qn (z).
The parameters may complex numbers.
The Legendre functions of the second kind give a second set of solutions to the (associated) Legendre dierential equation. (See legenp() (page 871).) Unlike the Legendre
functions of the rst kind, they are not polynomials of z for integer n, m but rational or
logarithmic functions with poles at z = 1.
There are various ways to dene Legendre functions of the second kind, giving rise to
dierent complex structure. A version can be selected using the type keyword argument.
The type=2 and type=3 functions are given respectively by
(
)
(1 + m + n) m
m
Qm
(z)
=
cos(m)P
(z)
P
(z)
n
n
2 sin(m)
(1 m + n) n
)
(
(1 + m + n) m
m
im
m
(z)
(z)
(z)
=
P
P
Q
e
n
n
2 sin(m)
(1 m + n) n
where P and P are the type=2 and type=3 Legendre functions of the rst kind. The
formulas above should be understood as limits when m is an integer.
These functions correspond to LegendreQ[n,m,2,z] (or LegendreQ[n,m,z]) and LegendreQ[n,m,3,z] in Mathematica. The type=3 function is essentially the same as the
function dened in Abramowitz & Stegun (eq. 8.1.3) but with (z + 1)m/2 (z 1)m/2 instead
of (z 2 1)m/2 , giving slightly dierent branches.
Examples
Evaluation for arbitrary parameters and arguments:
>>> from sympy.mpmath import
>>> mp.dps = 25; mp.pretty =
>>> legenq(2, 0, 0.5)
-0.8186632680417568557122028
>>> legenq(-1.5, -2, 2.5)
(0.6655964618250228714288277
>>> legenq(2-j, 3+4j, -6+5j)
(-10001.95256487468541686564
*
True
+ 0.3937692045497259717762649j)
- 6011.691337610097577791134j)
872
Chebyshev polynomials
chebyt()
mpmath.chebyt(n, x)
chebyt(n, x) evaluates the Chebyshev polynomial of the rst kind Tn (x), dened by the
identity
Tn (cos x) = cos(nx).
The Chebyshev polynomials of the rst kind are a special case of the Jacobi polynomials,
and by extension of the hypergeometric function 2 F1 . They can thus also be evaluated
for nonintegral n.
Plots
# Chebyshev polynomials T_n(x) on [-1,1] for n=0,1,2,3,4
f0 = lambda x: chebyt(0,x)
f1 = lambda x: chebyt(1,x)
f2 = lambda x: chebyt(2,x)
f3 = lambda x: chebyt(3,x)
f4 = lambda x: chebyt(4,x)
plot([f0,f1,f2,f3,f4],[-1,1])
Basic evaluation
The coecients of the n-th polynomial can be recovered using using degree-n Taylor
expansion:
873
Orthogonality
The Chebyshev polynomials of the rstkind are orthogonal on the interval [1, 1] with
respect to the weight function w(x) = 1/ 1 x2 :
>>> f = lambda x: chebyt(m,x)*chebyt(n,x)/sqrt(1-x**2)
>>> m, n = 3, 4
>>> nprint(quad(f, [-1, 1]),1)
0.0
>>> m, n = 4, 4
>>> quad(f, [-1, 1])
1.57079632596448
chebyu()
mpmath.chebyu(n, x)
chebyu(n, x) evaluates the Chebyshev polynomial of the second kind Un (x), dened by
the identity
Un (cos x) =
sin((n + 1)x)
.
sin(x)
The Chebyshev polynomials of the second kind are a special case of the Jacobi polynomials, and by extension of the hypergeometric function 2 F1 . They can thus also be
evaluated for nonintegral n.
Plots
# Chebyshev polynomials U_n(x) on [-1,1] for n=0,1,2,3,4
f0 = lambda x: chebyu(0,x)
f1 = lambda x: chebyu(1,x)
f2 = lambda x: chebyu(2,x)
f3 = lambda x: chebyu(3,x)
f4 = lambda x: chebyu(4,x)
plot([f0,f1,f2,f3,f4],[-1,1])
874
Basic evaluation
The coecients of the n-th polynomial can be recovered using using degree-n Taylor
expansion:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> for n in range(5):
...
nprint(chop(taylor(lambda x: chebyu(n, x), 0, n)))
...
[1.0]
[0.0, 2.0]
[-1.0, 0.0, 4.0]
[0.0, -4.0, 0.0, 8.0]
[1.0, 0.0, -12.0, 0.0, 16.0]
Orthogonality
The Chebyshev polynomials of the second
kind are orthogonal on the interval [1, 1] with
respect to the weight function w(x) = 1 x2 :
>>> f = lambda x: chebyu(m,x)*chebyu(n,x)*sqrt(1-x**2)
>>> m, n = 3, 4
>>> quad(f, [-1, 1])
0.0
>>> m, n = 4, 4
>>> quad(f, [-1, 1])
1.5707963267949
875
Jacobi polynomials
jacobi()
mpmath.jacobi(n, a, b, z)
(a,b)
jacobi(n, a, b, x) evaluates the Jacobi polynomial Pn (x). The Jacobi polynomials
are a special case of the hypergeometric function 2 F1 given by:
(
)
(
)
n+a
1x
(a,b)
Pn (x) =
.
2 F1 n, 1 + a + b + n, a + 1,
n
2
Note that this denition generalizes to nonintegral values of n. When n is an integer, the
hypergeometric series terminates after a nite number of terms, giving a polynomial in
x.
Evaluation of Jacobi polynomials
(
)
(a,b)
A special evaluation is Pn (1) = n+a
n :
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> jacobi(4, 0.5, 0.25, 1)
2.4609375
>>> binomial(4+0.5, 4)
2.4609375
A Jacobi polynomial of degree n is equal to its Taylor polynomial of degree n. The explicit coecients of Jacobi polynomials can therefore be recovered easily using taylor()
(page 1015):
>>> for n in range(5):
...
nprint(taylor(lambda x: jacobi(n,1,2,x), 0, n))
...
[1.0]
[-0.5, 2.5]
[-0.75, -1.5, 5.25]
[0.5, -3.5, -3.5, 10.5]
[0.625, 2.5, -11.25, -7.5, 20.625]
Orthogonality
The Jacobi polynomials are orthogonal on the interval [1, 1] with respect to the weight
(a,b)
(a,b)
function w(x) = (1 x)a (1 + x)b . That is, w(x)Pn (x)Pm (x) integrates to zero if m 6= n and
to a nonzero number if m = n.
The orthogonality is easy to verify using numerical quadrature:
>>>
>>>
>>>
>>>
>>>
>>>
0.0
>>>
876
P = jacobi
f = lambda x: (1-x)**a * (1+x)**b * P(m,a,b,x) * P(n,a,b,x)
a = 2
b = 3
m, n = 3, 4
chop(quad(f, [-1, 1]), 1)
m, n = 4, 4
Dierential equation
The Jacobi polynomials are solutions of the dierential equation
(1 x2 )y 00 + (b a (a + b + 2)x)y 0 + n(n + a + b + 1)y = 0.
We can verify that jacobi() (page 876) approximately satises this equation:
>>> from sympy.mpmath import *
>>> mp.dps = 15
>>> a = 2.5
>>> b = 4
>>> n = 3
>>> y = lambda x: jacobi(n,a,b,x)
>>> x = pi
>>> A0 = n*(n+a+b+1)*y(x)
>>> A1 = (b-a-(a+b+2)*x)*diff(y,x)
>>> A2 = (1-x**2)*diff(y,x,2)
>>> nprint(A2 + A1 + A0, 1)
4.0e-12
The dierence of order 1012 is as close to zero as it could be at 15-digit working precision, since the terms are large:
>>> A0, A1, A2
(26560.2328981879, -21503.7641037294, -5056.46879445852)
Gegenbauer polynomials
gegenbauer()
mpmath.gegenbauer(n, a, z)
Evaluates the Gegenbauer polynomial, or ultraspherical polynomial,
(
)
(
)
n + 2a 1
1 1
(a)
Cn (z) =
2 F1 n, n + 2a; a + ; (1 z) .
n
2 2
When n is a nonnegative integer, this formula gives a polynomial in z of degree n, but
all parameters are permitted to be complex numbers. With a = 1/2, the Gegenbauer
polynomial reduces to a Legendre polynomial.
Examples
Evaluation for arbitrary arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> gegenbauer(3, 0.5, -10)
-2485.0
>>> gegenbauer(1000, 10, 100)
3.012757178975667428359374e+2322
>>> gegenbauer(2+3j, -0.75, -1000j)
(-5038991.358609026523401901 + 9414549.285447104177860806j)
877
>>> gegenbauer(-4,
-1.0
>>> gegenbauer(-4,
0.0
>>> gegenbauer(-4,
0.0
>>> gegenbauer(-7,
8989.0
2, 1.75)
3, 1.75)
2j, 1.75)
0.5, 3)
The Gegenbauer polynomials are orthogonal on [1, 1] with respect to the weight (1
1
z 2 )a 2 :
>>>
>>>
>>>
>>>
0.0
a, n, m = 2.5, 4, 5
Cn = lambda z: gegenbauer(n, a, z, zeroprec=1000)
Cm = lambda z: gegenbauer(m, a, z, zeroprec=1000)
chop(quad(lambda z: Cn(z)*Cm(z)*(1-z**2)*(a-0.5), [-1, 1]))
Hermite polynomials
hermite()
mpmath.hermite(n, z)
Evaluates the Hermite polynomial Hn (z), which may be dened using the recurrence
H0 (z) = 1
H1 (z) = 2z
Hn+1 = 2zHn (z) 2nHn1 (z).
The Hermite polynomials are orthogonal on (, ) with respect to the weight ez .
More generally, allowing arbitrary complex values of n, the Hermite function Hn (z) is
dened as
)
(
1
n 1n
, 2
Hn (z) = (2z)n 2 F0 ,
2
2
z
2
878
(
)
(
))
n 1 2
2z
1n 3 2
(
) 1 F1 , , z ( n ) 1 F1
, ,z
.
2 2
2
2
1n
2
2
1
Plots
# Hermite polynomials H_n(x) on the real line for n=0,1,2,3,4
f0 = lambda x: hermite(0,x)
f1 = lambda x: hermite(1,x)
f2 = lambda x: hermite(2,x)
f3 = lambda x: hermite(3,x)
f4 = lambda x: hermite(4,x)
plot([f0,f1,f2,f3,f4],[-2,2],[-25,25])
Examples
Evaluation for arbitrary arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> hermite(0, 10)
1.0
>>> hermite(1, 10); hermite(2, 10)
20.0
398.0
>>> hermite(10000, 2)
4.950440066552087387515653e+19334
>>> hermite(3, -10**8)
879
-7999999999999998800000000.0
>>> hermite(-3, -10**8)
1.675159751729877682920301e+4342944819032534
>>> hermite(2+3j, -1+2j)
(-0.07652130602993513389421901 - 0.1084662449961914580276007j)
Values at z = 0:
>>> for n in range(-5, 9):
...
hermite(n, 0)
...
0.02769459142039868792653387
0.08333333333333333333333333
0.2215567313631895034122709
0.5
0.8862269254527580136490837
1.0
0.0
-2.0
0.0
12.0
0.0
-120.0
0.0
1680.0
n = 4
f = lambda z: hermite(n, z)
z = 1.5
chop(diff(f,z,2) - 2*z*diff(f,z) + 2*n*f(z))
Verifying orthogonality:
>>> chop(quad(lambda t: hermite(2,t)*hermite(4,t)*exp(-t**2), [-inf,inf]))
0.0
Laguerre polynomials
laguerre()
880
mpmath.laguerre(n, a, z)
Gives the generalized (associated) Laguerre polynomial, dened by
Lan (z) =
(n + b + 1)
1 F1 (n, a + 1, z).
(b + 1)(n + 1)
Examples
Evaluation for arbitrary arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> laguerre(5, 0, 0.25)
0.03726399739583333333333333
>>> laguerre(1+j, 0.5, 2+3j)
881
(4.474921610704496808379097 - 11.02058050372068958069241j)
>>> laguerre(2, 0, 10000)
49980001.0
>>> laguerre(2.5, 0, 10000)
-9.327764910194842158583189e+4328
Verifying orthogonality:
>>>
>>>
>>>
>>>
0.0
Lm = lambda t: laguerre(m,a,t)
Ln = lambda t: laguerre(n,a,t)
a, n, m = 2.5, 2, 3
chop(quad(lambda t: exp(-t)*t**a*Lm(t)*Ln(t), [0,inf]))
Spherical harmonics
spherharm()
mpmath.spherharm(l, m, theta, phi)
Evaluates the spherical harmonic Ylm (, ),
2l + 1 (l m)! m
m
Yl (, ) =
P (cos )eim
4 (l + m)! l
where Plm is an associated Legendre function (see legenp() (page 871)).
Here [0, ] denotes the polar coordinate (ranging from the north pole to the south
pole) and [0, 2] denotes the azimuthal coordinate on a sphere. Care should be used
since many dierent conventions for spherical coordinate variables are used.
Usually spherical harmonics are considered for l N, m Z, |m| l. More generally,
l, m, , are permitted to be complex numbers.
Note: spherharm() (page 882) returns a complex number, even the value is purely real.
Plots
# Real part of spherical harmonic Y_(4,0)(theta,phi)
def Y(l,m):
def g(theta,phi):
R = abs(fp.re(fp.spherharm(l,m,theta,phi)))
x = R*fp.cos(phi)*fp.sin(theta)
y = R*fp.sin(phi)*fp.sin(theta)
z = R*fp.cos(theta)
882
return [x,y,z]
return g
fp.splot(Y(4,0), [0,fp.pi], [0,2*fp.pi], points=300)
# fp.splot(Y(4,0), [0,fp.pi], [0,2*fp.pi], points=300)
# fp.splot(Y(4,1), [0,fp.pi], [0,2*fp.pi], points=300)
# fp.splot(Y(4,2), [0,fp.pi], [0,2*fp.pi], points=300)
# fp.splot(Y(4,3), [0,fp.pi], [0,2*fp.pi], points=300)
Y4,0 :
Y4,1 :
883
Y4,2 :
884
Y4,3 :
885
Y4,4 :
886
Examples
Some low-order spherical harmonics with reference values:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> theta = pi/4
>>> phi = pi/3
>>> spherharm(0,0,theta,phi); 0.5*sqrt(1/pi)*expj(0)
(0.2820947917738781434740397 + 0.0j)
(0.2820947917738781434740397 + 0.0j)
>>> spherharm(1,-1,theta,phi); 0.5*sqrt(3/(2*pi))*expj(-phi)*sin(theta)
(0.1221506279757299803965962 - 0.2115710938304086076055298j)
(0.1221506279757299803965962 - 0.2115710938304086076055298j)
>>> spherharm(1,0,theta,phi); 0.5*sqrt(3/pi)*cos(theta)*expj(0)
(0.3454941494713354792652446 + 0.0j)
(0.3454941494713354792652446 + 0.0j)
>>> spherharm(1,1,theta,phi); -0.5*sqrt(3/(2*pi))*expj(phi)*sin(theta)
(-0.1221506279757299803965962 - 0.2115710938304086076055298j)
(-0.1221506279757299803965962 - 0.2115710938304086076055298j)
With the normalization convention used, the spherical harmonics are orthonormal on the
unit sphere:
>>>
>>>
>>>
>>>
sphere = [0,pi],
dS = lambda t,p:
Y1 = lambda t,p:
Y2 = lambda t,p:
[0,2*pi]
fp.sin(t)
# differential element
fp.spherharm(l1,m1,t,p)
fp.conj(fp.spherharm(l2,m2,t,p))
887
>>> l1 = l2 = 3; m1 = m2 = 2
>>> print(fp.quad(lambda t,p: Y1(t,p)*Y2(t,p)*dS(t,p), *sphere))
(1+0j)
>>> m2 = 1
# m1 != m2
>>> print(fp.chop(fp.quad(lambda t,p: Y1(t,p)*Y2(t,p)*dS(t,p), *sphere)))
0.0
Hypergeometric functions
The functions listed in Exponential integrals and error functions (page 794), Bessel functions and related functions (page 809) and Orthogonal polynomials (page 868), and many
other functions as well, are merely particular instances of the generalized hypergeometric
function p Fq . The functions listed in the following section enable ecient direct evaluation
of the underlying hypergeometric series, as well as linear combinations, limits with respect
to parameters, and analytic continuations thereof. Extensions to twodimensional series are
also provided. See also the basic or q-analog of the hypergeometric series in q-functions
(page 968).
For convenience, most of the hypergeometric series of low order are provided as standalone
functions. They can equivalently be evaluated using hyper() (page 895). As will be demonstrated in the respective docstrings, all the hyp#f# functions implement analytic continuations
and/or asymptotic expansions with respect to the argument z, thereby permitting evaluation
for z anywhere in the complex plane. Functions of higher degree can be computed via hyper()
(page 895), but generally only in rapidly convergent instances.
Most hypergeometric and hypergeometric-derived functions accept optional keyword arguments to specify options for hypercomb() or hyper(). Some useful options are maxprec,
maxterms, zeroprec, accurate small, hmag, force series, asymp tol and eliminate. These options give control over what to do in case of slow convergence, extreme loss of accuracy
or evaluation at zeros (these two cases cannot generally be distinguished from each other
automatically), and singular parameter combinations.
Common hypergeometric series
hyp0f1()
mpmath.hyp0f1(a, z)
Gives the hypergeometric function 0 F1 , sometimes known as the conuent limit function,
dened as
0 F1 (a, z)
1 zk
.
(a)k k!
k=0
This function satises the dierential equation zf 00 (z) + af 0 (z) = f (z), and is related to the
Bessel function of the rst kind (see besselj() (page 810)).
888
hyp1f1()
mpmath.hyp1f1(a, b, z)
Gives the conuent hypergeometric function of the rst kind,
1 F1 (a, b, z)
(a)k z k
,
(b)k k!
k=0
also known as Kummers function and sometimes denoted by M (a, b, z). This function
gives one solution to the conuent (Kummers) dierential equation
zf 00 (z) + (b z)f 0 (z) af (z) = 0.
A second solution is given by the U function; see hyperu() (page 862). Solutions are
also given in an alternate form by the Whittaker functions (whitm() (page 863), whitw()
(page 864)).
hyp1f1(a,b,z) is equivalent to hyper([a],[b],z); see documentation for hyper()
(page 895) for more information.
Examples
Evaluation for real and complex values of the argument z, with xed parameters a =
2, b = 1/3:
889
An integral representation:
>>> a, b = 1.5, 3
>>> z = 1.5
>>> hyp1f1(a,b,z)
2.269381460919952778587441
>>> g = lambda t: exp(z*t)*t**(a-1)*(1-t)**(b-a-1)
>>> gammaprod([b],[a,b-a])*quad(g, [0,1])
2.269381460919952778587441
hyp1f2()
mpmath.hyp1f2(a1, b1, b2, z)
Gives the hypergeometric function 1 F2 (a1 , a2 ; b1 , b2 ; z). The call hyp1f2(a1,b1,b2,z) is
equivalent to hyper([a1],[b1,b2],z).
Evaluation works for complex and arbitrarily large arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
890
hyp2f0()
mpmath.hyp2f0(a, b, z)
Gives the hypergeometric function 2 F0 , dened formally by the series
2 F0 (a, b; ; z)
n=0
(a)n (b)n
zn
.
n!
This series usually does not converge. For small enough z, it can be viewed as an asymptotic series that may be summed directly with an appropriate truncation. When this is
not the case, hyp2f0() (page 891) gives a regularized sum, or equivalently, it uses a
representation in terms of the hypergeometric U function [1]. The series also converges
when either a or b is a nonpositive integer, as it then terminates into a polynomial after
a or b terms.
Examples
Evaluation is supported for arbitrary complex arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> hyp2f0((2,3), 1.25, -100)
0.07095851870980052763312791
>>> hyp2f0((2,3), 1.25, 100)
(-0.03254379032170590665041131 + 0.07269254613282301012735797j)
>>> hyp2f0(-0.75, 1-j, 4j)
(-0.3579987031082732264862155 - 3.052951783922142735255881j)
Even with real arguments, the regularized value of 2F0 is often complex-valued, but the
imaginary part decreases exponentially as z 0. In the following example, the rst call
uses complex evaluation while the second has a small enough z to evaluate using the
direct series and thus the returned value is strictly real (this should be taken to indicate
that the imaginary part is less than eps):
>>> mp.dps = 15
>>> hyp2f0(1.5, 0.5, 0.05)
(1.04166637647907 + 8.34584913683906e-8j)
>>> hyp2f0(1.5, 0.5, 0.0005)
1.00037535207621
In the polynomial case (the series terminating), 2F0 can evaluate exactly:
891
>>> mp.dps = 15
>>> hyp2f0(-6,-6,2)
291793.0
>>> identify(hyp2f0(-2,1,0.25))
(5/8)
0, 10))
0.0, 0.0, 0.0]
0, 10))
0.0, 0.0, 0.0]
(a)k (b)k z k
.
(c)k k!
k=0
and for |z| 1 by analytic continuation, with a branch cut on (1, ) when necessary.
Special cases of this function include many of the orthogonal polynomials as well as the
incomplete beta function and other functions. Properties of the Gauss hypergeometric
function are documented comprehensively in many references, for example Abramowitz
& Stegun, section 15.
The implementation supports the analytic continuation as well as evaluation close
to the unit circle where |z| 1. The syntax hyp2f1(a,b,c,z) is equivalent to hyper([a,b],[c],z).
Examples
Evaluation with z inside, outside and on the unit circle, for xed parameters:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> hyp2f1(2, (1,2), 4, 0.75)
1.303703703703703703703704
>>> hyp2f1(2, (1,2), 4, -1.75)
0.7431290566046919177853916
>>> hyp2f1(2, (1,2), 4, 1.75)
(1.418075801749271137026239 - 1.114976146679907015775102j)
>>> hyp2f1(2, (1,2), 4, 1)
1.6
>>> hyp2f1(2, (1,2), 4, -1)
0.8235498012182875315037882
>>> hyp2f1(2, (1,2), 4, j)
(0.9144026291433065674259078 + 0.2050415770437884900574923j)
>>> hyp2f1(2, (1,2), 4, 2+j)
(0.9274013540258103029011549 + 0.7455257875808100868984496j)
>>> hyp2f1(2, (1,2), 4, 0.25j)
(0.9931169055799728251931672 + 0.06154836525312066938147793j)
892
Evaluation with z = 1:
>>> hyp2f1(-2.5, 3.5, 1.5, 1)
0.0
>>> hyp2f1(-2.5, 3, 4, 1)
0.06926406926406926406926407
>>> hyp2f1(2, 3, 4, 1)
+inf
An integral representation:
>>> a,b,c,z = -0.5, 1, 2.5, 0.25
>>> g = lambda t: t**(b-1) * (1-t)**(c-b-1) * (1-t*z)**(-a)
>>> gammaprod([c],[b,c-b]) * quad(g, [0,1])
0.9480458814362824478852618
>>> hyp2f1(a,b,c,z)
0.9480458814362824478852618
hyp2f2()
mpmath.hyp2f2(a1, a2, b1, b2, z)
Gives the hypergeometric function 2 F2 (a1 , a2 ; b1 , b2 ; z). The call hyp2f2(a1,a2,b1,b2,z)
is equivalent to hyper([a1,a2],[b1,b2],z).
Evaluation works for complex and arbitrarily large arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> a, b, c, d = 1.5, (-1,3), 2.25, 4
>>> hyp2f2(a, b, c, d, 10**20)
-5.275758229007902299823821e+43429448190325182663
>>> hyp2f2(a, b, c, d, -10**20)
2561445.079983207701073448
>>> hyp2f2(a, b, c, d, 10**20*j)
(2218276.509664121194836667 - 1280722.539991603850462856j)
>>> hyp2f2(2+3j, -2j, 0.5j, 4j, 10-20j)
(80500.68321405666957342788 - 20346.82752982813540993502j)
hyp2f3()
893
call
hyp3f2()
mpmath.hyp3f2(a1, a2, a3, b1, b2, z)
Gives the generalized hypergeometric function 3 F2 , dened for |z| < 1 as
3 F2 (a1 , a2 , a3 , b1 , b2 , z) =
k=0
and for |z| 1 by analytic continuation. The analytic structure of this function is similar
to that of 2 F1 , generally with a singularity at z = 1 and a branch cut on (1, ).
Evaluation is supported inside, on, and outside the circle of convergence |z| = 1:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> hyp3f2(1,2,3,4,5,0.25)
1.083533123380934241548707
>>> hyp3f2(1,2+2j,3,4,5,-10+10j)
(0.1574651066006004632914361 - 0.03194209021885226400892963j)
>>> hyp3f2(1,2,3,4,5,-10)
0.3071141169208772603266489
>>> hyp3f2(1,2,3,4,5,10)
(-0.4857045320523947050581423 - 0.5988311440454888436888028j)
>>> hyp3f2(0.25,1,1,2,1.5,1)
1.157370995096772047567631
>>> (8-pi-2*ln2)/3
1.157370995096772047567631
>>> hyp3f2(1+j,0.5j,2,1,-2j,-1)
(1.74518490615029486475959 + 0.1454701525056682297614029j)
>>> hyp3f2(1+j,0.5j,2,1,-2j,sqrt(j))
(0.9829816481834277511138055 - 0.4059040020276937085081127j)
>>> hyp3f2(-3,2,1,-5,4,1)
1.41
>>> hyp3f2(-3,2,1,-5,4,2)
2.12
894
>>> hyp3f2(1,2,3,4,5,1.0001)
(1.564877796743282766872279 - 3.76821518787438186031973e-11j)
>>> hyp3f2(1,2,3,4,5,1+0.0001j)
(1.564747153061671573212831 + 0.0001305757570366084557648482j)
>>> hyp3f2(1,2,3,4,5,0.9999)
1.564616644881686134983664
>>> hyp3f2(1,2,3,4,5,-0.9999)
0.7823896253461678060196207
Note: Evaluation for |z1| small can currently be inaccurate or slow for some parameter
combinations.
For various parameter combinations, 3 F2 admits representation in terms of hypergeometric functions of lower degree, or in terms of simpler functions:
>>> for a, b, z in [(1,2,-1), (2,0.5,1)]:
...
hyp2f1(a,b,a+b+0.5,z)**2
...
hyp3f2(2*a,a+b,2*b,a+b+0.5,2*a+2*b,z)
...
0.4246104461966439006086308
0.4246104461966439006086308
7.111111111111111111111111
7.111111111111111111111111
>>> z = 2+3j
>>> hyp3f2(0.5,1,1.5,2,2,z)
(0.7621440939243342419729144 + 0.4249117735058037649915723j)
>>> 4*(pi-2*ellipe(z))/(pi*z)
(0.7621440939243342419729144 + 0.4249117735058037649915723j)
where (x)n denotes the rising factorial (see rf() (page 784)).
The parameters lists a s and b s may contain integers, real numbers, complex numbers,
as well as exact fractions given in the form of tuples (p, q). hyper() (page 895) is optimized to handle integers and fractions more eciently than arbitrary oating-point
parameters (since rational parameters are by far the most common).
Examples
Verifying that hyper() (page 895) gives the sum in the denition, by comparison with
nsum() (page 979):
>>>
>>>
>>>
>>>
895
>>> hyper([a,b],[c,d],x)
1.078903941164934876086237
>>> fn = lambda n: rf(a,n)*rf(b,n)/rf(c,n)/rf(d,n)*x**n/fac(n)
>>> nsum(fn, [0, inf])
1.078903941164934876086237
The parameters can be any combination of integers, fractions, oats and complex numbers:
>>> a, b, c, d, e = 1, (-1,2), pi, 3+4j, (2,3)
>>> x = 0.2j
>>> hyper([a,b],[c,d,e],x)
(0.9923571616434024810831887 - 0.005753848733883879742993122j)
>>> b, e = -0.5, mpf(2)/3
>>> fn = lambda n: rf(a,n)*rf(b,n)/rf(c,n)/rf(d,n)/rf(e,n)*x**n/fac(n)
>>> nsum(fn, [0, inf])
(0.9923571616434024810831887 - 0.005753848733883879742993122j)
If any ak coecient is a nonpositive integer, the series terminates into a nite polynomial:
>>> hyper([1,1,1,-3],[2,5],1)
0.7904761904761904761904762
>>> identify(_)
(83/105)
If any bk is a nonpositive integer, the function is undened (unless the series terminates
before the division by zero occurs):
>>> hyper([1,1,1,-3],[-2,5],1)
Traceback (most recent call last):
...
ZeroDivisionError: pole in hypergeometric series
>>> hyper([1,1,1,-1],[-2,5],1)
1.1
Traceback (most recent call last):
...
ZeroDivisionError: pole in hypergeometric series
Except for polynomial cases, the radius of convergence R of the hypergeometric series
is either R = (if p q), R = 1 (if p = q + 1), or R = 0 (if p > q + 1).
The analytic continuations of the functions with p = q + 1, i.e. 2 F1 , 3 F2 , 4 F3 , etc, are all
implemented and therefore these functions can be evaluated for |z| 1. The shortcuts
hyp2f1() (page 892), hyp3f2() (page 894) are available to handle the most common
cases (see their documentation), but functions of higher degree are also supported via
hyper() (page 895):
896
Please note that, as currently implemented, evaluation of p Fp1 with p 3 may be slow
or inaccurate when |z 1| is small, for some parameter values.
When p > q + 1, hyper computes the (iterated) Borel sum of the divergent series. For 2 F0
the Borel sum has an analytic solution and can be computed eciently (see hyp2f0()
(page 891)). For higher degrees, the functions is evaluated rst by attempting to sum
it directly as an asymptotic series (this only works for tiny |z|), and then by evaluating
the Borel regularized sum using numerical integration. Except for special parameter
combinations, this can be extremely slow.
>>> hyper([1,1], [], 0.5)
# regularization of 2F0
(1.340965419580146562086448 + 0.8503366631752726568782447j)
>>> hyper([1,1,1,1], [1], 0.5)
# regularization of 4F1
(1.108287213689475145830699 + 0.5327107430640678181200491j)
With the following magnitude of argument, the asymptotic series for 3 F1 gives only a few
digits. Using Borel summation, hyper can produce a value with full accuracy:
>>> mp.dps = 15
>>> hyper([2,0.5,4], [5.25], 0.08, force_series=True)
Traceback (most recent call last):
...
NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms.
>>> hyper([2,0.5,4], [5.25], 0.08, asymp_tol=1e-4)
1.0725535790737
>>> hyper([2,0.5,4], [5.25], 0.08)
(1.07269542893559 + 5.54668863216891e-5j)
>>> hyper([2,0.5,4], [5.25], -0.08, asymp_tol=1e-4)
0.946344925484879
>>> hyper([2,0.5,4], [5.25], -0.08)
0.946312503737771
>>> mp.dps = 25
>>> hyper([2,0.5,4], [5.25], -0.08)
0.9463125037377662296700858
Traceback (most recent call last):
...
NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms.
Note that with the positive z value, there is a complex part in the correct result, which
falls below the tolerance of the asymptotic series.
5.15. Welcome to mpmaths documentation!
897
hypercomb()
mpmath.hypercomb(ctx, function, params=[], discard known zeros=True, **kwargs)
Computes a weighted combination of hypergeometric functions
[l
]
mr
N
r
(r,k )
cr,k
k=1
n r
wr,k
pr Fqr (ar,1 , . . . , ar,p ; br,1 , . . . , br,q ; zr ) .
k=1 (r,k )
r=1
k=1
Typically the parameters are linear combinations of a small set of base parameters; hypercomb() (page 898) permits computing a correct value in the case that some of the ,
, b turn out to be nonpositive integers, or if division by zero occurs for some wc , assuming
that there are opposing singularities that cancel out. The limit is computed by evaluating
the function with the base parameters perturbed, at a higher working precision.
The rst argument should be a function that takes the perturbable base parameters
params as input and returns N tuples (w, c, alpha, beta, a, b, z), where the
coecients w, c, gamma factors alpha, beta, and hypergeometric coecients a, b each
should be lists of numbers, and z should be a single number.
Examples
The following evaluates
(a 1)
(a 3)
z
1 F1 (a, a 1, z) = e (a 4)(a + z 1)
(a 4)
with a = 1, z = 3. There is a zero factor, two gamma function poles, and the 1F1 function
is singular; all singularities cancel out to give a nite value:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> hypercomb(lambda a: [([a-1],[1],[a-3],[a-4],[a],[a-1],3)], [1])
-180.769832308689
>>> -9*exp(3)
-180.769832308689
Meijer G-function
meijerg()
mpmath.meijerg(a s, b s, z, r=1, **kwargs)
Evaluates the Meijer G-function, dened as
(
Gm,n
p,q
m
n
)
(1 aj s)
1
a1 , . . . , an ; an+1 . . . ap
j=1 (bj + s)
qj=1
p
z s/r ds
z; r =
b1 , . . . , bm ; bm+1 . . . bq
2i L j=n+1 (aj + s) j=m+1 (1 bj s)
898
Algorithm
The Meijer G-function is evaluated as a combination of hypergeometric series. There are
two versions of the function, which can be selected with the optional series argument.
series=1 uses a sum of m p Fq1 functions of z
series=2 uses a sum of n q Fp1 functions of 1/z
The default series is chosen based on the degree and |z| in order to be consistent with
Mathematicas. This denition of the Meijer G-function has a discontinuity at |z| = 1 for
some orders, which can be avoided by explicitly specifying a series.
Keyword arguments are forwarded to hypercomb() (page 898).
Examples
Many standard functions are special cases of the Meijer G-function (possibly rescaled
and/or with branch cut corrections). We dene some test parameters:
>>>
>>>
>>>
>>>
>>>
(
z
G1,0
0,1
)
z
0
G1,2
2,2
)
1, 1
z
1, 0
A rational function:
z
z+1
G1,2
2,2
)
1, 1
z
1, 1
1,0
1 sin(2 z) = G
1
0,2
z
2, 0
)
(
1,0
1
z
cos(2 z) = G
0,2
0, 12
>>> meijerg([[],[]], [[0.5],[0]], (z/2)**2)
0.4389807929218676682296453
>>> sin(z)/sqrt(pi)
0.4389807929218676682296453
>>> meijerg([[],[]], [[0],[0.5]], (z/2)**2)
-0.3544090145996275423331762
899
>>> cos(z)/sqrt(pi)
-0.3544090145996275423331762
Bessel functions:
)
(
1,0
Ja (2 z) = G0,2 a a z
2,2
)
(
a1
2,0
2
Ya (2 z) = G1,3 a a a1 z
2,2,
2
(
1,0
a/2 a/2
(z) z
Ia (2 z) = G0,2 a a
,
2 2
)
(
2Ka (2 z) = G2,0
a
a z
0,2
2,2
)
z
As the example with the Bessel I function shows, a branch factor is required for some
arguments when inverting the square root.
>>> meijerg([[],[]], [[a/2],[-a/2]], (z/2)**2)
0.5059425789597154858527264
>>> besselj(a,z)
0.5059425789597154858527264
>>> meijerg([[],[(-a-1)/2]], [[a/2,-a/2],[(-a-1)/2]], (z/2)**2)
0.1853868950066556941442559
>>> bessely(a, z)
0.1853868950066556941442559
>>> meijerg([[],[]], [[a/2],[-a/2]], -(z/2)**2)
(0.8685913322427653875717476 + 2.096964974460199200551738j)
>>> (-z)**(a/2) / z**(a/2) * besseli(a, z)
(0.8685913322427653875717476 + 2.096964974460199200551738j)
>>> 0.5*meijerg([[],[]], [[a/2,-a/2],[]], (z/2)**2)
0.09334163695597828403796071
>>> besselk(a,z)
0.09334163695597828403796071
Error functions:
(
2(a1)
z
erfc(z) = G2,0
1,2
a
a 1, a
1
2
)
z, 1
2
A Meijer G-function of still higher degree, (4,1,2,4), that can be expanded as a messy
combination of exponential integrals:
>>> meijerg([[a],[2*b-a]], [[b,a,b-0.5,-1-a+2*b],[]], z)
0.3323667133658557271898061
>>> chop(4**(a-b+1)*sqrt(pi)*gamma(2*b-2*a)*z**a*\
...
expint(2*b-2*a, -2*sqrt(-z))*expint(2*b-2*a, 2*sqrt(-z)))
0.3323667133658557271898061
900
References
1.http://en.wikipedia.org/wiki/Meijer G-function
2.http://mathworld.wolfram.com/MeijerG-Function.html
3.http://functions.wolfram.com/HypergeometricFunctions/MeijerG/
4.http://functions.wolfram.com/HypergeometricFunctions/MeijerG1/
Bilateral hypergeometric series
bihyper()
mpmath.bihyper(a s, b s, z, **kwargs)
Evaluates the bilateral hypergeometric series
A HB (a1 , . . . , ak ; b1 , . . . , bB ; z)
(a1 )n . . . (aA )n n
z
(b1 )n . . . (bB )n
n=
where, for direct convergence, A = B and |z| = 1, although a regularized sum exists more
generally by considering the bilateral series as a sum of two ordinary hypergeometric
functions. In order for the series to make sense, none of the parameters may be integers.
Examples
The value of 2 H2 at z = 1 is given by Dougalls formula:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> a,b,c,d = 0.5, 1.5, 2.25, 3.25
>>> bihyper([a,b],[c,d],1)
-14.49118026212345786148847
>>> gammaprod([c,d,1-a,1-b,c+d-a-b-1],[c-a,d-a,c-b,d-b])
-14.49118026212345786148847
The regularized function 1 H0 can be expressed as the sum of one 2 F0 function and one
1 F1 function:
>>> a = mpf(0.25)
>>> z = mpf(0.75)
>>> bihyper([a], [], z)
(0.2454393389657273841385582 + 0.2454393389657273841385582j)
>>> hyper([a,1],[],z) + (hyper([1],[1-a],-1/z)-1)
(0.2454393389657273841385582 + 0.2454393389657273841385582j)
>>> hyper([a,1],[],z) + hyper([1],[2-a],-1/z)/z/(a-1)
(0.2454393389657273841385582 + 0.2454393389657273841385582j)
References
1.[Slater] (page 1910) (chapter 6: Bilateral Series, pp. 180-189)
2.[Wikipedia] (page 1910) http://en.wikipedia.org/wiki/Bilateral hypergeometric series
5.15. Welcome to mpmaths documentation!
901
P ((a), m, n) xm y n
Q((b), m, n) m!n!
m=0 n=0
where (a) = (a1 , . . . , ar ), (b) = (b1 , . . . , bs ) and where P and Q are products of rising factorials
such as (aj )n or (aj )m+n . P and Q are specied in the form of dicts, with the m and n
dependence as keys and parameter lists as values. The supported rising factorials are
given in the following table (note that only a few are supported in Q):
Key
m
n
m+n
m-n
n-m
2m+n
2m-n
2n-m
Rising factorial
(aj )m
(aj )n
(aj )m+n
(aj )mn
(aj )nm
(aj )2m+n
(aj )2mn
(aj )2nm
Q
Yes
Yes
Yes
No
No
No
No
No
(a)m+n (b)m+n xm y n
F4 =
(c)m (d)n
m!n!
m=0 n=0
902
2.666666666666666666666667
>>> hyper2d({m:[1,2],n:[3,4]}, {m:[5],n:[6]}, x,y)
4.164358531238938319669856
>>> hyp2f1(1,2,5,x)*hyp2f1(3,4,6,y)
4.164358531238938319669856
References
1.[SrivastavaKarlsson] (page 1910)
2.[Weisstein] (page 1910) http://mathworld.wolfram.com/HornFunction.html
3.[Weisstein] (page 1910) http://mathworld.wolfram.com/AppellHypergeometricFunction.html
appellf1()
903
This series is only generally convergent when |x| < 1 and |y| < 1, although appellf1()
(page 903) can evaluate an analytic continuation with respecto to either variable, and
sometimes both.
Examples
Evaluation is supported for real and complex parameters:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> appellf1(1,0,0.5,1,0.5,0.25)
1.154700538379251529018298
>>> appellf1(1,1+j,0.5,1,0.5,0.5j)
(1.138403860350148085179415 + 1.510544741058517621110615j)
The analytic continuation with respect to either x or y, and sometimes with respect to
both, can be evaluated:
>>> appellf1(2,3,4,5,100,0.5)
(0.0006231042714165329279738662 + 0.0000005769149277148425774499857j)
>>> appellf1(1.1, 0.3, 0.2+2j, 0.4, 0.2, 1.5+3j)
(-0.1782604566893954897128702 + 0.002472407104546216117161499j)
>>> appellf1(1,2,3,4,10,12)
-0.07122993830066776374929313
904
>>> chop(y*(1-y)*diff(F,(x,y),(0,2)) +
...
x*(1-y)*diff(F,(x,y),(1,1)) +
...
(c-(a+b2+1)*y)*diff(F,(x,y),(0,1)) ...
b2*x*diff(F,(x,y),(1,0)) ...
a*b2*F(x,y))
0.0
References
1.[WolframFunctions] (page 1910) http://functions.wolfram.com/EllipticIntegrals/EllipticE2/26/01/
2.[SrivastavaKarlsson] (page 1910)
3.[CabralRosetti] (page 1910)
4.[Vidunas] (page 1910)
5.[Slater] (page 1910)
905
appellf2()
mpmath.appellf2(a, b1, b2, c1, c2, x, y, **kwargs)
Gives the Appell F2 hypergeometric function of two variables
F2 (a, b1 , b2 , c1 , c2 , x, y) =
A transformation formula:
>>> a,b1,b2,c1,c2,x,y = map(mpf, [1,2,0.5,0.25,1.625,-0.125,0.125])
>>> appellf2(a,b1,b2,c1,c2,x,y)
0.2299211717841180783309688
>>> (1-x)**(-a)*appellf2(a,c1-b1,b2,c1,c2,x/(x-1),y/(1-x))
0.2299211717841180783309688
References
See references for appellf1() (page 903).
appellf3()
906
The series is generally absolutely convergent for |x| < 1, |y| < 1.
Examples
Evaluation for various parameters and variables:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> appellf3(1,2,3,4,5,0.5,0.25)
2.221557778107438938158705
>>> appellf3(1,2,3,4,5,6,0); hyp2f1(1,3,5,6)
(-0.5189554589089861284537389 - 0.1454441043328607980769742j)
(-0.5189554589089861284537389 - 0.1454441043328607980769742j)
>>> appellf3(1,-2,-3,1,1,4,6)
-17.4
>>> appellf3(1,2,-3,1,1,4,6)
(17.7876136773677356641825 + 19.54768762233649126154534j)
>>> appellf3(1,2,-3,1,1,6,4)
(85.02054175067929402953645 + 148.4402528821177305173599j)
>>> chop(appellf3(1+j,2,1-j,2,3,0.25,0.25))
1.719992169545200286696007
Many transformations and evaluations for special combinations of the parameters are
possible, e.g.:
>>> a,b,c,x,y = map(mpf, [0.5,0.25,0.125,0.125,-0.125])
>>> appellf3(a,c-a,b,c-b,c,x,y)
1.093432340896087107444363
>>> (1-y)**(a+b-c)*hyp2f1(a,b,c,x+y-x*y)
1.093432340896087107444363
>>> x**2*appellf3(1,1,1,1,3,x,-x)
0.01568646277445385390945083
>>> polylog(2,x**2)
0.01568646277445385390945083
>>> a1,a2,b1,b2,c,x = map(mpf, [0.5,0.25,0.125,0.5,4.25,0.125])
>>> appellf3(a1,a2,b1,b2,c,x,1)
1.03947361709111140096947
>>> gammaprod([c,c-a2-b2],[c-a2,c-b2])*hyp3f2(a1,b1,c-a2-b2,c-a2,c-b2,x)
1.03947361709111140096947
907
References
See references for appellf1() (page 903).
appellf4()
mpmath.appellf4(a, b, c1, c2, x, y, **kwargs)
Gives the Appell F4 hypergeometric function of two variables
F4 (a, b, c1 , c2 , x, y) =
(a)m+n (b)m+n xm y n
.
(c1 )m (c2 )n m!n!
m=0 n=0
Examples
Evaluation for various parameters and arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> appellf4(1,1,2,2,0.25,0.125)
1.286182069079718313546608
>>> appellf4(-2,-3,4,5,4,5)
34.8
>>> appellf4(5,4,2,3,0.25j,-0.125j)
(-0.2585967215437846642163352 + 2.436102233553582711818743j)
References
See references for appellf1() (page 903).
908
Elliptic functions
Elliptic functions historically comprise the elliptic integrals and their inverses, and originate
from the problem of computing the arc length of an ellipse. From a more modern point of
view, an elliptic function is dened as a doubly periodic function, i.e. a function which satises
f (z + 21 ) = f (z + 22 ) = f (z)
for some half-periods 1 , 2 with Im[1 /2 ] > 0. The canonical elliptic functions are the Jacobi
elliptic functions. More broadly, this section includes quasi-doubly periodic functions (such
as the Jacobi theta functions) and other functions useful in the study of elliptic functions.
Many dierent conventions for the arguments of elliptic functions are in use. It is even standard to use dierent parameterizations for dierent functions in the same text or software
(and mpmath is no exception). The usual parameters are the elliptic nome q, which usually
must satisfy |q| < 1; the elliptic parameter m (an arbitrary complex number); the elliptic modulus k (an arbitrary complex number); and the half-period ratio , which usually must satisfy
Im[ ] > 0. These quantities can be expressed in terms of each other using the following relations:
m = k2
= i
K(1 m)
K(m)
q = ei
k=
42 (q)
43 (q)
In addition, an alternative denition is used for the nome in number theory, which we here
denote by q-bar:
q = q 2 = e2i
For convenience, mpmath provides functions to convert between the various parameters
(qfrom() (page 909), mfrom() (page 910), kfrom() (page 911), taufrom() (page 911), qbarfrom() (page 910)).
References
1. [AbramowitzStegun] (page 1910)
2. [WhittakerWatson] (page 1910)
Elliptic arguments
qfrom()
mpmath.qfrom(**kwargs)
Returns the elliptic nome q, given any of q, m, k, , q:
909
qbarfrom()
mpmath.qbarfrom(**kwargs)
Returns the number-theoretic nome q, given any of q, m, k, , q:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> qbarfrom(qbar=0.25)
0.25
>>> qbarfrom(q=qfrom(qbar=0.25))
0.25
>>> qbarfrom(m=extraprec(20)(mfrom)(qbar=0.25))
0.25
>>> qbarfrom(k=extraprec(20)(kfrom)(qbar=0.25))
0.25
>>> qbarfrom(tau=taufrom(qbar=0.25))
(0.25 + 0.0j)
# ill-conditioned
# ill-conditioned
mfrom()
mpmath.mfrom(**kwargs)
Returns the elliptic parameter m, given any of q, m, k, , q:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> mfrom(m=0.25)
0.25
>>> mfrom(q=qfrom(m=0.25))
0.25
>>> mfrom(k=kfrom(m=0.25))
0.25
>>> mfrom(tau=taufrom(m=0.25))
(0.25 + 0.0j)
>>> mfrom(qbar=qbarfrom(m=0.25))
0.25
910
>>> mfrom(q=-1)
-inf
kfrom()
mpmath.kfrom(**kwargs)
Returns the elliptic modulus k, given any of q, m, k, , q:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> kfrom(k=0.25)
0.25
>>> kfrom(m=mfrom(k=0.25))
0.25
>>> kfrom(q=qfrom(k=0.25))
0.25
>>> kfrom(tau=taufrom(k=0.25))
(0.25 + 0.0j)
>>> kfrom(qbar=qbarfrom(k=0.25))
0.25
taufrom()
mpmath.taufrom(**kwargs)
Returns the elliptic half-period ratio , given any of q, m, k, , q:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> taufrom(tau=0.5j)
(0.0 + 0.5j)
>>> taufrom(q=qfrom(tau=0.5j))
(0.0 + 0.5j)
>>> taufrom(m=mfrom(tau=0.5j))
(0.0 + 0.5j)
>>> taufrom(k=kfrom(tau=0.5j))
(0.0 + 0.5j)
>>> taufrom(qbar=qbarfrom(tau=0.5j))
(0.0 + 0.5j)
911
ellipk()
mpmath.ellipk(m, **kwargs)
Evaluates the complete elliptic integral of the rst kind, K(m), dened by
K(m) =
0
/2
dt
= 2 F1
2
2
1 m sin t
)
1 1
, , 1, m .
2 2
Note that the argument is the parameter m = k 2 , not the modulus k which is sometimes
used.
Plots
# Complete elliptic integrals K(m) and E(m)
plot([ellipk, ellipe], [-2,1], [0,3], points=600)
Examples
Values and limits include:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> ellipk(0)
1.570796326794896619231322
>>> ellipk(inf)
(0.0 + 0.0j)
>>> ellipk(-inf)
0.0
>>> ellipk(1)
+inf
912
>>> ellipk(-1)
1.31102877714605990523242
>>> ellipk(2)
(1.31102877714605990523242 - 1.31102877714605990523242j)
A denite integral:
>>> quad(ellipk, [0, 1])
2.0
ellipf()
mpmath.ellipf(phi, m)
Evaluates the Legendre incomplete elliptic integral of the rst kind
F (, m) =
0
dt
1 m sin2 t
or equivalently
sin
F (, m) =
0
dt
(
) (
).
1 t2
1 mt2
The function reduces to a complete elliptic integral of the rst kind (see ellipk()
(page 912)) when = 2 ; that is,
( )
F
, m = K(m).
2
In the dening integral, it is assumed that the principal branch of the square root is
taken and that the path of integration avoids crossing any branch cuts. Outside /2
<() /2, the function extends quasi-periodically as
F ( + n, m) = 2nK(m) + F (, m), n Z.
Plots
# Elliptic integral F(z,m) for some different m
f1 = lambda z: ellipf(z,-1)
f2 = lambda z: ellipf(z,-0.5)
f3 = lambda z: ellipf(z,0)
f4 = lambda z: ellipf(z,0.5)
f5 = lambda z: ellipf(z,1)
plot([f1,f2,f3,f4,f5], [0,pi], [0,4])
913
Examples
Basic values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> ellipf(0,1)
0.0
>>> ellipf(0,0)
0.0
>>> ellipf(1,0); ellipf(2+3j,0)
1.0
(2.0 + 3.0j)
>>> ellipf(1,1); log(sec(1)+tan(1))
1.226191170883517070813061
1.226191170883517070813061
>>> ellipf(pi/2, -0.5); ellipk(-0.5)
1.415737208425956198892166
1.415737208425956198892166
>>> ellipf(pi/2+eps, 1); ellipf(-pi/2-eps, 1)
+inf
+inf
>>> ellipf(1.5, 1)
3.340677542798311003320813
914
For |<(z)| < /2, the function can be expressed as a hypergeometric series of two variables (see appellf1() (page 903)):
>>> z,m = 0.5, 0.25
>>> ellipf(z,m)
0.5050887275786480788831083
>>> sin(z)*appellf1(0.5,0.5,0.5,1.5,sin(z)**2,m*sin(z)**2)
0.5050887275786480788831083
ellipe()
mpmath.ellipe(*args)
Called with a single argument m, evaluates the Legendre complete elliptic integral of
the second kind, E(m), dened by
/2
E(m) =
0
(
)
1 1
2
1 m sin t dt = 2 F1
, , 1, m .
2
2 2
Called with two arguments , m, evaluates the incomplete elliptic integral of the second
kind
E(, m) =
2
1 m sin t dt =
sin z
1 mt2
dt.
1 t2
2;
that is,
In the dening integral, it is assumed that the principal branch of the square root is
taken and that the path of integration avoids crossing any branch cuts. Outside /2
<(z) /2, the function extends quasi-periodically as
E( + n, m) = 2nE(m) + F (, m), n Z.
Plots
915
916
>>> ellipe(0.5)
1.350643881047675502520175
>>> quad(lambda t: sqrt(1-0.5*sin(t)**2), [0, pi/2])
1.350643881047675502520175
>>> pi/2*hyp2f1(0.5,-0.5,1,0.5)
1.350643881047675502520175
A denite integral:
>>> quad(ellipe, [0,1])
1.333333333333333333333333
917
(48.30138799412005235090766 + 17.47255216721987688224357j)
(48.30138799412005235090766 + 17.47255216721987688224357j)
For |<(z)| < /2, the function can be expressed as a hypergeometric series of two variables (see appellf1() (page 903)):
>>> z,m = 0.5, 0.25
>>> ellipe(z,m)
0.4950017030164151928870375
>>> sin(z)*appellf1(0.5,0.5,-0.5,1.5,sin(z)**2,m*sin(z)**2)
0.4950017030164151928870376
ellippi()
mpmath.ellippi(*args)
Called with three arguments n, , m, evaluates the Legendre incomplete elliptic integral
of the third kind
sin
dt
dt
(n; , m) =
=
.
2
2
2
(1 nt ) 1 t2 1 mt2
0 (1 n sin t) 1 m sin t
0
Called with two arguments n, m, evaluates the complete elliptic integral of the third kind
(n, m) = (n; 2 , m).
In the dening integral, it is assumed that the principal branch of the square root is
taken and that the path of integration avoids crossing any branch cuts. Outside /2
<() /2, the function extends quasi-periodically as
(n, + k, m) = 2k(n, m) + (n, , m), k Z.
Plots
# Elliptic integral Pi(n,z,m) for some different n, m
f1 = lambda z: ellippi(0.9,z,0.9)
f2 = lambda z: ellippi(0.5,z,0.5)
f3 = lambda z: ellippi(-2,z,-0.9)
f4 = lambda z: ellippi(-0.5,z,0.5)
f5 = lambda z: ellippi(-1,z,0.5)
plot([f1,f2,f3,f4,f5], [0,pi], [0,4])
918
919
1
dt
RF (x, y, z) =
2 0
(t + x)(t + y)(t + z)
which is dened for x, y, z
/ (, 0), and with at most one of x, y, z being zero.
For real x, y, z 0, the principal square root is taken in the integrand. For complex x, y, z,
the principal square root is taken as t and as t 0 non-principal branches are
chosen as necessary so as to make the integrand continuous.
Examples
920
With the following arguments, the square root in the integrand becomes
discontinuous
at t = 1/2 ifthe principal branch is used. To obtain the right value, r must be taken
instead of r on t (0, 1/2):
921
References
1.[Carlson] (page 1910)
2.[DLMF] (page 1910) Chapter 19. Elliptic Integrals
elliprc()
mpmath.elliprc(x, y, pv=True)
Evaluates the degenerate Carlson symmetric elliptic integral of the rst kind
1
dt
RC (x, y) = RF (x, y, y) =
.
2 0 (t + y) (t + x)
If y (, 0), either a value dened by continuity, or with pv=True the Cauchy principal
value, can be computed.
If x 0, y > 0, the value can be expressed in terms of elementary functions as
( )
x
1
cos
,
x<y
x
y
1
x=y.
RC (x, y) = ,
y
(
)
cosh
, x>y
xy
y
Examples
Some special values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> elliprc(1,2)*4; elliprc(0,1)*2; +pi
3.141592653589793238462643
3.141592653589793238462643
3.141592653589793238462643
>>> elliprc(1,0)
+inf
>>> elliprc(5,5)**2
0.2
>>> elliprc(1,inf); elliprc(inf,1); elliprc(inf,inf)
0.0
0.0
0.0
922
elliprj()
mpmath.elliprj(x, y, z, p)
Evaluates the Carlson symmetric elliptic integral of the third kind
3
dt
RJ (x, y, z, p) =
.
2 0 (t + p) (t + x)(t + y)(t + z)
Like elliprf() (page 920), the branch of the square root in the integrand is dened so
as to be continuous along the path of integration for complex values of the arguments.
Examples
Some values and limits:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> elliprj(1,1,1,1)
1.0
>>> elliprj(2,2,2,2); 1/(2*sqrt(2))
0.3535533905932737622004222
0.3535533905932737622004222
>>> elliprj(0,1,2,2)
1.067937989667395702268688
>>> 3*(2*gamma(5/4)**2-pi**2/gamma(1/4)**2)/(sqrt(2*pi))
1.067937989667395702268688
>>> elliprj(0,1,1,2); 3*pi*(2-sqrt(2))/4
1.380226776765915172432054
1.380226776765915172432054
>>> elliprj(1,3,2,0); elliprj(0,1,1,0); elliprj(0,0,0,0)
+inf
+inf
+inf
>>> elliprj(1,inf,1,0); elliprj(1,1,1,inf)
0.0
0.0
>>> chop(elliprj(1+j, 1-j, 1, 1))
0.8505007163686739432927844
Scale transformation:
923
elliprd()
mpmath.elliprd(x, y, z)
Evaluates the degenerate Carlson symmetric elliptic integral of the third kind or Carlson
elliptic integral of the second kind RD (x, y, z) = RJ (x, y, z, z).
See elliprj() (page 923) for additional information.
Examples
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> elliprd(1,2,3)
0.2904602810289906442326534
>>> elliprj(1,2,3,3)
0.2904602810289906442326534
elliprg()
mpmath.elliprg(x, y, z)
Evaluates the Carlson completely symmetric elliptic integral of the second kind
)
(
1
t
y
z
x
RG (x, y, z) =
+
+
dt.
4 0
(t + x)(t + y)(t + z) t + x t + y t + z
Examples
Evaluation for real and complex arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
924
(1)n q n
n=0
1/4
n2 +n
+n
sin((2n + 1)z)
cos((2n + 1)z)
n=0
3 (z, q) = 1 + 2
q n cos(2nz)
n=1
4 (z, q) = 1 + 2
(q)n cos(2nz)
n=1
The compact notations n (q) = n (0, q) and n = n (0, q) are also frequently encountered.
Finally, Jacobi theta functions are frequently considered as functions of the half-period
ratio and then usually denoted by n (z| ).
Optionally, jtheta(n, z, q, derivative=d) with d > 0 computes a d-th derivative with
respect to z.
Examples and basic properties
Considered as functions of z, the Jacobi theta functions may be viewed as generalizations
of the ordinary trigonometric functions cos and sin. They are periodic functions:
5.15. Welcome to mpmaths documentation!
925
Indeed, the series dening the theta functions are essentially trigonometric Fourier series. The coecients can be retrieved using fourier() (page 1017):
>>> mp.dps = 10
>>> nprint(fourier(lambda x: jtheta(2, x, 0.5), [-pi, pi], 4))
([0.0, 1.68179, 0.0, 0.420448, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0])
The Jacobi theta functions are also so-called quasiperiodic functions of z and , meaning
that for xed , n (z, q) and n (z + , q) are the same except for an exponential factor:
>>> mp.dps = 25
>>> tau = 3*j/10
>>> q = exp(pi*j*tau)
>>> z = 10
>>> jtheta(4, z+tau*pi, q)
(-0.682420280786034687520568 + 1.526683999721399103332021j)
>>> -exp(-2*j*z)/q * jtheta(4, z, q)
(-0.682420280786034687520568 + 1.526683999721399103332021j)
The Jacobi theta functions satisfy a huge number of other functional equations, such as
the following identity (valid for any q):
>>> q = mpf(3)/10
>>> jtheta(3,0,q)**4
6.823744089352763305137427
>>> jtheta(2,0,q)**4 + jtheta(4,0,q)**4
6.823744089352763305137427
Extensive listings of identities satised by the Jacobi theta functions can be found in
standard reference works.
The Jacobi theta functions are related to the gamma function for special arguments:
>>> jtheta(3, 0, exp(-pi))
1.086434811213308014575316
>>> pi**(1/4.) / gamma(3/4.)
1.086434811213308014575316
jtheta() (page 925) supports arbitrary precision evaluation and complex arguments:
>>> mp.dps = 50
>>> jtheta(4, sqrt(2), 0.5)
2.0549510717571539127004115835148878097035750653737
>>> mp.dps = 25
>>> jtheta(4, 1+2j, (1+j)/5)
(7.180331760146805926356634 - 1.634292858119162417301683j)
Evaluation of derivatives:
>>> mp.dps = 25
>>> jtheta(1, 7, 0.25, 1); diff(lambda z: jtheta(1, z, 0.25), 7)
1.209857192844475388637236
1.209857192844475388637236
926
z: jtheta(1, z, 0.25), 7, 2)
z: jtheta(2, z, 0.25), 7)
z: jtheta(2, z, 0.25), 7, 2)
z: jtheta(3, z, 0.25), 7)
z: jtheta(3, z, 0.25), 7, 2)
z: jtheta(4, z, 0.25), 7)
z: jtheta(4, z, 0.25), 7, 2)
Possible issues
For |q| 1 or =( ) 0, jtheta() (page 925) raises ValueError. This exception is also
raised for |q| extremely close to 1 (or equivalently very close to 0), since the series
would converge too slowly:
>>> jtheta(1, 10, 0.99999999 * exp(0.5*j))
Traceback (most recent call last):
...
ValueError: abs(q) > THETA_Q_LIM = 1.000000
Traceback (most recent call last):
...
ValueError: abs(q) > THETA_Q_LIM = 1.000000
or more generally computes a ratio of two such functions. Here t = u/3 (0, q)2 , and
q = q(m) denotes the nome (see nome()). Optionally, you can specify the nome directly
instead of m by passing q=<value>, or you can directly specify the elliptic parameter k
with k=<value>.
927
The rst argument should be a two-character string specifying the function using any
combination of s, c, d, n. These letters respectively denote the basic functions
sn(u, m), cn(u, m), dn(u, m), and 1. The identier species the ratio of two such functions.
For example, ns identies the function
ns(u, m) =
1
sn(u, m)
cd(u, m) =
cn(u, m)
.
dn(u, m)
If called with only the rst argument, a function object evaluating the chosen function
for given arguments is returned.
Examples
Basic evaluation:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> ellipfun(cd, 3.5, 0.5)
-0.9891101840595543931308394
>>> ellipfun(cd, 3.5, q=0.25)
0.07111979240214668158441418
The sn-function is doubly periodic in the complex plane with periods 4K(m) and 2iK(1m)
(see ellipk() (page 912)):
>>> sn = ellipfun(sn)
>>> sn(2, 0.25)
0.9628981775982774425751399
>>> sn(2+4*ellipk(0.25), 0.25)
0.9628981775982774425751399
>>> chop(sn(2+2*j*ellipk(1-0.25), 0.25))
0.9628981775982774425751399
The cn-function is doubly periodic with periods 4K(m) and 4iK(1 m):
>>> cn = ellipfun(cn)
>>> cn(2, 0.25)
-0.2698649654510865792581416
>>> cn(2+4*ellipk(0.25), 0.25)
-0.2698649654510865792581416
>>> chop(cn(2+4*j*ellipk(1-0.25), 0.25))
-0.2698649654510865792581416
The dn-function is doubly periodic with periods 2K(m) and 4iK(1 m):
>>> dn = ellipfun(dn)
>>> dn(2, 0.25)
0.8764740583123262286931578
>>> dn(2+2*ellipk(0.25), 0.25)
0.8764740583123262286931578
>>> chop(dn(2+4*j*ellipk(1-0.25), 0.25))
0.8764740583123262286931578
Modular functions
928
kleinj()
mpmath.kleinj(tau=None, **kwargs)
Evaluates the Klein j-invariant, which is a modular function dened for in the upper
half-plane as
J( ) =
g23 ( )
g23 ( ) 27g32 ( )
where g2 and g3 are the modular invariants of the Weierstrass elliptic function,
(m + n)4
g2 ( ) = 60
(m,n)Z2 \(0,0)
g3 ( ) = 140
(m + n)6 .
(m,n)Z2 \(0,0)
929
Examples
Verifying the functional equation J( ) = J( + 1) = J( 1 ):
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> tau = 0.625+0.75*j
>>> tau = 0.625+0.75*j
>>> kleinj(tau)
(-0.1507492166511182267125242 + 0.07595948379084571927228948j)
>>> kleinj(tau+1)
(-0.1507492166511182267125242 + 0.07595948379084571927228948j)
>>> kleinj(-1/tau)
(-0.1507492166511182267125242 + 0.07595948379084571927228946j)
The j-function has a famous Laurent series expansion in terms of the nome q, j( ) =
q1 + 744 + 196884
q + . . .:
>>> mp.dps = 15
>>> taylor(lambda q: 1728*q*kleinj(qbar=q), 0, 5, singular=True)
[1.0, 744.0, 196884.0, 21493760.0, 864299970.0, 20245856256.0]
The j-function admits exact evaluation at special algebraic points related to the Heegner
numbers 1, 2, 3, 7, 11, 19, 43, 67, 163:
>>> @extraprec(10)
... def h(n):
...
v = (1+sqrt(n)*j)
...
if n > 2:
930
...
v *= 0.5
...
return v
...
>>> mp.dps = 25
>>> for n in [1,2,3,7,11,19,43,67,163]:
...
n, chop(1728*kleinj(h(n)))
...
(1, 1728.0)
(2, 8000.0)
(3, 0.0)
(7, -3375.0)
(11, -32768.0)
(19, -884736.0)
(43, -884736000.0)
(67, -147197952000.0)
(163, -262537412640768000.0)
Also at other special points, the j-function assumes explicit algebraic values, e.g.:
>>> chop(1728*kleinj(j*sqrt(5)))
1264538.909475140509320227
>>> identify(cbrt(_))
# note: not simplified
((100+sqrt(13520))/2)
>>> (50+26*sqrt(5))**3
1264538.909475140509320227
This section includes the Riemann zeta functions and associated functions pertaining to analytic number theory.
Riemann and Hurwitz zeta functions
zeta()
mpmath.zeta(s, a=1, derivative=0)
Computes the Riemann zeta function
(s) = 1 +
1
1
1
+ s + s + ...
2s
3
4
k=0
1
.
(a + k)s
log (a + k)
k=0
(a + k)s
Although these series only converge for <(s) > 1, the Riemann and Hurwitz zeta functions
are dened through analytic continuation for arbitrary complex s 6= 1 (s = 1 is a pole).
The implementation uses three algorithms: the Borwein algorithm for the Riemann zeta
function when s is close to the real line; the Riemann-Siegel formula for the Riemann zeta
5.15. Welcome to mpmaths documentation!
931
function when s is large imaginary, and Euler-Maclaurin summation in all other cases.
The reection formula for <(s) < 0 is implemented in some cases. The algorithm can
be chosen with method = borwein, method=riemann-siegel or method = eulermaclaurin.
The parameter a is usually a rational number a = p/q, and may be specied as such by
passing an integer tuple (p, q). Evaluation is supported for arbitrary complex a, but may
be slow and/or inaccurate when <(s) < 0 for nonrational a or when computing derivatives.
Examples
Some values of the Riemann zeta function:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> zeta(2); pi**2 / 6
1.644934066848226436472415
1.644934066848226436472415
>>> zeta(0)
-0.5
>>> zeta(-1)
-0.08333333333333333333333333
>>> zeta(-2)
0.0
The Riemann zeta function has so-called nontrivial zeros on the critical line s = 1/2 + it:
>>> findroot(zeta, 0.5+14j); zetazero(1)
(0.5 + 14.13472514173469379045725j)
(0.5 + 14.13472514173469379045725j)
>>> findroot(zeta, 0.5+21j); zetazero(2)
(0.5 + 21.02203963877155499262848j)
(0.5 + 21.02203963877155499262848j)
>>> findroot(zeta, 0.5+25j); zetazero(3)
(0.5 + 25.01085758014568876321379j)
(0.5 + 25.01085758014568876321379j)
>>> chop(zeta(zetazero(10)))
0.0
932
Evaluation on and near the critical line is supported for large heights t by means of the
Riemann-Siegel formula (currently for a = 1, n 4):
>>> zeta(0.5+100000j)
(1.073032014857753132114076 + 5.780848544363503984261041j)
>>> zeta(0.75+1000000j)
(0.9535316058375145020351559 + 0.9525945894834273060175651j)
>>> zeta(0.5+10000000j)
(11.45804061057709254500227 - 8.643437226836021723818215j)
>>> zeta(0.5+100000000j, derivative=1)
(51.12433106710194942681869 + 43.87221167872304520599418j)
>>> zeta(0.5+100000000j, derivative=2)
(-444.2760822795430400549229 - 896.3789978119185981665403j)
>>> zeta(0.5+100000000j, derivative=3)
(3230.72682687670422215339 + 14374.36950073615897616781j)
>>> zeta(0.5+100000000j, derivative=4)
(-11967.35573095046402130602 - 218945.7817789262839266148j)
>>> zeta(1+10000000j)
# off the line
(2.859846483332530337008882 + 0.491808047480981808903986j)
>>> zeta(1+10000000j, derivative=1)
(-4.333835494679647915673205 - 0.08405337962602933636096103j)
>>> zeta(1+10000000j, derivative=4)
(453.2764822702057701894278 - 581.963625832768189140995j)
For investigation of the zeta function zeros, the Riemann-Siegel Z-function is often
more convenient than working with the Riemann zeta function directly (see siegelz()
(page 939)).
Some values of the Hurwitz zeta function:
>>> zeta(2, 3); -5./4 + pi**2/6
0.3949340668482264364724152
0.3949340668482264364724152
>>> zeta(2, (3,4)); pi**2 - 8*catalan
2.541879647671606498397663
2.541879647671606498397663
For positive integer values of s, the Hurwitz zeta function is equivalent to a polygamma
function (except for a normalizing factor):
>>> zeta(4, (1,5)); psi(3, 1/5)/6
625.5408324774542966919938
625.5408324774542966919938
Evaluation of derivatives:
>>> zeta(0, 3+4j, 1); loggamma(3+4j) - ln(2*pi)/2
(-2.675565317808456852310934 + 4.742664438034657928194889j)
(-2.675565317808456852310934 + 4.742664438034657928194889j)
>>> zeta(2, 1, 20)
2432902008176640000.000242
>>> zeta(3+4j, 5.5+2j, 4)
(-0.140075548947797130681075 - 0.3109263360275413251313634j)
>>> zeta(0.5+100000j, 1, 4)
(-10407.16081931495861539236 + 13777.78669862804508537384j)
>>> zeta(-100+0.5j, (1,3), derivative=4)
(4.007180821099823942702249e+79 + 4.916117957092593868321778e+78j)
933
References
1.http://mathworld.wolfram.com/RiemannZetaFunction.html
2.http://mathworld.wolfram.com/HurwitzZetaFunction.html
3.http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P155.pdf
Dirichlet L-series
altzeta()
mpmath.altzeta(s)
Gives the Dirichlet eta function, (s), also known as the alternating zeta function. This
function is dened in analogy with the Riemann zeta function as providing the sum of
934
(1)k
k=0
ks
=1
1
1
1
+ s s + ...
2s
3
4
The eta function, unlike the Riemann zeta function, is an entire function, having a nite
value for all complex s. The special case (1) = log(2) gives the value of the alternating
harmonic series.
The alternating zeta function may expressed using the Riemann zeta function as (s) =
(1 21s )(s). It can also be expressed in terms of the Hurwitz zeta function, for example
using dirichlet() (page 936) (see documentation for that function).
Examples
Some special values are:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> altzeta(1)
0.693147180559945
>>> altzeta(0)
0.5
>>> altzeta(-1)
0.25
>>> altzeta(-2)
0.0
An example of a sum that can be computed more accurately and eciently via altzeta()
(page 934) than via numerical summation:
>>> sum(-(-1)**n / mpf(n)**2.5 for n in range(1, 100))
0.867204951503984
>>> altzeta(2.5)
0.867199889012184
At positive even integers, the Dirichlet eta function evaluates to a rational multiple of a
power of :
>>> altzeta(2)
0.822467033424113
>>> pi**2/12
0.822467033424113
Like the Riemann zeta function, (s), approaches 1 as s approaches positive innity,
although it does so from below rather than from above:
>>> altzeta(30)
0.999999999068682
>>> altzeta(inf)
1.0
>>> mp.pretty = False
>>> altzeta(1000, rounding=d)
mpf(0.99999999999999989)
>>> altzeta(1000, rounding=u)
mpf(1.0)
References
1.http://mathworld.wolfram.com/DirichletEtaFunction.html
2.http://en.wikipedia.org/wiki/Dirichlet eta function
5.15. Welcome to mpmaths documentation!
935
dirichlet()
mpmath.dirichlet(s, chi, derivative=0)
Evaluates the Dirichlet L-function
L(s, ) =
(k)
k=1
ks
(1)k
k=0 (2k+1)s
Stieltjes constants
stieltjes()
mpmath.stieltjes(n, a=1)
For a nonnegative integer n, stieltjes(n) computes the n-th Stieltjes constant n , dened as the n-th coecient in the Laurent series expansion of the Riemann zeta function
around the pole at s = 1. That is, we have:
(s) =
1 (1)n
n (s 1)n
s 1 n=0 n!
More generally, stieltjes(n, a) gives the corresponding coecient n (a) for the Hurwitz zeta function (s, a) (with n = n (1)).
Examples
The zeroth Stieltjes constant is just Eulers constant :
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> stieltjes(0)
0.577215664901533
Algorithm
937
stieltjes() (page 937) numerically evaluates the integral in the following representation due to Ainsworth, Howell and Coey [1], [2]:
n
n (a) =
n+1
log a log
(a) 2
+ <
2a
n+1
a
These functions are used for the study of the Riemann zeta function
zetazero()
mpmath.zetazero(n, verbose=False)
Computes the n-th nontrivial zero of (s) on the critical line, i.e. returns an approximation of the n-th largest complex number s = 12 + ti for which (s) = 0. Equivalently, the
imaginary part t is a zero of the Z-function (siegelz() (page 939)).
Examples
The rst few zeros:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> zetazero(1)
(0.5 + 14.13472514173469379045725j)
>>> zetazero(2)
(0.5 + 21.02203963877155499262848j)
>>> zetazero(20)
(0.5 + 77.14484006887480537268266j)
938
This means that the zero is between Gram points 542964969 and 542964978; it is the
6-th zero between them. Finally (01311110) is the pattern of zeros in this interval. The
numbers indicate the number of zeros in each Gram interval (Rosser blocks between
parenthesis). In this case there is only one Rosser block of length nine.
nzeros()
mpmath.nzeros(t)
Computes the number of zeros of the Riemann zeta function in (0, 1) (0, t], usually denoted by N (t).
Examples
The rst zero has imaginary part between 14 and 15:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> nzeros(14)
0
>>> nzeros(15)
1
>>> zetazero(1)
(0.5 + 14.1347251417347j)
This conrms the data given by J. van de Lune, H. J. J. te Riele and D. T. Winter in 1986.
siegelz()
5.15. Welcome to mpmaths documentation!
939
mpmath.siegelz(t)
Computes the Z-function, also known as the Riemann-Siegel Z function,
Z(t) = ei(t) (1/2 + it)
where (s) is the Riemann zeta function (zeta() (page 931)) and where (t) denotes the
Riemann-Siegel theta function (see siegeltheta() (page 941)).
Evaluation is supported for real and complex arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> siegelz(1)
-0.7363054628673177346778998
>>> siegelz(3+4j)
(-0.1852895764366314976003936 - 0.2773099198055652246992479j)
The rst four derivatives are supported, using the optional derivative keyword argument:
>>> siegelz(1234567, derivative=3)
56.89689348495089294249178
>>> diff(siegelz, 1234567, n=3)
56.89689348495089294249178
The Z-function Z(t) is equal to |(s)| on the critical line s = 1/2+it (i.e. for real arguments
t to Z). Its zeros coincide with those of the Riemann zeta function:
>>> findroot(siegelz, 14)
14.13472514173469379045725
>>> findroot(siegelz, 20)
21.02203963877155499262848
>>> findroot(zeta, 0.5+14j)
(0.5 + 14.13472514173469379045725j)
>>> findroot(zeta, 0.5+20j)
(0.5 + 21.02203963877155499262848j)
Since the Z-function is real-valued on the critical line (and unlike |(s)| analytic), it is
useful for investigating the zeros of the Riemann zeta function. For example, one can
use a root-nding algorithm based on sign changes:
>>> findroot(siegelz, [100, 200], solver=bisect)
176.4414342977104188888926
To locate roots, Gram points gn which can be computed by grampoint() (page 941) are
useful. If (1)n Z(gn ) is positive for two consecutive n, then Z(t) must have a zero between
those points:
>>> g10 = grampoint(10)
>>> g11 = grampoint(11)
>>> (-1)**10 * siegelz(g10) > 0
True
>>> (-1)**11 * siegelz(g11) > 0
True
>>> findroot(siegelz, [g10, g11], solver=bisect)
56.44624769706339480436776
940
siegeltheta()
mpmath.siegeltheta(t)
Computes the Riemann-Siegel theta function,
(
)
(
)
log 1+2it
log 12it
log
4
4
(t) =
t.
2i
2
The Riemann-Siegel theta function is important in providing the phase factor for the
Z-function (see siegelz() (page 939)). Evaluation is supported for real and complex
arguments:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> siegeltheta(0)
0.0
>>> siegeltheta(inf)
+inf
>>> siegeltheta(-inf)
-inf
>>> siegeltheta(1)
-1.767547952812290388302216
>>> siegeltheta(10+0.25j)
(-3.068638039426838572528867 + 0.05804937947429712998395177j)
The Riemann-Siegel theta function has odd symmetry around t = 0, two local extreme
points and three real roots including 0 (located symmetrically):
>>> nprint(chop(taylor(siegeltheta, 0, 5)))
[0.0, -2.68609, 0.0, 2.69433, 0.0, -6.40218]
>>> findroot(diffun(siegeltheta), 7)
6.28983598883690277966509
>>> findroot(siegeltheta, 20)
17.84559954041086081682634
For large t, there is a famous asymptotic formula for (t), to rst order given by:
>>> t = mpf(10**6)
>>> siegeltheta(t)
5488816.353078403444882823
>>> -t*log(2*pi/t)/2-t/2
5488816.745777464310273645
grampoint()
mpmath.grampoint(n)
Gives the n-th Gram point gn , dened as the solution to the equation (gn ) = n where
(t) is the Riemann-Siegel theta function (siegeltheta() (page 941)).
5.15. Welcome to mpmaths documentation!
941
Gram points are useful when studying the Z-function (siegelz() (page 939)). See the
documentation of that function for additional examples.
grampoint() (page 941) can solve the dening equation for nonintegral n. There is a
xed point where g(x) = x:
>>> findroot(lambda x: grampoint(x) - x, 10000)
9146.698193171459265866198
References
1.http://mathworld.wolfram.com/GramPoint.html
backlunds()
mpmath.backlunds(t)
Computes the function S(t) = arg ( 12 + it)/.
See Titchmarsh Section 9.3 for details of the denition.
Examples
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> backlunds(217.3)
0.16302205431184
Generally, the value is a small number. At Gram points it is an integer, frequently equal
to 0:
>>> chop(backlunds(grampoint(200)))
0.0
>>> backlunds(extraprec(10)(grampoint)(211))
1.0
>>> backlunds(extraprec(10)(grampoint)(232))
-1.0
942
The number of zeros of the Riemann zeta function up to height t satises N (t) = (t)/ +
1 + S(t) (see :func:nzeros and siegeltheta()):
>>> t = 1234.55
>>> nzeros(t)
842
>>> siegeltheta(t)/pi+1+backlunds(t)
842.0
Lerch transcendent
lerchphi()
mpmath.lerchphi(z, s, a)
Gives the Lerch transcendent, dened for |z| < 1 and <a > 0 by
(z, s, a) =
k=0
zk
(a + k)s
and generally by the recurrence (z, s, a) = z(z, s, a + 1) + as along with the integral
representation valid for <a > 0
1
zt
sin(t log z s arctan(t/a)
(z, s, a) = s +
dt 2
dt.
s
2a
(a
+
t)
(a2 + t2 )s/2 (e2t 1)
0
0
The Lerch transcendent generalizes the Hurwitz zeta function zeta() (z = 1) and the
polylogarithm polylog() (a = 1).
Examples
Several evaluations in terms of simpler functions:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> lerchphi(-1,2,0.5); 4*catalan
3.663862376708876060218414
3.663862376708876060218414
>>> diff(lerchphi, (-1,-2,1), (0,1,0)); 7*zeta(3)/(4*pi**2)
0.2131391994087528954617607
0.2131391994087528954617607
>>> lerchphi(-4,1,1); log(5)/4
0.4023594781085250936501898
0.4023594781085250936501898
>>> lerchphi(-3+2j,1,0.5); 2*atanh(sqrt(-3+2j))/sqrt(-3+2j)
(1.142423447120257137774002 + 0.2118232380980201350495795j)
(1.142423447120257137774002 + 0.2118232380980201350495795j)
943
References
1.[DLMF] (page 1910) section 25.14
Polylogarithms and Clausen functions
polylog()
mpmath.polylog(s, z)
Computes the polylogarithm, dened by the sum
Lis (z) =
zk
k=1
ks
This series is convergent only for |z| < 1, so elsewhere the analytic continuation is implied.
The polylogarithm should not be confused with the logarithmic integral (also denoted by
Li or li), which is implemented as li() (page 799).
Examples
The polylogarithm satises a huge number of functional identities. A sample of polylogarithm evaluations is shown below:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> polylog(1,0.5), log(2)
(0.693147180559945, 0.693147180559945)
>>> polylog(2,0.5), (pi**2-6*log(2)**2)/12
(0.582240526465012, 0.582240526465012)
>>> polylog(2,-phi), -log(phi)**2-pi**2/10
(-1.21852526068613, -1.21852526068613)
>>> polylog(3,0.5), 7*zeta(3)/8-pi**2*log(2)/12+log(2)**3/6
(0.53721319360804, 0.53721319360804)
polylog() (page 944) can evaluate the analytic continuation of the polylogarithm when
s is an integer:
944
Some more examples, with arguments on the unit circle (note that the series denition
cannot be used for computation here):
>>> polylog(2,j)
(-0.205616758356028 + 0.915965594177219j)
>>> j*catalan-pi**2/48
(-0.205616758356028 + 0.915965594177219j)
>>> polylog(3,exp(2*pi*j/3))
(-0.534247512515375 + 0.765587078525922j)
>>> -4*zeta(3)/9 + 2*j*pi**3/81
(-0.534247512515375 + 0.765587078525921j)
The series dening the polylogarithm is simultaneously a Taylor series and an L-series.
For certain values of z, the polylogarithm reduces to a pure zeta function:
>>> polylog(pi, 1), zeta(pi)
(1.17624173838258, 1.17624173838258)
>>> polylog(pi, -1), -altzeta(pi)
(-0.909670702980385, -0.909670702980385)
Evaluation for arbitrary, nonintegral s is supported for z within the unit circle:
945
It is also currently supported outside of the unit circle for z not too large in magnitude:
>>> polylog(1+j, 20+40j)
(-7.1421172179728 - 3.92726697721369j)
>>> polylog(1+j, 200+400j)
Traceback (most recent call last):
...
NotImplementedError: polylog for arbitrary s and z
Traceback (most recent call last):
...
NotImplementedError: polylog for arbitrary s and z
References
1.Richard
Crandall,
Note
on
fast
polylogarithm
http://people.reed.edu/crandall/papers/Polylog.pdf
computation
2.http://en.wikipedia.org/wiki/Polylogarithm
3.http://mathworld.wolfram.com/Polylogarithm.html
clsin()
mpmath.clsin(s, z)
Computes the Clausen sine function, dened formally by the series
Cls (z) =
sin(kz)
k=1
ks
The special case Cl2 (z) (i.e. clsin(2,z)) is the classical Clausen function. More generally, the Clausen function is dened for complex s and z, even when the series does not
converge. The Clausen function is related to the polylogarithm (polylog() (page 944))
as
( )
(
))
1 (
Lis eiz Lis eiz
2i
[
]
= Im Lis (eiz )
(s, z R),
Cls (z) =
and this representation can be taken to provide the analytic continuation of the series.
The complementary function clcos() (page 948) gives the corresponding cosine sum.
Examples
Evaluation for arbitrarily chosen s and z:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> s, z = 3, 4
>>> clsin(s, z); nsum(lambda k: sin(z*k)/k**s, [1,inf])
-0.6533010136329338746275795
-0.6533010136329338746275795
946
With s = 1, the sum can be expressed in closed form using elementary functions:
>>> z = 1 + sqrt(3)
>>> clsin(1, z)
0.2047709230104579724675985
>>> chop((log(1-exp(-j*z)) - log(1-exp(j*z)))/(2*j))
0.2047709230104579724675985
>>> nsum(lambda k: sin(k*z)/k, [1,inf])
0.2047709230104579724675985
The classical Clausen function Cl2 () gives the value of the integral
for 0 < < 2:
ln(2 sin(x/2))dx
The Clausen sine function can be expressed in closed form when s is an odd integer
(becoming zero when s < 0):
>>> z = 1 + sqrt(2)
>>> clsin(1, z); (pi-z)/2
0.3636895456083490948304773
0.3636895456083490948304773
>>> clsin(3, z); pi**2/6*z - pi*z**2/4 + z**3/12
0.5661751584451144991707161
0.5661751584451144991707161
>>> clsin(-1, z)
0.0
>>> clsin(-3, z)
0.0
It can also be expressed in closed form for even integer s 0, providing a nite sum for
series such as sin(z) + sin(2z) + sin(3z) + . . .:
>>> z = 1 + sqrt(2)
>>> clsin(0, z)
947
0.1903105029507513881275865
>>> cot(z/2)/2
0.1903105029507513881275865
>>> clsin(-2, z)
-0.1089406163841548817581392
>>> -cot(z/2)*csc(z/2)**2/4
-0.1089406163841548817581392
clcos()
mpmath.clcos(s, z)
Computes the Clausen cosine function, dened formally by the series
f s (z) =
Cl
cos(kz)
k=1
ks
This function is complementary to the Clausen sine function clsin() (page 946). In
terms of the polylogarithm,
f s (z) = 1 (Lis (eiz ) + Lis (eiz ))
Cl
[2
]
= Re Lis (eiz )
(s, z R).
Examples
Evaluation for arbitrarily chosen s and z:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> s, z = 3, 4
>>> clcos(s, z); nsum(lambda k: cos(z*k)/k**s, [1,inf])
-0.6518926267198991308332759
-0.6518926267198991308332759
With s = 1, the sum can be expressed in closed form using elementary functions:
948
>>> z = 1 + sqrt(3)
>>> clcos(1, z)
-0.6720334373369714849797918
>>> chop(-0.5*(log(1-exp(j*z))+log(1-exp(-j*z))))
-0.6720334373369714849797918
>>> -log(abs(2*sin(0.5*z)))
# Equivalent to above when z is real
-0.6720334373369714849797918
>>> nsum(lambda k: cos(k*z)/k, [1,inf])
-0.6720334373369714849797918
It can also be expressed in closed form when s is an even integer. For example,
>>> clcos(2,z)
-0.7805359025135583118863007
>>> pi**2/6 - pi*z/2 + z**2/4
-0.7805359025135583118863007
With z = , the series reduces to that of the Riemann zeta function (more generally, if
z = p/q, it is a nite sum over Hurwitz zeta function values):
>>> clcos(2.5, 0); zeta(2.5)
1.34148725725091717975677
1.34148725725091717975677
>>> clcos(2.5, pi); -altzeta(2.5)
-0.8671998890121841381913472
-0.8671998890121841381913472
949
polyexp()
mpmath.polyexp(s, z)
Evaluates the polyexponential function, dened for arbitrary complex s, z by the series
Es (z) =
ks
k=1
k!
zk .
Es (z) is constructed from the exponential function analogously to how the polylogarithm
is constructed from the ordinary logarithm; as a function of s (with z xed), Es is an
L-series It is an entire function of both s and z.
The polyexponential function provides a generalization of the Bell polynomials Bn (x) (see
bell() (page 960)) to noninteger orders n. In terms of the Bell polynomials,
Es (z) = ez Bs (z) sinc(s).
Note that Bn (x) and ex En (x) are identical if n is a nonzero integer, but not otherwise. In
particular, they dier at n = 0.
Examples
Evaluating a series:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> nsum(lambda k: sqrt(k)/fac(k), [1,inf])
2.101755547733791780315904
>>> polyexp(0.5,1)
2.101755547733791780315904
950
4.042192318847986561771779
>>> x*hyper([1]*(n+1), [2]*(n+1), x)
4.042192318847986561771779
1
ps
p
where the sum is taken over all prime numbers p. Although this sum only converges for
Re(s) > 1, the function is dened by analytic continuation in the half-plane Re(s) > 0.
Examples
Arbitrary-precision evaluation for real and complex arguments is supported:
>>> from sympy.mpmath import *
>>> mp.dps = 30; mp.pretty = True
>>> primezeta(2)
0.452247420041065498506543364832
>>> primezeta(pi)
0.15483752698840284272036497397
>>> mp.dps = 50
>>> primezeta(3)
0.17476263929944353642311331466570670097541212192615
>>> mp.dps = 20
>>> primezeta(3+4j)
(-0.12085382601645763295 - 0.013370403397787023602j)
The prime zeta function has a logarithmic pole at s = 1, with residue equal to the dierence of the Mertens and Euler constants:
>>> primezeta(1)
+inf
>>> extradps(25)(lambda x: primezeta(1+x)+log(x))(+eps)
-0.31571845205389007685
>>> mertens-euler
-0.31571845205389007685
The analytic continuation to 0 < Re(s) 1 is implemented. In this strip the function exhibits very complex behavior; on the unit interval, it has poles at 1/n for every squarefree
integer n:
>>> primezeta(0.5)
# Pole at s = 1/2
(-inf + 3.1415926535897932385j)
>>> primezeta(0.25)
(-1.0416106801757269036 + 0.52359877559829887308j)
>>> primezeta(0.5+10j)
(0.54892423556409790529 + 0.45626803423487934264j)
Although evaluation works in principle for any Re(s) > 0, it should be noted that the
evaluation time increases exponentially as s approaches the imaginary axis.
5.15. Welcome to mpmaths documentation!
951
References
Carl-Erik Froberg, On the prime zeta function, BIT 8 (1968), pp. 187-202.
secondzeta()
mpmath.secondzeta(s, a=0.015, **kwargs)
Evaluates the secondary zeta function Z(s), dened for Re(s) > 1 by
Z(s) =
where
1
2
1
s
n=1 n
Z(s) extends to a meromorphic function on C with a double pole at s = 1 and simple poles
at the points 2n for n = 0, 1, 2, ...
Examples
>>> from sympy.mpmath import *
>>> mp.pretty = True; mp.dps = 15
>>> secondzeta(2)
0.023104993115419
>>> xi = lambda s: 0.5*s*(s-1)*pi**(-0.5*s)*gamma(0.5*s)*zeta(s)
>>> Xi = lambda t: xi(0.5+t*j)
>>> -0.5*diff(Xi,0,n=2)/Xi(0)
(0.023104993115419 + 0.0j)
The function has poles at the negative odd integers, and dyadic rational values at the
negative even integers:
>>> mp.dps = 30
>>> secondzeta(-8)
-0.67236328125
>>> secondzeta(-7)
+inf
Implementation notes
The function is computed as sum of four terms Z(s) = A(s) P (s) + E(s) S(s) respectively
main, prime, exponential and singular terms. The main term A(s) is computed from the
zeros of zeta. The prime term depends on the von Mangoldt function. The singular term
is responsible for the poles of the function.
952
The four terms depends on a small parameter a. We may change the value of a. Theoretically this has no eect on the sum of the four terms, but in practice may be important.
A smaller value of the parameter a makes A(s) depend on a smaller number of zeros of
zeta, but P (s) uses more values of von Mangoldt function.
We may also add a verbose option to obtain data about the values of the four terms.
>>> mp.dps = 10
>>> secondzeta(0.5 + 40j, error=True, verbose=True)
main term = (-30190318549.138656312556 - 13964804384.624622876523j)
computed using 19 zeros of zeta
prime term = (132717176.89212754625045 + 188980555.17563978290601j)
computed using 9 values of the von Mangoldt function
exponential term = (542447428666.07179812536 + 362434922978.80192435203j)
singular term = (512124392939.98154322355 + 348281138038.65531023921j)
((0.059471043 + 0.3463514534j), 1.455191523e-11)
>>> secondzeta(0.5 + 40j, a=0.04, error=True, verbose=True)
main term = (-151962888.19606243907725 - 217930683.90210294051982j)
computed using 9 zeros of zeta
prime term = (2476659342.3038722372461 + 28711581821.921627163136j)
computed using 37 values of the von Mangoldt function
exponential term = (178506047114.7838188264 + 819674143244.45677330576j)
singular term = (175877424884.22441310708 + 790744630738.28669174871j)
((0.059471043 + 0.3463514534j), 1.455191523e-11)
Notice the great cancellation between the four terms. Changing a, the four terms are
very dierent numbers but the cancellation gives the good value of Z(s).
References
A. Voros, Zeta functions for the Riemann zeros, Ann.
665699.
A. Voros, Zeta functions over Zeros of Zeta Functions, Lecture Notes of the Unione
Matematica Italiana, Springer, 2009.
Number-theoretical, combinatorial and integer functions
For factorial-type functions, including binomial coecients, double factorials, etc., see the
separate section Factorials and gamma functions (page 777).
Fibonacci numbers
fibonacci()/fib()
mpmath.fibonacci(n, **kwargs)
fibonacci(n) computes the n-th Fibonacci number, F (n). The Fibonacci numbers are
dened by the recurrence F (n) = F (n1)+F (n2) with the initial values F (0) = 0, F (1) = 1.
fibonacci() (page 953) extends this denition to arbitrary real and complex arguments
using the formula
F (z) =
z cos(z)z
953
where is the golden ratio. fibonacci() (page 953) also uses this continuous formula
to compute F (n) for extremely large n, where calculating the exact integer would be
wasteful.
For convenience, fib() is available as an alias for fibonacci() (page 953).
Basic examples
Some small Fibonacci numbers are:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> for i in range(10):
...
print(fibonacci(i))
...
0.0
1.0
1.0
2.0
3.0
5.0
8.0
13.0
21.0
34.0
>>> fibonacci(50)
12586269025.0
Large Fibonacci numbers will be computed approximately unless the precision is set
high enough:
>>> fib(200)
2.8057117299251e+41
>>> mp.dps = 45
>>> fib(200)
280571172992510140037611932413038677189525.0
954
The Fibonacci function has innitely many roots on the negative half-real axis. The rst
root is at 0, the second is close to -0.18, and then there are innitely many roots that
asymptotically approach n + 1/2:
>>> findroot(fib, -0.2)
-0.183802359692956
>>> findroot(fib, -2)
-1.57077646820395
>>> findroot(fib, -17)
-16.4999999596115
>>> findroot(fib, -24)
-23.5000000000479
Mathematical relationships
For large n, F (n + 1)/F (n) approaches the golden ratio:
>>> mp.dps = 50
>>> fibonacci(101)/fibonacci(100)
1.6180339887498948482045868343656381177203127439638
>>> +phi
1.6180339887498948482045868343656381177203091798058
The sum of reciprocal Fibonacci numbers converges to an irrational number for which
no closed form expression is known:
>>> mp.dps = 15
>>> nsum(lambda n: 1/fib(n), [1, inf])
3.35988566624318
Amazingly, however, the sum of odd-index reciprocal Fibonacci numbers can be expressed in terms of a Jacobi theta function:
>>> nsum(lambda n: 1/fib(2*n+1), [0, inf])
1.82451515740692
>>> sqrt(5)*jtheta(2,0,(3-sqrt(5))/2)**2/4
1.82451515740692
955
>>> phi-1
0.618033988749895
References
1.http://mathworld.wolfram.com/FibonacciNumber.html
Bernoulli numbers and polynomials
bernoulli()
mpmath.bernoulli(n)
Computes the nth Bernoulli number, Bn , for any integer n 0.
The Bernoulli numbers are rational numbers, but this function returns a oating-point
approximation. To obtain an exact fraction, use bernfrac() (page 957) instead.
Examples
Numerical values of the rst few Bernoulli numbers:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> for n in range(15):
...
print(%s %s % (n, bernoulli(n)))
...
0 1.0
1 -0.5
2 0.166666666666667
3 0.0
4 -0.0333333333333333
5 0.0
6 0.0238095238095238
7 0.0
8 -0.0333333333333333
9 0.0
10 0.0757575757575758
11 0.0
12 -0.253113553113553
13 0.0
14 1.16666666666667
The Bernoulli numbers are related to the Riemann zeta function at integer arguments:
>>> -bernoulli(8) * (2*pi)**8 / (2*fac(8))
1.00407735619794
>>> zeta(8)
1.00407735619794
956
Algorithm
For small n (n < 3000) bernoulli() (page 956) uses a recurrence formula due to Ramanujan. All results in this range are cached, so sequential computation of small Bernoulli
numbers is guaranteed to be fast.
For larger n, Bn is evaluated in terms of the Riemann zeta function.
bernfrac()
mpmath.bernfrac(n)
Returns a tuple of integers (p, q) such that p/q = Bn exactly, where Bn denotes the n-th
Bernoulli number. The fraction is always reduced to lowest terms. Note that for n > 1
and n odd, Bn = 0, and (0, 1) is returned.
Examples
The rst few Bernoulli numbers are exactly:
>>> from sympy.mpmath import *
>>> for n in range(15):
...
p, q = bernfrac(n)
...
print(%s %s/%s % (n, p, q))
...
0 1/1
1 -1/2
2 1/6
3 0/1
4 -1/30
5 0/1
6 1/42
7 0/1
8 -1/30
9 0/1
10 5/66
11 0/1
12 -691/2730
13 0/1
14 7/6
Note: bernoulli() (page 956) computes a oating-point approximation directly, without computing the exact fraction rst. This is much faster for large n.
Algorithm
bernfrac() (page 957) works by computing the value of Bn numerically and then using
the von Staudt-Clausen theorem [1] to reconstruct the exact fraction. For large n, this is
5.15. Welcome to mpmaths documentation!
957
En n
t .
sech(t) =
n!
n=0
958
The Euler numbers are closely related to Bernoulli numbers and Bernoulli polynomials.
They can also be evaluated in terms of Euler polynomials (see eulerpoly() (page 959))
as En = 2n En (1/2).
Examples
Computing the rst few Euler numbers and verifying that they agree with the Taylor
series:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> [eulernum(n) for n in range(11)]
[1.0, 0.0, -1.0, 0.0, 5.0, 0.0, -61.0, 0.0, 1385.0, 0.0, -50521.0]
>>> chop(diffs(sech, 0, 10))
[1.0, 0.0, -1.0, 0.0, 5.0, 0.0, -61.0, 0.0, 1385.0, 0.0, -50521.0]
Euler numbers grow very rapidly. eulernum() (page 958) eciently computes numerical
approximations for large indices:
>>> eulernum(50)
-6.053285248188621896314384e+54
>>> eulernum(1000)
3.887561841253070615257336e+2371
>>> eulernum(10**20)
4.346791453661149089338186e+1936958564106659551331
eulerpoly()
mpmath.eulerpoly(n, z)
Evaluates the Euler polynomial En (z), dened by the generating function representation
tn
2ezt
=
E
(z)
.
n
et + 1 n=0
n!
The Euler polynomials may also be represented in terms of Bernoulli polynomials (see
bernpoly() (page 958)) using various formulas, for example
( z ))
2 (
En (z) =
Bn (z) 2n+1 Bn
.
n+1
2
Special values include the Euler numbers En = 2n En (1/2) (see eulernum() (page 958)).
Examples
Computing the coecients of the rst few Euler polynomials:
5.15. Welcome to mpmaths documentation!
959
960
of which are
B0 (x) = 1
B1 (x) = x
B2 (x) = x2 + x
B3 (x) = x3 + 3x2 + x
If x = 1 or bell() (page 960) is called with only one argument, it gives the n-th Bell
number Bn , which is the number of partitions of a set with n elements. By setting the
precision to at least log10 Bn digits, bell() (page 960) provides fast calculation of exact
Bell numbers.
In general, bell() (page 960) computes
Bn (x) = ex (sinc(n) + En (x))
where En (x) is the generalized exponential function implemented by polyexp()
(page 950). This is an extension of Dobinskis formula [1], where the modication is
the sinc term ensuring that Bn (x) is continuous in n; bell() (page 960) can thus be
evaluated, dierentiated, etc for arbitrary complex arguments.
Examples
Simple evaluations:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> bell(0, 2.5)
1.0
>>> bell(1, 2.5)
2.5
>>> bell(2, 2.5)
8.75
961
>>> mp.dps = 50
>>> bell(50)
185724268771078270438257767181908917499221852770.0
>>> bell(50,-1)
-29113173035759403920216141265491160286912.0
References
1.http://mathworld.wolfram.com/DobinskisFormula.html
Stirling numbers
stirling1()
mpmath.stirling1(n, k, exact=False)
Gives the Stirling number of the rst kind s(n, k), dened by
x(x 1)(x 2) (x n + 1) =
s(n, k)xk .
k=0
The value is computed using an integer recurrence. The implementation is not optimized
for approximating large values quickly.
Examples
Comparing with the generating function:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> taylor(lambda x: ff(x, 5), 0, 5)
[0.0, 24.0, -50.0, 35.0, -10.0, 1.0]
>>> [stirling1(5, k) for k in range(6)]
[0.0, 24.0, -50.0, 35.0, -10.0, 1.0]
Recurrence relation:
>>> n, k = 5, 3
>>> stirling1(n+1,k) + n*stirling1(n,k) - stirling1(n,k-1)
0.0
962
The matrices of Stirling numbers of rst and second kind are inverses of each other:
>>> A = matrix(5, 5); B = matrix(5, 5)
>>> for n in range(5):
...
for k in range(5):
...
A[n,k] = stirling1(n,k)
...
B[n,k] = stirling2(n,k)
...
>>> A * B
[1.0 0.0 0.0 0.0 0.0]
[0.0 1.0 0.0 0.0 0.0]
[0.0 0.0 1.0 0.0 0.0]
[0.0 0.0 0.0 1.0 0.0]
[0.0 0.0 0.0 0.0 1.0]
stirling2()
mpmath.stirling2(n, k, exact=False)
Gives the Stirling number of the second kind S(n, k), dened by
xn =
k=0
The value is computed using integer arithmetic to evaluate a power sum. The implementation is not optimized for approximating large values quickly.
Examples
Comparing with the generating function:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> taylor(lambda x: sum(stirling2(5,k) * ff(x,k) for k in range(6)), 0, 5)
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
Recurrence relation:
>>> n, k = 5, 3
>>> stirling2(n+1,k) - k*stirling2(n,k) - stirling2(n,k-1)
0.0
963
primepi()
mpmath.primepi(x)
Evaluates the prime counting function, (x), which gives the number of primes less than
or equal to x. The argument x may be fractional.
The prime counting function is very expensive to evaluate precisely for large x, and the
present implementation is not optimized in any way. For numerical approximation of
the prime counting function, it is better to use primepi2() (page 964) or riemannr()
(page 965).
Some values of the prime counting function:
>>> from sympy.mpmath import *
>>> [primepi(k) for k in range(20)]
[0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8]
>>> primepi(3.5)
2
>>> primepi(100000)
9592
primepi2()
mpmath.primepi2(x)
Returns an interval (as an mpi instance) providing bounds for the value of the prime
counting function (x). For small x, primepi2() (page 964) returns an exact interval
based on the output of primepi() (page 964). For x > 2656, a loose interval based on
Schoenfelds inequality
x log x
|(x) li(x)| <
8
is returned. This estimate is rigorous assuming the truth of the Riemann hypothesis, and
can be computed very quickly.
Examples
Exact values of the prime counting function for small x:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> iv.dps = 15; iv.pretty = True
>>> primepi2(10)
[4.0, 4.0]
>>> primepi2(100)
[25.0, 25.0]
>>> primepi2(1000)
[168.0, 168.0]
As x increases, the absolute error gets worse while the relative error improves. The
exact value of (1023 ) is 1925320391606803968923, and primepi2() (page 964) gives 9
signicant digits:
964
>>> p = primepi2(10**23)
>>> p
[1.9253203909477020467e+21, 1.925320392280406229e+21]
>>> mpf(p.delta) / mpf(p.a)
6.9219865355293e-10
A more precise, nonrigorous estimate for (x) can be obtained using the Riemann R function (riemannr() (page 965)). For large enough x, the value returned by primepi2()
(page 964) essentially amounts to a small perturbation of the value returned by riemannr() (page 965):
>>> primepi2(10**100)
[4.3619719871407024816e+97, 4.3619719871407032404e+97]
>>> riemannr(10**100)
4.3619719871407e+97
riemannr()
mpmath.riemannr(x)
Evaluates the Riemann R function, a smooth approximation of the prime counting function (x) (see primepi() (page 964)). The Riemann R function gives a fast numerical
approximation useful e.g. to roughly estimate the number of primes in a given interval.
The Riemann R function is computed using the rapidly convergent Gram series,
R(x) = 1 +
k=1
log x
.
kk!(k + 1)
From the Gram series, one sees that the Riemann R function is a well-dened analytic
function (except for a branch cut along the negative real half-axis); it can be evaluated
for arbitrary real or complex arguments.
The Riemann R function gives a very accurate approximation of the prime counting function. For example, it is wrong by at most 2 for x < 1000, and for x = 109 diers from the
exact value of (x) by 79, or less than two parts in a million. It is about 10 times more
accurate than the logarithmic integral estimate (see li() (page 799)), which however is
even faster to evaluate. It is orders of magnitude more accurate than the extremely fast
x/ log x estimate.
Examples
For small arguments, the Riemann R function almost exactly gives the prime counting
function if rounded to the nearest integer:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> primepi(50), riemannr(50)
(15, 14.9757023241462)
>>> max(abs(primepi(n)-int(round(riemannr(n)))) for n in range(100))
1
>>> max(abs(primepi(n)-int(round(riemannr(n)))) for n in range(300))
2
The Riemann R function can be evaluated for arguments far too large for exact determination of (x) to be computationally feasible with any presently known algorithm:
>>> riemannr(10**30)
1.46923988977204e+28
>>> riemannr(10**100)
965
4.3619719871407e+97
>>> riemannr(10**1000)
4.3448325764012e+996
A comparison of the Riemann R function and logarithmic integral estimates for (x) using
exact values of (10n ) up to n = 9. The fractional error is shown in parentheses:
>>> exact = [4,25,168,1229,9592,78498,664579,5761455,50847534]
>>> for n, p in enumerate(exact):
...
n += 1
...
r, l = riemannr(10**n), li(10**n)
...
rerr, lerr = nstr((r-p)/p,3), nstr((l-p)/p,3)
...
print(%i %i %s(%s) %s(%s) % (n, p, r, rerr, l, lerr))
...
1 4 4.56458314100509(0.141) 6.1655995047873(0.541)
2 25 25.6616332669242(0.0265) 30.1261415840796(0.205)
3 168 168.359446281167(0.00214) 177.609657990152(0.0572)
4 1229 1226.93121834343(-0.00168) 1246.13721589939(0.0139)
5 9592 9587.43173884197(-0.000476) 9629.8090010508(0.00394)
6 78498 78527.3994291277(0.000375) 78627.5491594622(0.00165)
7 664579 664667.447564748(0.000133) 664918.405048569(0.000511)
8 5761455 5761551.86732017(1.68e-5) 5762209.37544803(0.000131)
9 50847534 50847455.4277214(-1.55e-6) 50849234.9570018(3.35e-5)
The derivative of the Riemann R function gives the approximate probability for a number
of magnitude x to be prime:
>>> diff(riemannr, 1000)
0.141903028110784
>>> mpf(primepi(1050) - primepi(950)) / 100
0.15
Cyclotomic polynomials
cyclotomic()
mpmath.cyclotomic(n, x)
Evaluates the cyclotomic polynomial n (x), dened by
n (x) =
(x )
where ranges over all primitive n-th roots of unity (see unitroots() (page 754)). An
equivalent representation, used for computation, is
n (x) =
(xd 1)(n/d) = n (x)
d|n
966
where (m) denotes the Moebius function. The cyclotomic polynomials are integer polynomials, the rst of which can be written explicitly as
0 (x) = 1
1 (x) = x 1
2 (x) = x + 1
3 (x) = x3 + x2 + 1
4 (x) = x2 + 1
5 (x) = x4 + x3 + x2 + x + 1
6 (x) = x2 x + 1
Examples
The coecients of low-order cyclotomic polynomials can be recovered using Taylor expansion:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> for n in range(9):
...
p = chop(taylor(lambda x: cyclotomic(n,x), 0, 10))
...
print(%s %s % (n, nstr(p[:10+1-p[::-1].index(1)])))
...
0 [1.0]
1 [-1.0, 1.0]
2 [1.0, 1.0]
3 [1.0, 1.0, 1.0]
4 [1.0, 0.0, 1.0]
5 [1.0, 1.0, 1.0, 1.0, 1.0]
6 [1.0, -1.0, 1.0]
7 [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
8 [1.0, 0.0, 0.0, 0.0, 1.0]
The denition as a product over primitive roots may be checked by computing the product explicitly (for a real argument, this method will generally introduce numerical noise
in the imaginary part):
>>> mp.dps = 25
>>> z = 3+4j
>>> cyclotomic(10, z)
(-419.0 - 360.0j)
>>> fprod(z-r for r in unitroots(10, primitive=True))
(-419.0 - 360.0j)
>>> z = 3
>>> cyclotomic(10, z)
61.0
>>> fprod(z-r for r in unitroots(10, primitive=True))
(61.0 - 3.146045605088568607055454e-25j)
967
>>>
>>> for r in unitroots(6, primitive=True):
...
print(r)
...
(0.5 + 0.8660254037844386467637232j)
(0.5 - 0.8660254037844386467637232j)
Arithmetic functions
mangoldt()
mpmath.mangoldt(n)
Evaluates the von Mangoldt function (n) = log p if n = pk a power of a prime, and (n) = 0
otherwise.
Examples
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> [mangoldt(n) for n in range(-2,3)]
[0.0, 0.0, 0.0, 0.0, 0.6931471805599453094172321]
>>> mangoldt(6)
0.0
>>> mangoldt(7)
1.945910149055313305105353
>>> mangoldt(8)
0.6931471805599453094172321
>>> fsum(mangoldt(n) for n in range(101))
94.04531122935739224600493
>>> fsum(mangoldt(n) for n in range(10001))
10013.39669326311478372032
q-functions
q-Pochhammer symbol
qp()
mpmath.qp(a, q=None, n=None, **kwargs)
Evaluates the q-Pochhammer symbol (or q-rising factorial)
(a; q)n =
n1
(1 aq k )
k=0
where n = is permitted if |q| < 1. Called with two arguments, qp(a,q) computes (a; q) ;
with a single argument, qp(q) computes (q; q) . The special case
(q) = (q; q) =
(1 q ) =
k=1
(1)k q (3k
k)/2
k=
is also known as the Euler function, or (up to a factor q 1/24 ) the Dedekind eta function.
Examples
If n is a positive integer, the function amounts to a nite product:
968
The Taylor series of the reciprocal Euler function gives the partition function P (n), i.e.
the number of ways of writing n as a sum of positive integers:
>>> taylor(lambda q: 1/qp(q), 0, 10)
[1.0, 1.0, 2.0, 3.0, 5.0, 7.0, 11.0, 15.0, 22.0, 30.0, 42.0]
# location of maximum
The q-Pochhammer symbol is related to the Jacobi theta functions. For example, the
following identity holds:
>>> q = mpf(0.5)
# arbitrary
>>> qp(q)
0.2887880950866024212788997
>>> root(3,-2)*root(q,-24)*jtheta(2,pi/6,root(q,6))
0.2887880950866024212788997
(q; q)
(1 q)1z .
(q z ; q)
Examples
Evaluation for real and complex arguments:
5.15. Welcome to mpmaths documentation!
969
The q-gamma function satises a functional equation similar to that of the ordinary
gamma function:
>>> q = mpf(0.25)
>>> z = mpf(2.5)
>>> qgamma(z+1,q)
1.428277424823760954685912
>>> (1-q**z)/(1-q)*qgamma(z,q)
1.428277424823760954685912
qfac()
mpmath.qfac(z, q, **kwargs)
Evaluates the q-factorial,
[n]q ! = (1 + q)(1 + q + q 2 ) (1 + q + + q n1 )
or more generally
[z]q ! =
(q; q)z
.
(1 q)z
Examples
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> qfac(0,0)
1.0
>>> qfac(4,3)
2080.0
>>> qfac(5,6)
121226245.0
>>> qfac(1+1j, 2+1j)
(0.4370556551322672478613695 + 0.2609739839216039203708921j)
Hypergeometric q-series
qhyper()
mpmath.qhyper(a s, b s, q, z, **kwargs)
Evaluates the basic hypergeometric series or hypergeometric q-series
[
]
)1+sr z n
n
(a1 ; q)n , . . . , (ar ; q)n (
a1 a2 . . . ar
(1)n q ( 2 )
; q, z =
r s
b1 b2 . . . bs
(b1 ; q)n , . . . , (bs ; q)n
(q; q)n
n=0
where (a; q)n denotes the q-Pochhammer symbol (see qp() (page 968)).
Examples
Evaluation works for real and complex arguments:
970
Comparing with a summation of the dening series, using nsum() (page 979):
>>> b, q, z = 3, 0.25, 0.5
>>> qhyper([], [b], q, z)
0.6221136748254495583228324
>>> nsum(lambda n: z**n / qp(q,q,n)/qp(b,q,n) * q**(n*(n-1)), [0,inf])
0.6221136748254495583228324
Numerical calculus
Polynomials
The coecients and the evaluation point may be any combination of real or complex
numbers.
Polynomial roots (polyroots)
mpmath.polyroots(ctx, coes, maxsteps=50, cleanup=True,
ror=False)
Computes all roots (real or complex) of a given polynomial.
extraprec=10,
er-
The roots are returned as a sorted list, where real roots appear rst followed by complex conjugate roots as adjacent elements. The polynomial should be given as a list of
coecients, in the format used by polyval() (page 971). The leading coecient must
be nonzero.
With error=True, polyroots() (page 971) returns a tuple (roots, err) where err is an
estimate of the maximum error among the computed roots.
5.15. Welcome to mpmaths documentation!
971
Examples
Finding the three real roots of x3 x2 14x + 24:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> nprint(polyroots([1,-1,-14,24]), 4)
[-4.0, 2.0, 3.0]
Finding the two complex conjugate roots of 4x2 + 3x + 2, with an error estimate:
>>> roots, err = polyroots([4,3,2], error=True)
>>> for r in roots:
...
print(r)
...
(-0.375 + 0.59947894041409j)
(-0.375 - 0.59947894041409j)
>>>
>>> err
2.22044604925031e-16
>>>
>>> polyval([4,3,2], roots[0])
(2.22044604925031e-16 + 0.0j)
>>> polyval([4,3,2], roots[1])
(2.22044604925031e-16 + 0.0j)
The following example computes all the 5th roots of unity; that is, the roots of x5 1:
>>> mp.dps = 20
>>> for r in polyroots([1, 0, 0, 0, 0, -1]):
...
print(r)
...
1.0
(-0.8090169943749474241 + 0.58778525229247312917j)
(-0.8090169943749474241 - 0.58778525229247312917j)
(0.3090169943749474241 + 0.95105651629515357212j)
(0.3090169943749474241 - 0.95105651629515357212j)
972
3.14626436994197234232913506571557044551247712918732870123249
>>>
>>> sqrt(3) + sqrt(2)
3.14626436994197234232913506571557044551247712918732870123249
>>> sqrt(3) - sqrt(2)
0.317837245195782244725757617296174288373133378433432554879127
Algorithm
polyroots() (page 971) implements the Durand-Kerner method [1], which uses complex arithmetic to locate all roots simultaneously. The Durand-Kerner method can be
viewed as approximately performing simultaneous Newton iteration for all the roots. In
particular, the convergence to simple roots is quadratic, just like Newtons method.
Although all roots are internally calculated using complex arithmetic, any root found to
have an imaginary part smaller than the estimated numerical error is truncated to a real
number (small real parts are also chopped). Real roots are placed rst in the returned
list, sorted by value. The remaining complex roots are sorted by their real parts so that
conjugate roots end up next to each other.
References
1.http://en.wikipedia.org/wiki/Durand-Kerner method
Root-nding and optimization
Root-nding (findroot)
mpmath.findroot(f, x0, solver=Secant, tol=None, verbose=False, verify=True,
**kwargs)
Find a solution to f (x) = 0, using x0 as starting point or interval for x.
Multidimensional overdetermined systems are supported. You can specify them using a
function or a list of functions.
If the found root does not satisfy |f (x)2 < tol|, an exception is raised (this can be disabled
with verify=False).
Arguments
f one dimensional function
x0 starting point, several starting points or interval (depends on solver)
tol the returned solution has an error smaller than this
verbose print additional information for each iteration if true
verify verify the solution and raise a ValueError if |f (x) > tol|
solver a generator for f and x0 returning approximative solution and error
maxsteps after how many steps the solver will cancel
df rst derivative of f (used by some solvers)
d2f second derivative of f (used by some solvers)
multidimensional force multidimensional solving
J Jacobian matrix of f (used by multidimensional solvers)
norm used vector norm (used by multidimensional solvers)
973
solver has to be callable with (f, x0, **kwargs) and return an generator yielding
pairs of approximative solution and estimated error (which is expected to be positive).
You can use the following string aliases: secant, mnewton, halley, muller, illinois,
pegasus, anderson, ridder, anewton, bisect
See mpmath.optimization for their documentation.
Examples
The function findroot() (page 973) locates a root of a given function using the secant
method by default. A simple example use of the secant method is to compute as the
root of sin x closest to x0 = 3:
>>> from sympy.mpmath import *
>>> mp.dps = 30; mp.pretty = True
>>> findroot(sin, 3)
3.14159265358979323846264338328
The secant method can be used to nd complex roots of analytic functions, although it
must in that case generally be given a nonreal starting value (or else it will never leave
the real line):
>>> mp.dps = 15
>>> findroot(lambda x: x**3 + 2*x + 1, j)
(0.226698825758202 + 1.46771150871022j)
A nice application is to compute nontrivial roots of the Riemann zeta function with many
digits (good initial values are needed for convergence):
>>> mp.dps = 30
>>> findroot(zeta, 0.5+14j)
(0.5 + 14.1347251417346937904572519836j)
The secant method can also be used as an optimization algorithm, by passing it a derivative of a function. The following example locates the positive minimum of the gamma
function:
>>> mp.dps = 20
>>> findroot(lambda x: diff(gamma, x), 1)
1.4616321449683623413
974
Multiple roots
For multiple roots all methods of the Newtonian family (including secant) converge
slowly. Consider this example:
>>> f = lambda x: (x - 1)**99
>>> findroot(f, 0.9, verify=False)
0.918073542444929
Even for a very close starting point the secant method converges very slowly. Use verbose=True to illustrate this.
It is possible to modify Newtons method to make it converge regardless of the roots
multiplicity:
>>> findroot(f, -10, solver=mnewton)
1.0
This variant uses the rst and second derivative of the function, which is not very ecient.
Alternatively you can use an experimental Newtonian solver that keeps track of the speed
of convergence and accelerates it using Steensens method if necessary:
>>> findroot(f, -10, solver=anewton, verbose=True)
x:
-9.88888888888888888889
error: 0.111111111111111111111
converging slowly
x:
-9.77890011223344556678
error: 0.10998877665544332211
converging slowly
x:
-9.67002233332199662166
error: 0.108877778911448945119
converging slowly
accelerating convergence
x:
-9.5622443299551077669
error: 0.107778003366888854764
converging slowly
x:
0.99999999999999999214
error: 10.562244329955107759
x:
1.0
975
error: 7.8598304758094664213e-18
ZeroDivisionError: canceled with x = 1.0
1.0
Complex roots
For complex roots its recommended to use Mullers method as it converges even for real
starting points very fast:
>>> findroot(lambda x: x**4 + x + 1, (0, 1, 2), solver=muller)
(0.727136084491197 + 0.934099289460529j)
Intersection methods
When you need to nd a root in a known interval, its highly recommended to use an
intersection-based solver like anderson or ridder. Usually they converge faster
and more reliable. They have however problems with multiple roots and usually need a
sign change to nd a root:
>>> findroot(lambda x: x**3, (-1, 1), solver=anderson)
0.0
It fails even for better starting points, because there is no sign change:
>>> findroot(lambda x: x**2, (-1, .5), solver=anderson)
Traceback (most recent call last):
...
ValueError: Could not find root within given tolerance. (1 > 2.1684e-19)
Try another starting point or tweak arguments.
Traceback (most recent call last):
...
ValueError: Could not find root within given tolerance. (1 > 2.1684e-19)
Solvers
class mpmath.calculus.optimization.Secant(ctx, f, x0, **kwargs)
1d-solver generating pairs of approximative root and error.
Needs starting points x0 and x1 close to the root. x1 defaults to x0 + 0.25.
Pro:
converges fast
Contra:
converges slowly for multiple roots
class mpmath.calculus.optimization.Newton(ctx, f, x0, **kwargs)
1d-solver generating pairs of approximative root and error.
converges fast
sometimes more robust than secant with bad second starting point
Contra:
converges slowly for multiple roots
needs rst derivative
2 function evaluations per iteration
Contra:
needs rst and second derivative of f
3 function evaluations per iteration
Contra:
needs rst and second derivative of f
3 function evaluations per iteration
converges slowly for multiple roots
Contra:
converges slowly for multiple roots
may have complex values for real starting points and real roots
http://en.wikipedia.org/wiki/Mullers method
class mpmath.calculus.optimization.Bisection(ctx, f, x0, **kwargs)
1d-solver generating pairs of approximative root and error.
Uses bisection method to nd a root of f in [a, b]. Might fail for multiple roots (needs
sign change).
5.15. Welcome to mpmaths documentation!
977
Pro:
robust and reliable
Contra:
converges slowly
needs sign change
Contra:
has problems with multiple roots
needs sign change
class mpmath.calculus.optimization.Pegasus
1d-solver generating pairs of approximative root and error.
Uses Pegasus method to nd a root of f in [a, b].
method=pegasus.
class mpmath.calculus.optimization.Anderson
1d-solver generating pairs of approximative root and error.
Uses Anderson-Bjoerk method to nd a root of f in [a, b]. Wrapper for illinois to use
method=pegasus.
class mpmath.calculus.optimization.Ridder(ctx, f, x0, **kwargs)
1d-solver generating pairs of approximative root and error.
Ridders method to nd a root of f in [a, b]. Is told to perform as well as Brents method
while being simpler.
Pro:
very fast
simpler than Brents method
Contra:
two function evaluations per step
has problems with multiple roots
needs sign change
http://en.wikipedia.org/wiki/Ridders method
978
The functions listed here permit approximation of innite sums, products, and other sequence
limits. Use mpmath.fsum() (page 732) and mpmath.fprod() (page 732) for summation and
multiplication of nite sequences.
Summation
nsum()
mpmath.nsum(ctx, f, *intervals, **options)
Computes the sum
S=
f (k)
k=a
where (a, b) = interval, and where a = and/or b = are allowed, or more generally
S=
b1
k1 =a1
bn
f (k1 , . . . , kn )
kn =an
979
When appropriate, nsum() (page 979) applies convergence acceleration to accurately estimate the sums of slowly convergent series. If the series is nite, nsum() (page 979) currently does not attempt to perform any extrapolation, and simply calls fsum() (page 732).
Multidimensional innite series are reduced to a single-dimensional series over expanding hypercubes; if both innite and nite dimensions are present, the nite ranges are
moved innermost. For more advanced control over the summation order, use nested
calls to nsum() (page 979), or manually rewrite the sum as a single-dimensional series.
Options
tol Desired maximum nal error. Defaults roughly to the epsilon of the working precision.
method Which summation algorithm to use (described below). Default: richardson+shanks.
maxterms Cancel after at most this many terms. Default: 10*dps.
steps An iterable giving the number of terms to add between each extrapolation attempt. The default sequence is [10, 20, 30, 40, ...]. For example, if you know that
approximately 100 terms will be required, eciency might be improved by setting
this to [100, 10]. Then the rst extrapolation will be performed after 100 terms, the
second after 110, etc.
verbose Print details about progress.
ignore If enabled, any term that raises ArithmeticError or ValueError (e.g. through
division by zero) is replaced by a zero. This is convenient for lattice sums with a
singular term near the origin.
Methods
Unfortunately, an algorithm that can eciently sum any innite series does not exist.
nsum() (page 979) implements several dierent algorithms that each work well in different cases. The method keyword argument selects a method.
The default method is r+s, i.e. both Richardson extrapolation and Shanks transformation is attempted. A slower method that handles more cases is r+s+e. For very high
precision summation, or if the summation needs to be fast (for example if multiple sums
need to be evaluated), it is a good idea to investigate which one method works best and
only use that.
richardson / r: Uses Richardson extrapolation. Provides useful extrapolation
when f (k) P (k)/Q(k) or when f (k) (1)k P (k)/Q(k) for polynomials P and Q. See
richardson() (page 991) for additional information.
shanks / s: Uses Shanks transformation. Typically provides useful extrapolation
when f (k) ck or when successive terms alternate signs. Is able to sum some divergent series. See shanks() (page 992) for additional information.
levin / l: Uses the Levin transformation. It performs better than the Shanks
transformation for logarithmic convergent or alternating divergent series. The
levin variant-keyword selects the variant. Valid choices are u, t, v and
980
all whereby all uses all three u,t and v simultanously (This is good for performance comparison in conjunction with verbose=True). Instead of the Levin transform one can also use the Sidi-S transform by selecting the method sidi. See
levin() (page 994) for additional details.
alternating / a: This is the convergence acceleration of alternating series developped by Cohen, Villegras and Zagier. See cohen alt() (page 998) for additional
details.
euler-maclaurin / e: Uses the Euler-Maclaurin summation formula to approximate the remainder sum by an integral. This requires high-order numerical derivatives and numerical integration. The advantage of this algorithm is that it works
regardless of the decay rate of f , as long as f is suciently smooth. See sumem()
(page 986) for additional information.
direct / d: Does not perform any extrapolation. This can be used (and should only
be used for) rapidly convergent series. The summation automatically stops when
the terms decrease below the target tolerance.
Basic examples
A nite sum:
>>> nsum(lambda k: 1/k, [1, 6])
2.45
The following sum converges very rapidly, so it is most ecient to sum it by disabling
convergence acceleration:
>>> mp.dps = 1000
>>> a = nsum(lambda k: -(-1)**k * k**2 / fac(2*k), [1, inf],
...
method=direct)
>>> b = (cos(1)+sin(1))/4
>>> abs(a-b) < mpf(1e-998)
True
981
2.9348022005446793094172454999380755676568497036204
>>> pi**2/2-2
2.9348022005446793094172454999380755676568497036204
>>> nsum(lambda k: (-1)**k / k**3, [1, inf],
...
method=richardson)
-0.90154267736969571404980362113358749307373971925537
>>> -3*zeta(3)/4
-0.90154267736969571404980362113358749307373971925538
Finally, Shanks method works very well for alternating series where f (k) = (1)k g(k),
and often does so regardless of the exact decay rate of g(k):
>>> mp.dps = 15
>>> nsum(lambda k: (-1)**(k+1) / k**1.5, [1, inf],
...
method=shanks)
0.765147024625408
>>> (2-sqrt(2))*zeta(1.5)/2
0.765147024625408
The following slowly convergent alternating series has no known closed-form value.
Evaluating the sum a second time at higher precision indicates that the value is probably
correct:
>>> nsum(lambda k: (-1)**k / log(k), [2, inf],
...
method=shanks)
0.924299897222939
>>> mp.dps = 30
>>> nsum(lambda k: (-1)**k / log(k), [2, inf],
...
method=shanks)
0.92429989722293885595957018136
982
Now we sum the zeta function outside its range of convergence (attention: This does not
work at the negative integers!):
>>> mp.dps = 15
>>> w = mp.nsum(lambda n: n ** (2 + 3j), [1, mp.inf], method = levin, levin_variant = v)
>>> print(mp.chop(w - mp.zeta(-2-3j)))
0.0
mp.dps = 15
z = mp.mpf(10)
# exact = mp.quad(lambda x: mp.exp(-x)/(1+x/z),[0,mp.inf])
exact = z * mp.exp(z) * mp.expint(1,z) # this is the symbolic expression for the integral
w = mp.nsum(lambda n: (-1) ** n * mp.fac(n) * z ** (-n), [0, mp.inf], method = sidi, levin
print(mp.chop(w - exact))
Following highly divergent asymptotic expansion needs some care. Firstly we need copious amount of working precision. Secondly the stepsize must not be chosen to large,
otherwise nsum may miss the point where the Levin transform converges and reach the
point where only numerical garbage is produced due to numerical cancellation.
>>>
>>>
>>>
>>>
>>>
...
>>>
0.0
mp.dps = 15
z = mp.mpf(2)
# exact = mp.quad(lambda x: mp.exp( -x * x / 2 - z * x ** 4), [0,mp.inf]) * 2 / mp.sqrt(2 *
exact = mp.exp(mp.one / (32 * z)) * mp.besselk(mp.one / 4, mp.one / (32 * z)) / (4 * mp.sqrt
w = mp.nsum(lambda n: (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n)),
[0, mp.inf], method = levin, levin_variant = t, workprec = 8*mp.prec, steps = [2] + [1
print(mp.chop(w - exact))
The hypergeoemtric function can also be summed outside its range of convergence:
>>>
>>>
>>>
>>>
>>>
>>>
0.0
mp.dps = 15
z = 2 + 1j
exact = mp.hyp2f1(2 / mp.mpf(3), 4 / mp.mpf(3), 1 / mp.mpf(3), z)
f = lambda n: mp.rf(2 / mp.mpf(3), n) * mp.rf(4 / mp.mpf(3), n) * z**n / (mp.rf(1 / mp.mpf(3
v = mp.nsum(f, [0, mp.inf], method = levin, steps = [10 for x in xrange(1000)])
print(mp.chop(exact-v))
The derivate of the alternating zeta function outside its range of convergence:
>>> v = mp.nsum(lambda n: (-1)**n * mp.log(n) * n, [1, mp.inf], method = a)
>>> print(mp.chop(v - mp.diff(lambda s: mp.altzeta(s), -1)))
0.0
983
The sum in the following example has the wrong rate of convergence for either Richardson or Shanks to be eective.
>>> f = lambda k: log(k)/k**2.5
>>> mp.dps = 15
>>> nsum(f, [1, inf], method=euler-maclaurin)
0.38734195032621
>>> -diff(zeta, 2.5)
0.38734195032621
Divergent series
The Shanks transformation is able to sum some divergent series. In particular, it is often
able to sum Taylor series beyond their radius of convergence (this is due to a relation between the Shanks transformation and Pade approximations; see pade() (page 1015) for
an alternative way to evaluate divergent Taylor series). Furthermore the Levin-transform
examples above contain some divergent series resummation.
Here we apply it to log(1 + x) far outside the region of convergence:
>>> mp.dps = 50
>>> nsum(lambda k: -(-9)**k/k, [1, inf],
...
method=shanks)
2.3025850929940456840179914546843642076011014886288
>>> log(10)
2.3025850929940456840179914546843642076011014886288
A particular type of divergent series that can be summed using the Shanks transformation is geometric series. The result is the same as using the closed-form formula for an
innite geometric series:
>>> mp.dps = 15
>>> for n in range(-8, 8):
...
if n == 1:
...
continue
...
print(%s %s %s % (mpf(n), mpf(1)/(1-n),
...
nsum(lambda k: n**k, [0, inf], method=shanks)))
...
-8.0 0.111111111111111 0.111111111111111
-7.0 0.125 0.125
-6.0 0.142857142857143 0.142857142857143
-5.0 0.166666666666667 0.166666666666667
-4.0 0.2 0.2
-3.0 0.25 0.25
-2.0 0.333333333333333 0.333333333333333
-1.0 0.5 0.5
0.0 1.0 1.0
2.0 -1.0 -1.0
3.0 -0.5 -0.5
4.0 -0.333333333333333 -0.333333333333333
5.0 -0.25 -0.25
6.0 -0.2 -0.2
984
Multidimensional sums
Any combination of nite and innite ranges is allowed for the summation indices:
>>> mp.dps = 15
>>> nsum(lambda
28.0
>>> nsum(lambda
6.0
>>> nsum(lambda
6.0
>>> nsum(lambda
7.0
>>> nsum(lambda
7.0
>>> nsum(lambda
7.0
Some nice examples of double series with analytic solutions or reductions to singledimensional series (see [1]):
>>> nsum(lambda m, n: 1/2**(m*n), [1,inf], [1,inf])
1.60669515241529
>>> nsum(lambda n: 1/(2**n-1), [1,inf])
1.60669515241529
>>> nsum(lambda i,j: (-1)**(i+j)/(i**2+j**2), [1,inf], [1,inf])
0.278070510848213
>>> pi*(pi-3*ln2)/12
0.278070510848213
>>> nsum(lambda i,j: (-1)**(i+j)/(i+j)**2, [1,inf], [1,inf])
0.129319852864168
>>> altzeta(2) - altzeta(1)
0.129319852864168
>>> nsum(lambda i,j: (-1)**(i+j)/(i+j)**3, [1,inf], [1,inf])
0.0790756439455825
>>> altzeta(3) - altzeta(2)
0.0790756439455825
>>> nsum(lambda m,n: m**2*n/(3**m*(n*3**m+m*3**n)),
...
[1,inf], [1,inf])
0.28125
>>> mpf(9)/32
0.28125
>>> nsum(lambda i,j: fac(i-1)*fac(j-1)/fac(i+j),
...
[1,inf], [1,inf], workprec=400)
1.64493406684823
>>> zeta(2)
1.64493406684823
985
References
1.[Weisstein] (page 1910) http://mathworld.wolfram.com/DoubleSeries.html,
2.[Weisstein] (page 1910) http://mathworld.wolfram.com/MadelungConstants.html
sumem()
mpmath.sumem(ctx, f, interval, tol=None, reject=10, integral=None, adis=None, bdis=None, verbose=False, error=False, fast abort=False)
Uses the Euler-Maclaurin formula to compute an approximation accurate to within tol
(which defaults to the present epsilon) of the sum
S=
f (k)
k=a
where (a, b) are given by interval and a or b may be innite. The approximation is
f (x) dx +
a
)
f (a) + f (b) B2k ( (2k1)
+
f
(b) f (2k1) (a) .
2
(2k)!
k=1
The last sum in the Euler-Maclaurin formula is not generally convergent (a notable exception is if f is a polynomial, in which case Euler-Maclaurin actually gives an exact
result).
The summation is stopped as soon as the quotient between two consecutive terms falls
below reject. That is, by default (reject = 10), the summation is continued as long as
each term adds at least one decimal.
Although not convergent, convergence to a given tolerance can often be forced if b =
by summing up to a + N and then applying the Euler-Maclaurin formula to the sum over
the range (a + N + 1, . . . , ). This procedure is implemented by nsum() (page 979).
By default numerical quadrature and dierentiation is used. If the symbolic values of the
integral and endpoint derivatives are known, it is more ecient to pass the value of the
integral explicitly as integral and the derivatives explicitly as adiffs and bdiffs. The
derivatives should be given as iterables that yield f (a), f 0 (a), f 00 (a), . . . (and the equivalent
for b).
986
Examples
Summation of an innite series, with automatic and symbolic integral and derivative
values (the second should be much faster):
>>> from sympy.mpmath import *
>>> mp.dps = 50; mp.pretty = True
>>> sumem(lambda n: 1/n**2, [32, inf])
0.03174336652030209012658168043874142714132886413417
>>> I = mpf(1)/32
>>> D = adiffs=((-1)**n*fac(n+1)*32**(-2-n) for n in range(999))
>>> sumem(lambda n: 1/n**2, [32, inf], integral=I, adiffs=D)
0.03174336652030209012658168043874142714132886413417
sumap()
mpmath.sumap(ctx, f, interval, integral=None, error=False)
Evaluates an innite series of an analytic summand f using the Abel-Plana formula
k=0
f (k) =
0
1
f (t)dt + f (0) + i
2
f (it) f (it)
dt.
e2t 1
Unlike the Euler-Maclaurin formula (see sumem() (page 986)), the Abel-Plana formula
does not require derivatives. However, it only works when |f (it)f (it)| does not increase
too rapidly with t.
Examples
The Abel-Plana formula is particularly useful when the summand decreases like a power
of k; for example when the sum is a pure zeta function:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> sumap(lambda k: 1/k**2.5, [1,inf])
1.34148725725091717975677
>>> zeta(2.5)
1.34148725725091717975677
>>> sumap(lambda k: 1/(k+1j)**(2.5+2.5j), [1,inf])
(-3.385361068546473342286084 - 0.7432082105196321803869551j)
>>> zeta(2.5+2.5j, 1+1j)
(-3.385361068546473342286084 - 0.7432082105196321803869551j)
If the series is alternating, numerical quadrature along the real line is likely to give poor
results, so it is better to evaluate the rst term symbolically whenever possible:
>>> n=3; z=-0.75
>>> I = expint(n,-log(z))
>>> chop(sumap(lambda k: z**k / k**n, [1,inf], integral=I))
-0.6917036036904594510141448
>>> polylog(n,z)
-0.6917036036904594510141448
987
Products
nprod()
mpmath.nprod(ctx, f, interval, nsum=False, **kwargs)
Computes the product
P =
f (k)
k=a
P = exp
log(f (k)) .
k=a
This is slower, but can sometimes yield better results. It is also required (and used
automatically) when Euler-Maclaurin summation is requested.
Examples
A simple nite product:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> nprod(lambda k: k, [1, 4])
24.0
A large number of innite products have known exact values, and can therefore be used
as a reference. Most of the following examples are taken from MathWorld [1].
A few innite products with simple values are:
>>> 2*nprod(lambda k: (4*k**2)/(4*k**2-1), [1, inf])
3.141592653589793238462643
>>> nprod(lambda k: (1+1/k)**2/(1+2/k), [1, inf])
2.0
>>> nprod(lambda k: (k**3-1)/(k**3+1), [2, inf])
0.6666666666666666666666667
>>> nprod(lambda k: (1-1/k**2), [2, inf])
0.5
988
0.8480540493529003921296502
>>> nprod(lambda k: (1+1/k+1/k**2)**2/(1+2/k+3/k**2), [1, inf])
1.848936182858244485224927
>>> 3*sqrt(2)*cosh(pi*sqrt(3)/2)**2*csch(pi*sqrt(2))/pi
1.848936182858244485224927
>>> nprod(lambda k: (1-1/k**4), [2, inf]); sinh(pi)/(4*pi)
0.9190194775937444301739244
0.9190194775937444301739244
>>> nprod(lambda k: (1-1/k**6), [2, inf])
0.9826842777421925183244759
>>> (1+cosh(pi*sqrt(3)))/(12*pi**2)
0.9826842777421925183244759
>>> nprod(lambda k: (1+1/k**2), [2, inf]); sinh(pi)/(2*pi)
1.838038955187488860347849
1.838038955187488860347849
>>> nprod(lambda n: (1+1/n)**n * exp(1/(2*n)-1), [1, inf])
1.447255926890365298959138
>>> exp(1+euler/2)/sqrt(2*pi)
1.447255926890365298959138
The following two products are equivalent and can be evaluated in terms of a Jacobi
theta function. Pi can be replaced by any value (as long as convergence is preserved):
>>> nprod(lambda k: (1-pi**-k)/(1+pi**-k), [1, inf])
0.3838451207481672404778686
>>> nprod(lambda k: tanh(k*log(pi)/2), [1, inf])
0.3838451207481672404778686
>>> jtheta(4,0,1/pi)
0.3838451207481672404778686
References
989
A limit for :
>>> f = lambda n: 2**(4*n+1)*fac(n)**4/(2*n+1)/fac(2*n)**2
>>> limit(f, inf)
3.14159265358979323846264338328
990
With default settings, the following limit converges too slowly to be evaluated accurately.
Changing to exponential sampling however gives a perfect result:
>>> f = lambda x: sqrt(x**3+x**2)/(sqrt(x**3)+x)
>>> limit(f, inf)
0.992831158558330281129249686491
>>> limit(f, inf, exp=True)
1.0
Extrapolation The following functions provide a direct interface to extrapolation algorithms. nsum() and limit() essentially work by calling the following functions with an increasing number of terms until the extrapolated limit is accurate enough.
The following functions may be useful to call directly if the precise number of terms needed
to achieve a desired accuracy is known in advance, or if one wishes to study the convergence
properties of the algorithms.
richardson()
mpmath.richardson(ctx, seq)
Given a list seq of the rst N elements of a slowly convergent innite sequence, richardson() (page 991) computes the N -term Richardson extrapolate for the limit.
richardson() (page 991) returns (v, c) where v is the estimated limit and c is the magnitude of the largest weight used during the computation. The weight provides an estimate
of the precision lost to cancellation. Due to cancellation eects, the sequence must be
typically be computed at a much higher precision than the target accuracy of the extrapolation.
Applicability and issues
The N -step Richardson extrapolation algorithm used by richardson() (page 991) is described in [1].
Richardson extrapolation only works for a specic type of sequence, namely one converging like partial sums of P (1)/Q(1) + P (2)/Q(2) + . . . where P and Q are polynomials. When
the sequence does not convergence at such a rate richardson() (page 991) generally
produces garbage.
991
Richardson extrapolation has the advantage of being fast: the N -term extrapolate requires only O(N ) arithmetic operations, and usually produces an estimate that is accurate to O(N ) digits. Contrast with the Shanks transformation (see shanks() (page 992)),
which requires O(N 2 ) operations.
richardson() (page 991) is unable to produce an estimate for the approximation error.
One way to estimate the error is to perform two extrapolations with slightly dierent N
and comparing the results.
Richardson extrapolation does not work for oscillating sequences.
As a simple
workaround, richardson() (page 991) detects if the last three elements do not dier
monotonically, and in that case applies extrapolation only to the even-index elements.
Example
Applying Richardson extrapolation to the Leibniz series for :
>>> from sympy.mpmath import *
>>> mp.dps = 30; mp.pretty = True
>>> S = [4*sum(mpf(-1)**n/(2*n+1) for n in range(m))
...
for m in range(1,30)]
>>> v, c = richardson(S[:10])
>>> v
3.2126984126984126984126984127
>>> nprint([v-pi, c])
[0.0711058, 2.0]
>>> v, c = richardson(S[:30])
>>> v
3.14159265468624052829954206226
>>> nprint([v-pi, c])
[1.09645e-9, 20833.3]
References
1.[BenderOrszag] (page 1910) pp. 375-376
shanks()
mpmath.shanks(ctx, seq, table=None, randomized=False)
Given a list seq of the rst N elements of a slowly convergent innite sequence (Ak ), shanks() (page 992) computes the iterated Shanks transformation
S(A), S(S(A)), . . . , S N /2 (A). The Shanks transformation often provides strong convergence
acceleration, especially if the sequence is oscillating.
The iterated Shanks transformation is computed using the Wynn epsilon algorithm (see
[1]). shanks() (page 992) returns the full epsilon table generated by Wynns algorithm,
which can be read o as follows:
The table is a list of lists forming a lower triangular matrix, where higher row and
column indices correspond to more accurate values.
The columns with even index hold dummy entries (required for the computation)
and the columns with odd index hold the actual extrapolates.
The last element in the last row is typically the most accurate estimate of the limit.
The dierence to the third last element in the last row provides an estimate of the
approximation error.
The magnitude of the second last element provides an estimate of the numerical
accuracy lost to cancellation.
992
For convenience, so the extrapolation is stopped at an odd index so that shanks(seq)[1][-1] always gives an estimate of the limit.
Optionally, an existing table can be passed to shanks() (page 992). This can be used
to eciently extend a previous computation after new elements have been appended to
the sequence. The table will then be updated in-place.
The Shanks transformation
The Shanks transformation is dened as follows (see [2]): given the input sequence
(A0 , A1 , . . .), the transformed sequence is given by
S(Ak ) =
The Shanks transformation gives the exact limit A in a single step if Ak = A + aq k . Note
in particular that it extrapolates the exact sum of a geometric series in a single step.
Applying the Shanks transformation once often improves convergence substantially for
an arbitrary sequence, but the optimal eect is obtained by applying it iteratively:
S(S(Ak )), S(S(S(Ak ))), . . ..
Wynns epsilon algorithm provides an ecient way to generate the table of iterated
Shanks transformations. It reduces the computation of each element to essentially a
single division, at the cost of requiring dummy elements in the table. See [1] for details.
Precision issues
Due to cancellation eects, the sequence must be typically be computed at a much higher
precision than the target accuracy of the extrapolation.
If the Shanks transformation converges to the exact limit (such as if the sequence is
a geometric series), then a division by zero occurs. By default, shanks() (page 992)
handles this case by terminating the iteration and returning the table it has generated so
far. With randomized=True, it will instead replace the zero by a pseudorandom number
close to zero. (TODO: nd a better solution to this problem.)
Examples
We illustrate by applying Shanks transformation to the Leibniz series for :
>>> from sympy.mpmath import *
>>> mp.dps = 50
>>> S = [4*sum(mpf(-1)**n/(2*n+1) for n in range(m))
...
for m in range(1,30)]
>>>
>>> T = shanks(S[:7])
>>> for row in T:
...
nprint(row)
...
[-0.75]
[1.25, 3.16667]
[-1.75, 3.13333, -28.75]
[2.25, 3.14524, 82.25, 3.14234]
[-2.75, 3.13968, -177.75, 3.14139, -969.937]
[3.25, 3.14271, 327.25, 3.14166, 3515.06, 3.14161]
The extrapolated accuracy is about 4 digits, and about 4 digits may have been lost due
to cancellation:
>>> L = T[-1]
>>> nprint([abs(L[-1] - pi), abs(L[-1] - L[-3]), abs(L[-2])])
[2.22532e-5, 4.78309e-5, 3515.06]
993
The value for pi is now accurate to 18 digits. About 18 digits may also have been lost to
cancellation.
Here is an example with a geometric series, where the convergence is immediate (the
sum is exactly 1):
>>> mp.dps = 15
>>> for row in shanks([0.5, 0.75, 0.875, 0.9375, 0.96875]):
...
nprint(row)
[4.0]
[8.0, 1.0]
References
1.[GravesMorris] (page 1910)
2.[BenderOrszag] (page 1910) pp. 368-375
levin()
mpmath.levin(ctx, method=levin, variant=u)
This interface implements Levins (nonlinear) sequence transformation for convergence acceleration and summation of divergent series. It performs better than the
Shanks/Wynn-epsilon algorithm for logarithmic convergent or alternating divergent series.
Let A be the series we want to sum:
A=
ak
k=0
ak .
k=0
Methods
Calling levin returns an object with the following methods.
update(...) works with the list of individual terms ak of A, and update step(...)
works with the list of partial sums sk of A:
v, e = ...update([a_0, a_1,..., a_k])
v, e = ...update_psum([s_0, s_1,..., s_k])
step(...) works with the individual terms ak and step psum(...) works with the partial sums sk :
v, e = ...step(a_k)
v, e = ...step_psum(s_k)
994
v is the current estimate for A, and e is an error estimate which is simply the dierence between the current estimate and the last estimate. One should not mix update,
update psum, step and step psum.
A word of caution
One can only hope for good results (i.e. convergence acceleration or resummation) if the
sn have some well dend asymptotic behavior for large n and are not erratic or random.
Furthermore one usually needs very high working precision because of the numerical
cancellation. If the working precision is insucient, levin may produce silently numerical garbage. Furthermore even if the Levin-transformation converges, in the general
case there is no proof that the result is mathematically sound. Only for very special
classes of problems one can prove that the Levin-transformation converges to the expected result (for example Stieltjes-type integrals). Furthermore the Levin-transform is
quite expensive (i.e. slow) in comparison to Shanks/Wynn-epsilon, Richardson & co. In
summary one can say that the Levin-transformation is powerful but unreliable and that
it may need a copious amount of working precision.
The Levin transform has several variants diering in the choice of weights. Some variants are better suited for the possible avours of convergence behaviour of A than other
variants:
convergence behaviour
logarithmic
linear
alternating divergent
levin-u
+
+
+
levin-t
+
+
levin-v
+
+
+
shanks/wynn-epsilon
+
+
The variant is controlled though the variant keyword (i.e. variant=u, variant=t or
variant=v). Overall u is probably the best choice.
Finally it is possible to use the Sidi-S transform instead of the Levin transform by using
the keyword method=sidi. The Sidi-S transform works better than the Levin transformation for some divergent series (see the examples).
Parameters:
method
variant
The Levin transform is also accessible through the nsum interface. method=l or
method=levin select the normal Levin transform while method=sidi selects the
Sidi-S transform. The variant is in both cases selected through the levin variant keyword. The stepsize in nsum() (page 979) must not be chosen too large, otherwise it
will miss the point where the Levin transform converges resulting in numerical overow/garbage. For highly divergent series a copious amount of working precision must
be chosen.
Examples
First we sum the zeta function:
>>>
>>>
>>>
>>>
...
995
...
S, s, n = [], 0, 1
...
while 1:
...
s += mp.one / (n * n)
...
n += 1
...
S.append(s)
...
v, e = L.update_psum(S)
...
if e < eps:
...
break
...
if n > 1000: raise RuntimeError(iteration limit exceeded)
>>> print(mp.chop(v - mp.pi ** 2 / 6))
0.0
>>> w = mp.nsum(lambda n: 1 / (n*n), [1, mp.inf], method = levin, levin_variant = u)
>>> print(mp.chop(v - w))
0.0
Now we sum the zeta function outside its range of convergence (attention: This does not
work at the negative integers!):
>>>
>>>
...
...
...
...
...
...
...
...
...
...
>>>
0.0
>>>
>>>
0.0
eps = mp.mpf(mp.eps)
with mp.extraprec(2 * mp.prec): # levin needs a high working precision
L = mp.levin(method = levin, variant = v)
A, n = [], 1
while 1:
s = mp.mpf(n) ** (2 + 3j)
n += 1
A.append(s)
v, e = L.update(A)
if e < eps:
break
if n > 1000: raise RuntimeError(iteration limit exceeded)
print(mp.chop(v - mp.zeta(-2-3j)))
w = mp.nsum(lambda n: n ** (2 + 3j), [1, mp.inf], method = levin, levin_variant = v)
print(mp.chop(v - w))
Now we sum the divergent asymptotic expansion of an integral related to the exponential
integral (see also [2] p.373). The Sidi-S transform works best here:
>>>
>>>
>>>
>>>
>>>
...
...
...
...
...
...
...
...
...
>>>
0.0
>>>
>>>
0.0
996
z = mp.mpf(10)
exact = mp.quad(lambda x: mp.exp(-x)/(1+x/z),[0,mp.inf])
# exact = z * mp.exp(z) * mp.expint(1,z) # this is the symbolic expression for the integral
eps = mp.mpf(mp.eps)
with mp.extraprec(2 * mp.prec): # high working precisions are mandatory for divergent resumm
L = mp.levin(method = sidi, variant = t)
n = 0
while 1:
s = (-1)**n * mp.fac(n) * z ** (-n)
v, e = L.step(s)
n += 1
if e < eps:
break
if n > 1000: raise RuntimeError(iteration limit exceeded)
print(mp.chop(v - exact))
z = mp.mpf(2)
eps = mp.mpf(mp.eps)
exact = mp.quad(lambda x: mp.exp( -x * x / 2 - z * x ** 4), [0,mp.inf]) *
# exact = mp.exp(mp.one / (32 * z)) * mp.besselk(mp.one / 4, mp.one / (32
with mp.extraprec(7 * mp.prec): # we need copious amount of precision to
L = mp.levin(method = levin, variant = t)
n, s = 0, 0
while 1:
s += (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 **
n += 1
v, e = L.step_psum(s)
if e < eps:
break
if n > 1000: raise RuntimeError(iteration limit exceeded)
print(mp.chop(v - exact))
2 / mp.sqrt(2 * mp
* z)) / (4 * mp.sq
sum this highly di
n))
These examples run with 15-20 decimal digits precision. For higher precision the working precision must be raised.
Examples for nsum
Here we calculate Eulers constant as the constant term in the Laurent expansion of (s)
at s = 1. This sum converges extremly slowly because of the logarithmic convergence
behaviour of the Dirichlet series for zeta:
>>>
>>>
>>>
>>>
0.0
mp.dps = 30
z = mp.mpf(10) ** (-10)
a = mp.nsum(lambda n: n**(-(1+z)), [1, mp.inf], method = l) - 1 / z
print(mp.chop(a - mp.euler, tol = 1e-10))
The Sidi-S transform performs excellently for the alternating series of log(2):
>>> a = mp.nsum(lambda n: (-1)**(n-1) / n, [1, mp.inf], method = sidi)
>>> print(mp.chop(a - mp.log(2)))
0.0
Hypergeometric series can also be summed outside their range of convergence. The
stepsize in nsum() (page 979) must not be chosen too large, otherwise it will miss the
point where the Levin transform converges resulting in numerical overow/garbage:
>>>
>>>
>>>
>>>
>>>
0.0
z = 2 + 1j
exact = mp.hyp2f1(2 / mp.mpf(3), 4 / mp.mpf(3), 1 / mp.mpf(3), z)
f = lambda n: mp.rf(2 / mp.mpf(3), n) * mp.rf(4 / mp.mpf(3), n) * z**n / (mp.rf(1 / mp.mpf(3
v = mp.nsum(f, [0, mp.inf], method = levin, steps = [10 for x in xrange(1000)])
print(mp.chop(exact-v))
References:
[1] E.J. Weniger - Nonlinear Sequence Transformations for the Acceleration of
Convergence and the Summation of Divergent Series arXiv:math/0306302
[2] A. Sidi - Pratical Extrapolation Methods
997
Scalar
Levin-Type
Sequence
Transformations
cohen alt()
mpmath.cohen alt(ctx)
This interface implements the convergence acceleration of alternating series as described in H. Cohen, F.R. Villegas, D. Zagier - Convergence Acceleration of Alternating
Series. This series transformation works only well if the individual terms of the series
have an alternating sign. It belongs to the class of linear series transformations (in contrast to the Shanks/Wynn-epsilon or Levin transform). This series transformation is also
able to sum some types of divergent series. See the paper under which conditions this
resummation is mathematical sound.
Let A be the series we want to sum:
A=
ak
k=0
ak .
k=0
Interface
Calling cohen alt returns an object with the following methods.
Then update(...) works with the list of individual terms ak and update psum(...)
works with the list of partial sums sk :
v, e = ...update([a_0, a_1,..., a_k])
v, e = ...update_psum([s_0, s_1,..., s_k])
v is the current estimate for A, and e is an error estimate which is simply the dierence
between the current estimate and the last estimate.
Examples
Here we compute the alternating zeta function using update psum:
>>>
>>>
>>>
>>>
...
...
...
...
...
...
...
>>>
0.0
n=1
>>> A = []
>>> AC = mp.cohen_alt()
>>> n = 1
998
>>> while 1:
...
A.append( mp.loggamma(1 + mp.one / (2 * n - 1)))
...
A.append(-mp.loggamma(1 + mp.one / (2 * n)))
...
n += 1
...
v, e = AC.update(A)
...
if e < mp.eps:
...
break
...
if n > 1000: raise RuntimeError(iteration limit exceeded)
>>> v = mp.exp(v)
>>> print(mp.chop(v - 1.06215090557106, tol = 1e-12))
0.0
cohen alt is also accessible through the nsum() (page 979) interface:
>>>
>>>
0.0
>>>
>>>
0.0
>>>
>>>
0.0
Dierentiation
# exp(x) = exp(x)
Even more generally, given a tuple of arguments (x1 , . . . , xk ) and order (n1 , . . . , nk ), the
partial derivative f (n1 ,...,nk ) (x1 , . . . , xk ) is evaluated. For example:
>>> diff(lambda x,y: 3*x*y + 2*y - x, (0.25, 0.5), (0,1))
2.75
>>> diff(lambda x,y: 3*x*y + 2*y - x, (0.25, 0.5), (1,1))
3.0
Options
The following optional keyword arguments are recognized:
method Supported methods are step or quad: derivatives may be computed using
either a nite dierence with a small step size h (default), or numerical quadrature.
999
direction Direction of nite dierence: can be -1 for a left dierence, 0 for a central
dierence (default), or +1 for a right dierence; more generally can be any complex
number.
addprec Extra precision for h used to account for the functions sensitivity to perturbations (default = 10).
relative Choose h relative to the magnitude of x, rather than an absolute value; useful
for large or tiny x (default = False).
h As an alternative to addprec and relative, manually select the step size h.
singular If True, evaluation exactly at the point x is avoided; this is useful for dierentiating functions with removable singularities. Default = False.
radius Radius of integration contour (with method = quad). Default = 0.25. A larger
radius typically is faster and more accurate, but it must be chosen so that f has no
singularities within the radius from the evaluation point.
A nite dierence requires n + 1 function evaluations and must be performed at (n + 1)
times the target precision. Accordingly, f must support fast evaluation at high precision.
With integration, a larger number of function evaluations is required, but not much extra
precision is required. For high order derivatives, this method may thus be faster if f is
very expensive to evaluate at high precision.
Further examples
The direction option is useful for computing left- or right-sided derivatives of nonsmooth
functions:
>>> diff(abs, 0, direction=0)
0.0
>>> diff(abs, 0, direction=1)
1.0
>>> diff(abs, 0, direction=-1)
-1.0
More generally, if the direction is nonzero, a right dierence is computed where the step
size is multiplied by sign(direction). For example, with direction=+j, the derivative from
the positive imaginary direction will be computed:
>>> diff(abs, 0, direction=j)
(0.0 - 1.0j)
With integration, the result may have a small imaginary part even even if the result is
purely real:
>>> diff(sqrt, 1, method=quad)
(0.5 - 4.59...e-26j)
>>> chop(_)
0.5
1000
1001
-12.4632923122697
-12.4632923122697
Examples
There is an exact formula for the fractional derivative of a monomial xp , which may be
used as a reference. For example, the following gives a half-derivative (order 0.5):
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> x = mpf(3); p = 2; n = 0.5
>>> differint(lambda t: t**p, x, n)
7.81764019044672
>>> gamma(p+1)/gamma(p-n+1) * x**(p-n)
7.81764019044672
Another useful test function is the exponential function, whose integration / dierentiation formula easy generalizes to arbitrary order. Here we rst compute a third derivative, and then a triply nested integral. (The reference point x0 is set to to avoid
nonzero endpoint terms.):
>>> differint(lambda x: exp(pi*x), -1.5, 3)
0.278538406900792
>>> exp(pi*-1.5) * pi**3
0.278538406900792
>>> differint(lambda x: exp(pi*x), 3.5, -3, -inf)
1922.50563031149
>>> exp(pi*3.5) / pi**3
1922.50563031149
However, for noninteger n, the dierentiation formula for the exponential function must
be modied to give the same result as the Riemann-Liouville dierintegral:
>>> x = mpf(3.5)
>>> c = pi
>>> n = 1+2*j
>>> differint(lambda x: exp(c*x), x, n)
(-123295.005390743 + 140955.117867654j)
>>> x**(-n) * exp(c)**x * (x*c)**n * gammainc(-n, 0, x*c) / gamma(-n)
(-123295.005390743 + 140955.117867654j)
A basic 2D integral:
>>> f = lambda x, y: cos(x+y/2)
>>> quad(f, [-pi/2, pi/2], [0, pi])
4.0
Interval format
1003
The integration range for each dimension may be specied using a list or tuple. Arguments are interpreted as follows:
x
quad(f, [x1, x2]) calculates x12 f (x) dx
x y
quad(f, [x1, x2], [y1, y2]) calculates x12 y12 f (x, y) dy dx
x y z
quad(f, [x1, x2], [y1, y2], [z1, z2]) calculates x12 y12 z12 f (x, y, z) dz dy dx
Endpoints may be nite or innite. An interval descriptor may also contain more than
two points. In this case, the integration is split into subintervals, between each pair
of consecutive points. This is useful for dealing with mid-interval discontinuities, or
integrating over large intervals where the function is irregular or oscillates.
Options
quad() (page 1003) recognizes the following keyword arguments:
method Chooses integration algorithm (described below).
error If set to true, quad() (page 1003) returns (v, e) where v is the integral and e is the
estimated error.
maxdegree Maximum degree of the quadrature rule to try before quitting.
verbose Print details about progress.
Algorithms
Mpmath presently implements two integration algorithms: tanh-sinh quadrature
and Gauss-Legendre quadrature.
These can be selected using method=tanhsinh or method=gauss-legendre or by passing the classes method=TanhSinh,
method=GaussLegendre. The functions quadts() and quadgl() are also available as
shortcuts.
Both algorithms have the property that doubling the number of evaluation points roughly
doubles the accuracy, so both are ideal for high precision quadrature (hundreds or thousands of digits).
At high precision, computing the nodes and weights for the integration can be expensive
(more expensive than computing the function values). To make repeated integrations
fast, nodes are automatically cached.
The advantages of the tanh-sinh algorithm are that it tends to handle endpoint singularities well, and that the nodes are cheap to compute on the rst run. For these reasons,
it is used by quad() (page 1003) as the default algorithm.
Gauss-Legendre quadrature often requires fewer function evaluations, and is therefore
often faster for repeated use, but the algorithm does not handle endpoint singularities
as well and the nodes are more expensive to compute. Gauss-Legendre quadrature can
be a better choice if the integrand is smooth and repeated integrations are required (e.g.
for multiple integrals).
See the documentation for TanhSinh and GaussLegendre for additional details.
Examples of 1D integrals
Intervals may be innite or half-innite.
The following two examples evaluate the lim
its
of
the
inverse
tangent
function
(
1/(1
+ x2 ) = tan1 x), and the Gaussian integral
2
exp(x ) dx = :
>>> mp.dps = 15
>>> quad(lambda x: 2/(x**2+1), [0, inf])
3.14159265358979
1004
Integrals can typically be resolved to high precision. The following computes 50 digits
of by integrating the area of the half-circle dened by x2 + y 2 1, 1 x 1, y 0:
>>> mp.dps = 50
>>> 2*quad(lambda x: sqrt(1-x**2), [-1, 1])
3.1415926535897932384626433832795028841971693993751
Complex integrals are supported. The following computes a residue at z = 0 by integrating counterclockwise along the diamond-shaped path from 1 to +i to 1 to i to 1:
>>> mp.dps = 15
>>> chop(quad(lambda z: 1/z, [1,j,-1,-j,1]))
(0.0 + 6.28318530717959j)
1005
For nonrectangular areas, one can call quad() (page 1003) recursively. For example, we
can replicate the earlier example of calculating by integrating over the unit-circle, and
actually use double quadrature to actually measure the area circle:
>>> f = lambda x: quad(lambda y: 1, [-sqrt(1-x**2), sqrt(1-x**2)])
>>> quad(f, [-1, 1])
3.14159265358979
Singularities
Both tanh-sinh and Gauss-Legendre quadrature are designed to integrate smooth (innitely dierentiable) functions. Neither algorithm copes well with mid-interval singularities (such as mid-interval discontinuities in f (x) or f 0 (x)). The best solution is to split
the integral into parts:
>>> mp.dps = 15
>>> quad(lambda x: abs(sin(x)), [0, 2*pi])
# Bad
3.99900894176779
>>> quad(lambda x: abs(sin(x)), [0, pi, 2*pi]) # Good
4.0
The tanh-sinh rule often works well for integrands having a singularity at one or both
endpoints:
>>> mp.dps = 15
>>> quad(log, [0, 1], method=tanh-sinh) # Good
-1.0
>>> quad(log, [0, 1], method=gauss-legendre) # Bad
-0.999932197413801
This problem is not due to the quadrature rule per se, but to numerical amplication of
errors in the nodes. The problem can be circumvented by temporarily increasing the
precision:
>>>
>>>
>>>
>>>
2.0
mp.dps = 30
a = quad(lambda x: 1/sqrt(x), [0, 1], method=tanh-sinh)
mp.dps = 15
+a
1006
# Good
# Also good
Whether splitting the interval or increasing the degree is more ecient diers from case
to case. Another example is the function 1/(1 + x2 ), which has a sharp peak centered
around x = 0:
>>> f = lambda x: 1/(1+x**2)
>>> quad(f, [-100, 100])
# Bad
3.64804647105268
>>> quad(f, [-100, 100], maxdegree=10)
# Good
3.12159332021646
>>> quad(f, [-100, 0, 100])
# Also good
3.12159332021646
References
1.http://mathworld.wolfram.com/DoubleIntegral.html
Oscillatory quadrature (quadosc)
mpmath.quadosc(ctx, f, interval, omega=None, period=None, zeros=None)
Calculates
b
I=
f (x)dx
a
where at least one of a and b is innite and where f (x) = g(x) cos(x + ) for some slowly
decreasing function g(x). With proper input, quadosc() (page 1007) can also handle
oscillatory integrals where the oscillation rate is dierent from a pure sine or cosine
wave.
In the standard case when |a| < , b = , quadosc() (page 1007) works by evaluating
the innite series
x1
xk+1
I=
f (x)dx +
f (x)dx
a
k=1
xk
where xk are consecutive zeros (alternatively some other periodic reference point) of
f (x). Accordingly, quadosc() (page 1007) requires information about the zeros of f (x).
For a periodic function, you can specify the zeros by either providing the angular frequency (omega) or the period 2/. In general, you can specify the n-th zero by providing the zeros arguments. Below is an example of each:
1007
Note that zeros was specied to multiply n by the half-period, not the full period. In theory, it does not matter whether each partial integral is done over a half period or a full period. However, if done over half-periods, the innite series passed to nsum() (page 979)
becomes an alternating series and this typically makes the extrapolation much more
ecient.
Here is an example of an integration over the entire real line, and a half-innite integration starting at :
>>> quadosc(lambda x: cos(x)/(1+x**2), [-inf, inf], omega=1)
1.15572734979092
>>> pi/e
1.15572734979092
>>> quadosc(lambda x: cos(x)/x**2, [-inf, -1], period=2*pi)
-0.0844109505595739
>>> cos(1)+si(1)-pi/2
-0.0844109505595738
Of course, the integrand may contain a complex exponential just as well as a real sine
or cosine:
>>> quadosc(lambda x: exp(3*j*x)/(1+x**2), [-inf,inf], omega=3)
(0.156410688228254 + 0.0j)
>>> pi/e**3
0.156410688228254
>>> quadosc(lambda x: exp(3*j*x)/(2+x+x**2), [-inf,inf], omega=3)
(0.00317486988463794 - 0.0447701735209082j)
>>> 2*pi/sqrt(7)/exp(3*(j+sqrt(7))/2)
(0.00317486988463794 - 0.0447701735209082j)
Non-periodic functions
If f (x) = g(x)h(x) for some function h(x) that is not strictly periodic, omega or period
might not work, and it might be necessary to use zeros.
A notable exception can be made for Bessel functions which, though not periodic, are
asymptotically periodic in a suciently strong sense that the sum extrapolation will
work out:
>>> quadosc(j0, [0, inf], period=2*pi)
1.0
>>> quadosc(j1, [0, inf], period=2*pi)
1.0
More properly, one should provide the exact Bessel function zeros:
>>> j0zero = lambda n: findroot(j0, pi*(n-0.25))
>>> quadosc(j0, [0, inf], zeros=j0zero)
1008
1.0
For an example where zeros becomes necessary, consider the complete Fresnel integrals
cos x2 dx =
sin x2 dx =
.
8
0
0
Although the integrands do not decrease in magnitude as x , the integrals are convergent since the oscillation rate increases (causing consecutive periods to asymptotically cancel out). These integrals are virtually impossible to calculate to any kind of
accuracy using standard quadrature
rules. However, if one provides the correct asymp
totic distribution of zeros (xn n), quadosc() (page 1007) works:
>>> mp.dps = 30
>>> f = lambda x: cos(x**2)
>>> quadosc(f, [0,inf], zeros=lambda n:sqrt(pi*n))
0.626657068657750125603941321203
>>> f = lambda x: sin(x**2)
>>> quadosc(f, [0,inf], zeros=lambda n:sqrt(pi*n))
0.626657068657750125603941321203
>>> sqrt(pi/8)
0.626657068657750125603941321203
(Interestingly, these integrals can still be evaluated if one places some other constant
than in the square root sign.)
In general, if f (x) g(x) cos(h(x)), the zeros follow the inverse-function distribution
h1 (x):
>>> mp.dps = 15
>>> f = lambda x: sin(exp(x))
>>> quadosc(f, [1,inf], zeros=lambda n: log(n))
-0.25024394235267
>>> pi/2-si(e)
-0.250243942352671
Non-alternating functions
If the integrand oscillates around a positive value, without alternating signs, the extrapolation might fail. A simple trick that sometimes works is to multiply or divide the
frequency by 2:
>>> f = lambda x: 1/x**2+sin(x)/x**4
>>> quadosc(f, [1,inf], omega=1) # Bad
1.28642190869861
>>> quadosc(f, [1,inf], omega=0.5) # Perfect
1.28652953559617
>>> 1+(cos(1)+ci(1)+sin(1))/6
1.28652953559617
Fast decay
quadosc() (page 1007) is primarily useful for slowly decaying integrands. If the integrand decreases exponentially or faster, quad() (page 1003) will likely handle it without
trouble (and generally be much faster than quadosc() (page 1007)):
>>> quadosc(lambda x: cos(x)/exp(x), [0, inf], omega=1)
0.5
>>> quad(lambda x: cos(x)/exp(x), [0, inf])
0.5
1009
Quadrature rules
class mpmath.calculus.quadrature.QuadratureRule(ctx)
Quadrature rules are implemented using this class, in order to simplify the code and
provide a common infrastructure for tasks such as error estimation and node caching.
You can implement a custom quadrature rule by subclassing QuadratureRule and implementing the appropriate methods. The subclass can then be used by quad() (page 1003)
by passing it as the method argument.
QuadratureRule instances are supposed to be singletons. QuadratureRule therefore
implements instance caching in new ().
calc nodes(degree, prec, verbose=False)
Compute nodes for the standard interval [1, 1]. Subclasses should probably implement only this method, and use get nodes() method to retrieve the nodes.
clear()
Delete cached node data.
estimate error(results, prec, epsilon)
Given results from integrations [I1 , I2 , . . . , Ik ] done with a quadrature of rule of degree
1, 2, . . . , k, estimate the error of Ik .
For k = 2, we estimate |I I2 | as |I2 I1 |.
For k > 2, we extrapolate |I Ik | |Ik+1 Ik | from |Ik Ik1 | and |Ik Ik2 | under the assumption that each degree increment roughly doubles the accuracy of
the quadrature rule (this is true for both TanhSinh and GaussLegendre). The extrapolation formula is given by Borwein, Bailey & Girgensohn. Although not very
conservative, this method seems to be very robust in practice.
get nodes(a, b, degree, prec, verbose=False)
Return nodes for given interval, degree and precision. The nodes are retrieved from
a cache if already computed; otherwise they are computed by calling calc nodes()
and are then cached.
Subclasses should probably not implement this method, but just implement
calc nodes() for the actual node computation.
guess degree(prec)
Given a desired precision p in bits, estimate the degree m of the quadrature required
to accomplish full accuracy for typical integrals. By default, quad() (page 1003) will
perform up to m iterations. The value of m should be a slight overestimate, so that
slightly bad integrals can be dealt with automatically using a few extra iterations.
On the other hand, it should not be too big, so quad() (page 1003) can quit within a
reasonable amount of time when it is given an unsolvable integral.
The default formula used by guess degree() is tuned for both TanhSinh and GaussLegendre. The output is roughly as follows:
p
50
100
500
3000
m
6
7
10
12
This formula is based purely on a limited amount of experimentation and will sometimes be wrong.
sum next(f, nodes, degree, prec,
previous, verbose=False)
Evaluates the step sum
wk f (xk ) where the nodes list contains the (wk , xk ) pairs.
1010
summation() will supply the list results of values computed by sum next() at previous degrees, in case the quadrature rule is able to reuse them.
summation(f, points, prec, epsilon, max degree, verbose=False)
Main integration function. Computes the 1D integral over the interval specied
by points. For each subinterval, performs quadrature of degree from 1 up to
max degree until estimate error() signals convergence.
summation() transforms each subintegration to the standard interval and then calls
sum next().
transform nodes(nodes, a, b, verbose=False)
Rescale standardized nodes (for [1, 1]) to a general interval [a, b]. For a nite interval,
a simple linear change of variables is used. Otherwise, the following transformations
are used:
1
+ (a 1)
x
1
[, b] : t = (b + 1)
x
x
[, ] : t =
1 x2
[a, ] : t =
Tanh-sinh rule
class mpmath.calculus.quadrature.TanhSinh(ctx)
This class implements tanh-sinh or doubly exponential quadrature. This quadrature rule is based on the Euler-Maclaurin integral formula. By performing a change
of variables involving nested exponentials / hyperbolic functions (hence the name), the
derivatives at the endpoints vanish rapidly. Since the error term in the Euler-Maclaurin
formula depends on the derivatives at the endpoints, a simple step sum becomes extremely accurate. In practice, this means that doubling the number of evaluation points
roughly doubles the number of accurate digits.
Comparison to Gauss-Legendre:
Initial computation of nodes is usually faster
Handles endpoint singularities better
Handles innite integration intervals better
Is slower for smooth integrands once nodes have been computed
The implementation of the tanh-sinh algorithm is based on the description given in Borwein, Bailey & Girgensohn, Experimentation in Mathematics - Computational Paths to
Discovery, A K Peters, 2003, pages 312-313. In the present implementation, a few
improvements have been made:
A more ecient scheme is used to compute nodes (exploiting recurrence for the
exponential function)
The nodes are computed successively instead of all at once
1011
For convenience, if the system is one-dimensional, you may optionally provide just a
scalar value for y0. In this case, F should accept a scalar y argument and return a scalar.
The solution function y will return scalar values instead of length-1 vectors.
Evaluation of the solution function y(x) is permitted for any x x0 .
A high-order ODE can be solved by transforming it into rst-order vector form. This
transformation is described in standard texts on ODEs. Examples will also be given
below.
Options, speed and accuracy
By default, odefun() (page 1012) uses a high-order Taylor series method. For reasonably
well-behaved problems, the solution will be fully accurate to within the working precision. Note that F must be possible to evaluate to very high precision for the generation
of Taylor series to work.
To get a faster but less accurate solution, you can set a large value for tol (which defaults
roughly to eps). If you just want to plot the solution or perform a basic simulation, tol =
0.01 is likely sucient.
The degree argument controls the degree of the solver (with method=taylor, this is
the degree of the Taylor series expansion). A higher degree means that a longer step
can be taken before a new local solution must be generated from F, meaning that fewer
steps are required to get from x0 to a given x1 . On the other hand, a higher degree also
means that each local solution becomes more expensive (i.e., more evaluations of F are
required per step, and at higher precision).
The optimal setting therefore involves a tradeo. Generally, decreasing the degree for
Taylor series is likely to give faster solution at low precision, while increasing is likely to
be better at higher precision.
The function object returned by odefun() (page 1012) caches the solutions at all step
points and uses polynomial interpolation between step points. Therefore, once y(x1 ) has
been evaluated for some x1 , y(x) can be evaluated very quickly for any x0 x x1 . and
continuing the evaluation up to x2 > x1 is also fast.
Examples of rst-order ODEs
We will solve the standard test problem y 0 (x) = y(x), y(0) = 1 which has explicit solution
y(x) = exp(x):
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> f = odefun(lambda x, y: y, 0, 1)
>>> for x in [0, 1, 2.5]:
...
print((f(x), exp(x)))
...
(1.0, 1.0)
(2.71828182845905, 2.71828182845905)
(12.1824939607035, 12.1824939607035)
1013
Using the more general vectorized form, the test problem can be input as (note that f
returns a 1-element vector):
>>> mp.dps = 15
>>> f = odefun(lambda x, y: [y[0]], 0, [1])
>>> f(1)
[2.71828182845905]
odefun() (page 1012) can solve nonlinear ODEs, which are generally impossible (and
at best dicult) to solve analytically. As an example of a nonlinear ODE, we will solve
y 0 (x) = x sin(y(x)) for y(0) = /2.
( An(exact
)) solution happens to be known for this problem,
and is given by y(x) = 2 tan1 exp x2 /2 :
>>> f = odefun(lambda x, y: x*sin(y), 0, pi/2)
>>> for x in [2, 5, 10]:
...
print((f(x), 2*atan(exp(mpf(x)**2/2))))
...
(2.87255666284091, 2.87255666284091)
(3.14158520028345, 3.14158520028345)
(3.14159265358979, 3.14159265358979)
1014
[-0.839071529076452, -0.54402111088937]
[-0.839071529076452, -0.54402111088937]
---
Note that we get both the sine and the cosine solutions simultaneously.
TODO
Better automatic choice of degree and step size
Make determination of Taylor series convergence radius more robust
Allow solution for x < x0
Allow solution for complex x
Test for dicult (ill-conditioned) problems
Implement Runge-Kutta and other algorithms
Function approximation
The coecients are computed using high-order numerical dierentiation. The function
must be possible to evaluate to arbitrary precision. See diff() (page 999) for additional
details and supported keyword options.
Note that to evaluate the Taylor polynomial as an approximation of f , e.g. with polyval()
(page 971), the coecients must be reversed, and the point of the Taylor expansion must
be subtracted from the argument:
>>> p = taylor(exp, 2.0, 10)
>>> polyval(p[::-1], 2.5 - 2.0)
12.1824939606092
>>> exp(2.5)
12.1824939607035
1015
pk xk
k=0
Q=
qk xk
k=0
Q0 = 1
A(x)Q(x) = P (x) + O(xL+M +1 )
P (x)/Q(x) can provide a good approximation to an analytic function beyond the radius of
convergence of its Taylor series (example from G.A. Baker Essentials of Pade Approximants Academic Press, Ch.1A):
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> one = mpf(1)
>>> def f(x):
...
return sqrt((one + 2*x)/(one + x))
...
>>> a = taylor(f, 0, 6)
>>> p, q = pade(a, 3, 3)
>>> x = 10
>>> polyval(p[::-1], x)/polyval(q[::-1], x)
1.38169105566806
>>> f(x)
1.38169855941551
1016
Sampling the true error at 1000 points shows that the error estimate generated by
chebyfit is remarkably good:
>>> error = lambda x: abs(cos(x) - polyval(poly, x))
>>> nprint(max([error(1+n/1000.) for n in range(1000)]), 12)
1.61349954245e-5
Choice of degree
The degree N can be set arbitrarily high, to obtain an arbitrarily good approximation. As
a rule of thumb, an N -term Chebyshev approximation is good to N /(b a) decimal places
on a unit interval (although this depends on how well-behaved f is). The cost grows
accordingly: chebyfit evaluates the function (N 2 )/2 times to compute the coecients
and an additional N times to estimate the error.
Possible issues
One should be careful to use a suciently high working precision both when calling
chebyfit and when evaluating the resulting polynomial, as the polynomial is sometimes
ill-conditioned. It is for example dicult to reach 15-digit accuracy when evaluating
the polynomial using machine precision oats, no matter the theoretical accuracy of the
polynomial. (The option to return the coecients in Chebyshev form should be made
available in the future.)
It is important to note the Chebyshev approximation works poorly if f is not smooth. A
function containing singularities, rapid oscillation, etc can be approximated more eectively by multiplying it by a weight function that cancels out the nonsmooth features, or
by dividing the interval into several segments.
Fourier series (fourier, fourierval)
mpmath.fourier(ctx, f, interval, N)
Computes the Fourier series of degree N of the given function on the interval [a, b]. More
precisely, fourier() (page 1017) returns two lists (c, s) of coecients (the cosine series
and sine series, respectively), such that
f (x)
ck cos(kmx) + sk sin(kmx)
k=0
1017
>>> nprint(s)
[0.0, 2.0, -1.0, 0.666667, -0.5, 0.4]
Fourier series generally converge slowly (and may not converge pointwise). For example,
if f (x) = cosh(x), a 10-term Fourier series gives an L2 error corresponding to 2-digit
accuracy:
>>> I = [-1, 1]
>>> cs = fourier(cosh, I, 9)
>>> g = lambda x: (cosh(x) - fourierval(cs, I, x))**2
>>> nprint(sqrt(quad(g, I)))
0.00467963
fourier() (page 1017) uses numerical quadrature. For nonsmooth functions, the accuracy (and speed) can be improved by including all singular points in the interval specication:
>>> nprint(fourier(abs, [-1, 1], 0), 10)
([0.5000441648], [0.0])
>>> nprint(fourier(abs, [-1, 0, 1], 0), 10)
([0.5], [0.0])
Basic methods Matrices in mpmath are implemented using dictionaries. Only non-zero
values are stored, so it is cheap to represent sparse matrices.
The most basic way to create one is to use the matrix class directly. You can create an empty
matrix specifying the dimensions:
>>> from mpmath import *
>>> mp.dps = 15; mp.pretty = False
>>> matrix(2)
matrix(
[[0.0, 0.0],
1018
[0.0, 0.0]])
>>> matrix(2, 3)
matrix(
[[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0]])
You can also change the dimension of an existing matrix. This will set the new elements to 0.
If the new dimension is smaller than before, the concerning elements are discarded:
>>> A.rows = 2
>>> A
matrix(
[[0.0, 0.0],
[0.0, 0.0]])
Internally convert is applied every time an element is set. This is done using the syntax
A[row,column], counting from 0:
>>> A = matrix(2)
>>> A[1,1] = 1 + 1j
>>> print A
[0.0
0.0]
[0.0 (1.0 + 1.0j)]
A more comfortable way to create a matrix lets you use nested lists:
>>> matrix([[1, 2], [3, 4]])
matrix(
[[1.0, 2.0],
[3.0, 4.0]])
Advanced methods
trices:
>>> zeros(2)
matrix(
[[0.0, 0.0],
[0.0, 0.0]])
>>> ones(2)
matrix(
[[1.0, 1.0],
[1.0, 1.0]])
>>> diag([1, 2, 3]) # diagonal matrix
1019
matrix(
[[1.0, 0.0, 0.0],
[0.0, 2.0, 0.0],
[0.0, 0.0, 3.0]])
>>> eye(2) # identity matrix
matrix(
[[1.0, 0.0],
[0.0, 1.0]])
Vectors Vectors may also be represented by the matrix class (with rows = 1 or cols = 1).
For vectors there are some things which make life easier. A column vector can be created
using a at list, a row vectors using an almost at nested list:
>>> matrix([1, 2, 3])
matrix(
[[1.0],
[2.0],
[3.0]])
>>> matrix([[1, 2, 3]])
matrix(
[[1.0, 2.0, 3.0]])
Optionally vectors can be accessed like lists, using only a single index:
>>> x = matrix([1, 2, 3])
>>> x[1]
mpf(2.0)
>>> x[1,0]
mpf(2.0)
0.427895717335467]
0.615134039977379]
0.686210904770947]
8.29e-1]
2.06e-2]
5.71e-1]
2.59e-1]
2.79e-1]
1020
>>> A = matrix(2)
>>> A
matrix(
[[0.0, 0.0],
[0.0, 0.0]])
>>> B = A.copy()
>>> B[0,0] = 1
>>> B
matrix(
[[1.0, 0.0],
[0.0, 0.0]])
>>> A
matrix(
[[0.0, 0.0],
[0.0, 0.0]])
Finally, it is possible to convert a matrix to a nested list. This is very useful, as most Python
libraries involving matrices or arrays (namely NumPy or SymPy) support this format:
>>> B.tolist()
[[mpf(1.0), mpf(0.0)], [mpf(0.0), mpf(0.0)]]
Matrix operations
It is possible to multiply or add matrices and scalars. In the latter case the operation will be
done element-wise:
>>> A * 2
matrix(
[[2.0, 4.0],
[6.0, 8.0]])
>>> A / 4
matrix(
1021
[[0.25, 0.5],
[0.75, 1.0]])
>>> A - 1
matrix(
[[0.0, 1.0],
[2.0, 3.0]])
Of course you can perform matrix multiplication, if the dimensions are compatible:
>>> A * B
matrix(
[[8.0, 22.0],
[14.0, 48.0]])
>>> matrix([[1, 2, 3]]) * matrix([[-6], [7], [-2]])
matrix(
[[2.0]])
Norms Sometimes you need to know how large a matrix or vector is. Due to their multidimensional nature its not possible to compare them, but there are several functions to map
a matrix or a vector to a positive real number, the so called norms.
mpmath.norm(ctx, x, p=2)
1/p
Gives the entrywise p-norm of an iterable x, i.e. the vector norm ( k |xk |p ) , for any
given 1 p .
Special cases:
If x is not iterable, this just returns absmax(x).
p=1 gives the sum of absolute values.
1022
mpmath.mnorm(ctx, A, p=1)
Gives the matrix (operator) p-norm of A. Currently p=1 and p=inf are supported:
p=1 gives the 1-norm (maximal column sum)
p=inf gives the -norm (maximal row sum). You can use the string inf as well as
oat(inf) or mpf(inf)
p=2 (not implemented) for a square matrix is the usual spectral matrix norm, i.e. the
largest singular value.
p=f (or F, fro, Frobenius, frobenius) gives the Frobenius norm, which is the elementwise 2-norm. The Frobenius norm is an approximation of the spectral norm and
satises
1
Linear algebra
Decompositions
1023
mpmath.cholesky(ctx, A, tol=None)
Cholesky decomposition of a symmetric positive-denite matrix A. Returns a lower triangular matrix L such that A = L LT . More generally, for a complex Hermitian positivedenite matrix, a Cholesky decomposition satisfying A = L LH is returned.
The Cholesky decomposition can be used to solve linear equation systems twice as eciently as LU decomposition, or to test whether A is positive-denite.
The optional parameter tol determines the tolerance for verifying positive-deniteness.
Examples
Cholesky decomposition of a positive-denite symmetric matrix:
>>> from sympy.mpmath import *
>>> mp.dps = 25; mp.pretty = True
>>> A = eye(3) + hilbert(3)
>>> nprint(A)
[
2.0
0.5 0.333333]
[
0.5 1.33333
0.25]
[0.333333
0.25
1.2]
>>> L = cholesky(A)
>>> nprint(L)
[ 1.41421
0.0
0.0]
[0.353553 1.09924
0.0]
[0.235702 0.15162 1.05899]
>>> chop(A - L*L.T)
[0.0 0.0 0.0]
[0.0 0.0 0.0]
[0.0 0.0 0.0]
References
1.[Wikipedia] (page 1910) http://en.wikipedia.org/wiki/Cholesky decomposition
Linear equations
equation system:
1024
Basic linear algebra is implemented; you can for example solve the linear
x + 2*y = -10
3*x + 4*y = 10
using lu solve:
>>> A = matrix([[1, 2], [3, 4]])
>>> b = matrix([-10, 10])
>>> x = lu_solve(A, b)
>>> x
matrix(
[[30.0],
[-20.0]])
If you dont trust the result, use residual to calculate the residual ||A*x-b||:
>>> residual(A, x, b)
matrix(
[[3.46944695195361e-18],
[3.46944695195361e-18]])
>>> str(eps)
2.22044604925031e-16
As you can see, the solution is quite accurate. The error is caused by the inaccuracy of the
internal oating point arithmetic. Though, its even smaller than the current machine epsilon,
which basically means you can trust the result.
If you need more speed, use NumPy, or use fp instead mp matrices and methods:
>>> A = fp.matrix([[1, 2], [3, 4]])
>>> b = fp.matrix([-10, 10])
>>> fp.lu_solve(A, b)
matrix(
[[30.0],
[-20.0]])
lu solve accepts overdetermined systems. It is usually not possible to solve such systems,
so the residual is minimized instead. Internally this is done using Cholesky decomposition to
compute a least squares approximation. This means that that lu solve will square the errors.
If you cant aord this, use qr solve instead. It is twice as slow but more accurate, and it
calculates the residual automatically.
Matrix factorization The function lu computes an explicit LU factorization of a matrix:
>>> P, L, U = lu(matrix([[0,2,3],[4,5,6],[7,8,9]]))
>>> print P
[0.0 0.0 1.0]
[1.0 0.0 0.0]
[0.0 1.0 0.0]
>>> print L
[
1.0
0.0 0.0]
[
0.0
1.0 0.0]
[0.571428571428571 0.214285714285714 1.0]
>>> print U
[7.0 8.0
9.0]
[0.0 2.0
3.0]
[0.0 0.0 0.214285714285714]
>>> print P.T*L*U
[0.0 2.0 3.0]
1025
[4.0
[7.0
5.0
8.0
6.0]
9.0]
The singular value decomposition The routines svd r and svd c compute the singular
value decomposition of a real or complex matrix A. svd is an unied interface calling either
svd r or svd c depending on whether A is real or complex.
Given A, two orthogonal (A real) or unitary (A complex) matrices U and V are calculated such
that
A = U SV,
U 0 U = 1,
VV0 =1
where S is a suitable shaped matrix whose o-diagonal elements are zero. Here denotes the
hermitian transpose (i.e. transposition and complex conjugation). The diagonal elements of
S are the singular values of A, i.e. the square roots of the eigenvalues of A0 A or AA0 .
Examples:
>>> from mpmath import mp
>>> A = mp.matrix([[2, -2, -1], [3, 4, -2], [-2, -2, 0]])
>>> S = mp.svd_r(A, compute_uv = False)
>>> print S
[6.0]
[3.0]
[1.0]
>>> U, S, V = mp.svd_r(A)
>>> print mp.chop(A - U * mp.diag(S) * V)
[0.0 0.0 0.0]
[0.0 0.0 0.0]
[0.0 0.0 0.0]
The Schur decomposition This routine computes the Schur decomposition of a square
matrix A. Given A, a unitary matrix Q is determined such that
Q0 AQ = R,
1026
Q0 Q = QQ0 = 1
where R is an upper right triangular matrix. Here denotes the hermitian transpose (i.e.
transposition and conjugation).
Examples:
>>> from mpmath import mp
>>> A = mp.matrix([[3, -1, 2], [2, 5, -5], [-2, -3, 7]])
>>> Q, R = mp.schur(A)
>>> mp.nprint(R, 3)
[2.0 0.417 -2.53]
[0.0
4.0 -4.74]
[0.0
0.0
9.0]
>>> print(mp.chop(A - Q * R * Q.transpose_conj()))
[0.0 0.0 0.0]
[0.0 0.0 0.0]
[0.0 0.0 0.0]
The eigenvalue problem The routine eig solves the (ordinary) eigenvalue problem for a
real or complex square matrix A. Given A, a vector E and matrices ER and EL are calculated
such that
A ER[:,i] =
E[i] ER[:,i]
EL[i,:] A
= EL[i,:] E[i]
The symmetric eigenvalue problem The routines eigsy and eighe solve the (ordinary)
eigenvalue problem for a real symmetric or complex hermitian square matrix A. eigh is an
unied interface for this two functions calling either eigsy or eighe depending on whether
A is real or complex.
Given A, an orthogonal (A real) or unitary matrix Q (A complex) is calculated which diagonalizes A:
Q0 AQ = diag(E),
QQ0 = Q0 Q = 1
1027
Here diag(E) a is diagonal matrix whose diagonal is E. denotes the hermitian transpose (i.e.
ordinary transposition and complex conjugation).
The columns of Q are the eigenvectors of A and E contains the eigenvalues:
A Q[:,i] = E[i] Q[:,i]
Examples:
>>> from mpmath import mp
>>> A = mp.matrix([[3, 2], [2, 0]])
>>> E = mp.eigsy(A, eigvals_only = True)
>>> print E
[-1.0]
[ 4.0]
>>> A = mp.matrix([[1, 2], [2, 3]])
>>> E, Q = mp.eigsy(A)
# alternative: E, Q = mp.eigh(A)
>>> print mp.chop(A * Q[:,0] - E[0] * Q[:,0])
[0.0]
[0.0]
>>> A = mp.matrix([[1, 2 + 5j], [2 - 5j, 3]])
>>> E, Q = mp.eighe(A)
# alternative: E, Q = mp.eigh(A)
>>> print mp.chop(A * Q[:,0] - E[0] * Q[:,0])
[0.0]
[0.0]
The iv.matrix and fp.matrix classes convert inputs to intervals and Python oating-point
numbers respectively.
Interval matrices can be used to perform linear algebra operations with rigorous error tracking:
>>> a = iv.matrix([[0.1,0.3,1.0],
...
[7.1,5.5,4.8],
...
[3.2,4.4,5.6]])
>>>
>>> b = iv.matrix([4,0.6,0.5])
>>> c = iv.lu_solve(a, b)
>>> print c
[ [5.2582327113062393041, 5.2582327113062749951]]
[[-13.155049396267856583, -13.155049396267821167]]
[ [7.4206915477497212555, 7.4206915477497310922]]
>>> print a*c
[ [3.9999999999999866773, 4.0000000000000133227]]
[[0.59999999999972430942, 0.60000000000027142733]]
[[0.49999999999982236432, 0.50000000000018474111]]
Matrix functions
mpmath.expm(ctx, A, method=taylor)
Computes the matrix exponential of a square matrix A, which is dened by the power
series
exp(A) = I + A +
1028
A3
A2
+
+ ...
2!
3!
With method=taylor, the matrix exponential is computed using the Taylor series. With
method=pade, Pade approximants are used instead.
Examples
Basic examples:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> expm(zeros(3))
[1.0 0.0 0.0]
[0.0 1.0 0.0]
[0.0 0.0 1.0]
>>> expm(eye(3))
[2.71828182845905
0.0
0.0]
[
0.0 2.71828182845905
0.0]
[
0.0
0.0 2.71828182845905]
>>> expm([[1,1,0],[1,0,1],[0,1,0]])
[ 3.86814500615414 2.26812870852145 0.841130841230196]
[ 2.26812870852145 2.44114713886289
1.42699786729125]
[0.841130841230196 1.42699786729125
1.6000162976327]
>>> expm([[1,1,0],[1,0,1],[0,1,0]], method=pade)
[ 3.86814500615414 2.26812870852145 0.841130841230196]
[ 2.26812870852145 2.44114713886289
1.42699786729125]
[0.841130841230196 1.42699786729125
1.6000162976327]
>>> expm([[1+j, 0], [1+j,1]])
[(1.46869393991589 + 2.28735528717884j)
0.0]
[ (1.03776739863568 + 3.536943175722j) (2.71828182845905 + 0.0j)]
9.14228140091932e+2050488462815550]
1.47925220414035e+2050488462815551]
The identity exp(A + B) = exp(A) exp(B) does not hold for noncommuting matrices:
>>> A = hilbert(3)
>>> B = A + eye(3)
>>> chop(mnorm(A*B - B*A))
0.0
>>> chop(mnorm(expm(A+B) - expm(A)*expm(B)))
0.0
>>> B = A + ones(3)
>>> mnorm(A*B - B*A)
1.8
>>> mnorm(expm(A+B) - expm(A)*expm(B))
42.0927851137247
mpmath.cosm(ctx, A)
Gives the cosine of a square matrix A, dened in analogy with the matrix exponential.
Examples:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> X = eye(3)
>>> cosm(X)
[0.54030230586814
0.0
[
0.0 0.54030230586814
[
0.0
0.0
0.0]
0.0]
0.54030230586814]
1029
>>> X = hilbert(3)
>>> cosm(X)
[ 0.424403834569555 -0.316643413047167 -0.221474945949293]
[-0.316643413047167
0.820646708837824 -0.127183694770039]
[-0.221474945949293 -0.127183694770039
0.909236687217541]
>>> X = matrix([[1+j,-2],[0,-j]])
>>> cosm(X)
[(0.833730025131149 - 0.988897705762865j) (1.07485840848393 - 0.17192140544213j)]
[
0.0
(1.54308063481524 + 0.0j)]
mpmath.sinm(ctx, A)
Gives the sine of a square matrix A, dened in analogy with the matrix exponential.
Examples:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> X = eye(3)
>>> sinm(X)
[0.841470984807897
0.0
0.0]
[
0.0 0.841470984807897
0.0]
[
0.0
0.0 0.841470984807897]
>>> X = hilbert(3)
>>> sinm(X)
[0.711608512150994 0.339783913247439 0.220742837314741]
[0.339783913247439 0.244113865695532 0.187231271174372]
[0.220742837314741 0.187231271174372 0.155816730769635]
>>> X = matrix([[1+j,-2],[0,-j]])
>>> sinm(X)
[(1.29845758141598 + 0.634963914784736j) (-1.96751511930922 + 0.314700021761367j)]
[
0.0
(0.0 - 1.1752011936438j)]
1030
(0.568864481005783 + 0.351577584254143j)]
(0.351577584254143 - 0.568864481005783j)]
>>> sqrtm([[j,0],[0,j]])
[(0.707106781186547 + 0.707106781186547j)
[
0.0
0.0]
(0.707106781186547 + 0.707106781186547j)]
A square root of a rotation matrix, giving the corresponding half-angle rotation matrix:
>>> t1 = 0.75
>>> t2 = t1 * 0.5
>>> A1 = matrix([[cos(t1), -sin(t1)], [sin(t1), cos(t1)]])
>>> A2 = matrix([[cos(t2), -sin(t2)], [sin(t2), cos(t2)]])
>>> sqrtm(A1)
[0.930507621912314 -0.366272529086048]
[0.366272529086048
0.930507621912314]
>>> A2
[0.930507621912314 -0.366272529086048]
[0.366272529086048
0.930507621912314]
1031
...
[0,1,-4,6,-4],
...
[0,0,1,-4,5]])
>>> Y = matrix(\
...
[[2,-1,-0,-0,-0],
...
[-1,2,-1,0,-0],
...
[0,-1,2,-1,0],
...
[-0,0,-1,2,-1],
...
[-0,-0,-0,-1,2]])
>>> mnorm(sqrtm(X) - Y)
4.53155328326114e-19
mpmath.logm(ctx, A)
Computes a logarithm of the square matrix A, i.e. returns a matrix B = log(A) such that
exp(B) = A. The logarithm of a matrix, if it exists, is not unique.
Examples
Logarithms of some simple matrices:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> X = eye(3)
>>> logm(X)
[0.0 0.0 0.0]
[0.0 0.0 0.0]
[0.0 0.0 0.0]
>>> logm(2*X)
[0.693147180559945
0.0
[
0.0 0.693147180559945
[
0.0
0.0
>>> logm(expm(X))
[1.0 0.0 0.0]
[0.0 1.0 0.0]
[0.0 0.0 1.0]
0.0]
0.0]
0.693147180559945]
A matrix X close to the identity matrix, for which log(exp(X)) = exp(log(X)) = X holds:
>>> X = eye(3) + hilbert(3)/4
>>> X
[
1.25
0.125
[
0.125 1.08333333333333
[0.0833333333333333
0.0625
>>> logm(expm(X))
[
1.25
0.125
[
0.125 1.08333333333333
[0.0833333333333333
0.0625
>>> expm(logm(X))
1032
0.0833333333333333]
0.0625]
1.05]
0.0833333333333333]
0.0625]
1.05]
[
1.25
[
0.125
[0.0833333333333333
0.125
1.08333333333333
0.0625
0.0833333333333333]
0.0625]
1.05]
* 10**20).apply(re)
1.27721006042799 0.317662687717978]
42.5222778973542
2.24003708791604]
2.24003708791604
42.395212822267]
mpmath.powm(ctx, A, r)
Computes Ar = exp(A log r) for a matrix A and complex number r.
Examples
Powers and inverse powers of a matrix:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> A = matrix([[4,1,4],[7,8,9],[10,2,11]])
>>> powm(A, 2)
[ 63.0 20.0
69.0]
[174.0 89.0 199.0]
[164.0 48.0 179.0]
>>> chop(powm(powm(A, 4), 1/4.))
[ 4.0 1.0
4.0]
[ 7.0 8.0
9.0]
[10.0 2.0 11.0]
>>> powm(extraprec(20)(powm)(A, -4), -1/4.)
[ 4.0 1.0
4.0]
[ 7.0 8.0
9.0]
[10.0 2.0 11.0]
>>> chop(powm(powm(A, 1+0.5j), 1/(1+0.5j)))
[ 4.0 1.0
4.0]
[ 7.0 8.0
9.0]
[10.0 2.0 11.0]
>>> powm(extraprec(5)(powm)(A, -1.5), -1/(1.5))
[ 4.0 1.0
4.0]
1033
[ 7.0
[10.0
8.0
2.0
9.0]
11.0]
A Fibonacci-generating matrix:
>>> powm([[1,1],[1,0]], 10)
[89.0 55.0]
[55.0 34.0]
>>> fib(10)
55.0
>>> powm([[1,1],[1,0]], 6.5)
[(16.5166626964253 - 0.0121089837381789j)
[(10.2078589271083 + 0.0195927472575932j)
>>> (phi**6.5 - (1-phi)**6.5)/sqrt(5)
(10.2078589271083 - 0.0195927472575932j)
>>> powm([[1,1],[1,0]], 6.2)
[ (14.3076953002666 - 0.008222855781077j)
[(8.81733464837593 + 0.0133048601383712j)
>>> (phi**6.2 - (1-phi)**6.2)/sqrt(5)
(8.81733464837593 - 0.0133048601383712j)
(10.2078589271083 + 0.0195927472575932j)]
(6.30880376931698 - 0.0317017309957721j)]
(8.81733464837593 + 0.0133048601383712j)]
(5.49036065189071 - 0.0215277159194482j)]
Number identication
Most function in mpmath are concerned with producing approximations from exact mathematical formulas. It is also useful to consider the inverse problem: given only a decimal
approximation for a number, such as 0.7320508075688772935274463, is it possible to nd
an exact formula?
Subject to certain restrictions, such reverse engineering is indeed possible thanks to the
existence of integer relation algorithms. Mpmath implements the PSLQ algorithm (developed
by H. Ferguson), which is one such algorithm.
Automated number recognition based on PSLQ is not a silver bullet. Any occurring transcendental constants (, e, etc) must be guessed by the user, and the relation between those
constants in the formula must be linear (such as x = 3 + 4e). More complex formulas can be
found by combining PSLQ with functional transformations; however, this is only feasible to a
limited extent since the computation time grows exponentially with the number of operations
that need to be combined.
The number identication facilities in mpmath are inspired by the Inverse Symbolic Calculator (ISC). The ISC is more powerful than mpmath, as it uses a lookup table of millions of
precomputed constants (thereby mitigating the problem with exponential complexity).
Constant recognition
identify()
mpmath.identify(ctx, x, constants=[], tol=None, maxcoe=1000, full=False, verbose=False)
Given a real number x, identify(x) attempts to nd an exact formula for x. This formula
is returned as a string. If no match is found, None is returned. With full=True, a list of
matching formulas is returned.
As a simple example, identify() (page 1034) will nd an algebraic formula for the
golden ratio:
1034
identify() (page 1034) can identify simple algebraic numbers and simple combinations
of given base constants, as well as certain basic transformations thereof. More specically, identify() (page 1034) looks for the following:
1.Fractions
2.Quadratic algebraic numbers
3.Rational linear combinations of the base constants
4.Any of the above after rst transforming x into f (x) where f (x) is 1/x, x, x2 , log x
or exp x, either directly or with x or f (x) multiplied or divided by one of the base
constants
5.Products of fractional powers of the base constants and small integers
Base constants can be given as a list of strings representing mpmath expressions (identify() (page 1034) will eval the strings to numerical values and use the original strings
for the output), or as a dict of formula:value pairs.
In order not to produce spurious results, identify() (page 1034) should be used with
high precision; preferably 50 digits or more.
Examples
Simple identications can be performed safely at standard precision. Here the default
recognition of rational, algebraic, and exp/log of algebraic numbers is demonstrated:
>>> mp.dps = 15
>>> identify(0.22222222222222222)
(2/9)
>>> identify(1.9662210973805663)
sqrt(((24+sqrt(48))/8))
>>> identify(4.1132503787829275)
exp((sqrt(8)/2))
>>> identify(0.881373587019543)
log(((2+sqrt(8))/2))
By default, identify() (page 1034) does not recognize . At standard precision it nds
a not too useful approximation. At slightly increased precision, this approximation is no
longer accurate enough and identify() (page 1034) more correctly returns None:
>>> identify(pi)
(2**(176/117)*3**(20/117)*5**(35/39))/(7**(92/117))
>>> mp.dps = 30
>>> identify(pi)
>>>
Here is an example using a dict of constants. Note that the constants need not be
atomic; identify() (page 1034) can just as well express the given number in terms
of expressions given by formulas:
1035
An example of an erroneous solution being found when too low precision is used:
>>> mp.dps = 15
>>> identify(1/(3*pi-4*e+sqrt(8)), [pi, e, sqrt(2)])
((11/25) + (-158/75)*pi + (76/75)*e + (44/15)*sqrt(2))
>>> mp.dps = 50
>>> identify(1/(3*pi-4*e+sqrt(8)), [pi, e, sqrt(2)])
1/(3*pi + (-4)*e + 2*sqrt(2))
With full=True, and by supplying a few base constants, identify can generate almost
endless lists of approximations for any number (the output below has been truncated to
show only the rst few):
>>> for p in identify(pi, [e, catalan], tol=1e-5, full=True):
...
print(p)
...
e/log((6 + (-4/3)*e))
(3**3*5*e*catalan**2)/(2*7**2)
sqrt(((-13) + 1*e + 22*catalan))
log(((-6) + 24*e + 4*catalan)/e)
exp(catalan*((-1/5) + (8/15)*e))
catalan*(6 + (-6)*e + 15*catalan)
sqrt((5 + 26*e + (-3)*catalan))/e
e*sqrt(((-27) + 2*e + 25*catalan))
1036
The numerical values are roughly as close to as permitted by the specied tolerance:
>>> e/log(6-4*e/3)
3.14157719846001
>>> 135*e*catalan**2/98
3.14166950419369
>>> sqrt(e-13+22*catalan)
3.14158000062992
>>> log(24*e-6+4*catalan)-1
3.14158791577159
Symbolic processing
The output formula can be evaluated as a Python expression. Note however that if fractions (like 2/3) are present in the formula, Pythons eval() may erroneously perform
integer division. Note also that the output is not necessarily in the algebraically simplest
form:
>>> identify(sqrt(2))
(sqrt(8)/2)
As a solution to both problems, consider using SymPys sympify() to convert the formula
into a symbolic expression. SymPy can be used to pretty-print or further simplify the
formula symbolically:
>>> from sympy import sympify
>>> sympify(identify(sqrt(2)))
2**(1/2)
Sometimes identify() (page 1034) can simplify an expression further than a symbolic
algorithm:
>>> from sympy import simplify
>>> x = sympify(-1/(-3/2+(1/2)*5**(1/2))*(3/2-1/2*5**(1/2))**(1/2))
>>> x
(3/2 - 5**(1/2)/2)**(-1/2)
>>> x = simplify(x)
>>> x
2/(6 - 2*5**(1/2))**(1/2)
>>> mp.dps = 30
>>> x = sympify(identify(x.evalf(30)))
>>> x
1/2 + 5**(1/2)/2
(In fact, this functionality is available directly in SymPy as the function nsimplify(),
which is essentially a wrapper for identify() (page 1034).)
Miscellaneous issues and limitations
The input x must be a real number. All base constants must be positive real numbers
and must not be rationals or rational linear combinations of each other.
The worst-case computation time grows quickly with the number of base constants. Already with 3 or 4 base constants, identify() (page 1034) may require several seconds
to nish. To search for relations among a large number of constants, you should consider
using pslq() (page 1039) directly.
1037
The extended transformations are applied to x, not the constants separately. As a result,
identify will for example be able to recognize exp(2*pi+3) with pi given as a base
constant, but not 2*exp(pi)+3. It will be able to recognize the latter if exp(pi) is given
explicitly as a base constant.
Algebraic identication
findpoly()
mpmath.findpoly(ctx, x, n=1, **kwargs)
findpoly(x, n) returns the coecients of an integer polynomial P of degree at most
n such that P (x) 0. If no polynomial having x as a root can be found, findpoly()
(page 1038) returns None.
findpoly() (page 1038) works by successively calling pslq() (page 1039) with the vectors [1, x], [1, x, x2 ], [1, x, x2 , x3 ], ..., [1, x, x2 , .., xn ] as input. Keyword arguments given to
findpoly() (page 1038) are forwarded verbatim to pslq() (page 1039). In particular,
you can specify a tolerance for P (x) with tol and a maximum permitted coecient size
with maxcoeff.
For large values of n, it is recommended to run findpoly() (page 1038) at high precision;
preferably 50 digits or more.
Examples
By default (degree n = 1), findpoly() (page 1038) simply nds a linear polynomial with
a rational root:
>>> from sympy.mpmath import *
>>> mp.dps = 15; mp.pretty = True
>>> findpoly(0.7)
[-10, 7]
Numbers of the form m + n p for integers (m, n, p) are solutions to quadratic equations.
Despite only containing square roots, the following number results in a polynomial of
degree 4:
>>> findpoly(sqrt(2)+sqrt(3), 4)
[1, 0, -10, 0, 1]
1038
sion, findpoly() (page 1038) will usually nd the correct minimal polynomial of a given
algebraic number.
Non-algebraic numbers
If findpoly() (page 1038) fails to nd a polynomial with given coecient size and tolerance constraints, that means no such polynomial exists.
We can verify that is not an algebraic number of degree 3 with coecients less than
1000:
>>> mp.dps = 15
>>> findpoly(pi, 3)
>>>
It is unknown whether Eulers constant is transcendental (or even irrational). We can use
findpoly() (page 1038) to check that if is an algebraic number, its minimal polynomial
must have degree at least 7 and a coecient of magnitude at least 1000000:
>>> mp.dps = 200
>>> findpoly(euler, 6, maxcoeff=10**6, tol=1e-100, maxsteps=1000)
>>>
Note that the high precision and strict tolerance is necessary for such high-degree runs,
since otherwise unwanted low-accuracy approximations will be detected. It may also be
necessary to set maxsteps high to prevent a premature exit (before the coecient bound
has been reached). Running with verbose=True to get an idea what is happening can
be useful.
Integer relations (PSLQ)
pslq()
mpmath.pslq(ctx, x, tol=None, maxcoe=1000, maxsteps=100, verbose=False)
Given a vector of real numbers x = [x0 , x1 , ..., xn ], pslq(x) uses the PSLQ algorithm to nd
a list of integers [c0 , c1 , ..., cn ] such that
|c1 x1 + c2 x2 + ... + cn xn | < tol
and such that max |ck | < maxcoeff. If no such vector exists, pslq() (page 1039) returns
None. The tolerance defaults to 3/4 of the working precision.
Examples
5.15. Welcome to mpmaths documentation!
1039
To within the standard precision, it can however be approximated by at least one rational
number with denominator less than 1012 :
>>> p, q = pslq([-1, pi], maxcoeff=10**12)
>>> print(p); print(q)
238410049439
75888275702
>>> mpf(p)/q
3.14159265358979
The PSLQ algorithm can be applied to long vectors. For example, we can investigate the
rational (in)dependence of integer square roots:
>>>
>>>
>>>
>>>
>>>
>>>
[2,
mp.dps = 30
pslq([sqrt(n) for n in range(2, 5+1)])
pslq([sqrt(n) for n in range(2, 6+1)])
pslq([sqrt(n) for n in range(2, 8+1)])
0, 0, 0, 0, 0, -1]
Machin formulas
A famous formula for is Machins,
= acot 1
4
1040
mp.dps = 30
pslq([pi/4, acot(1)])
-1]
pslq([pi/4, acot(5), acot(239)])
-4, 1]
pslq([pi/4, acot(49), acot(57), acot(239), acot(110443)])
-12, -32, 5, -12]
We could try to generate a custom Machin-like formula by running the PSLQ algorithm
with a few inverse cotangent values, for example acot(2), acot(3) ... acot(10). Unfortunately, there is a linear dependence among these values, resulting in only that dependence being detected, with a zero coecient for :
>>> pslq([pi] + [acot(n) for n in range(2,11)])
[0, 1, -1, 0, 0, 0, -1, 0, 0, 0]
Algorithm
This
is
a
fairly
direct
translation
to
Python
of
the
given
by
David
Bailey,
The
PSLQ
Integer
Relation
http://www.cecm.sfu.ca/organics/papers/bailey/paper/html/node3.html
pseudocode
Algorithm:
1041
Like any complex numerical software, mpmath has implementation bugs. You should be
reasonably suspicious about any results computed by mpmath, even those it claims to be
able to compute correctly! If possible, verify results analytically, try dierent algorithms,
and cross-compare with other software.
Precision, error and tolerance
Error and accuracy can be measured either directly, or logarithmically in bits or digits. Specifically, if a y is an approximation for y, then
(Direct) absolute error = |
y y|
(Direct) relative error = |
y y||y|1
(Direct) absolute accuracy = |
y y|1
(Direct) relative accuracy = |
y y|1 |y|
(Logarithmic) absolute error = logb |
y y|
(Logarithmic) relative error = logb |
y y| logb |y|
(Logarithmic) absolute accuracy = logb |
y y|
(Logarithmic) relative accuracy = logb |
y y| + logb |y|
Full accuracy means that the accuracy of a result at least equals prec-1, i.e. it is correct
except possibly for the last bit.
Representation of numbers
Mpmath uses binary arithmetic. A binary oating-point number is a number of the form
man2exp where both man (the mantissa) and exp (the exponent) are integers. Some examples
of oating-point numbers are given in the following table.
Number
3
10
-16
1.25
Mantissa
3
5
-1
5
Exponent
0
1
4
-2
The representation as dened so far is not unique; one can always multiply the mantissa by 2
and subtract 1 from the exponent with no change in the numerical value. In mpmath, numbers
are always normalized so that man is an odd number, with the exception of zero which is
1042
always taken to have man = exp = 0. With these conventions, every representable number
has a unique representation. (Mpmath does not currently distinguish between positive and
negative zero.)
Simple mathematical operations are now easy to dene. Due to uniqueness, equality testing
of two numbers simply amounts to separately checking equality of the mantissas and the
exponents. Multiplication of nonzero numbers is straightforward: (m2e ) (n2f ) = (mn) 2e+f .
Addition is a bit more involved: we rst need to multiply the mantissa of one of the operands
by a suitable power of 2 to obtain equal exponents.
More technically, mpmath represents a oating-point number as a 4-tuple (sign, man, exp,
bc) where sign is 0 or 1 (indicating positive vs negative) and the mantissa is nonnegative; bc
(bitcount) is the size of the absolute value of the mantissa as measured in bits. Though redundant, keeping a separate sign eld and explicitly keeping track of the bitcount signicantly
speeds up arithmetic (the bitcount, especially, is frequently needed but slow to compute from
scratch due to the lack of a Python built-in function for the purpose).
Contrary to popular belief, oating-point numbers do not come with an inherent small uncertainty, although oating-point arithmetic generally is inexact. Every binary oating-point
number is an exact rational number. With arbitrary-precision integers used for the mantissa
and exponent, oating-point numbers can be added, subtracted and multiplied exactly. In
particular, integers and integer multiples of 1/2, 1/4, 1/8, 1/16, etc. can be represented,
added and multiplied exactly in binary oating-point arithmetic.
Floating-point arithmetic is generally approximate because the size of the mantissa must
be limited for eciency reasons. The maximum allowed width (bitcount) of the mantissa
is called the precision or prec for short. Sums and products of oating-point numbers are
exact as long as the absolute value of the mantissa is smaller than 2prec . As soon as the
mantissa becomes larger than this, it is truncated to contain at most prec bits (the exponent
is incremented accordingly to preserve the magnitude of the number), and this operation
introduces a rounding error. Division is also generally inexact; although we can add and
multiply exactly by setting the precision high enough, no precision is high enough to represent
for example 1/3 exactly (the same obviously applies for roots, trigonometric functions, etc).
The special numbers +inf, -inf and nan are represented internally by a zero mantissa and a
nonzero exponent.
Mpmath uses arbitrary precision integers for both the mantissa and the exponent, so numbers can be as large in magnitude as permitted by the computers memory. Some care may
be necessary when working with extremely large numbers. Although standard arithmetic
operators are safe, it is for example futile to attempt to compute the exponential function of
of 10100000 . Mpmath does not complain when asked to perform such a calculation, but instead
chugs away on the problem to the best of its ability, assuming that computer resources are
innite. In the worst case, this will be slow and allocate a huge amount of memory; if entirely impossible Python will at some point raise OverflowError: long int too large to
convert to int.
For further details on how the arithmetic is implemented, refer to the mpmath source code.
The basic arithmetic operations are found in the libmp directory; many functions there are
commented extensively.
Decimal issues
Mpmath uses binary arithmetic internally, while most interaction with the user is done via
the decimal number system. Translating between binary and decimal numbers is a somewhat
subtle matter; many Python novices run into the following bug (addressed in the General
Python FAQ):
1043
Decimal fractions fall into the category of numbers that generally cannot be represented
exactly in binary oating-point form. For example, none of the numbers 0.1, 0.01, 0.001 has
an exact representation as a binary oating-point number. Although mpmath can approximate
decimal fractions with any accuracy, it does not solve this problem for all uses; users who need
exact decimal fractions should look at the decimal module in Pythons standard library (or
perhaps use fractions, which are much faster).
With prec bits of precision, an arbitrary number can be approximated relatively to within
2prec , or within 10dps for dps decimal digits. The equivalent values for prec and dps are
therefore related proportionally via the factor C = log(10)/ log(2), or roughly 3.32. For example, the standard (binary) precision in mpmath is 53 bits, which corresponds to a decimal
precision of 15.95 digits.
More precisely, mpmath uses the following formulas to translate between prec and dps:
dps(prec) = max(1, int(round(int(prec) / C - 1)))
prec(dps) = max(1, int(round((int(dps) + 1) * C)))
Note that the dps is set 1 decimal digit lower than the corresponding binary precision. This
is done to hide minor rounding errors and artifacts resulting from binary-decimal conversion.
As a result, mpmath interprets 53 bits as giving 15 digits of decimal precision, not 16.
The dps value controls the number of digits to display when printing numbers with str(),
while the decimal precision used by repr() is set two or three digits higher. For example,
with 15 dps we have:
>>> from mpmath import *
>>> mp.dps = 15
>>> str(pi)
3.14159265358979
>>> repr(+pi)
mpf(3.1415926535897931)
The extra digits in the output from repr ensure that x == eval(repr(x)) holds, i.e. that
numbers can be converted to strings and back losslessly.
It should be noted that precision and accuracy do not always correlate when translating between binary and decimal. As a simple example, the number 0.1 has a decimal precision of 1
digit but is an innitely accurate representation of 1/10. Conversely, the number 250 has a
binary representation with 1 bit of precision that is innitely accurate; the same number can
actually be represented exactly as a decimal, but doing so requires 35 signicant digits:
0.00000000000000088817841970012523233890533447265625
All binary oating-point numbers can be represented exactly as decimals (possibly requiring
many digits), but the converse is false.
Correctness guarantees
Basic arithmetic operations (with the mp context) are always performed with correct rounding.
Results that can be represented exactly are guranteed to be exact, and results from single
inexact operations are guaranteed to be the best possible rounded values. For higher-level
operations, mpmath does not generally guarantee correct rounding. In general, mpmath only
guarantees that it will use at least the user-set precision to perform a given calculation. The
1044
user may have to manually set the working precision higher than the desired accuracy for the
result, possibly much higher.
Functions for evaluation of transcendental functions, linear algebra operations, numerical
integration, etc., usually automatically increase the working precision and use a stricter tolerance to give a correctly rounded result with high probability: for example, at 50 bits the
temporary precision might be set to 70 bits and the tolerance might be set to 60 bits. It can
often be assumed that such functions return values that have full accuracy, given inputs that
are exact (or suciently precise approximations of exact values), but the user must exercise
judgement about whether to trust mpmath.
The level of rigor in mpmath covers the entire spectrum from always correct by design
through nearly always correct and handling the most common errors to just computing
blindly and hoping for the best. Of course, a long-term development goal is to successively
increase the rigor where possible. The following list might give an idea of the current state.
Operations that are correctly rounded:
Addition, subtraction and multiplication of real and complex numbers.
Division and square roots of real numbers.
Powers of real numbers, assuming suciently small integer exponents (huge powers are
rounded in the right direction, but possibly farther than necessary).
Conversion from decimal to binary, for reasonably sized numbers (roughly between 10100
and 10100 ).
Typically, transcendental functions for exact input-output pairs.
Operations that should be fully accurate (however, the current implementation may be based
on a heuristic error analysis):
Radix conversion (large or small numbers).
Mathematical constants like .
Both real and imaginary parts of exp, cos, sin, cosh, sinh, log.
Other elementary functions (the largest of the real and imaginary part).
The gamma and log-gamma functions (the largest of the real and the imaginary part;
both, when close to real axis).
Some functions based on hypergeometric series (the largest of the real and imaginary
part).
Correctness of root-nding, numerical integration, etc. largely depends on the wellbehavedness of the input functions. Specic limitations are sometimes noted in the respective
sections of the documentation.
Double precision emulation
On most systems, Pythons float type represents an IEEE 754 double precision number, with
a precision of 53 bits and rounding-to-nearest. With default precision (mp.prec = 53), the
mpmath mpf type roughly emulates the behavior of the float type. Sources of incompatibility
include the following:
In hardware oating-point arithmetic, the size of the exponent is restricted to a xed
range: regular Python oats have a range between roughly 10300 and 10300 . Mpmath
does not emulate overow or underow when exponents fall outside this range.
1045
On some systems, Python uses 80-bit (extended double) registers for oating-point operations. Due to double rounding, this makes the float type less accurate. This problem
is only known to occur with Python versions compiled with GCC on 32-bit systems.
Machine oats very close to the exponent limit round subnormally, meaning that they
lose accuracy (Python may raise an exception instead of rounding a float subnormally).
Mpmath is able to produce more accurate results for transcendental functions.
Further reading
There are many excellent textbooks on numerical analysis and oating-point arithmetic. Some
good web resources are:
David Goldberg, What Every Computer Scientist Should Know About Floating-Point
Arithmetic
The Wikipedia article about numerical analysis
References
The following is a non-comprehensive list of works used in the development of mpmath or
cited for examples or mathematical denitions used in this documentation. References not
listed here can be found in the source code.
5.16.1 Contents
Basic functionality of the module
Introduction
This tutorial tries to give an overview of the functionality concerning polynomials within
SymPy. All code examples assume:
>>> from sympy import *
>>> x, y, z = symbols(x,y,z)
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
1046
Basic functionality
These functions provide dierent algorithms dealing with polynomials in the form of SymPy
expression, like symbols, sums etc.
Division The function div() provides division of polynomials with remainder. That is, for
polynomials f and g, it computes q and r, such that f = g q + r and deg(r) < q. For polynomials
in one variables with coecients in a eld, say, the rational numbers, q and r are uniquely
dened this way:
>>> f = 5*x**2 + 10*x + 3
>>> g = 2*x + 2
>>> q, r = div(f, g, domain=QQ)
>>> q
5*x
5
--- + 2
2
>>> r
-2
>>> (q*g + r).expand()
2
5*x + 10*x + 3
As you can see, q has a non-integer coecient. If you want to do division only in the ring of
polynomials with integer coecients, you can specify an additional parameter:
>>> q, r = div(f, g, domain=ZZ)
>>> q
0
>>> r
2
5*x + 10*x + 3
But be warned, that this ring is no longer Euclidean and that the degree of the remainder
doesnt need to be smaller than that of f. Since 2 doesnt divide 5, 2x doesnt divide 5x2 , even
if the degree is smaller. But:
>>> g = 5*x + 1
>>> q, r = div(f, g, domain=ZZ)
>>> q
x
>>> r
9*x + 3
>>> (q*g + r).expand()
2
5*x + 10*x + 3
1047
3
>>> r
0
In the last examples, all of the three variables x, y and z are assumed to be variables of
the polynomials. But if you have some unrelated constant as coecient, you can specify the
variables explicitly:
>>>
>>>
>>>
>>>
>>>
a*x
--3
a, b, c = symbols(a,b,c)
f = a*x**2 + b*x + c
g = 3*x + 2
q, r = div(f, g, domain=QQ)
q
2*a
b
- --- + 9
3
>>> r
4*a
2*b
--- - --- + c
9
3
GCD and LCM With division, there is also the computation of the greatest common divisor
and the least common multiple.
When the polynomials have integer coecients, the contents gcd is also considered:
>>> f = (12*x + 12)*x
>>> g = 16*x**2
>>> gcd(f, g)
4*x
But if the polynomials have rational coecients, then the returned polynomial is monic:
>>> f = 3*x**2/2
>>> g = 9*x/4
>>> gcd(f, g)
x
It also works with multiple variables. In this case, the variables are ordered alphabetically,
be default, which has inuence on the leading coecient:
>>> f = x*y/2 + y**2
>>> g = 3*x + 6*y
>>> gcd(f, g)
x + 2*y
The lcm is connected with the gcd and one can be computed using the other:
>>> f = x*y**2 + x**2*y
>>> g = x**2*y**2
>>> gcd(f, g)
x*y
>>> lcm(f, g)
3 2
2 3
x *y + x *y
>>> (f*g).expand()
4 3
3 4
1048
x *y + x *y
>>> (gcd(f, g, x, y)*lcm(f, g, x, y)).expand()
4 3
3 4
x *y + x *y
Factorization This function provides factorization of univariate and multivariate polynomials with rational coecients:
>>> factor(x**4/2 + 5*x**3/12 - x**2/3)
2
x *(2*x - 1)*(3*x + 4)
---------------------12
>>> factor(x**2 + 4*x*y + 4*y**2)
2
(x + 2*y)
Groebner bases
ders:
1049
>>> p = Symbol(p)
>>> q = Symbol(q)
>>> solve(x**2 + p*x + q, x)
__________
__________
/ 2
/ 2
p
\/ p - 4*q
p
\/ p - 4*q
[- - - -------------, - - + -------------]
2
2
2
2
>>> solve_poly_system([y - x, x - 5], x, y)
[(5, 5)]
>>> solve_poly_system([y**2 - x**3 + 1, y*x], x, y)
___
___
1
\/ 3 *I
1
\/ 3 *I
[(0, -I), (0, I), (1, 0), (- - - -------, 0), (- - + -------, 0)]
2
2
2
2
In this tutorial we present examples from Westers article concerning comparison and critique of mathematical abilities of several computer algebra systems (see [Wester1999]
(page 1910)). All the examples are related to polynomial and algebraic computations and
SymPy specic remarks were added to all of them.
Examples
All examples in this tutorial are computable, so one can just copy and paste them into a Python
shell and do something useful with them. All computations were done using the following
setup:
>>> from sympy import *
>>> init_printing(use_unicode=True, wrap_line=False, no_global=True)
>>> var(x,y,z,s,c,n)
(x, y, z, s, c, n)
To achieve the same eect in a more systematic way use primitive() function, which returns
the content and the primitive part of the input polynomial:
>>> primitive(6*x - 10)
(2, 3x - 5)
1050
Note: The content and the primitive part can be computed only over a ring. To simplify
coecients of a polynomial over a eld use monic().
We can compute the greatest common divisor (GCD) of two polynomials using gcd() function:
>>> gcd(f, g)
1
We see that f and g have no common factors. However, f*h and g*h have an obvious factor
h:
>>> gcd(expand(f*h), expand(g*h)) - h
0
Factorization of large univariate polynomials (of degree 120 in this case) over integers is also
possible:
>>> factor(expand(f*g))
60
47
34
8
5
60
52
39
25
23
10
-16x
+ 21x
- 64x
+ 126x + 46x + 8172x
- 83x - 22x
- 25x
- 19x
+ 54x
Multivariate GCD and factorization What can be done in univariate case, can be also
done for multivariate polynomials. Consider the following polynomials f, g and h in Z[x, y, z]:
>>> f = 24*x*y**19*z**8 - 47*x**17*y**5*z**8 + 6*x**15*y**9*z**2 - 3*x**22 + 5
>>> g = 34*x**5*y**8*z**13 + 20*x**7*y**7*z**7 + 12*x**9*y**16*z**4 + 80*y**14*z
>>> h = 11*x**12*y**7*z**13 - 23*x**2*y**8*z**10 + 47*x**17*y**5*z**8
>>> factor(expand(f*g))
7
9 9 3
7 6
5
12
7
22
17 5 8
15 9 2
19
-2y z6x y z + 10x z + 17x yz
+ 40y 3x
+ 47x y z - 6x y z - 24xy
1051
Testing if polynomials have common zeros To test if two polynomials have a root in common we can use resultant() function. The theory says that the resultant of two polynomials
vanishes if there is a common zero of those polynomials. For example:
>>> resultant(3*x**4 + 3*x**3 + x**2 - x - 2, x**3 - 3*x**2 + x + 5)
0
(x + 1)3x + x - 2
>>> factor(x**3 - 3*x**2 + x + 5)
2
(x + 1)x - 4x + 5
In both cases we obtained the factor x + 1 which tells us that the common root is x = 1.
Normalizing simple rational functions To remove common factors from the numerator
and the denominator of a rational function the elegant way, use cancel() function. For example:
>>> cancel((x**2 - 4)/(x**2 + 4*x + 4))
x - 2
----x + 2
Expanding expressions and factoring back One can work easily we expressions in both
expanded and factored forms. Consider a polynomial f in expanded form. We dierentiate it
and factor the result back:
>>> f = expand((x + 1)**20)
>>> g = diff(f, x)
>>> factor(g)
19
20(x + 1)
1052
(x - 1)x + x + 1x + x + x + x + 1x - x + x - x + x - x + 1
The original Westers example was x100 1, but was truncated for readability purpose. Note
that this is not a big struggle for factor() to decompose polynomials of degree 1000 or
greater.
Univariate factoring over Gaussian numbers
integer coecients:
3i
3i
4x - ---x + ---(x + 1 - 4i)(x + 1 + 4i)
2
2
As the result we got a splitting factorization of f with monic factors (this is a general rule
when computing in a eld with SymPy). The gaussian keyword is useful for improving code
readability, however the same result can be computed using more general syntax:
>>> factor(f, extension=I)
3i
3i
4x - ---x + ---(x + 1 - 4i)(x + 1 + 4i)
2
2
We would like to reduce degrees of the numerator and the denominator of a rational function
f/g. Do do this we employ cancel() function:
>>> cancel(f/g)
3
2
___ 2
___
___
x - 2x + \ 2 x - 3x - 2\ 2 x - 3\ 2
-----------------------------------------------2
x - 2
1053
___
x - \ 2
Univariate factoring over various domains Consider a univariate polynomial f with integer coecients:
>>> f = x**4 - 3*x**2 + 1
With sympy.polys we can obtain factorizations of f over dierent domains, which includes:
rationals:
>>> factor(f)
2
2
x - x - 1x + x - 1
nite elds:
>>> factor(f, modulus=5)
2
2
(x - 2) (x + 2)
algebraic numbers:
>>> alg = AlgebraicNumber((sqrt(5) - 1)/2, alias=alpha)
>>> factor(f, extension=alg)
(x - )(x + )(x - 1 - )(x + + 1)
Factoring polynomials into linear factors Currently SymPy can factor polynomials into
irreducibles over various domains, which can result in a splitting factorization (into linear
factors). However, there is currently no systematic way to infer a splitting eld (algebraic
number eld) automatically. In future the following syntax will be implemented:
>>> factor(x**3 + x**2 - 7, split=True)
Traceback (most recent call last):
...
NotImplementedError: split option is not implemented yet
Traceback (most recent call last):
...
NotImplementedError: split option is not implemented yet
Note this is dierent from extension=True, because the later only tells how expression parsing should be done, not what should be the domain of computation. One can simulate the
split keyword for several classes of polynomials using solve() function.
1054
>>> f = x**11 + x + 1
x + x + 1x - x + x - x + x - x + 1
obtaining polynomial f. This was done using symmetric polynomial representation over nite
elds The same thing can be done using non-symmetric representation:
>>> factor(f, modulus=65537, symmetric=False)
2
9
8
6
5
3
2
As with symmetric representation we can expand the factorization to get the input polynomial
back. This time, however, we need to truncate coecients of the expanded polynomial modulo
65537:
>>> trunc(expand(_), 65537)
11
x
+ x + 1
2
3
x - 2y + 3z
2
3
1055
Computing reduced Grbner bases To compute a reduced Grbner basis for a set of
polynomials use groebner() function. The function accepts various monomial orderings, e.g.:
lex, grlex and grevlex, or a user dened one, via order keyword. The lex ordering is
the most interesting because it has elimination property, which means that if the system of
polynomial equations to groebner() is zero-dimensional (has nite number of solutions) the
last element of the basis is a univariate polynomial. Consider the following example:
>>> f = expand((1 - c**2)**5 * (1 - s**2)**5 * (c**2 + s**2)**10)
>>> groebner([f, c**2 + s**2 - 1])
2
2
20
18
16
14
12
10
GroebnerBasisc + s - 1, c
- 5c
+ 10c
- 10c
+ 5c
- c , s, c, domain=, order=lex
The result is an ordinary Python list, so we can easily apply a function to all its elements, for
example we can factor those elements:
>>> list(map(factor, _))
2
2
10
5
5
c + s - 1, c (c - 1) (c + 1)
From the above we can easily nd all solutions of the system of polynomial equations. Or we
can use solve() to achieve this in a more systematic way:
>>> solve([f, s**2 + c**2 - 1], c, s)
[(-1, 0), (0, -1), (0, 1), (1, 0)]
Multivariate factoring over algebraic numbers Computing with multivariate polynomials over various domains
is as simple as in univariate case. For example consider the following
factorization over Q( 3):
>>> factor(x**3 +
(x + y)x + y
y**3, extension=sqrt(-3))
___
___
1
\ 3 i
1
\ 3 i
- - -------x + y- - + -------
2
2
2
2
Partial fraction decomposition Consider a univariate rational function f with integer coecients:
>>> f = (x**2 + 2*x + 3)/(x**3 + 4*x**2 + 5*x + 2)
To return from partial fractions to the rational function use a composition of together() and
cancel():
1056
>>> cancel(together(_))
2
x + 2x + 3
------------------3
2
x + 4x + 5x + 2
Literature
1057
Examples
>>> from sympy import degree_list
>>> from sympy.abc import x, y
>>> degree_list(x**2 + y*x + 1)
(2, 1)
1058
pquo(x**2 + 1, 2*x - 4)
+ 4
pquo(x**2 - 1, 2*x - 1)
+ 1
1059
Examples
>>> from sympy import div, ZZ, QQ
>>> from sympy.abc import x
>>> div(x**2 + 1, 2*x - 4, domain=ZZ)
(0, x**2 + 1)
>>> div(x**2 + 1, 2*x - 4, domain=QQ)
(x/2 + 1, 5)
quo(x**2 + 1, 2*x - 4)
+ 1
quo(x**2 - 1, x - 1)
1
1060
...
ExactQuotientFailed: 2*x - 4 does not divide x**2 + 1
1061
Examples
>>> from sympy import subresultants
>>> from sympy.abc import x
>>> subresultants(x**2 + 1, x**2 - 1)
[x**2 + 1, x**2 - 1, -2]
and for a single polynomial dis(f ) := dis(f, f ). Note that we make the denition max{} :=
.
See Also:
dispersionset
References
1062
fp = poly(x**4 - 3*x**2 + 1, x)
gp = fp.shift(-3)
sorted(dispersionset(fp, gp))
3, 4]
dispersion(fp, gp)
sorted(dispersionset(gp, fp))
dispersion(gp, fp)
We can even perform the computations for polynomials having symbolic coecients:
>>>
>>>
>>>
[0,
1063
dened as:
J(f, g) := {a N0 | gcd(f (x), g(x + a)) 6= 1}
= {a N0 | deg gcd(f (x), g(x + a)) 1}
fp = poly(x**4 - 3*x**2 + 1, x)
gp = fp.shift(-3)
sorted(dispersionset(fp, gp))
3, 4]
dispersion(fp, gp)
sorted(dispersionset(gp, fp))
dispersion(gp, fp)
1064
[2]
>>> sorted(dispersionset(gp, fp))
[1, 4]
We can even perform the computations for polynomials having symbolic coecients:
>>>
>>>
>>>
[0,
The default action of polys routines is to expand the expression given to them. terms gcd
follows this behavior:
>>> terms_gcd((3+3*x)*(x+x*y))
3*x*(x*y + x + y + 1)
If this is not desired then the hint expand can be set to False. In this case the expression
will be treated as though it were comprised of one or more terms:
>>> terms_gcd((3+3*x)*(x+x*y), expand=False)
(3*x + 3)*(x*y + x)
In order to traverse factors of a Mul or the arguments of other functions, the deep hint
can be used:
>>> terms_gcd((3 + 3*x)*(x + x*y), expand=False, deep=True)
3*x*(x + 1)*(y + 1)
>>> terms_gcd(cos(x + x*y), deep=True)
cos(x*(y + 1))
Only the y-term had a coecient that was a fraction; if one does not want to factor out
the 1/2 in cases like this, the ag clear can be set to False:
1065
1066
Examples
>>> from sympy import lcm
>>> from sympy.abc import x
>>> lcm(x**2 - 1, x**2 - 3*x + 2)
x**3 - 2*x**2 - x + 2
1067
Set expand to False to shut this o. Note that the extraction will not be recursive; use
the as content primitive method for recursive, non-destructive Rational extraction.
>>> primitive(eq, expand=False)
(1, x*(2*x + 2) + 2)
>>> eq.as_content_primitive()
(2, x*(x + 1) + 1)
Examples
>>> from sympy import sturm
>>> from sympy.abc import x
>>> sturm(x**3 - 2*x**2 + x - 3)
[x**3 - 2*x**2 + x - 3, 3*x**2 - 4*x + 1, 2*x/9 + 25/9, -2079/4]
1069
Examples
>>> from sympy import sqf_list
>>> from sympy.abc import x
>>> sqf_list(2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16)
(2, [(x + 1, 2), (x + 2, 3)])
1070
1071
1072
1073
method=buchberger)
x - 1, y - 55], x, y, domain=ZZ, order=lex)
method=f5b)
x - 1, y - 55], x, y, domain=ZZ, order=lex)
1074
References
David A. Cox, John B. Little, Donal OShea. Ideals, Varieties and Algorithms, 3rd edition,
p. 230
class sympy.polys.polytools.Poly
Generic class for representing polynomial expressions.
EC(f, order=None)
Returns the last non-zero coecient of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**3 + 2*x**2 + 3*x, x).EC()
3
EM(f, order=None)
Returns the last non-zero monomial of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(4*x**2 + 2*x*y**2 + x*y + 3*y, x, y).EM()
x**0*y**1
ET(f, order=None)
Returns the last non-zero term of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(4*x**2 + 2*x*y**2 + x*y + 3*y, x, y).ET()
(x**0*y**1, 3)
LC(f, order=None)
Returns the leading coecient of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(4*x**3 + 2*x**2 + 3*x, x).LC()
4
1075
LM(f, order=None)
Returns the leading monomial of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(4*x**2 + 2*x*y**2 + x*y + 3*y, x, y).LM()
x**2*y**0
LT(f, order=None)
Returns the leading term of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(4*x**2 + 2*x*y**2 + x*y + 3*y, x, y).LT()
(x**2*y**0, 4)
TC(f)
Returns the trailing coecient of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**3 + 2*x**2 + 3*x, x).TC()
0
abs(f)
Make all coecients in f positive.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 - 1, x).abs()
Poly(x**2 + 1, x, domain=ZZ)
add(f, g)
Add two polynomials f and g.
1076
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).add(Poly(x - 2, x))
Poly(x**2 + x - 1, x, domain=ZZ)
>>> Poly(x**2 + 1, x) + Poly(x - 2, x)
Poly(x**2 + x - 1, x, domain=ZZ)
all coeffs(f)
Returns all coecients from a univariate polynomial f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**3 + 2*x - 1, x).all_coeffs()
[1, 0, 2, -1]
all monoms(f)
Returns all monomials from a univariate polynomial f.
See Also:
all terms (page 1078)
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**3 + 2*x - 1, x).all_monoms()
[(3,), (2,), (1,), (0,)]
1077
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(2*x**3 - 7*x**2 + 4*x + 4).all_roots()
[-1/2, 2, 2]
>>> Poly(x**3 + x + 1).all_roots()
[RootOf(x**3 + x + 1, 0),
RootOf(x**3 + x + 1, 1),
RootOf(x**3 + x + 1, 2)]
all terms(f)
Returns all terms from a univariate polynomial f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**3 + 2*x - 1, x).all_terms()
[((3,), 1), ((2,), 0), ((1,), 2), ((0,), -1)]
args
Dont mess up with the core.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).args
(x**2 + 1,)
as expr(f, *gens)
Convert a Poly instance to an Expr instance.
1078
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> f = Poly(x**2 + 2*x*y**2 - y, x, y)
>>> f.as_expr()
x**2 + 2*x*y**2 - y
>>> f.as_expr({x: 5})
10*y**2 - y + 25
>>> f.as_expr(5, 6)
379
as list(f, native=False)
Switch to a list representation.
cancel(f, g, include=False)
Cancel common factors in a rational function f/g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(2*x**2 - 2, x).cancel(Poly(x**2 - 2*x + 1, x))
(1, Poly(2*x + 2, x, domain=ZZ), Poly(x - 1, x, domain=ZZ))
>>> Poly(2*x**2 - 2, x).cancel(Poly(x**2 - 2*x + 1, x), include=True)
(Poly(2*x + 2, x, domain=ZZ), Poly(x - 1, x, domain=ZZ))
f.clear_denoms()
Poly(3*x + 2, x, domain=QQ))
f.clear_denoms(convert=True)
Poly(3*x + 2, x, domain=ZZ))
1079
Examples
>>> from sympy import Poly, exp
>>> from sympy.abc import x, y
>>> p = Poly(24*x*y*exp(8) + 23*x, x, y)
>>> p.coeff_monomial(x)
23
>>> p.coeff_monomial(y)
0
>>> p.coeff_monomial(x*y)
24*exp(8)
Note that Expr.coeff() behaves dierently, collecting terms if possible; the Poly
must be converted to an Expr to use that method, however:
>>> p.as_expr().coeff(x)
24*y*exp(8) + 23
>>> p.as_expr().coeff(y)
24*x*exp(8)
>>> p.as_expr().coeff(x*y)
24*exp(8)
coeffs(f, order=None)
Returns all non-zero coecients from f in lex order.
See Also:
all coeffs (page 1077), coeff monomial (page 1079), nth (page 1100)
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**3 + 2*x + 3, x).coeffs()
[1, 2, 3]
cofactors(f, g)
Returns the GCD of f and g and their cofactors.
Returns polynomials (h, cff, cfg) such that h = gcd(f, g), and cff = quo(f,
h) and cfg = quo(g, h) are, so called, cofactors of f and g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 (Poly(x - 1, x,
Poly(x + 1, x,
Poly(x - 2, x,
1080
compose(f, g)
Computes the functional composition of f and g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + x, x).compose(Poly(x - 1, x))
Poly(x**2 - x, x, domain=ZZ)
content(f)
Returns the GCD of polynomial coecients.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(6*x**2 + 8*x + 12, x).content()
2
decompose(f)
Computes a functional decomposition of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**4 + 2*x**3 - x - 1, x, domain=ZZ).decompose()
[Poly(x**2 - x - 1, x, domain=ZZ), Poly(x**2 + x, x, domain=ZZ)]
deflate(f)
Reduce degree of f by mapping x i**m to y i.
1081
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**6*y**2 + x**3 + 1, x, y).deflate()
((3, 2), Poly(x**2*y + x + 1, x, y, domain=ZZ))
degree(f, gen=0)
Returns degree of f in x j.
The degree of 0 is negative innity.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + y*x + 1, x, y).degree()
2
>>> Poly(x**2 + y*x + y, x, y).degree(y)
1
>>> Poly(0, x).degree()
-oo
degree list(f)
Returns a list of degrees of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + y*x + 1, x, y).degree_list()
(2, 1)
diff(f, *specs)
Computes partial derivative of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + 2*x + 1, x).diff()
Poly(2*x + 2, x, domain=ZZ)
>>> Poly(x*y**2 + x, x, y).diff((0, 0), (1, 1))
Poly(2*x*y, x, y, domain=ZZ)
discriminant(f)
Computes the discriminant of f.
1082
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 2*x + 3, x).discriminant()
-8
dispersion(f, g=None)
Compute the dispersion of polynomials.
For two polynomials f (x) and g(x) with deg f > 0 and deg g > 0 the dispersion dis(f, g)
is dened as:
dis(f, g) := max{J(f, g) {0}}
= max{{a N| gcd(f (x), g(x + a)) 6= 1} {0}}
fp = poly(x**4 - 3*x**2 + 1, x)
gp = fp.shift(-3)
sorted(dispersionset(fp, gp))
3, 4]
1083
We can even perform the computations for polynomials having symbolic coecients:
>>>
>>>
>>>
[0,
dispersionset(f, g=None)
Compute the dispersion set of two polynomials.
For two polynomials f (x) and g(x) with deg f > 0 and deg g > 0 the dispersion set
J(f, g) is dened as:
J(f, g) := {a N0 | gcd(f (x), g(x + a)) 6= 1}
= {a N0 | deg gcd(f (x), g(x + a)) 1}
1084
fp = poly(x**4 - 3*x**2 + 1, x)
gp = fp.shift(-3)
sorted(dispersionset(fp, gp))
3, 4]
dispersion(fp, gp)
sorted(dispersionset(gp, fp))
dispersion(gp, fp)
We can even perform the computations for polynomials having symbolic coecients:
>>>
>>>
>>>
[0,
div(f, g, auto=True)
Polynomial division with remainder of f by g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).div(Poly(2*x - 4, x))
(Poly(1/2*x + 1, x, domain=QQ), Poly(5, x, domain=QQ))
>>> Poly(x**2 + 1, x).div(Poly(2*x - 4, x), auto=False)
(Poly(0, x, domain=ZZ), Poly(x**2 + 1, x, domain=ZZ))
domain
Get the ground domain of self.
eject(f, *gens)
Eject selected generators into the ground domain.
1085
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> f = Poly(x**2*y + x*y**3 + x*y + 1, x, y)
>>> f.eject(x)
Poly(x*y**3 + (x**2 + x)*y + 1, y, domain=ZZ[x])
>>> f.eject(y)
Poly(y*x**2 + (y**3 + y)*x + 1, x, domain=ZZ[y])
2})
+ 6, y, z, domain=ZZ)
2, y: 5})
z, domain=ZZ)
2, y: 5, z: 7})
exclude(f)
Remove unnecessary generators from f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import a, b, c, d, x
>>> Poly(a + x, a, b, c, d, x).exclude()
Poly(a + x, a, x, domain=ZZ)
exquo(f, g, auto=True)
Computes polynomial exact quotient of f by g.
1086
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 - 1, x).exquo(Poly(x - 1, x))
Poly(x + 1, x, domain=ZZ)
>>> Poly(x**2 + 1, x).exquo(Poly(2*x - 4, x))
Traceback (most recent call last):
...
ExactQuotientFailed: 2*x - 4 does not divide x**2 + 1
Traceback (most recent call last):
...
ExactQuotientFailed: 2*x - 4 does not divide x**2 + 1
factor list(f)
Returns a list of irreducible factors of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> f = 2*x**5 + 2*x**4*y + 4*x**3 + 4*x**2*y + 2*x + 2*y
>>> Poly(f).factor_list()
(2, [(Poly(x + y, x, y, domain=ZZ), 1),
(Poly(x**2 + 1, x, y, domain=ZZ), 2)])
1087
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> f = 2*x**5 + 2*x**4*y + 4*x**3 + 4*x**2*y + 2*x + 2*y
>>> Poly(f).factor_list_include()
[(Poly(2*x + 2*y, x, y, domain=ZZ), 1),
(Poly(x**2 + 1, x, y, domain=ZZ), 2)]
free symbols
Free symbols of a polynomial expression.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + 1).free_symbols
set([x])
>>> Poly(x**2 + y).free_symbols
set([x, y])
>>> Poly(x**2 + y, x).free_symbols
set([x, y])
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 - 1, x).gcd(Poly(x**2 - 3*x + 2, x))
Poly(x - 1, x, domain=ZZ)
gcdex(f, g, auto=True)
Extended Euclidean algorithm of f and g.
Returns (s, t, h) such that h = gcd(f, g) and s*f + t*g = h.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> f = x**4 - 2*x**3 - 6*x**2 + 12*x + 15
>>> g = x**3 + x**2 - 4*x - 4
>>> Poly(f).gcdex(Poly(g))
(Poly(-1/5*x + 3/5, x, domain=QQ),
Poly(1/5*x**2 - 6/5*x + 2, x, domain=QQ),
Poly(x + 1, x, domain=QQ))
gen
Return the principal generator.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).gen
x
get domain(f)
Get the ground domain of f.
get modulus(f)
Get the modulus of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, modulus=2).get_modulus()
2
gff list(f)
Computes greatest factorial factorization of f.
5.16. Polynomials Manipulation Module
1089
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> f = x**5 + 2*x**4 - x**3 - 2*x**2
>>> Poly(f).gff_list()
[(Poly(x, x, domain=ZZ), 1), (Poly(x + 2, x, domain=ZZ), 4)]
ground roots(f)
Compute roots of f by factorization in the ground domain.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**6 - 4*x**4 + 4*x**3 - x**2).ground_roots()
{0: 2, 1: 2}
homogeneous order(f)
Returns the homogeneous order of f.
1090
homogenize(f, s)
Returns the homogeneous polynomial of f.
A homogeneous polynomial is a polynomial whose all monomials with non-zero coecients have the same total degree. If you only want to check if a polynomial is
homogeneous, then use Poly.is homogeneous() (page 1093). If you want not only
to check if a polynomial is homogeneous but also compute its homogeneous order,
then use Poly.homogeneous order() (page 1090).
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y, z
>>> f = Poly(x**5 + 2*x**2*y**2 + 9*x*y**3)
>>> f.homogenize(z)
Poly(x**5 + 2*x**2*y**2*z + 9*x*y**3*z, x, y, z, domain=ZZ)
inject(f, front=False)
Inject ground domain generators into f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> f = Poly(x**2*y + x*y**3 + x*y + 1, x)
>>> f.inject()
Poly(x**2*y + x*y**3 + x*y + 1, x, y, domain=ZZ)
>>> f.inject(front=True)
Poly(y**3*x + y*x**2 + y*x + 1, y, x, domain=ZZ)
1091
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + 2*x + 1, x).integrate()
Poly(1/3*x**3 + x**2 + x, x, domain=QQ)
>>> Poly(x*y**2 + x, x, y).integrate((0, 1), (1, 0))
Poly(1/2*x**2*y**2 + 1/2*x**2, x, y, domain=QQ)
References:
1092
...
NotInvertible: zero divisor
is cyclotomic
Returns True if f is a cyclotomic polnomial.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> f = x**16 + x**14 - x**10 + x**8 - x**6 + x**2 + 1
>>> Poly(f).is_cyclotomic
False
>>> g = x**16 + x**14 - x**10 - x**8 - x**6 + x**2 + 1
>>> Poly(g).is_cyclotomic
True
is ground
Returns True if f is an element of the ground domain.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x, x).is_ground
False
>>> Poly(2, x).is_ground
True
>>> Poly(y, x).is_ground
True
is homogeneous
Returns True if f is a homogeneous polynomial.
A homogeneous polynomial is a polynomial whose all monomials with non-zero
coecients have the same total degree. If you want not only to check if a
polynomial is homogeneous but also compute its homogeneous order, then use
Poly.homogeneous order() (page 1090).
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + x*y, x, y).is_homogeneous
True
>>> Poly(x**3 + x*y, x, y).is_homogeneous
False
1093
is irreducible
Returns True if f has no factors over its domain.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + x + 1, x, modulus=2).is_irreducible
True
>>> Poly(x**2 + 1, x, modulus=2).is_irreducible
False
is linear
Returns True if f is linear in all its variables.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x + y + 2, x, y).is_linear
True
>>> Poly(x*y + 2, x, y).is_linear
False
is monic
Returns True if the leading coecient of f is one.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x + 2, x).is_monic
True
>>> Poly(2*x + 2, x).is_monic
False
is monomial
Returns True if f is zero or has only one term.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(3*x**2, x).is_monomial
True
>>> Poly(3*x**2 + 1, x).is_monomial
False
1094
is multivariate
Returns True if f is a multivariate polynomial.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 +
False
>>> Poly(x*y**2
True
>>> Poly(x*y**2
False
>>> Poly(x**2 +
True
x + 1, x).is_multivariate
+ x*y + 1, x, y).is_multivariate
+ x*y + 1, x).is_multivariate
x + 1, x, y).is_multivariate
is one
Returns True if f is a unit polynomial.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(0, x).is_one
False
>>> Poly(1, x).is_one
True
is primitive
Returns True if GCD of the coecients of f is one.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(2*x**2 + 6*x + 12, x).is_primitive
False
>>> Poly(x**2 + 3*x + 6, x).is_primitive
True
is quadratic
Returns True if f is quadratic in all its variables.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
1095
is sqf
Returns True if f is a square-free polynomial.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 - 2*x + 1, x).is_sqf
False
>>> Poly(x**2 - 1, x).is_sqf
True
is univariate
Returns True if f is a univariate polynomial.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 +
True
>>> Poly(x*y**2
False
>>> Poly(x*y**2
True
>>> Poly(x**2 +
False
x + 1, x).is_univariate
+ x*y + 1, x, y).is_univariate
+ x*y + 1, x).is_univariate
x + 1, x, y).is_univariate
is zero
Returns True if f is a zero polynomial.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(0, x).is_zero
True
>>> Poly(1, x).is_zero
False
l1 norm(f)
Returns l1 norm of f.
1096
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(-x**2 + 2*x - 3, x).l1_norm()
6
lcm(f, g)
Returns polynomial LCM of f and g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 - 1, x).lcm(Poly(x**2 - 3*x + 2, x))
Poly(x**3 - 2*x**2 - x + 2, x, domain=ZZ)
length(f)
Returns the number of non-zero terms in f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 2*x - 1).length()
3
lift(f)
Convert algebraic coecients to rationals.
Examples
>>> from sympy import Poly, I
>>> from sympy.abc import x
>>> Poly(x**2 + I*x + 1, x, extension=I).lift()
Poly(x**4 + 3*x**2 + 1, x, domain=QQ)
ltrim(f, gen)
Remove dummy generators from the left of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y, z
1097
max norm(f)
Returns maximum norm of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(-x**2 + 2*x - 3, x).max_norm()
3
monic(f, auto=True)
Divides all coecients by LC(f).
Examples
>>> from sympy import Poly, ZZ
>>> from sympy.abc import x
>>> Poly(3*x**2 + 6*x + 9, x, domain=ZZ).monic()
Poly(x**2 + 2*x + 3, x, domain=QQ)
>>> Poly(3*x**2 + 4*x + 2, x, domain=ZZ).monic()
Poly(x**2 + 4/3*x + 2/3, x, domain=QQ)
monoms(f, order=None)
Returns all non-zero monomials from f in lex order.
See Also:
all monoms (page 1077)
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + 2*x*y**2 + x*y + 3*y, x, y).monoms()
[(2, 0), (1, 2), (1, 1), (0, 1)]
mul(f, g)
Multiply two polynomials f and g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
1098
neg(f)
Negate all coecients in f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 - 1, x).neg()
Poly(-x**2 + 1, x, domain=ZZ)
>>> -Poly(x**2 - 1, x)
Poly(-x**2 + 1, x, domain=ZZ)
1099
nth(f, *N)
Returns the n-th coecient of f where N are the exponents of the generators in the
term of interest.
See Also:
coeff monomial (page 1079)
Examples
>>> from sympy import Poly, sqrt
>>> from sympy.abc import x, y
>>> Poly(x**3 + 2*x**2 + 3*x, x).nth(2)
2
>>> Poly(x**3 + 2*x*y**2 + y**2, x, y).nth(1, 2)
2
>>> Poly(4*sqrt(x)*y)
Poly(4*y*sqrt(x), y, sqrt(x), domain=ZZ)
>>> _.nth(1, 1)
4
one
Return one polynomial with selfs properties.
pdiv(f, g)
Polynomial pseudo-division of f by g.
1100
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).pdiv(Poly(2*x - 4, x))
(Poly(2*x + 4, x, domain=ZZ), Poly(20, x, domain=ZZ))
pexquo(f, g)
Polynomial exact pseudo-quotient of f by g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 - 1, x).pexquo(Poly(2*x - 2, x))
Poly(2*x + 2, x, domain=ZZ)
>>> Poly(x**2 + 1, x).pexquo(Poly(2*x - 4, x))
Traceback (most recent call last):
...
ExactQuotientFailed: 2*x - 4 does not divide x**2 + 1
Traceback (most recent call last):
...
ExactQuotientFailed: 2*x - 4 does not divide x**2 + 1
pow(f, n)
Raise f to a non-negative power n.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
1101
pquo(f, g)
Polynomial pseudo-quotient of f by g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).pquo(Poly(2*x - 4, x))
Poly(2*x + 4, x, domain=ZZ)
>>> Poly(x**2 - 1, x).pquo(Poly(2*x - 2, x))
Poly(2*x + 2, x, domain=ZZ)
prem(f, g)
Polynomial pseudo-remainder of f by g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).prem(Poly(2*x - 4, x))
Poly(20, x, domain=ZZ)
primitive(f)
Returns the content and a primitive form of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(2*x**2 + 8*x + 12, x).primitive()
(2, Poly(x**2 + 4*x + 6, x, domain=ZZ))
quo(f, g, auto=True)
Computes polynomial quotient of f by g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
1102
1103
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 - 3, x).refine_root(1, 2, eps=1e-2)
(19/11, 26/15)
rem(f, g, auto=True)
Computes the polynomial remainder of f by g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).rem(Poly(2*x - 4, x))
Poly(5, x, domain=ZZ)
>>> Poly(x**2 + 1, x).rem(Poly(2*x - 4, x), auto=False)
Poly(x**2 + 1, x, domain=ZZ)
replace(f, x, y=None)
Replace x with y in generators list.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + 1, x).replace(x, y)
Poly(y**2 + 1, y, domain=ZZ)
resultant(f, g, includePRS=False)
Computes the resultant of f and g via PRS.
If includePRS=True, it includes the subresultant PRS in the result. Because the PRS
is used to calculate the resultant, this is more ecient than calling subresultants()
(page 1061) separately.
1104
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> f = Poly(x**2 + 1, x)
>>> f.resultant(Poly(x**2 - 1, x))
4
>>> f.resultant(Poly(x**2 - 1, x), includePRS=True)
(4, [Poly(x**2 + 1, x, domain=ZZ), Poly(x**2 - 1, x, domain=ZZ),
Poly(-2, x, domain=ZZ)])
retract(f, eld=None)
Recalculate the ground domain of a polynomial.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> f = Poly(x**2 + 1, x, domain=QQ[y])
>>> f
Poly(x**2 + 1, x, domain=QQ[y])
>>> f.retract()
Poly(x**2 + 1, x, domain=ZZ)
>>> f.retract(field=True)
Poly(x**2 + 1, x, domain=QQ)
revert(f, n)
Compute f**(-1) mod x**n.
root(f, index, radicals=True)
Get an indexed root of a polynomial.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> f = Poly(2*x**3 - 7*x**2 + 4*x + 4)
>>> f.root(0)
-1/2
>>> f.root(1)
2
>>> f.root(2)
2
>>> f.root(3)
Traceback (most recent call last):
...
IndexError: root index out of [-3, 2] range, got 3
1105
shift(f, a)
Eciently compute Taylor shift f(x + a).
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 - 2*x + 1, x).shift(2)
Poly(x**2 + 2*x + 1, x, domain=ZZ)
slice(f, x, m, n=None)
Take a continuous subsequence of terms of f.
sqf list(f, all=False)
Returns a list of square-free factors of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> f = 2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16
>>> Poly(f).sqf_list()
(2, [(Poly(x + 1, x, domain=ZZ), 2),
(Poly(x + 2, x, domain=ZZ), 3)])
>>> Poly(f).sqf_list(all=True)
(2, [(Poly(1, x, domain=ZZ), 1),
(Poly(x + 1, x, domain=ZZ), 2),
(Poly(x + 2, x, domain=ZZ), 3)])
1106
sqf norm(f)
Computes square-free norm of f.
Returns s, f, r, such that g(x) = f(x-sa) and r(x) = Norm(g(x)) is a square-free
polynomial over K, where a is the algebraic extension of the ground domain.
Examples
>>> from sympy import Poly, sqrt
>>> from sympy.abc import x
>>> s, f, r = Poly(x**2 + 1, x, extension=[sqrt(3)]).sqf_norm()
>>> s
1
>>> f
Poly(x**2 - 2*sqrt(3)*x + 4, x, domain=QQ<sqrt(3)>)
>>> r
Poly(x**4 - 4*x**2 + 16, x, domain=QQ)
sqf part(f)
Computes square-free part of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
1107
sqr(f)
Square a polynomial f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x - 2, x).sqr()
Poly(x**2 - 4*x + 4, x, domain=ZZ)
>>> Poly(x - 2, x)**2
Poly(x**2 - 4*x + 4, x, domain=ZZ)
sturm(f, auto=True)
Computes the Sturm sequence of f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**3 - 2*x**2 + x - 3, x).sturm()
[Poly(x**3 - 2*x**2 + x - 3, x, domain=QQ),
Poly(3*x**2 - 4*x + 1, x, domain=QQ),
Poly(2/9*x + 25/9, x, domain=QQ),
Poly(-2079/4, x, domain=QQ)]
sub(f, g)
Subtract two polynomials f and g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).sub(Poly(x - 2, x))
Poly(x**2 - x + 3, x, domain=ZZ)
>>> Poly(x**2 + 1, x) - Poly(x - 2, x)
Poly(x**2 - x + 3, x, domain=ZZ)
1108
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x + 1).sub_ground(2)
Poly(x - 1, x, domain=ZZ)
subresultants(f, g)
Computes the subresultant PRS of f and g.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x).subresultants(Poly(x**2 - 1, x))
[Poly(x**2 + 1, x, domain=ZZ),
Poly(x**2 - 1, x, domain=ZZ),
Poly(-2, x, domain=ZZ)]
terms(f, order=None)
Returns all non-zero terms from f in lex order.
See Also:
all terms (page 1078)
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + 2*x*y**2 + x*y + 3*y, x, y).terms()
[((2, 0), 1), ((1, 2), 2), ((1, 1), 1), ((0, 1), 3)]
terms gcd(f)
Remove GCD of terms from the polynomial f.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**6*y**2 + x**3*y, x, y).terms_gcd()
((3, 1), Poly(x**3*y + 1, x, y, domain=ZZ))
1109
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> def func(k, coeff):
...
k = k[0]
...
return coeff//10**(2-k)
>>> Poly(x**2 + 20*x + 400).termwise(func)
Poly(x**2 + 2*x + 4, x, domain=ZZ)
to exact(f)
Make the ground domain exact.
Examples
>>> from sympy import Poly, RR
>>> from sympy.abc import x
>>> Poly(x**2 + 1.0, x, domain=RR).to_exact()
Poly(x**2 + 1, x, domain=QQ)
to field(f)
Make the ground domain a eld.
Examples
>>> from sympy import Poly, ZZ
>>> from sympy.abc import x
>>> Poly(x**2 + 1, x, domain=ZZ).to_field()
Poly(x**2 + 1, x, domain=QQ)
to ring(f)
Make the ground domain a ring.
Examples
>>> from sympy import Poly, QQ
>>> from sympy.abc import x
>>> Poly(x**2 + 1, domain=QQ).to_ring()
Poly(x**2 + 1, x, domain=ZZ)
total degree(f)
Returns the total degree of f.
1110
Examples
>>> from sympy import Poly
>>> from sympy.abc import x, y
>>> Poly(x**2 + y*x + 1, x, y).total_degree()
2
>>> Poly(x + y**5, x, y).total_degree()
5
trunc(f, p)
Reduce f modulo a constant p.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly(2*x**3 + 3*x**2 + 5*x + 7, x).trunc(3)
Poly(-x**3 - x + 1, x, domain=ZZ)
unify(f, g)
Make f and g belong to the same domain.
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> f, g = Poly(x/2 + 1), Poly(2*x + 1)
>>> f
Poly(1/2*x + 1, x, domain=QQ)
>>> g
Poly(2*x + 1, x, domain=ZZ)
>>> F, G = f.unify(g)
>>> F
Poly(1/2*x + 1, x, domain=QQ)
>>> G
Poly(2*x + 1, x, domain=QQ)
unit
Return unit polynomial with selfs properties.
zero
Return zero polynomial with selfs properties.
class sympy.polys.polytools.PurePoly
Class for representing pure polynomials.
free symbols
Free symbols of a polynomial.
1111
Examples
>>> from sympy import PurePoly
>>> from sympy.abc import x, y
>>> PurePoly(x**2 + 1).free_symbols
set()
>>> PurePoly(x**2 + y).free_symbols
set()
>>> PurePoly(x**2 + y, x).free_symbols
set([y])
class sympy.polys.polytools.GroebnerBasis
Represents a reduced Groebner basis.
contains(poly)
Check if poly belongs the ideal generated by self.
Examples
>>> from sympy import groebner
>>> from sympy.abc import x, y
>>> f = 2*x**3 + y**3 + 3*y
>>> G = groebner([x**2 + y**2 - 1, x*y - 2])
>>> G.contains(f)
True
>>> G.contains(f + 1)
False
fglm(order)
Convert a Groebner basis from one ordering to another.
The FGLM algorithm converts reduced Groebner bases of zero-dimensional ideals
from one ordering to another. This method is often used when it is infeasible to
compute a Groebner basis with respect to a particular ordering directly.
References
J.C. Faugere, P. Gianni, D. Lazard, T. Mora (1994). Ecient Computation of Zerodimensional Groebner Bases by Change of Ordering
Examples
>>> from sympy.abc import x, y
>>> from sympy import groebner
>>> F = [x**2 - 3*y - x + 1, y**2 - 2*x + y - 1]
>>> G = groebner(F, x, y, order=grlex)
1112
>>> list(G.fglm(lex))
[2*x - y**2 - y + 1, y**4 + 2*y**3 - 3*y**2 - 16*y + 7]
>>> list(groebner(F, x, y, order=lex))
[2*x - y**2 - y + 1, y**4 + 2*y**3 - 3*y**2 - 16*y + 7]
is zero dimensional
Checks if the ideal generated by a Groebner basis is zero-dimensional.
The algorithm checks if the set of monomials not divisible by the leading monomial
of any element of F is bounded.
References
David A. Cox, John B. Little, Donal OShea. Ideals, Varieties and Algorithms, 3rd
edition, p. 230
reduce(expr, auto=True)
Reduces a polynomial modulo a Groebner basis.
Given a polynomial f and a set of polynomials G = (g 1, ..., g n), computes a
set of quotients q = (q 1, ..., q n) and the remainder r such that f = q 1*f 1 +
... + q n*f n + r, where r vanishes or r is a completely reduced polynomial with
respect to G.
Examples
>>> from sympy import groebner, expand
>>> from sympy.abc import x, y
>>> f = 2*x**4 - x**2 + y**3 + y**2
>>> G = groebner([x**3 - x, y**3 - y])
>>> G.reduce(f)
([2*x, 1], x**2 + y**2 + y)
>>> Q, r = _
>>> expand(sum(q*g for q, g in zip(Q, G)) + r)
2*x**4 - x**2 + y**3 + y**2
>>> _ == f
True
1113
Examples
>>> from sympy.polys.polyfuncs import symmetrize
>>> from sympy.abc import x, y
>>> symmetrize(x**2 + y**2)
(-2*x*y + (x + y)**2, 0)
>>> symmetrize(x**2 + y**2, formal=True)
(s1**2 - 2*s2, 0, [(s1, x + y), (s2, x*y)])
>>> symmetrize(x**2 - y**2)
(-2*x*y + (x + y)**2, -2*y**2)
>>> symmetrize(x**2 - y**2, formal=True)
(s1**2 - 2*s2, -2*y**2, [(s1, x + y), (s2, x*y)])
sympy.polys.polyfuncs.interpolate(data, x)
Construct an interpolating polynomial for the data points.
1114
Examples
>>> from sympy.polys.polyfuncs import interpolate
>>> from sympy.abc import x
The (x, y) coordinates can also be given as keys and values of a dictionary (and the points
need not be equispaced):
>>> interpolate([(-1, 2), (1, 2), (2, 5)], x)
x**2 + 1
>>> interpolate({-1: 2, 1: 2, 2: 5}, x)
x**2 + 1
Domain constructors
1115
Notes
By default compose=True, the minimal polynomial of the subexpressions of ex are computed, then the arithmetic operations on them are performed using the resultant and
factorization. If compose=False, a bottom-up algorithm is used with groebner. The default algorithm stalls less frequently.
If no ground domain is given, it will be generated automatically from the expression.
Examples
>>> from sympy import minimal_polynomial, sqrt, solve, QQ
>>> from sympy.abc import x, y
>>> minimal_polynomial(sqrt(2), x)
x**2 - 2
>>> minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2)))
x - sqrt(2)
>>> minimal_polynomial(sqrt(2) + sqrt(3), x)
x**4 - 10*x**2 + 1
>>> minimal_polynomial(solve(x**3 + x + 3)[0], x)
x**3 + x + 3
>>> minimal_polynomial(sqrt(y), x)
x**2 - y
Options
compose : if True minpoly compose is used, if False the groebner algorithm polys : if
True returns a Poly object domain : ground domain
sympy.polys.numberfields.minpoly(ex, x=None, **args)
Computes the minimal polynomial of an algebraic element.
Parameters ex : algebraic element expression
x : independent variable of the minimal polynomial
Notes
By default compose=True, the minimal polynomial of the subexpressions of ex are computed, then the arithmetic operations on them are performed using the resultant and
factorization. If compose=False, a bottom-up algorithm is used with groebner. The default algorithm stalls less frequently.
If no ground domain is given, it will be generated automatically from the expression.
Examples
>>> from sympy import minimal_polynomial, sqrt, solve, QQ
>>> from sympy.abc import x, y
1116
>>> minimal_polynomial(sqrt(2), x)
x**2 - 2
>>> minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2)))
x - sqrt(2)
>>> minimal_polynomial(sqrt(2) + sqrt(3), x)
x**4 - 10*x**2 + 1
>>> minimal_polynomial(solve(x**3 + x + 3)[0], x)
x**3 + x + 3
>>> minimal_polynomial(sqrt(y), x)
x**2 - y
Options
compose : if True minpoly compose is used, if False the groebner algorithm polys : if
True returns a Poly object domain : ground domain
sympy.polys.numberfields.primitive element(extension, x=None, **args)
Construct a common number eld for all extensions.
sympy.polys.numberfields.field isomorphism(a, b, **args)
Construct an isomorphism between two number elds.
sympy.polys.numberfields.to number field(extension, theta=None, **args)
Express extension in the eld generated by theta.
sympy.polys.numberfields.isolate(alg, eps=None, fast=False)
Give a rational isolating interval for an algebraic number.
class sympy.polys.numberfields.AlgebraicNumber
Class for representing algebraic numbers in SymPy.
as expr(x=None)
Create a Basic expression from self.
as poly(x=None)
Create a Poly instance from self.
coeffs()
Returns all SymPy coecients of an algebraic number.
is aliased
Returns True if alias was set.
native coeffs()
Returns all native coecients of an algebraic number.
to algebraic integer()
Convert self to an algebraic integer.
Monomials encoded as tuples
1117
Given a set of variables V and a total degree N generate a set of monomials of degree at
most N . The total number of monomials is huge and is given by the following formula:
(#V + N )!
#V !N !
For example if we would like to generate a dense polynomial of a total degree N = 50 in
5 variables, assuming that exponents and all of coecients are 32-bit long and stored in
an array we would need almost 80 GiB of memory! Fortunately most polynomials, that
we will encounter, are sparse.
Examples
sympy.polys.monomials.monomial count(V, N)
Computes the number of monomials.
The number of monomials is given by the following formula:
(#V + N )!
#V !N !
where N is a total degree and V is a set of variables.
Examples
>>> from sympy.polys.monomials import itermonomials, monomial_count
>>> from sympy.polys.orderings import monomial_key
>>> from sympy.abc import x, y
>>> monomial_count(2, 2)
6
>>> M = itermonomials([x, y], 2)
>>> sorted(M, key=monomial_key(grlex, [y, x]))
[1, x, y, x**2, x*y, y**2]
>>> len(M)
6
Orderings of monomials
class sympy.polys.orderings.LexOrder
Lexicographic order of monomials.
1118
class sympy.polys.orderings.GradedLexOrder
Graded lexicographic order of monomials.
class sympy.polys.orderings.ReversedGradedLexOrder
Reversed graded lexicographic order of monomials.
Formal manipulation of roots of polynomials
class sympy.polys.rootoftools.RootOf
Represents k-th root of a univariate polynomial.
class sympy.polys.rootoftools.RootSum
Represents a sum of all roots of a univariate polynomial.
Symbolic root-nding algorithms
1119
>>> p = Poly(x**2-y, x, y)
>>> roots(Poly(p, x))
{-sqrt(y): 1, sqrt(y): 1}
>>> roots(x**2 - y, x)
{-sqrt(y): 1, sqrt(y): 1}
>>> roots([1, 0, -1])
{-1: 1, 1: 1}
Special polynomials
sympy.polys.rationaltools.together(expr, deep=False)
Denest and combine rational expressions using symbolic methods.
1120
This function takes an expression or a container of expressions and puts it (them) together by denesting and combining rational subexpressions. No heroic measures are
taken to minimize degree of the resulting numerator and denominator. To obtain completely reduced expression use cancel(). However, together() (page 1120) can preserve as much as possible of the structure of the input expression in the output (no
expansion is performed).
A wide variety of objects can be put together including lists, tuples, sets, relational objects, integrals and others. It is also possible to transform interior of function applications, by setting deep ag to True.
By denition, together() (page 1120) is a complement to apart(), so
apart(together(expr)) should return expr unchanged. Note however, that together() (page 1120) uses only symbolic methods, so it might be necessary to use
cancel() to perform algebraic simplication and minimise degree of the numerator and
denominator.
Examples
>>> from sympy import together, exp
>>> from sympy.abc import x, y, z
>>> together(1/x + 1/y)
(x + y)/(x*y)
>>> together(1/x + 1/y + 1/z)
(x*y + x*z + y*z)/(x*y*z)
>>> together(1/(x*y) + 1/y**2)
(x + y)/(x*y**2)
>>> together(1/(1 + 1/x) + 1/(1 + 1/y))
(x*(y + 1) + y*(x + 1))/((x + 1)*(y + 1))
>>> together(exp(1/x + 1/y))
exp(1/y + 1/x)
>>> together(exp(1/x + 1/y), deep=True)
exp((x + y)/(x*y))
>>> together(1/exp(x) + 1/(x*exp(x)))
(x + 1)*exp(-x)/x
>>> together(1/exp(2*x) + 1/(x*exp(3*x)))
(x*exp(x) + 1)*exp(-3*x)/x
1121
The undetermined coecients method does not provide a result when the denominators
roots are not rational:
>>> apart(y/(x**2 + x + 1), x)
y/(x**2 + x + 1)
The (not necessarily irreducible) polynomial D whose roots wi appear in the linear denominator of a bunch of related fraction terms. (This item can also be a
list of explicit roots. However, at the moment apart list never returns a result
1122
this way, but the related assemble partfrac list function accepts this format
as input.)
The numerator of the fraction, written as a function of the root w
The linear denominator of the fraction excluding its power exponent, written as
a function of the root w.
The power to which the denominator has to be raised.
On can always rebuild a plain expression by using the function assemble partfrac list.
See Also:
apart (page 1121), assemble partfrac list (page 1124)
References
A rst example:
>>> from sympy.polys.partfrac import apart_list, assemble_partfrac_list
>>> from sympy.abc import x, t
>>> f = (2*x**3 - 2*x) / (x**2 - 2*x + 1)
>>> pfd = apart_list(f)
>>> pfd
(1,
Poly(2*x + 4, x, domain=ZZ),
[(Poly(_w - 1, _w, domain=ZZ), Lambda(_a, 4), Lambda(_a, -_a + x), 1)])
>>> assemble_partfrac_list(pfd)
2*x + 4 + 4/(x - 1)
Second example:
>>> f = (-2*x - 2*x**2) / (3*x**2 - 6*x)
>>> pfd = apart_list(f)
>>> pfd
(-1,
Poly(2/3, x, domain=QQ),
[(Poly(_w - 2, _w, domain=ZZ), Lambda(_a, 2), Lambda(_a, -_a + x), 1)])
>>> assemble_partfrac_list(pfd)
-2/3 - 2/(x - 2)
1123
If we happen to know some roots we can provide them easily inside the structure:
>>> pfd = apart_list(2/(x**2-2))
>>> pfd
(1,
Poly(0, x, domain=ZZ),
[(Poly(_w**2 - 2, _w, domain=ZZ),
Lambda(_a, _a/2),
Lambda(_a, -_a + x),
1)])
1124
Dispersion of Polynomials
1125
>>>
>>>
[0,
>>>
6
fp = poly(x**4 - 3*x**2 + 1, x)
gp = fp.shift(-3)
sorted(dispersionset(fp, gp))
3, 4]
dispersion(fp, gp)
sorted(dispersionset(gp, fp))
dispersion(gp, fp)
We can even perform the computations for polynomials having symbolic coecients:
>>>
>>>
>>>
[0,
and for a single polynomial dis(f ) := dis(f, f ). Note that we make the denition max{} :=
.
See Also:
dispersionset (page 1063)
References
fp = poly(x**4 - 3*x**2 + 1, x)
gp = fp.shift(-3)
sorted(dispersionset(fp, gp))
3, 4]
dispersion(fp, gp)
sorted(dispersionset(gp, fp))
dispersion(gp, fp)
We can even perform the computations for polynomials having symbolic coecients:
>>>
>>>
>>>
[0,
1127
of equations over the Greek art of position and shape. This tapestry was originally
woven on European soil and is still being rened under the inuence of international
fashion. Algebraic geometry studies the delicate balance between the geometrically
plausible and the algebraically possible. Whenever one side of this mathematical
teeter-totter outweighs the other, one immediately loses interest and runs o in
search of a more exciting amusement.
George R. Kempf 1944 2002
Algebraic Geometry refers to the study of geometric problems via algebraic methods (and
sometimes vice versa). While this is a rather old topic, algebraic geometry as understood
today is very much a 20th century development. Building on ideas of e.g. Riemann and
Dedekind, it was realized that there is an intimate connection between properties of the set
of solutions of a system of polynomial equations (called an algebraic variety) and the behavior
of the set of polynomial functions on that variety (called the coordinate ring).
As in many geometric disciplines, we can distinguish between local and global questions (and
methods). Local investigations in algebraic geometry are essentially equivalent to the study of
certain rings, their ideals and modules. This latter topic is also called commutative algebra.
It is the basic local toolset of algebraic geometers, in much the same way that dierential
analysis is the local toolset of dierential geometers.
A good conceptual introduction to commutative algebra is [Atiyah69] (page 1911). An introduction more geared towards computations, and the work most of the algorithms in this
module are based on, is [Greuel2008] (page 1911).
This module aims to eventually allow expression and solution of both local and global geometric problems, both in the classical case over a eld and in the more modern arithmetic
cases. So far, however, there is no geometric functionality at all. Currently the module only
provides tools for computational commutative algebra over elds.
All code examples assume:
>>> from sympy import *
>>> x, y, z = symbols(x,y,z)
>>> init_printing(use_unicode=True, wrap_line=False, no_global=True)
Reference
In this section we document the usage of the AGCA module. For convenience of the reader,
some denitions and examples/explanations are interspersed.
Base Rings Almost all computations in commutative algebra are relative to a base ring.
(For example, when asking questions about an ideal, the base ring is the ring the ideal is
a subset of.) In principle all polys domains can be used as base rings. However, useful
functionality is only implemented for polynomial rings over elds, and various localizations
and quotients thereof.
As demonstrated in the examples below, the most convenient method to create objects you
are interested in is to build them up from the ground eld, and then use the various methods
to create new objects from old. For example, in order to create the local ring of the nodal
cubic y 2 = x3 at the origin, over Q, you do:
>>> lr = QQ.old_poly_ring(x, y, order=ilex) / [y**2 - x**3]
>>> lr
[x, y, order=ilex]
-------------------
1128
3
2\
\- x + y
Note how the python list notation can be used as a short cut to express ideals. You can use
the convert method to return ordinary sympy objects into objects understood by the AGCA
module (although in many cases this will be done automatically for example the list was
automatically turned into an ideal, and in the process the symbols x and y were automatically
converted into other representations). For example:
>>> X, Y = lr.convert(x), lr.convert(y) ; X
3
2\
x + \- x + y
>>> x**3 == y**2
False
>>> X**3 == Y**2
True
When no localisation is needed, a more mathematical notation can be used. For example, let
us create the coordinate ring of three-dimensional ane space A3 :
>>> ar = QQ.old_poly_ring(x, y, z); ar
[x, y, z]
For more details, refer to the following class documentation. Note that the base rings, being
domains, are the main point of overlap between the AGCA module and the rest of the polys
module. All domains are documented in detail in the polys reference, so we show here only
an abridged version, with the methods most pertinent to the AGCA module.
class sympy.polys.domains.ring.Ring
Represents a ring domain.
Attributes
alias
dtype
one
rep
zero
Ring.free module(rank)
Generate a free module of rank rank over self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2)
QQ[x]**2
Ring.ideal(*gens)
Generate an ideal of self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).ideal(x**2)
<x**2>
1129
Ring.quotient ring(e)
Form a quotient ring of self.
Here e can be an ideal or an iterable.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).quotient_ring(QQ.old_poly_ring(x).ideal(x**2))
QQ[x]/<x**2>
>>> QQ.old_poly_ring(x).quotient_ring([x**2])
QQ[x]/<x**2>
sympy.polys.domains.polynomialring.PolynomialRing(domain or ring,
symbols=None, order=None)
A class for representing multivariate polynomial rings.
Attributes
alias
domain
dtype
gens
ngens
rep
symbols
class sympy.polys.domains.quotientring.QuotientRing(ring, ideal)
Class representing (commutative) quotient rings.
You should not usually instantiate this by hand, instead use the constructor from the
base ring in the construction.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> I = QQ.old_poly_ring(x).ideal(x**3 + 1)
>>> QQ.old_poly_ring(x).quotient_ring(I)
QQ[x]/<x**3 + 1>
Attributes:
ring - the base ring
base ideal - the ideal used to form the quotient
1130
Attributes
alias
one
rep
zero
Modules, Ideals and their Elementary Properties Let A be a ring. An A-module is a set
M , together with two binary operations + : M M M and : R M M called addition
and scalar multiplication. These are required to satisfy certain axioms, which can be found
in e.g. [Atiyah69] (page 1911). In this way modules are a direct generalisation of both vector
spaces (A being a eld) and abelian groups (A = Z). A submodule of the A-module M is a
subset N M , such that the binary operations restrict to N , and N becomes an A-module
with these operations.
The ring A itself has a natural A-module structure where addition and multiplication in the
module coincide with addition and multiplication in the ring. This A-module is also written as
A. An A-submodule of A is called an ideal of A. Ideals come up very naturally in algebraic geometry. More general modules can be seen as a technically convenient elbow room beyond
talking only about ideals.
If M , N are A-modules, then there is a natural (componentwise) A-module structure on M N .
Similarly there are A-module structures on cartesian products of more components. (For
the categorically inclined: the cartesian product of nitely many A-modules, with this Amodule structure, is the nite biproduct in the category of all A-modules. With innitely
many components, it is the direct product (but the innite direct sum has to be constructed
dierently).) As usual, repeated product of the A-module M is denoted M, M 2 , M 3 . . . , or M I
for arbitrary index sets I.
An A-module M is called free if it is isomorphic to the A-module AI for some (not necessarily
nite) index set I (refer to the next section for a denition of isomorphism). The cardinality
of I is called the rank of M ; one may prove this is well-dened. In general, the AGCA module
only works with free modules of nite rank, and other closely related modules. The easiest
way to create modules is to use member methods of the objects they are made up from. For
example, let us create a free module of rank 4 over the coordinate ring of A2 we created above,
together with a submodule:
>>> F = ar.free_module(4) ; F
4
[x, y, z]
>>> S = F.submodule([1, x, x**2, x**3], [0, 1, 0, y]) ; S
2
3
\
\1, x, x , x , [0, 1, 0, y]
Note how python lists can be used as a short-cut notation for module elements (vectors). As
usual, the convert method can be used to convert sympy/python objects into the internal
AGCA representation (see detailed reference below).
Here is the detailed documentation of the classes for modules, free modules, and submodules:
class sympy.polys.agca.modules.Module(ring)
Abstract base class for modules.
Do not instantiate - use ring explicit constructors instead:
1131
Attributes:
dtype - type of elements
ring - containing ring
Non-implemented methods:
submodule
quotient module
is zero
is submodule
multiply ideal
1132
Non-implemented methods:
submodule
basis()
Return a set of basis elements.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(3).basis()
([1, 0, 0], [0, 1, 0], [0, 0, 1])
convert(elem, M=None)
Convert elem into the internal representation.
This method is called implicitly whenever computations involve elements not in the
internal representation.
>>>
>>>
>>>
>>>
[1,
dtype
alias of FreeModuleElement
identity hom()
Return the identity homomorphism on self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2).identity_hom()
Matrix([
[1, 0], : QQ[x]**2 -> QQ[x]**2
[0, 1]])
is submodule(other)
Returns True if other is a submodule of self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> M = F.submodule([2, x])
>>> F.is_submodule(F)
True
>>> F.is_submodule(M)
True
>>> M.is_submodule(F)
False
is zero()
Returns True if self is a zero module.
(If, as this implementation assumes, the coecient ring is not the zero ring, then
this is equivalent to the rank being zero.)
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(0).is_zero()
1133
True
>>> QQ.old_poly_ring(x).free_module(1).is_zero()
False
multiply ideal(other)
Multiply self by the ideal other.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> I = QQ.old_poly_ring(x).ideal(x)
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> F.multiply_ideal(I)
<[x, 0], [0, x]>
quotient module(submodule)
Return a quotient module.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = QQ.old_poly_ring(x).free_module(2)
>>> M.quotient_module(M.submodule([1, x], [x, 2]))
QQ[x]**2/<[1, x], [x, 2]>
Non-implemented methods:
contains
syzygies
in terms of generators
intersect
module quotient
convert(elem, M=None)
Convert elem into the internal represantition.
Mostly called implicitly.
>>>
>>>
>>>
>>>
[2,
1134
identity hom()
Return the identity homomorphism on self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2).submodule([x, x]).identity_hom()
Matrix([
[1, 0], : <[x, x]> -> <[x, x]>
[0, 1]])
in terms of generators(e)
Express element e of self in terms of the generators.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> M = F.submodule([1, 0], [1, 1])
>>> M.in_terms_of_generators([x, x**2])
[-x**2 + x, x**2]
inclusion hom()
Return a homomorphism representing the inclusion map of self.
That is, the natural map from self to self.container.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2).submodule([x, x]).inclusion_hom()
Matrix([
[1, 0], : <[x, x]> -> QQ[x]**2
[0, 1]])
intersect(other, **options)
Returns the intersection of self with submodule other.
>>> from sympy.abc import x, y
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x, y).free_module(2)
>>> F.submodule([x, x]).intersect(F.submodule([y, y]))
<[x*y, x*y]>
The above result says: the intersection module is generated by the single element
(xy, xy) = y(x, x) = x(y, y), where (x, x) and (y, y) respectively are the unique
generators of the two modules being intersected.
is full module()
Return True if self is the entire free module.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
1135
is submodule(other)
Returns True if other is a submodule of self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> M = F.submodule([2, x])
>>> N = M.submodule([2*x, x**2])
>>> M.is_submodule(M)
True
>>> M.is_submodule(N)
True
>>> N.is_submodule(M)
False
is zero()
Return True if self is a zero module.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> F.submodule([x, 1]).is_zero()
False
>>> F.submodule([0, 0]).is_zero()
True
Some implementations allow further options to be passed. Currently, the only one
implemented is relations=True, which may only be passed if other is prinicipal.
In this case the function will return a pair (res, rel) where res is the ideal, and
rel is a list of coecient vectors, expressing the generators of the ideal, multiplied
by the generator of other in terms of generators of self.
>>> S.module_quotient(T, relations=True)
(<y>, [[1]])
This means that the quotient ideal is generated by the single element y, and that
y(x, x) = 1(xy, xy), (x, x) and (xy, xy) being the generators of T and S, respectively.
multiply ideal(I)
Multiply self by the ideal I.
1136
reduce element(x)
Reduce the element x of our ring modulo the ideal self.
Here reduce has no specic meaning, it could return a unique normal form, simplify the expression a bit, or just do nothing.
submodule(*gens)
Generate a submodule.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = QQ.old_poly_ring(x).free_module(2).submodule([x, 1])
>>> M.submodule([x**2, x])
<[x**2, x]>
syzygy module(**opts)
Compute the syzygy module of the generators of self.
Suppose M is generated by f1 , . . . , fn over the ring R. Consider the homomorphism
: Rn M , given by sending (r1 , . . . , rn ) r1 f1 + + rn fn . The syzygy module is
dened to be the kernel of .
The syzygy module is zero i the generators generate freely a free submodule:
>>> from sympy.abc import x, y
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2).submodule([1, 0], [1, 1]).syzygy_module().is_zero()
True
1137
union(other)
Returns the module generated by the union of self and other.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(1)
>>> M = F.submodule([x**2 + x]) # <x(x+1)>
>>> N = F.submodule([x**2 - 1]) # <(x-1)(x+1)>
>>> M.union(N) == F.submodule([x+1])
True
Ideals are created very similarly to modules. For example, lets verify that the nodal cubic is
indeed singular at the origin:
>>> I = lr.ideal(x, y)
>>> I == lr.ideal(x)
False
>>> I == lr.ideal(y)
False
We are using here the fact that a curve is non-singular at a point if and only if the maximal ideal
of the local ring is principal, and that in this case at least one of x and y must be generators.
This is the detailed documentation of the class ideal. Please note that most of the methods
regarding properties of ideals (primality etc.) are not yet implemented.
class sympy.polys.agca.ideals.Ideal(ring)
Abstract base class for ideals.
Do not instantiate - use explicit constructors in the ring class instead:
>>> from sympy import QQ
>>> from sympy.abc import x
>>> QQ.old_poly_ring(x).ideal(x+1)
<x + 1>
Attributes
ring - the ring this ideal belongs to
Non-implemented methods:
contains elem
contains ideal
quotient
intersect
union
product
is whole ring
is zero
is prime, is maximal, is primary, is radical
is principal
height, depth
radical
reduce element
contains(elem)
Return True if elem is an element of this ideal.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).ideal(x+1, x-1).contains(3)
True
>>> QQ.old_poly_ring(x).ideal(x**2, x**3).contains(x)
False
depth()
Compute the depth of self.
height()
Compute the height of self.
intersect(J)
Compute the intersection of self with ideal J.
>>> from sympy.abc import x, y
>>> from sympy import QQ
>>> R = QQ.old_poly_ring(x, y)
>>> R.ideal(x).intersect(R.ideal(y))
<x*y>
is maximal()
Return True if self is a maximal ideal.
is primary()
Return True if self is a primary ideal.
is prime()
Return True if self is a prime ideal.
is principal()
Return True if self is a principal ideal.
is radical()
Return True if self is a radical ideal.
is whole ring()
Return True if self is the whole ring.
is zero()
Return True if self is the zero ideal.
product(J)
Compute the ideal product of self and J.
That is, compute the ideal generated by products xy, for x an element of self and
y J.
>>> from sympy.abc import x, y
>>> from sympy import QQ
>>> QQ.old_poly_ring(x, y).ideal(x).product(QQ.old_poly_ring(x, y).ideal(y))
<x*y>
quotient(J, **opts)
Compute the ideal quotient of self by J.
That is, if self is the ideal I, compute the set I : J = {x R|xJ I}.
1139
>>>
>>>
>>>
>>>
<y>
radical()
Compute the radical of self.
reduce element(x)
Reduce the element x of our ring modulo the ideal self.
Here reduce has no specic meaning: it could return a unique normal form, simplify the expression a bit, or just do nothing.
saturate(J)
Compute the ideal saturation of self by J.
That is, if self is the ideal I, compute the set I : J = {x R|xJ n I for some n}.
subset(other)
Returns True if other is is a subset of self.
Here other may be an ideal.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> I = QQ.old_poly_ring(x).ideal(x+1)
>>> I.subset([x**2 - 1, x**2 + 2*x + 1])
True
>>> I.subset([x**2 + 1, x + 1])
False
>>> I.subset(QQ.old_poly_ring(x).ideal(x**2 - 1))
True
union(J)
Compute the ideal generated by the union of self and J.
convert(elem, M=None)
Convert elem into the internal representation.
1140
This method is called implicitly whenever computations involve elements not in the
internal representation.
>>>
>>>
>>>
>>>
[1,
dtype
alias of QuotientModuleElement
identity hom()
Return the identity homomorphism on self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = QQ.old_poly_ring(x).free_module(2) / [(1, 2), (1, x)]
>>> M.identity_hom()
Matrix([
[1, 0], : QQ[x]**2/<[1, 2], [1, x]> -> QQ[x]**2/<[1, 2], [1, x]>
[0, 1]])
is submodule(other)
Return True if other is a submodule of self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> Q = QQ.old_poly_ring(x).free_module(2) / [(x, x)]
>>> S = Q.submodule([1, 0])
>>> Q.is_submodule(S)
True
>>> S.is_submodule(Q)
False
is zero()
Return True if self is a zero module.
This happens if and only if the base module is the same as the submodule being
killed.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> (F/[(1, 0)]).is_zero()
False
>>> (F/[(1, 0), (0, 1)]).is_zero()
True
quotient hom()
Return the quotient homomorphism to self.
That is, return a homomorphism representing the natural map from self.base to
self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = QQ.old_poly_ring(x).free_module(2) / [(1, 2), (1, x)]
>>> M.quotient_hom()
Matrix([
1141
submodule(*gens, **opts)
Generate a submodule.
This is the same as taking a quotient of a submodule of the base module.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> Q = QQ.old_poly_ring(x).free_module(2) / [(x, x)]
>>> Q.submodule([x, 0])
<[x, 0] + <[x, x]>>
Attributes:
base - base module we are quotient of
killed module - submodule used to form the quotient
is full module()
Return True if self is the entire free module.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> F.submodule([x, 1]).is_full_module()
False
>>> F.submodule([1, 1], [1, 2]).is_full_module()
True
quotient hom()
Return the quotient homomorphism to self.
That is, return the natural map from self.base to self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = (QQ.old_poly_ring(x).free_module(2) / [(1, x)]).submodule([1, 0])
>>> M.quotient_hom()
Matrix([
[1, 0], : <[1, 0], [1, x]> -> <[1, 0] + <[1, x]>, [1, x] + <[1, x]>>
[0, 1]])
1142
1143
Examples
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> R = QQ.old_poly_ring(x)
>>> T = R.free_module(2)
1144
Attributes:
ring - the ring over which we are considering modules
domain - the domain module
codomain - the codomain module
ker - cached kernel
img - cachd image
Non-implemented methods:
kernel
image
restrict domain
restrict codomain
quotient domain
quotient codomain
apply
mul scalar
compose
add
image()
Compute the image of self.
That is, if self is the homomorphism : M N , then compute im() = {(x)|x M }.
This is a submodule of N .
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> homomorphism(F, F, [[1, 0], [x, 0]]).image() == F.submodule([1, 0])
True
is injective()
Return True if self is injective.
That is, check if the elements of the domain are mapped to the same codomain
element.
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
1145
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h.is_injective()
False
>>> h.quotient_domain(h.kernel()).is_injective()
True
is isomorphism()
Return True if self is an isomorphism.
That is, check if every element of the codomain has precisely one preimage. Equivalently, self is both injective and surjective.
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h = h.restrict_codomain(h.image())
>>> h.is_isomorphism()
False
>>> h.quotient_domain(h.kernel()).is_isomorphism()
True
is surjective()
Return True if self is surjective.
That is, check if every element of the codomain has at least one preimage.
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h.is_surjective()
False
>>> h.restrict_codomain(h.image()).is_surjective()
True
is zero()
Return True if self is a zero morphism.
That is, check if every element of the domain is mapped to zero under self.
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h.is_zero()
False
>>> h.restrict_domain(F.submodule()).is_zero()
True
>>> h.quotient_codomain(h.image()).is_zero()
True
1146
kernel()
Compute the kernel of self.
That is, if self is the homomorphism : M N , then compute ker() = {x M |(x) =
0}. This is a submodule of M .
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> homomorphism(F, F, [[1, 0], [x, 0]]).kernel()
<[x, -1]>
quotient codomain(sm)
Return self with codomain replaced by codomain/sm.
Here sm must be a submodule of self.codomain.
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2
[0, 0]])
>>> h.quotient_codomain(F.submodule([1, 1]))
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2/<[1, 1]>
[0, 0]])
This is the same as composing with the quotient map on the left:
>>> (F/[(1, 1)]).quotient_hom() * h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2/<[1, 1]>
[0, 0]])
quotient domain(sm)
Return self with domain replaced by domain/sm.
Here sm must be a submodule of self.kernel().
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2
[0, 0]])
>>> h.quotient_domain(F.submodule([-x, 1]))
Matrix([
[1, x], : QQ[x]**2/<[-x, 1]> -> QQ[x]**2
[0, 0]])
1147
restrict codomain(sm)
Return self, with codomain restricted to to sm.
Here sm has to be a submodule of self.codomain containing the image.
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2
[0, 0]])
>>> h.restrict_codomain(F.submodule([1, 0]))
Matrix([
[1, x], : QQ[x]**2 -> <[1, 0]>
[0, 0]])
restrict domain(sm)
Return self, with the domain restricted to sm.
Here sm has to be a submodule of self.domain.
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2
[0, 0]])
>>> h.restrict_domain(F.submodule([1, 0]))
Matrix([
[1, x], : <[1, 0]> -> QQ[x]**2
[0, 0]])
This is the same as just composing on the right with the submodule inclusion:
>>> h * F.submodule([1, 0]).inclusion_hom()
Matrix([
[1, x], : <[1, 0]> -> QQ[x]**2
[0, 0]])
There is one additional complication in the implementation. This comes from the fact that
all polynomial manipulations are relative to a ground domain. For example, when factoring
a polynomial like x10 1, one has to decide what ring the coecients are supposed to belong
to, or less trivially, what coecients are allowed to appear in the factorization. This choice
of coecients is called a ground domain. Typical choices include the integers Z, the rational
numbers Q or various related rings and elds. But it is perfectly legitimate (although in this
case uninteresting) to factorize over polynomial rings such as k[Y ], where k is some xed eld.
Thus the polynomial manipulation algorithms (both complicated ones like factoring, and simpler ones like addition or multiplication) have to rely on other code to manipulate the coecients. In the polynomial manipulation module, such code is encapsulated in so-called
domains. A domain is basically a factory object: it takes various representations of data,
and converts them into objects with unied interface. Every object created by a domain has
to implement the arithmetic operations +, and . Other operations are accessed through
the domain, e.g. as in ZZ.quo(ZZ(4), ZZ(2)).
Note that there is some amount of circularity: the polynomial ring domains use the level
one classes, the level one classes use the level zero functions, and level zero functions use
domains. It is possible, in principle, but not in the current implementation, to work in rings
like k[X][Y ]. This would create even more layers. For this reason, working in the isomorphic
ring k[X, Y ] is preferred.
Domains
Here we document the various implemented ground domains. There are three types: abstract
domains, concrete domains, and implementation domains. Abstract domains cannot be
(usefully) instantiated at all, and just collect together functionality shared by many other
domains. Concrete domains are those meant to be instantiated and used in the polynomial
manipulation algorithms. In some cases, there are various possible ways to implement the
data type the domain provides. For example, depending on what libraries are available on the
system, the integers are implemented either using the python built-in integers, or using gmpy.
Note that various aliases are created automatically depending on the libraries available. As
such e.g. ZZ always refers to the most ecient implementation of the integer ring available.
Abstract Domains
class sympy.polys.domains.domain.Domain
Represents an abstract domain.
Attributes
alias
dtype
one
rep
zero
abs(a)
Absolute value of a, implies
add(a, b)
Sum of a and b, implies
abs .
add .
algebraic field(*extension)
Returns an algebraic eld, i.e. K(, . . . ).
5.16. Polynomials Manipulation Module
1149
almosteq(a, b, tolerance=None)
Check if a and b are almost equal.
characteristic()
Return the characteristic of this domain.
cofactors(a, b)
Returns GCD and cofactors of a and b.
convert(element, base=None)
Convert element to self.dtype.
convert from(element, base)
Convert element to self.dtype given the base domain.
denom(a)
Returns denominator of a.
div(a, b)
Division of a and b, implies something.
evalf(a, prec=None, **options)
Returns numerical approximation of a.
exquo(a, b)
Exact quotient of a and b, implies something.
frac field(*symbols, **kwargs)
Returns a fraction eld, i.e. K(X).
from AlgebraicField(K1, a, K0)
Convert an algebraic number to dtype.
from ComplexField(K1, a, K0)
Convert a complex element to dtype.
from ExpressionDomain(K1, a, K0)
Convert a EX object to dtype.
from FF gmpy(K1, a, K0)
Convert ModularInteger(mpz) to dtype.
from FF python(K1, a, K0)
Convert ModularInteger(int) to dtype.
from FractionField(K1, a, K0)
Convert a rational function to dtype.
from GlobalPolynomialRing(K1, a, K0)
Convert a polynomial to dtype.
from PolynomialRing(K1, a, K0)
Convert a polynomial to dtype.
from QQ gmpy(K1, a, K0)
Convert a GMPY mpq object to dtype.
from QQ python(K1, a, K0)
Convert a Python Fraction object to dtype.
from RealField(K1, a, K0)
Convert a real element object to dtype.
from ZZ gmpy(K1, a, K0)
Convert a GMPY mpz object to dtype.
1150
mul .
neg .
1151
numer(a)
Returns numerator of a.
of type(element)
Check if a is of type dtype.
old frac field(*symbols, **kwargs)
Returns a fraction eld, i.e. K(X).
old poly ring(*symbols, **kwargs)
Returns a polynomial ring, i.e. K[X].
poly ring(*symbols, **kwargs)
Returns a polynomial ring, i.e. K[X].
pos(a)
Returns a positive, implies
pos .
pow(a, b)
Raise a to power b, implies
pow .
quo(a, b)
Quotient of a and b, implies something.
rem(a, b)
Remainder of a and b, implies
mod .
revert(a)
Returns a**(-1) if possible.
sqrt(a)
Returns square root of a.
sub(a, b)
Dierence of a and b, implies
sub .
to sympy(a)
Convert a to a SymPy object.
unify(K0, K1, symbols=None)
Construct a minimal domain that contains elements of K0 and K1.
Known domains (from smallest to largest):
GF(p)
ZZ
QQ
RR(prec, tol)
CC(prec, tol)
ALG(a, b, c)
K[x, y, z]
K(x, y, z)
EX
class sympy.polys.domains.field.Field
Represents a eld domain.
1152
Attributes
alias
dtype
one
rep
zero
div(a, b)
Division of a and b, implies
div .
exquo(a, b)
Exact quotient of a and b, implies
div .
gcd(a, b)
Returns GCD of a and b.
This denition of GCD over elds allows to clear denominators in primitive().
>>> from sympy.polys.domains import QQ
>>> from sympy import S, gcd, primitive
>>> from sympy.abc import x
>>> QQ.gcd(QQ(2, 3), QQ(4, 9))
2/9
>>> gcd(S(2)/3, S(4)/9)
2/9
>>> primitive(2*x/3 + S(4)/9)
(2/9, 3*x + 2)
get field()
Returns a eld associated with self.
get ring()
Returns a ring associated with self.
lcm(a, b)
Returns LCM of a and b.
>>> from sympy.polys.domains import QQ
>>> from sympy import S, lcm
>>> QQ.lcm(QQ(2, 3), QQ(4, 9))
4/3
>>> lcm(S(2)/3, S(4)/9)
4/3
quo(a, b)
Quotient of a and b, implies
div .
rem(a, b)
Remainder of a and b, implies nothing.
revert(a)
Returns a**(-1) if possible.
class sympy.polys.domains.ring.Ring
Represents a ring domain.
1153
Attributes
alias
dtype
one
rep
zero
denom(a)
Returns denominator of a.
div(a, b)
Division of a and b, implies
divmod .
exquo(a, b)
Exact quotient of a and b, implies
floordiv .
free module(rank)
Generate a free module of rank rank over self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2)
QQ[x]**2
get ring()
Returns a ring associated with self.
ideal(*gens)
Generate an ideal of self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).ideal(x**2)
<x**2>
invert(a, b)
Returns inversion of a mod b.
numer(a)
Returns numerator of a.
quo(a, b)
Quotient of a and b, implies
floordiv .
quotient ring(e)
Form a quotient ring of self.
Here e can be an ideal or an iterable.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).quotient_ring(QQ.old_poly_ring(x).ideal(x**2))
QQ[x]/<x**2>
>>> QQ.old_poly_ring(x).quotient_ring([x**2])
QQ[x]/<x**2>
1154
rem(a, b)
Remainder of a and b, implies
mod .
revert(a)
Returns a**(-1) if possible.
class sympy.polys.domains.simpledomain.SimpleDomain
Base class for simple domains, e.g. ZZ, QQ.
Attributes
alias
dtype
one
rep
zero
inject(*gens)
Inject generators into this domain.
class sympy.polys.domains.compositedomain.CompositeDomain
Base class for composite domains, e.g. ZZ[x], ZZ(X).
Attributes
alias
domain
dtype
gens
ngens
one
rep
symbols
zero
inject(*symbols)
Inject generators into this domain.
Concrete Domains
class sympy.polys.domains.FiniteField(mod, dom=None, symmetric=True)
General class for nite elds.
Attributes
alias
dom
dtype
mod
one
zero
characteristic()
Return the characteristic of this domain.
5.16. Polynomials Manipulation Module
1155
alias
dtype
one
zero
algebraic field(*extension)
Returns an algebraic eld, i.e. Q(, . . . ).
from AlgebraicField(K1, a, K0)
Convert a ANP object to dtype.
get field()
Returns a eld associated with self.
log(a, b)
Returns b-base logarithm of a.
class sympy.polys.domains.PolynomialRing(domain or ring,
der=None)
A class for representing multivariate polynomial rings.
1156
symbols=None,
or-
Attributes
alias
domain
dtype
gens
ngens
rep
symbols
factorial(a)
Returns factorial of a.
from AlgebraicField(K1, a, K0)
Convert an algebraic number to dtype.
from FractionField(K1, a, K0)
Convert a rational function to dtype.
from PolynomialRing(K1, a, K0)
Convert a polynomial to dtype.
from QQ gmpy(K1, a, K0)
Convert a GMPY mpq object to dtype.
from QQ python(K1, a, K0)
Convert a Python F raction object to dtype.
from RealField(K1, a, K0)
Convert a mpmath mpf object to dtype.
from ZZ gmpy(K1, a, K0)
Convert a GMPY mpz object to dtype.
from ZZ python(K1, a, K0)
Convert a Python int object to dtype.
from sympy(a)
Convert SymPys expression to dtype.
gcd(a, b)
Returns GCD of a and b.
gcdex(a, b)
Extended GCD of a and b.
get field()
Returns a eld associated with self .
is negative(a)
Returns True if LC(a) is negative.
is nonnegative(a)
Returns True if LC(a) is non-negative.
is nonpositive(a)
Returns True if LC(a) is non-positive.
is positive(a)
Returns True if LC(a) is positive.
lcm(a, b)
Returns LCM of a and b.
1157
to sympy(a)
Convert a to a SymPy object.
class sympy.polys.domains.RationalField
General class for rational elds.
Attributes
alias
dtype
one
zero
algebraic field(*extension)
Returns an algebraic eld, i.e. Q(, . . . ).
from AlgebraicField(K1, a, K0)
Convert a ANP object to dtype.
class sympy.polys.domains.AlgebraicField(dom, *ext)
A class for representing algebraic number elds.
Attributes
alias
one
rep
zero
algebraic field(*extension)
Returns an algebraic eld, i.e. Q(, . . . ).
denom(a)
Returns denominator of a.
dtype
alias of ANP
from QQ gmpy(K1, a, K0)
Convert a GMPY mpq object to dtype.
from QQ python(K1, a, K0)
Convert a Python Fraction object to dtype.
from RealField(K1, a, K0)
Convert a mpmath mpf object to dtype.
from ZZ gmpy(K1, a, K0)
Convert a GMPY mpz object to dtype.
from ZZ python(K1, a, K0)
Convert a Python int object to dtype.
from sympy(a)
Convert SymPys expression to dtype.
get ring()
Returns a ring associated with self.
1158
is negative(a)
Returns True if a is negative.
is nonnegative(a)
Returns True if a is non-negative.
is nonpositive(a)
Returns True if a is non-positive.
is positive(a)
Returns True if a is positive.
numer(a)
Returns numerator of a.
to sympy(a)
Convert a to a SymPy object.
class sympy.polys.domains.FractionField(domain or eld,
symbols=None,
der=None)
A class for representing multivariate rational function elds.
or-
Attributes
alias
domain
dtype
gens
ngens
rep
symbols
denom(a)
Returns denominator of a.
factorial(a)
Returns factorial of a.
from AlgebraicField(K1, a, K0)
Convert an algebraic number to dtype.
from FractionField(K1, a, K0)
Convert a rational function to dtype.
from PolynomialRing(K1, a, K0)
Convert a polynomial to dtype.
from QQ gmpy(K1, a, K0)
Convert a GMPY mpq object to dtype.
from QQ python(K1, a, K0)
Convert a Python F raction object to dtype.
from RealField(K1, a, K0)
Convert a mpmath mpf object to dtype.
from ZZ gmpy(K1, a, K0)
Convert a GMPY mpz object to dtype.
from ZZ python(K1, a, K0)
Convert a Python int object to dtype.
1159
from sympy(a)
Convert SymPys expression to dtype.
get ring()
Returns a eld associated with self .
is negative(a)
Returns True if LC(a) is negative.
is nonnegative(a)
Returns True if LC(a) is non-negative.
is nonpositive(a)
Returns True if LC(a) is non-positive.
is positive(a)
Returns True if LC(a) is positive.
numer(a)
Returns numerator of a.
to sympy(a)
Convert a to a SymPy object.
class sympy.polys.domains.RealField(prec=53, dps=None, tol=None)
Real numbers up to the given precision.
Attributes
alias
dtype
one
zero
almosteq(a, b, tolerance=None)
Check if a and b are almost equal.
from sympy(expr)
Convert SymPys number to dtype.
gcd(a, b)
Returns GCD of a and b.
get exact()
Returns an exact domain associated with self.
get ring()
Returns a ring associated with self.
lcm(a, b)
Returns LCM of a and b.
to rational(element, limit=True)
Convert a real number to rational number.
to sympy(element)
Convert element to SymPy number.
class sympy.polys.domains.ExpressionDomain
A class for arbitrary expressions.
1160
Attributes
alias
class Expression(ex)
An arbitrary expression.
ExpressionDomain.denom(a)
Returns denominator of a.
ExpressionDomain.dtype
alias of Expression (page 1161)
ExpressionDomain.from ExpressionDomain(K1, a, K0)
Convert a EX object to dtype.
ExpressionDomain.from FractionField(K1, a, K0)
Convert a DMF object to dtype.
ExpressionDomain.from PolynomialRing(K1, a, K0)
Convert a DMP object to dtype.
ExpressionDomain.from QQ gmpy(K1, a, K0)
Convert a GMPY mpq object to dtype.
ExpressionDomain.from QQ python(K1, a, K0)
Convert a Python Fraction object to dtype.
ExpressionDomain.from RealField(K1, a, K0)
Convert a mpmath mpf object to dtype.
ExpressionDomain.from ZZ gmpy(K1, a, K0)
Convert a GMPY mpz object to dtype.
ExpressionDomain.from ZZ python(K1, a, K0)
Convert a Python int object to dtype.
ExpressionDomain.from sympy(a)
Convert SymPys expression to dtype.
ExpressionDomain.get field()
Returns a eld associated with self.
ExpressionDomain.get ring()
Returns a ring associated with self.
ExpressionDomain.is negative(a)
Returns True if a is negative.
ExpressionDomain.is nonnegative(a)
Returns True if a is non-negative.
ExpressionDomain.is nonpositive(a)
Returns True if a is non-positive.
ExpressionDomain.is positive(a)
Returns True if a is positive.
ExpressionDomain.numer(a)
Returns numerator of a.
ExpressionDomain.to sympy(a)
Convert a to a SymPy object.
1161
Implementation Domains
class sympy.polys.domains.PythonFiniteField(mod, symmetric=True)
Finite eld based on Pythons integers.
Attributes
dom
dtype
mod
one
zero
class sympy.polys.domains.GMPYFiniteField(mod, symmetric=True)
Finite eld based on GMPY integers.
Attributes
dom
dtype
mod
one
zero
class sympy.polys.domains.PythonIntegerRing
Integer ring based on Pythons int type.
class sympy.polys.domains.GMPYIntegerRing
Integer ring based on GMPYs mpz type.
class sympy.polys.domains.PythonRationalField
Rational eld based on Python rational number type.
class sympy.polys.domains.GMPYRationalField
Rational eld based on GMPY mpq class.
Level One
1162
all monoms(f)
Returns all monomials from f.
all terms(f)
Returns all terms from a f.
cancel(f, g, include=True)
Cancel common factors in a rational function f/g.
clear denoms(f)
Clear denominators, but keep the ground domain.
coeffs(f, order=None)
Returns all non-zero coecients from f in lex order.
cofactors(f, g)
Returns GCD of f and g and their cofactors.
compose(f, g)
Computes functional composition of f and g.
content(f)
Returns GCD of polynomial coecients.
convert(f, dom)
Convert the ground domain of f.
count complex roots(f, inf=None, sup=None)
Return the number of complex roots of f in [inf, sup].
count real roots(f, inf=None, sup=None)
Return the number of real roots of f in [inf, sup].
decompose(f)
Computes functional decomposition of f.
deflate(f)
Reduce degree of f by mapping xm
i to yi .
degree(f, j=0)
Returns the leading degree of f in x j.
degree list(f)
Returns a list of degrees of f.
diff(f, m=1, j=0)
Computes the m-th order derivative of f in x j.
discriminant(f)
Computes discriminant of f.
div(f, g)
Polynomial division with remainder of f and g.
eject(f, dom, front=False)
Eject selected generators into the ground domain.
eval(f, a, j=0)
Evaluates f at the given point a in x j.
exclude(f)
Remove useless generators from f.
Returns the removed generators and the new excluded f.
1163
Examples
>>> from sympy.polys.polyclasses import DMP
>>> from sympy.polys.domains import ZZ
>>> DMP([[[ZZ(1)]], [[ZZ(1)], [ZZ(2)]]], ZZ).exclude()
([2], DMP([[1], [1, 2]], ZZ, None))
exquo(f, g)
Computes polynomial exact quotient of f and g.
exquo ground(f, c)
Exact quotient of f by a an element of the ground domain.
factor list(f)
Returns a list of irreducible factors of f.
factor list include(f)
Returns a list of irreducible factors of f.
classmethod from dict(rep, lev, dom)
Construct and instance of cls from a dict representation.
classmethod from list(rep, lev, dom)
Create an instance of cls given a list of native coecients.
classmethod from sympy list(rep, lev, dom)
Create an instance of cls given a list of SymPy coecients.
gcd(f, g)
Returns polynomial GCD of f and g.
gcdex(f, g)
Extended Euclidean algorithm, if univariate.
gff list(f)
Computes greatest factorial factorization of f.
half gcdex(f, g)
Half extended Euclidean algorithm, if univariate.
homogeneous order(f)
Returns the homogeneous order of f.
homogenize(f, s)
Return homogeneous polynomial of f
inject(f, front=False)
Inject ground domain generators into f.
integrate(f, m=1, j=0)
Computes the m-th order indenite integral of f in x j.
intervals(f, all=False, eps=None, inf=None, sup=None, fast=False, sqf=False)
Compute isolating intervals for roots of f.
invert(f, g)
Invert f modulo g, if possible.
is cyclotomic
Returns True if f is a cyclotomic polynomial.
is ground
Returns True if f is an element of the ground domain.
1164
is homogeneous
Returns True if f is a homogeneous polynomial.
is irreducible
Returns True if f has no factors over its domain.
is linear
Returns True if f is linear in all its variables.
is monic
Returns True if the leading coecient of f is one.
is monomial
Returns True if f is zero or has only one term.
is one
Returns True if f is a unit polynomial.
is primitive
Returns True if the GCD of the coecients of f is one.
is quadratic
Returns True if f is quadratic in all its variables.
is sqf
Returns True if f is a square-free polynomial.
is zero
Returns True if f is a zero polynomial.
l1 norm(f)
Returns l1 norm of f.
lcm(f, g)
Returns polynomial LCM of f and g.
lift(f)
Convert algebraic coecients to rationals.
max norm(f)
Returns maximum norm of f.
monic(f)
Divides all coecients by LC(f).
monoms(f, order=None)
Returns all non-zero monomials from f in lex order.
mul(f, g)
Multiply two multivariate polynomials f and g.
mul ground(f, c)
Multiply f by a an element of the ground domain.
neg(f)
Negate all coecients in f.
nth(f, *N)
Returns the n-th coecient of f.
pdiv(f, g)
Polynomial pseudo-division of f and g.
per(f, rep, dom=None, kill=False, ring=None)
Create a DMP out of the given representation.
1165
permute(f, P)
Returns a polynomial in K[xP (1) , ..., xP (n) ].
Examples
>>> from sympy.polys.polyclasses import DMP
>>> from sympy.polys.domains import ZZ
>>> DMP([[[ZZ(2)], [ZZ(1), ZZ(0)]], [[]]], ZZ).permute([1, 0, 2])
DMP([[[2], []], [[1, 0], []]], ZZ, None)
>>> DMP([[[ZZ(2)], [ZZ(1), ZZ(0)]], [[]]], ZZ).permute([1, 2, 0])
DMP([[[1], []], [[2, 0], []]], ZZ, None)
pexquo(f, g)
Polynomial exact pseudo-quotient of f and g.
pow(f, n)
Raise f to a non-negative power n.
pquo(f, g)
Polynomial pseudo-quotient of f and g.
prem(f, g)
Polynomial pseudo-remainder of f and g.
primitive(f)
Returns content and a primitive form of f.
quo(f, g)
Computes polynomial quotient of f and g.
quo ground(f, c)
Quotient of f by a an element of the ground domain.
refine root(f, s, t, eps=None, steps=None, fast=False)
Rene an isolating interval to the given precision.
eps should be a rational number.
rem(f, g)
Computes polynomial remainder of f and g.
resultant(f, g, includePRS=False)
Computes resultant of f and g via PRS.
revert(f, n)
Compute f**(-1) mod x**n.
shift(f, a)
Eciently compute Taylor shift f(x + a).
slice(f, m, n, j=0)
Take a continuous subsequence of terms of f.
sqf list(f, all=False)
Returns a list of square-free factors of f.
sqf list include(f, all=False)
Returns a list of square-free factors of f.
1166
sqf norm(f)
Computes square-free norm of f.
sqf part(f)
Computes square-free part of f.
sqr(f)
Square a multivariate polynomial f.
sturm(f)
Computes the Sturm sequence of f.
sub(f, g)
Subtract two multivariate polynomials f and g.
sub ground(f, c)
Subtract an element of the ground domain from f.
subresultants(f, g)
Computes subresultant PRS sequence of f and g.
terms(f, order=None)
Returns all non-zero terms from f in lex order.
terms gcd(f)
Remove GCD of terms from the polynomial f.
to dict(f, zero=False)
Convert f to a dict representation with native coecients.
to exact(f)
Make the ground domain exact.
to field(f)
Make the ground domain a eld.
to ring(f)
Make the ground domain a ring.
to sympy dict(f, zero=False)
Convert f to a dict representation with SymPy coecients.
to tuple(f)
Convert f to a tuple representation with native coecients.
This is needed for hashing.
total degree(f)
Returns the total degree of f.
trunc(f, p)
Reduce f modulo a constant p.
unify(f, g)
Unify representations of two multivariate polynomials.
class sympy.polys.polyclasses.DMF(rep, dom, lev=None, ring=None)
Dense Multivariate Fractions over K.
add(f, g)
Add two multivariate fractions f and g.
cancel(f)
Remove common factors from f.num and f.den.
denom(f)
Returns the denominator of f.
5.16. Polynomials Manipulation Module
1167
exquo(f, g)
Computes quotient of fractions f and g.
frac unify(f, g)
Unify representations of two multivariate fractions.
half per(f, rep, kill=False)
Create a DMP out of the given representation.
invert(f, check=True)
Computes inverse of a fraction f.
is one
Returns True if f is a unit fraction.
is zero
Returns True if f is a zero fraction.
mul(f, g)
Multiply two multivariate fractions f and g.
neg(f)
Negate all coecients in f.
numer(f)
Returns the numerator of f.
per(f, num, den, cancel=True, kill=False, ring=None)
Create a DMF out of the given representation.
poly unify(f, g)
Unify a multivariate fraction and a polynomial.
pow(f, n)
Raise f to a non-negative power n.
quo(f, g)
Computes quotient of fractions f and g.
sub(f, g)
Subtract two multivariate fractions f and g.
class sympy.polys.polyclasses.ANP(rep, mod, dom)
Dense Algebraic Number Polynomials over a eld.
LC(f)
Returns the leading coecient of f.
TC(f)
Returns the trailing coecient of f.
is ground
Returns True if f is an element of the ground domain.
is one
Returns True if f is a unit algebraic number.
is zero
Returns True if f is a zero algebraic number.
pow(f, n)
Raise f to a non-negative power n.
to dict(f)
Convert f to a dict representation with native coecients.
1168
to list(f)
Convert f to a list representation with native coecients.
to sympy dict(f)
Convert f to a dict representation with SymPy coecients.
to sympy list(f)
Convert f to a list representation with SymPy coecients.
to tuple(f)
Convert f to a tuple representation with native coecients.
This is needed for hashing.
unify(f, g)
Unify representations of two algebraic numbers.
Level Zero
Level zero contains the bulk code of the polynomial manipulation module.
Manipulation of dense, multivariate polynomials These functions can be used to manipulate polynomials in K[X0 , . . . , Xu ]. Functions for manipulating multivariate polynomials in
the dense representation have the prex dmp . Functions which only apply to univariate polynomials (i.e. u = 0) have the prex dup . The ground domain K has to be passed explicitly.
For many multivariate polynomial manipulation functions also the level u, i.e. the number of
generators minus one, has to be passed. (Note that, in many cases, dup versions of functions
are available, which may be slightly more ecient.)
Basic manipulation:
sympy.polys.densebasic.dmp LC(f, K)
Return leading coecient of f.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import poly_LC
>>> poly_LC([], ZZ)
0
>>> poly_LC([ZZ(1), ZZ(2), ZZ(3)], ZZ)
1
sympy.polys.densebasic.dmp TC(f, K)
Return trailing coecient of f.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import poly_TC
1169
sympy.polys.densebasic.dmp degree(f, u)
Return the leading degree of f in x 0 in K[X].
Note that the degree of 0 is negative innity (the SymPy object -oo).
1170
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_degree
>>> dmp_degree([[[]]], 2)
-oo
>>> f = ZZ.map([[2], [1, 2, 3]])
>>> dmp_degree(f, 1)
1
sympy.polys.densebasic.dmp strip(f, u)
Remove leading zeros from f in K[X].
Examples
>>> from sympy.polys.densebasic import dmp_strip
>>> dmp_strip([[], [0, 1, 2], [1]], 1)
[[0, 1, 2], [1]]
1171
Examples
>>> from sympy.polys.densebasic import dmp_validate
>>> dmp_validate([[], [0, 1, 2], [1]])
([[1, 2], [1]], 1)
>>> dmp_validate([[1], 1])
Traceback (most recent call last):
...
ValueError: invalid data structure for a multivariate polynomial
Traceback (most recent call last):
...
ValueError: invalid data structure for a multivariate polynomial
sympy.polys.densebasic.dup reverse(f)
Compute x**n * f(1/x), i.e.: reverse f in K[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dup_reverse
>>> f = ZZ.map([1, 2, 3, 0])
>>> dup_reverse(f)
[3, 2, 1]
sympy.polys.densebasic.dmp copy(f, u)
Create a new copy of a polynomial f in K[X].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_copy
>>> f = ZZ.map([[1], [1, 2]])
>>> dmp_copy(f, 1)
[[1], [1, 2]]
sympy.polys.densebasic.dmp to tuple(f, u)
Convert f into a nested tuple of tuples.
This is needed for hashing. This is similar to dmp copy().
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_to_tuple
1172
sympy.polys.densebasic.dmp normal(f, u, K)
Normalize a multivariate polynomial in the given domain.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_normal
>>> dmp_normal([[], [0, 1.5, 2]], 1, ZZ)
[[1, 2]]
sympy.polys.densebasic.dmp nth(f, n, u, K)
Return the n-th coecient of f in K[x].
Examples
1173
sympy.polys.densebasic.dmp zero(u)
Return a multivariate zero.
Examples
>>> from sympy.polys.densebasic import dmp_zero
>>> dmp_zero(4)
[[[[[]]]]]
1174
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_one_p
>>> dmp_one_p([[[ZZ(1)]]], 2, ZZ)
True
sympy.polys.densebasic.dmp one(u, K)
Return a multivariate one over K.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_one
>>> dmp_one(2, ZZ)
[[[1]]]
sympy.polys.densebasic.dmp ground(c, u)
Return a multivariate constant.
Examples
>>> from sympy.polys.densebasic import dmp_ground
>>> dmp_ground(3, 5)
[[[[[[3]]]]]]
>>> dmp_ground(1, -1)
1
sympy.polys.densebasic.dmp zeros(n, u, K)
Return a list of multivariate zeros.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_zeros
1175
sympy.polys.densebasic.dmp grounds(c, n, u)
Return a list of multivariate constants.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_grounds
>>> dmp_grounds(ZZ(4), 3, 2)
[[[[4]]], [[[4]]], [[[4]]]]
>>> dmp_grounds(ZZ(4), 3, -1)
[4, 4, 4]
1176
>>> dmp_from_dict({(0, 0): ZZ(3), (0, 1): ZZ(2), (2, 1): ZZ(1)}, 1, ZZ)
[[1, 0], [], [2, 3]]
>>> dmp_from_dict({}, 0, ZZ)
[]
sympy.polys.densebasic.dmp swap(f, i, j, u, K)
Transform K[..x i..x j..] to K[..x j..x i..].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_swap
>>> f = ZZ.map([[[2], [1, 0]], []])
>>> dmp_swap(f, 0, 1, 2, ZZ)
[[[2], []], [[1, 0], []]]
>>> dmp_swap(f, 1, 2, 2, ZZ)
[[[1], [2, 0]], [[]]]
>>> dmp_swap(f, 0, 2, 2, ZZ)
[[[1, 0]], [[2, 0], []]]
sympy.polys.densebasic.dmp permute(f, P, u, K)
Return a polynomial in K[x {P(1)},..,x {P(n)}].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_permute
>>> f = ZZ.map([[[2], [1, 0]], []])
>>> dmp_permute(f, [1, 0, 2], 2, ZZ)
[[[2], []], [[1, 0], []]]
>>> dmp_permute(f, [1, 2, 0], 2, ZZ)
[[[1], []], [[2, 0], []]]
sympy.polys.densebasic.dmp nest(f, l, K)
Return a multivariate value nested l-levels.
1177
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_nest
>>> dmp_nest([[ZZ(1)]], 2, ZZ)
[[[[1]]]]
sympy.polys.densebasic.dmp raise(f, l, u, K)
Return a multivariate polynomial raised l-levels.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_raise
>>> f = ZZ.map([[], [1, 2]])
>>> dmp_raise(f, 2, 1, ZZ)
[[[[]]], [[[1]], [[2]]]]
sympy.polys.densebasic.dmp deflate(f, u, K)
Map x i**m i to y i in a polynomial in K[X].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_deflate
>>> f = ZZ.map([[1, 0, 0, 2], [], [3, 0, 0, 4]])
>>> dmp_deflate(f, 1, ZZ)
((2, 3), [[1, 2], [3, 4]])
sympy.polys.densebasic.dmp inflate(f, M, u, K)
Map y i to x i**k i in a polynomial in K[X].
1178
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_inflate
>>> f = ZZ.map([[1, 2], [3, 4]])
>>> dmp_inflate(f, (2, 3), 1, ZZ)
[[1, 0, 0, 2], [], [3, 0, 0, 4]]
sympy.polys.densebasic.dmp exclude(f, u, K)
Exclude useless levels from f.
Return the levels excluded, the new excluded f, and the new u.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_exclude
>>> f = ZZ.map([[[1]], [[1], [2]]])
>>> dmp_exclude(f, 2, ZZ)
([2], [[1], [1, 2]], 1)
sympy.polys.densebasic.dmp include(f, J, u, K)
Include useless levels in f.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_include
>>> f = ZZ.map([[1], [1, 2]])
>>> dmp_include(f, [2], 1, ZZ)
[[[1]], [[1], [2]]]
1179
1180
sympy.polys.densebasic.dmp slice(f, m, n, u, K)
Take a continuous subsequence of terms of f in K[X].
sympy.polys.densebasic.dup random(n, a, b, K)
Return a polynomial of degree n with coecients in [a, b].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dup_random
>>> dup_random(3, -10, 10, ZZ)
[-2, -8, 9, -4]
Arithmetic operations:
sympy.polys.densearith.dmp add term(f, c, i, u, K)
Add c(x 2..x u)*x 0**i to f in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_add_term(x*y + 1, 2, 2)
2*x**2 + x*y + 1
1181
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_mul_term(x**2*y + x, 3*y, 2)
3*x**4*y**2 + 3*x**3*y
1182
sympy.polys.densearith.dup lshift(f, n, K)
Eciently multiply f by x**n in K[x].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x = ring(x, ZZ)
>>> R.dup_lshift(x**2 + 1, 2)
x**4 + x**2
sympy.polys.densearith.dup rshift(f, n, K)
Eciently divide f by x**n in K[x].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x = ring(x, ZZ)
>>> R.dup_rshift(x**4 + x**2, 2)
x**2 + 1
>>> R.dup_rshift(x**4 + x**2 + 2, 2)
x**2 + 1
sympy.polys.densearith.dmp abs(f, u, K)
Make all coecients positive in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
1183
>>> R.dmp_abs(x**2*y - x)
x**2*y + x
sympy.polys.densearith.dmp neg(f, u, K)
Negate a polynomial in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_neg(x**2*y - x)
-x**2*y + x
sympy.polys.densearith.dmp add(f, g, u, K)
Add dense polynomials in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_add(x**2 + y, x**2*y + x)
x**2*y + x**2 + x + y
sympy.polys.densearith.dmp sub(f, g, u, K)
Subtract dense polynomials in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_sub(x**2 + y, x**2*y + x)
-x**2*y + x**2 - x + y
1184
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_sub_mul(x**2 + y, x, x + 2)
-2*x + y
sympy.polys.densearith.dmp mul(f, g, u, K)
Multiply dense polynomials in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_mul(x*y + 1, x)
x**2*y + x
sympy.polys.densearith.dmp sqr(f, u, K)
Square dense polynomials in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_sqr(x**2 + x*y + y**2)
x**4 + 2*x**3*y + 3*x**2*y**2 + 2*x*y**3 + y**4
sympy.polys.densearith.dmp pow(f, n, u, K)
Raise f to the n-th power in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_pow(x*y + 1, 3)
x**3*y**3 + 3*x**2*y**2 + 3*x*y + 1
sympy.polys.densearith.dmp pdiv(f, g, u, K)
Polynomial pseudo-division in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
1185
sympy.polys.densearith.dmp prem(f, g, u, K)
Polynomial pseudo-remainder in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_prem(x**2 + x*y, 2*x + 2)
-4*y + 4
sympy.polys.densearith.dmp pquo(f, g, u, K)
Polynomial exact pseudo-quotient in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> f = x**2 + x*y
>>> g = 2*x + 2*y
>>> h = 2*x + 2
>>> R.dmp_pquo(f, g)
2*x
>>> R.dmp_pquo(f, h)
2*x + 2*y - 2
sympy.polys.densearith.dmp pexquo(f, g, u, K)
Polynomial pseudo-quotient in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> f = x**2 + x*y
>>> g = 2*x + 2*y
>>> h = 2*x + 2
>>> R.dmp_pexquo(f, g)
2*x
>>> R.dmp_pexquo(f, h)
Traceback (most recent call last):
...
ExactQuotientFailed: [[2], [2]] does not divide [[1], [1, 0], []]
Traceback (most recent call last):
1186
...
ExactQuotientFailed: [[2], [2]] does not divide [[1], [1, 0], []]
sympy.polys.densearith.dmp rr div(f, g, u, K)
Multivariate division with remainder over a ring.
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_rr_div(x**2 + x*y, 2*x + 2)
(0, x**2 + x*y)
sympy.polys.densearith.dmp ff div(f, g, u, K)
Polynomial division with remainder over a eld.
Examples
>>> from sympy.polys import ring, QQ
>>> R, x,y = ring(x,y, QQ)
>>> R.dmp_ff_div(x**2 + x*y, 2*x + 2)
(1/2*x + 1/2*y - 1/2, -y + 1)
sympy.polys.densearith.dmp div(f, g, u, K)
Polynomial division with remainder in K[X].
Examples
>>> from sympy.polys import ring, ZZ, QQ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_div(x**2 + x*y, 2*x + 2)
(0, x**2 + x*y)
>>> R, x,y = ring(x,y, QQ)
>>> R.dmp_div(x**2 + x*y, 2*x + 2)
(1/2*x + 1/2*y - 1/2, -y + 1)
sympy.polys.densearith.dmp rem(f, g, u, K)
Returns polynomial remainder in K[X].
Examples
>>> from sympy.polys import ring, ZZ, QQ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_rem(x**2 + x*y, 2*x + 2)
x**2 + x*y
1187
sympy.polys.densearith.dmp quo(f, g, u, K)
Returns exact polynomial quotient in K[X].
Examples
>>> from sympy.polys import ring, ZZ, QQ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_quo(x**2 + x*y, 2*x + 2)
0
>>> R, x,y = ring(x,y, QQ)
>>> R.dmp_quo(x**2 + x*y, 2*x + 2)
1/2*x + 1/2*y - 1/2
sympy.polys.densearith.dmp exquo(f, g, u, K)
Returns polynomial quotient in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> f = x**2 + x*y
>>> g = x + y
>>> h = 2*x + 2
>>> R.dmp_exquo(f, g)
x
>>> R.dmp_exquo(f, h)
Traceback (most recent call last):
...
ExactQuotientFailed: [[2], [2]] does not divide [[1], [1, 0], []]
Traceback (most recent call last):
...
ExactQuotientFailed: [[2], [2]] does not divide [[1], [1, 0], []]
1188
sympy.polys.densearith.dmp l1 norm(f, u, K)
Returns l1 norm of a polynomial in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_l1_norm(2*x*y - x - 3)
6
sympy.polys.densearith.dmp expand(polys, u, K)
Multiply together several polynomials in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_expand([x**2 + y**2, x + 1])
x**3 + x**2 + x*y**2 + y**2
Further tools:
sympy.polys.densetools.dmp integrate(f, m, u, K)
Computes the indenite integral of f in x 0 in K[X].
Examples
>>> from sympy.polys import ring, QQ
>>> R, x,y = ring(x,y, QQ)
>>> R.dmp_integrate(x + 2*y, 1)
1/2*x**2 + 2*x*y
>>> R.dmp_integrate(x + 2*y, 2)
1/6*x**3 + x**2*y
sympy.polys.densetools.dmp diff(f, m, u, K)
m-th order derivative in x 0 of a polynomial in K[X].
5.16. Polynomials Manipulation Module
1189
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> f = x*y**2 + 2*x*y + 3*x + 2*y**2 + 3*y + 1
>>> R.dmp_diff(f, 1)
y**2 + 2*y + 3
>>> R.dmp_diff(f, 2)
0
sympy.polys.densetools.dmp eval(f, a, u, K)
Evaluate a polynomial at x 0 = a in K[X] using the Horner scheme.
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> R.dmp_eval(2*x*y + 3*x + y + 2, 2)
5*y + 8
1190
R.dmp_eval_in(f, 2, 0)
+ 8
R.dmp_eval_in(f, 2, 1)
+ 4
sympy.polys.densetools.dmp trunc(f, p, u, K)
Reduce a K[X] polynomial modulo a polynomial p in K[Y].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> f = 3*x**2*y + 8*x**2 + 5*x*y + 6*x + 2*y + 3
>>> g = (y - 1).drop(x)
>>> R.dmp_trunc(f, g)
11*x**2 + 11*x + 5
1191
sympy.polys.densetools.dup monic(f, K)
Divide all coecients by LC(f) in K[x].
Examples
>>> from sympy.polys import ring, ZZ, QQ
>>> R, x = ring(x, ZZ)
>>> R.dup_monic(3*x**2 + 6*x + 9)
x**2 + 2*x + 3
>>> R, x = ring(x, QQ)
>>> R.dup_monic(3*x**2 + 4*x + 2)
x**2 + 4/3*x + 2/3
sympy.polys.densetools.dup content(f, K)
Compute the GCD of coecients of f in K[x].
Examples
>>> from sympy.polys import ring, ZZ, QQ
>>> R, x = ring(x, ZZ)
>>> f = 6*x**2 + 8*x + 12
1192
>>> R.dup_content(f)
2
>>> R, x = ring(x, QQ)
>>> f = 6*x**2 + 8*x + 12
>>> R.dup_content(f)
2
sympy.polys.densetools.dup primitive(f, K)
Compute content and the primitive form of f in K[x].
Examples
>>> from sympy.polys import ring, ZZ, QQ
>>> R, x = ring(x, ZZ)
>>> f = 6*x**2 + 8*x + 12
>>> R.dup_primitive(f)
(2, 3*x**2 + 4*x + 6)
>>> R, x = ring(x, QQ)
>>> f = 6*x**2 + 8*x + 12
>>> R.dup_primitive(f)
(2, 3*x**2 + 4*x + 6)
1193
Examples
>>> from sympy.polys import ring, ZZ, QQ
>>> R, x,y = ring(x,y, ZZ)
>>> f = 2*x*y + 6*x + 4*y + 12
>>> R.dmp_ground_primitive(f)
(2, x*y + 3*x + 2*y + 6)
>>> R, x,y = ring(x,y, QQ)
>>> f = 2*x*y + 6*x + 4*y + 12
>>> R.dmp_ground_primitive(f)
(2, x*y + 3*x + 2*y + 6)
sympy.polys.densetools.dup extract(f, g, K)
Extract common content from a pair of polynomials in K[x].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x = ring(x, ZZ)
>>> R.dup_extract(6*x**2 + 12*x + 18, 4*x**2 + 8*x + 12)
(2, 3*x**2 + 6*x + 9, 2*x**2 + 4*x + 6)
sympy.polys.densetools.dup mirror(f, K)
Evaluate eciently the composition f(-x) in K[x].
1194
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x = ring(x, ZZ)
>>> R.dup_mirror(x**3 + 2*x**2 - 4*x + 2)
-x**3 + 2*x**2 + 4*x + 2
sympy.polys.densetools.dup scale(f, a, K)
Evaluate eciently composition f(a*x) in K[x].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x = ring(x, ZZ)
>>> R.dup_scale(x**2 - 2*x + 1, ZZ(2))
4*x**2 - 4*x + 1
sympy.polys.densetools.dup shift(f, a, K)
Evaluate eciently Taylor shift f(x + a) in K[x].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x = ring(x, ZZ)
>>> R.dup_shift(x**2 - 2*x + 1, ZZ(2))
x**2 + 2*x + 1
sympy.polys.densetools.dup transform(f, p, q, K)
Evaluate functional transformation q**n * f(p/q) in K[x].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x = ring(x, ZZ)
>>> R.dup_transform(x**2 - 2*x + 1, x**2 + 1, x - 1)
x**4 - 2*x**3 + 5*x**2 - 4*x + 4
sympy.polys.densetools.dmp compose(f, g, u, K)
Evaluate functional composition f(g) in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
1195
sympy.polys.densetools.dup decompose(f, K)
Computes functional decomposition of f in K[x].
Given a univariate polynomial f with coecients in a eld of characteristic zero, returns
list [f 1, f 2, ..., f n], where:
f = f 1 o f 2 o ... f n = f 1(f 2(... f n))
and f 2, ..., f n are monic and homogeneous polynomials of at least second degree.
Unlike factorization, complete functional decompositions of polynomials are not unique,
consider examples:
1.f o g = f(x + b) o (g - b)
2.x**n o x**m = x**m o x**n
3.T n o T m = T m o T n
where T n and T m are Chebyshev polynomials.
References
sympy.polys.densetools.dmp lift(f, u, K)
Convert algebraic coecients to integers in K[X].
Examples
>>> from sympy.polys import ring, QQ
>>> from sympy import I
>>> K = QQ.algebraic_field(I)
>>> R, x = ring(x, K)
>>> f = x**2 + K([QQ(1), QQ(0)])*x + K([QQ(2), QQ(0)])
>>> R.dmp_lift(f)
x**8 + 2*x**6 + 9*x**4 - 8*x**2 + 16
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x = ring(x, ZZ)
>>> R.dup_sign_variations(x**4 - x**2 - x + 1)
2
R.dmp_clear_denoms(f, convert=False)
3*x + 2*y + 6)
R.dmp_clear_denoms(f, convert=True)
3*x + 2*y + 6)
sympy.polys.densetools.dmp revert(f, g, u, K)
Compute f**(-1) mod x**n using Newton iteration.
Examples
>>> from sympy.polys import ring, QQ
>>> R, x,y = ring(x,y, QQ)
1197
sympy.polys.galoistools.gf crt2(U, M, p, E, S, K)
Second part of the Chinese Remainder Theorem.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_crt2
>>>
>>>
>>>
>>>
>>>
U
M
p
E
S
=
=
=
=
=
sympy.polys.galoistools.gf int(a, p)
Coerce a mod p to an integer in the range [-p/2, p/2].
Examples
>>> from sympy.polys.galoistools import gf_int
>>> gf_int(2, 7)
2
>>> gf_int(5, 7)
-2
sympy.polys.galoistools.gf degree(f)
Return the leading degree of f.
1198
Examples
>>> from sympy.polys.galoistools import gf_degree
>>> gf_degree([1, 1, 2, 0])
3
>>> gf_degree([])
-1
sympy.polys.galoistools.gf LC(f, K)
Return the leading coecient of f.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_LC
>>> gf_LC([3, 0, 1], ZZ)
3
sympy.polys.galoistools.gf TC(f, K)
Return the trailing coecient of f.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_TC
>>> gf_TC([3, 0, 1], ZZ)
1
sympy.polys.galoistools.gf strip(f)
Remove leading zeros from f.
Examples
>>> from sympy.polys.galoistools import gf_strip
>>> gf_strip([0, 0, 0, 3, 0, 1])
[3, 0, 1]
sympy.polys.galoistools.gf trunc(f, p)
Reduce all coecients modulo p.
Examples
>>> from sympy.polys.galoistools import gf_trunc
>>> gf_trunc([7, -2, 3], 5)
[2, 3, 3]
1199
sympy.polys.galoistools.gf normal(f, p, K)
Normalize all coecients in K.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_normal
>>> gf_normal([5, 10, 21, -3], 5, ZZ)
[1, 2]
gf_to_dict([4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4], 5)
-1, 4: -2, 10: -1}
gf_to_dict([4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4], 5, symmetric=False)
4, 4: 3, 10: 4}
1200
Examples
>>> from sympy.polys.galoistools import gf_to_int_poly
>>>
[2,
>>>
[2,
gf_to_int_poly([2, 3, 3], 5)
-2, -2]
gf_to_int_poly([2, 3, 3], 5, symmetric=False)
3, 3]
sympy.polys.galoistools.gf neg(f, p, K)
Negate a polynomial in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_neg
>>> gf_neg([3, 2, 1, 0], 5, ZZ)
[2, 3, 4, 0]
1201
sympy.polys.galoistools.gf add(f, g, p, K)
Add polynomials in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_add
>>> gf_add([3, 2, 4], [2, 2, 2], 5, ZZ)
[4, 1]
sympy.polys.galoistools.gf sub(f, g, p, K)
Subtract polynomials in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_sub
>>> gf_sub([3, 2, 4], [2, 2, 2], 5, ZZ)
[1, 0, 2]
sympy.polys.galoistools.gf mul(f, g, p, K)
Multiply polynomials in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_mul
>>> gf_mul([3, 2, 4], [2, 2, 2], 5, ZZ)
[1, 0, 3, 2, 3]
sympy.polys.galoistools.gf sqr(f, p, K)
Square polynomials in GF(p)[x].
1202
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_sqr
>>> gf_sqr([3, 2, 4], 5, ZZ)
[4, 2, 3, 1, 1]
sympy.polys.galoistools.gf expand(F, p, K)
Expand results of factor() in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_expand
>>> gf_expand([([3, 2, 4], 1), ([2, 2], 2), ([3, 1], 3)], 5, ZZ)
[4, 3, 0, 3, 0, 1, 4, 1]
sympy.polys.galoistools.gf div(f, g, p, K)
Division with remainder in GF(p)[x].
Given univariate polynomials f and g with coecients in a nite eld with p elements,
returns polynomials q and r (quotient and remainder) such that f = q*g + r.
Consider polynomials x**3 + x + 1 and x**2 + x in GF(2):
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_div, gf_add_mul
>>> gf_div(ZZ.map([1, 0, 1, 1]), ZZ.map([1, 1, 0]), 2, ZZ)
([1, 1], [1])
1203
References
sympy.polys.galoistools.gf quo(f, g, p, K)
Compute exact quotient in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_quo
>>>
[1,
>>>
[3,
sympy.polys.galoistools.gf exquo(f, g, p, K)
Compute polynomial quotient in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_exquo
>>> gf_exquo(ZZ.map([1, 0, 3, 2, 3]), ZZ.map([2, 2, 2]), 5, ZZ)
[3, 2, 4]
>>> gf_exquo(ZZ.map([1, 0, 1, 1]), ZZ.map([1, 1, 0]), 2, ZZ)
Traceback (most recent call last):
...
ExactQuotientFailed: [1, 1, 0] does not divide [1, 0, 1, 1]
1204
sympy.polys.galoistools.gf lshift(f, n, K)
Eciently multiply f by x**n.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_lshift
>>> gf_lshift([3, 2, 4], 4, ZZ)
[3, 2, 4, 0, 0, 0, 0]
sympy.polys.galoistools.gf rshift(f, n, K)
Eciently divide f by x**n.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_rshift
>>> gf_rshift([1, 2, 3, 4, 0], 3, ZZ)
([1, 2], [3, 4, 0])
sympy.polys.galoistools.gf pow(f, n, p, K)
Compute f**n in GF(p)[x] using repeated squaring.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_pow
>>> gf_pow([3, 2, 4], 3, 5, ZZ)
[2, 4, 4, 2, 2, 1, 4]
1205
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_pow_mod
>>> gf_pow_mod(ZZ.map([3, 2, 4]), 3, ZZ.map([1, 1]), 5, ZZ)
[]
sympy.polys.galoistools.gf gcd(f, g, p, K)
Euclidean Algorithm in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_gcd
>>> gf_gcd(ZZ.map([3, 2, 4]), ZZ.map([2, 2, 3]), 5, ZZ)
[1, 3]
sympy.polys.galoistools.gf lcm(f, g, p, K)
Compute polynomial LCM in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_lcm
>>> gf_lcm(ZZ.map([3, 2, 4]), ZZ.map([2, 2, 3]), 5, ZZ)
[1, 2, 0, 4]
sympy.polys.galoistools.gf cofactors(f, g, p, K)
Compute polynomial GCD and cofactors in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_cofactors
>>> gf_cofactors(ZZ.map([3, 2, 4]), ZZ.map([2, 2, 3]), 5, ZZ)
([1, 3], [3, 3], [2, 1])
sympy.polys.galoistools.gf gcdex(f, g, p, K)
Extended Euclidean Algorithm in GF(p)[x].
Given polynomials f and g in GF(p)[x], computes polynomials s, t and h, such that h =
gcd(f, g) and s*f + t*g = h. The typical application of EEA is solving polynomial
diophantine equations.
Consider polynomials f = (x + 7) (x + 1), g = (x + 7) (x**2 + 1) in GF(11)[x].
Application of Extended Euclidean Algorithm gives:
1206
References
sympy.polys.galoistools.gf diff(f, p, K)
Dierentiate polynomial in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_diff
>>> gf_diff([3, 2, 4], 5, ZZ)
[1, 2]
sympy.polys.galoistools.gf eval(f, a, p, K)
Evaluate f(a) in GF(p) using Horner scheme.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_eval
1207
sympy.polys.galoistools.gf compose(f, g, p, K)
Compute polynomial composition f(g) in GF(p)[x].
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_compose
>>> gf_compose([3, 2, 4], [2, 2, 2], 5, ZZ)
[2, 4, 0, 3, 0]
In factorization context, b = x**p mod f and c = x mod f. This way we can eciently
compute trace polynomials in equal degree factorization routine, much faster than with
other methods, like iterated Frobenius algorithm, for large degrees.
References
sympy.polys.galoistools.gf random(n, p, K)
Generate a random polynomial in GF(p)[x] of degree n.
Examples
>>>
>>>
>>>
[1,
sympy.polys.galoistools.gf irreducible(n, p, K)
Generate random irreducible polynomial of degree n in GF(p)[x].
Examples
>>>
>>>
>>>
[1,
1209
This phenomenon doesnt happen in characteristic zero. However we can still compute
square-free decomposition of f using gf sqf():
>>> gf_sqf_list(f, 11, ZZ)
(1, [([1, 1], 11)])
References
sympy.polys.galoistools.gf Qbasis(Q, p, K)
Compute a basis of the kernel of Q.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_Qmatrix, gf_Qbasis
>>> gf_Qbasis(gf_Qmatrix([1, 0, 0, 0, 1], 5, ZZ), 5, ZZ)
[[1, 0, 0, 0], [0, 0, 1, 0]]
>>> gf_Qbasis(gf_Qmatrix([3, 2, 4], 5, ZZ), 5, ZZ)
[[1, 0]]
sympy.polys.galoistools.gf berlekamp(f, p, K)
Factor a square-free f in GF(p)[x] for small p.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_berlekamp
>>> gf_berlekamp([1, 0, 0, 0, 1], 5, ZZ)
[[1, 0, 2], [1, 0, 3]]
sympy.polys.galoistools.gf zassenhaus(f, p, K)
Factor a square-free f in GF(p)[x] for medium p.
Examples
1211
sympy.polys.galoistools.gf shoup(f, p, K)
Factor a square-free f in GF(p)[x] for large p.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.galoistools import gf_shoup
>>> gf_shoup(ZZ.map([1, 4, 3]), 5, ZZ)
[[1, 1], [1, 3]]
sympy.polys.galoistools.gf factor(f, p, K)
Factor (non square-free) polynomials in GF(p)[x].
Given a possibly non square-free polynomial f in GF(p)[x], returns its complete factorization into irreducibles:
f 1(x)**e 1 f 2(x)**e 2 ... f d(x)**e d
1212
Square-free factors of f can be factored into irreducibles over GF(p) using three very
dierent methods:
Berlekamp ecient for very small values of p (usually p < 25)
Cantor-Zassenhaus ecient on average input and with typical p
Shoup-Kaltofen-Gathen ecient with very large inputs and modulus
If you want to use a specic factorization method, instead of the default one, set
GF FACTOR METHOD with one of berlekamp, zassenhaus or shoup values.
References
sympy.polys.galoistools.gf csolve(f, n)
To solve f(x) congruent 0 mod(n).
n is divided into canonical factors and f(x) cong 0 mod(p**e) will be solved for each factor.
Applying the Chinese Remainder Theorem to the results returns the nal answers.
References
1213
1214
Examples
>>> from sympy.polys.rings import vring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex
>>> vring(x,y,z, ZZ, lex)
Polynomial ring in x, y, z over ZZ with lex order
>>> x + y + z
x + y + z
>>> type(_)
<class sympy.polys.rings.PolyElement>
from
from
from
from
>>> x, y, z = symbols(x,y,z)
>>> R, f = sring(x + 2*y + 3*z)
>>> R
Polynomial ring in x, y, z over ZZ with lex order
>>> f
x + 2*y + 3*z
>>> type(_)
<class sympy.polys.rings.PolyElement>
class sympy.polys.rings.PolyRing
Multivariate distributed polynomial ring.
Attributes
domain
gens
ngens
order
symbols
add(*objs)
Add a sequence of polynomials or containers of polynomials.
1215
Example
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> R, x = ring(x, ZZ)
>>> R.add([ x**2 + 2*i + 3 for i in range(4) ])
4*x**2 + 24
>>> _.factor_list()
(4, [(x**2 + 6, 1)])
drop(*gens)
Remove specied generators from this ring.
drop to ground(*gens)
Remove specied generators from the ring and inject them into its domain.
index(gen)
Compute index of gen in self.gens.
monomial basis(i)
Return the ith-basis element.
mul(*objs)
Multiply a sequence of polynomials or containers of polynomials.
Example
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> R, x = ring(x, ZZ)
>>> R.mul([ x**2 + 2*i + 3 for i in range(4) ])
x**8 + 24*x**6 + 206*x**4 + 744*x**2 + 945
>>> _.factor_list()
(1, [(x**2 + 3, 1), (x**2 + 5, 1), (x**2 + 7, 1), (x**2 + 9, 1)])
class sympy.polys.rings.PolyElement
Element of multivariate distributed polynomial ring.
almosteq(p1, p2, tolerance=None)
Approximate equality test for polynomials.
cancel(f, g)
Cancel common factors in a rational function f/g.
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> (2*x**2 - 2).cancel(x**2 - 2*x + 1)
(2*x + 2, x - 1)
coeff(element)
Returns the coecient that stands next to the given monomial.
1216
coeffs(order=None)
Ordered list of polynomial coecients.
Parameters order : Order or coercible, optional
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex, grlex
>>> _, x, y = ring(x, y, ZZ, lex)
>>> f = x*y**7 + 2*x**2*y**3
>>>
[2,
>>>
[1,
f.coeffs()
1]
f.coeffs(grlex)
2]
const()
Returns the constant coecient.
content(f)
Returns GCD of polynomials coecients.
copy()
Return a copy of polynomial self.
Polynomials are mutable; if one is interested in preserving a polynomial, and one
plans to use inplace operations, one can copy the polynomial. This method makes a
shallow copy.
Examples
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.rings import ring
1217
degree(f, x=None)
The leading degree in x or the main variable.
Note that the degree of 0 is negative innity (the SymPy object -oo).
degrees(f)
A tuple containing leading degrees in all variables.
Note that the degree of 0 is negative innity (the SymPy object -oo)
diff(f, x)
Computes partial derivative in x.
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring(x,y, ZZ)
>>> p = x + x**2*y**3
>>> p.diff(x)
2*x*y**3 + 1
div(fv)
Division algorithm, see [CLO] p64.
fv array of polynomials return qv, r such that self = sum(fv[i]*qv[i]) + r
All polynomials are required not to be Laurent polynomials.
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring(x, y, ZZ)
>>> f = x**3
>>> f0 = x - y**2
>>> f1 = x - y
>>> qv, r = f.div((f0, f1))
>>> qv[0]
x**2 + x*y**2 + y**4
>>> qv[1]
0
1218
>>> r
y**6
imul num(p, c)
multiply inplace the polynomial p by an element in the coecient ring, provided p
is not one of the generators; else multiply not inplace
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring(x, y, ZZ)
>>> p = x + y**2
>>> p1 = p.imul_num(3)
>>> p1
3*x + 3*y**2
>>> p1 is p
True
>>> p = x
>>> p1 = p.imul_num(3)
>>> p1
3*x
>>> p1 is p
False
itercoeffs()
Iterator over coecients of a polynomial.
itermonoms()
Iterator over monomials of a polynomial.
iterterms()
Iterator over terms of a polynomial.
leading expv()
Leading monomial tuple according to the monomial ordering.
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>>
>>>
>>>
(4,
_, x, y, z = ring(x, y, z, ZZ)
p = x**4 + x**3*y + x**2*z**2 + z**7
p.leading_expv()
0, 0)
leading monom()
Leading monomial as a polynomial element.
1219
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring(x, y, ZZ)
>>> (3*x*y + y**2).leading_monom()
x*y
leading term()
Leading term as a polynomial element.
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring(x, y, ZZ)
>>> (3*x*y + y**2).leading_term()
3*x*y
listcoeffs()
Unordered list of polynomial coecients.
listmonoms()
Unordered list of polynomial monomials.
listterms()
Unordered list of polynomial terms.
monic(f)
Divides all coecients by the leading coecient.
monoms(order=None)
Ordered list of polynomial monomials.
Parameters order : Order or coercible, optional
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex, grlex
>>> _, x, y = ring(x, y, ZZ, lex)
>>> f = x*y**7 + 2*x**2*y**3
>>> f.monoms()
[(2, 3), (1, 7)]
>>> f.monoms(grlex)
[(1, 7), (2, 3)]
primitive(f)
Returns content and a primitive polynomial.
square()
square of a polynomial
1220
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring(x, y, ZZ)
>>> p = x + y**2
>>> p.square()
x**2 + 2*x*y**2 + y**4
strip zero()
Eliminate monomials with zero coecient.
tail degree(f, x=None)
The tail degree in x or the main variable.
Note that the degree of 0 is negative innity (the SymPy object -oo)
tail degrees(f)
A tuple containing tail degrees in all variables.
Note that the degree of 0 is negative innity (the SymPy object -oo)
terms(order=None)
Ordered list of polynomial terms.
Parameters order : Order or coercible, optional
Examples
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex, grlex
>>> _, x, y = ring(x, y, ZZ, lex)
>>> f = x*y**7 + 2*x**2*y**3
>>> f.terms()
[((2, 3), 2), ((1, 7), 1)]
>>> f.terms(grlex)
[((1, 7), 1), ((2, 3), 2)]
In commutative algebra, one often studies not only polynomials, but also modules over polynomial rings. The polynomial manipulation module provides rudimentary low-level support
for nitely generated free modules. This is mainly used for Groebner basis computations (see
there), so manipulation functions are only provided to the extend needed. They carry the
prex sdm . Note that in examples, the generators of the free module are called f1 , f2 , . . . .
sympy.polys.distributedmodules.sdm monomial mul(M, X)
Multiply tuple X representing a monomial of K[X] into the tuple M representing a monomial of F .
Examples
1221
Positive examples:
In the following examples, the monomial is given in terms of x, y and the generator(s),
f 1, f 2 etc. The tuple form of that monomial is used in the call to sdm monomial divides.
Note: the generator appears last in the expression but rst in the tuple and other factors
appear in the same order that they appear in the monomial expression.
A = f1 divides B = f1
>>> from sympy.polys.distributedmodules import sdm_monomial_divides
>>> sdm_monomial_divides((1, 0, 0), (1, 0, 0))
True
A = f1 divides B = x2 yf1
>>> sdm_monomial_divides((1, 0, 0), (1, 2, 1))
True
Negative examples:
A = f1 does not divide B = f2
>>> sdm_monomial_divides((1, 0, 0), (2, 0, 0))
False
1222
sympy.polys.distributedmodules.sdm LC(f, K)
Returns the leading coecient of f.
sympy.polys.distributedmodules.sdm to dict(f)
Make a dictionary from a distributed polynomial.
sympy.polys.distributedmodules.sdm from dict(d, O)
Create an sdm from a dictionary.
Here O is the monomial order to use.
>>> from sympy.polys.distributedmodules import sdm_from_dict
>>> from sympy.polys import QQ, lex
>>> dic = {(1, 1, 0): QQ(1), (1, 0, 0): QQ(2), (0, 1, 0): QQ(0)}
>>> sdm_from_dict(dic, lex)
[((1, 1, 0), 1), ((1, 0, 0), 2)]
sympy.polys.distributedmodules.sdm add(f, g, O, K)
Add two module elements f, g.
Addition is done over the ground eld K, monomials are ordered according to O.
Examples
(xyf1 ) + (xyf1 ) = 0
>>> sdm_add([((1, 1, 1), QQ(1))], [((1, 1, 1), QQ(-1))], lex, QQ)
[]
sympy.polys.distributedmodules.sdm LM(f)
Returns the leading monomial of f.
Only valid if f 6= 0.
Examples
>>> from sympy.polys.distributedmodules import sdm_LM, sdm_from_dict
>>> from sympy.polys import QQ, lex
>>> dic = {(1, 2, 3): QQ(1), (4, 0, 0): QQ(1), (4, 0, 1): QQ(1)}
1223
sympy.polys.distributedmodules.sdm LT(f)
Returns the leading term of f.
Only valid if f 6= 0.
Examples
>>> from sympy.polys.distributedmodules import sdm_LT, sdm_from_dict
>>> from sympy.polys import QQ, lex
>>> dic = {(1, 2, 3): QQ(1), (4, 0, 0): QQ(2), (4, 0, 1): QQ(3)}
>>> sdm_LT(sdm_from_dict(dic, lex))
((4, 0, 1), 3)
0f1 = 0
>>> from sympy.polys.distributedmodules import sdm_mul_term
>>> from sympy.polys import lex, QQ
>>> sdm_mul_term([((1, 0, 0), QQ(1))], ((0, 0), QQ(0)), lex, QQ)
[]
x0 = 0
>>> sdm_mul_term([], ((1, 0), QQ(1)), lex, QQ)
[]
(x)(f1 ) = xf1
>>> sdm_mul_term([((1, 0, 0), QQ(1))], ((1, 0), QQ(1)), lex, QQ)
[((1, 1, 0), 1)]
sympy.polys.distributedmodules.sdm zero()
Return the zero module element.
sympy.polys.distributedmodules.sdm deg(f)
Degree of f.
This is the maximum of the degrees of all its monomials. Invalid if f is zero.
1224
Examples
>>> from sympy.polys.distributedmodules import sdm_deg
>>> sdm_deg([((1, 2, 3), 1), ((10, 0, 1), 1), ((2, 3, 4), 4)])
7
sympy.polys.euclidtools.dmp gcdex(f, g, u, K)
Extended Euclidean algorithm in F [X].
1225
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
sympy.polys.euclidtools.dmp invert(f, g, u, K)
Compute multiplicative inverse of f modulo g in F [X].
Examples
>>> from sympy.polys import ring, QQ
>>> R, x = ring(x, QQ)
1226
sympy.polys.euclidtools.dmp subresultants(f, g, u, K)
Computes subresultant PRS of two polynomials in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring(x,y, ZZ)
>>> f = 3*x**2*y - y**3 - 4
>>> g = x**2 + x*y**3 - 9
>>> a = 3*x*y**4 + y**3 - 27*y + 4
>>> b = -3*y**10 - 12*y**7 + y**6 - 54*y**4 + 8*y**3 + 729*y**2 - 216*y + 16
>>> R.dmp_subresultants(f, g) == [f, g, a, b]
True
1227
>>> R.dmp_zz_modular_resultant(f, g, 5)
-2*y**2 + 1
sympy.polys.euclidtools.dmp discriminant(f, u, K)
Computes discriminant of a polynomial in K[X].
1228
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y,z,t = ring(x,y,z,t, ZZ)
>>> R.dmp_discriminant(x**2*y + x*z + t)
-4*y*t + z**2
The algorithm is purely heuristic which means it may fail to compute the GCD. This will
be signaled by raising an exception. In this case you will need to switch to another GCD
method.
1229
The algorithm computes the polynomial GCD by evaluating polynomials f and g at certain
points and computing (fast) integer GCD of those evaluations. The polynomial GCD is
recovered from the integer image by interpolation. The evaluation proces reduces f and
g variable by variable into a large integer. The nal step is to verify if the interpolated
polynomial is the correct GCD. This gives cofactors of the input polynomials as a side
eect.
References
1230
sympy.polys.euclidtools.dmp gcd(f, g, u, K)
Computes polynomial GCD of f and g in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y, = ring(x,y, ZZ)
>>> f = x**2 + 2*x*y + y**2
>>> g = x**2 + x*y
>>> R.dmp_gcd(f, g)
x + y
sympy.polys.euclidtools.dmp lcm(f, g, u, K)
Computes polynomial LCM of f and g in K[X].
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y, = ring(x,y, ZZ)
>>> f = x**2 + 2*x*y + y**2
>>> g = x**2 + x*y
>>> R.dmp_lcm(f, g)
x**3 + 2*x**2*y + x*y**2
sympy.polys.euclidtools.dmp content(f, u, K)
Returns GCD of multivariate coecients.
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y, = ring(x,y, ZZ)
>>> R.dmp_content(2*x*y + 6*x + 4*y + 12)
2*y + 6
sympy.polys.euclidtools.dmp primitive(f, u, K)
Returns multivariate content and a primitive polynomial.
1231
Examples
>>> from sympy.polys import ring, ZZ
>>> R, x,y, = ring(x,y, ZZ)
>>> R.dmp_primitive(2*x*y + 6*x + 4*y + 12)
(2*y + 6, x + 2)
References
1232
Given a prime p, polynomial f over Z[x] such that lc(f ) is a unit modulo p, monic pair-wise
coprime polynomials fi over Z[x] satisfying:
f = lc(f) f 1 ... f r (mod p)
References
1233
The factorization is computed by reducing the input polynomial into a primitive squarefree polynomial and factoring it using Zassenhaus algorithm. Trial division is used to
recover the multiplicities of factors.
The result is returned as a tuple consisting of:
(content(f), [(f 1, k 1), ..., (f n, k n))
Consider polynomial f = 2 x 4 2:
>>> from sympy.polys import ring, ZZ
>>> R, x = ring(x, ZZ)
>>> R.dup_zz_factor(2*x**4 - 2)
(2, [(x - 1, 1), (x + 1, 1), (x**2 + 1, 1)])
Note that this is a complete factorization over integers, however over Gaussian integers
we can factor the last term.
By default, polynomials xn1 and xn+1 are factored using cyclotomic decomposition
to speedup computations. To disable this behaviour set cyclotomic=False.
References
1234
where ai , for i = 2, ..., n, are carefully chosen integers. The mapping is used to transform f
into a univariate polynomial in Z[x1 ], which can be factored eciently using Zassenhaus
algorithm. The last step is to lift univariate factors to obtain true multivariate factors.
For this purpose a parallel Hensel lifting procedure is used.
The parameter seed is passed to randint and can be used to seed randint (when an
integer) or (for testing purposes) can be a sequence of numbers.
References
The factorization is computed by reducing the input polynomial into a primitive squarefree polynomial and factoring it using Enhanced Extended Zassenhaus (EEZ) algorithm.
Trial division is used to recover the multiplicities of factors.
The result is returned as a tuple consisting of:
(content(f), [(f 1, k 1), ..., (f n, k n))
References
1235
1236
sympy.polys.distributedmodules.sdm ecart(f)
Compute the ecart of f.
This is dened to be the dierence of the total degree of f and the total degree of the
leading monomial of f [SCA, defn 2.3.7].
Invalid if f is zero.
Examples
>>> from sympy.polys.distributedmodules import sdm_ecart
>>> sdm_ecart([((1, 2, 3), 1), ((1, 0, 1), 1)])
0
>>> sdm_ecart([((2, 2, 1), 1), ((1, 5, 1), 1)])
3
1237
1238
class sympy.polys.polyerrors.UnivariatePolynomialError
class sympy.polys.polyerrors.MultivariatePolynomialError
class sympy.polys.polyerrors.PolificationFailed(opt, origs, exprs, seq=False)
class sympy.polys.polyerrors.OptionError
class sympy.polys.polyerrors.FlagError
Reference
Modular GCD
class sympy.polys.modulargcd.modgcd univariate
Computes the GCD of two polynomials in Z[x] using a modular algorithm.
The algorithm computes the GCD of two univariate integer polynomials f and g by computing the GCD in Zp [x] for suitable primes p and then reconstructing the coecients
with the Chinese Remainder Theorem. Trial division is only made for candidates which
are very likely the desired GCD.
Parameters f : PolyElement
univariate integer polynomial
g : PolyElement
univariate integer polynomial
Returns h : PolyElement
GCD of the polynomials f and g
c : PolyElement
cofactor of f , i.e.
f
h
cfg : PolyElement
cofactor of g, i.e.
g
h
References
1239
>>> cff * h == f
True
>>> cfg * h == g
True
>>> f = 6*x**2 - 6
>>> g = 2*x**2 + 4*x + 2
>>> h, cff, cfg = modgcd_univariate(f, g)
>>> h, cff, cfg
(2*x + 2, 3*x - 3, x + 1)
>>> cff * h == f
True
>>> cfg * h == g
True
f
h
cfg : PolyElement
cofactor of g, i.e.
g
h
References
1240
f
h
cfg : PolyElement
cofactor of g, i.e.
g
h
See Also:
modgcd multivariate p
1241
References
obtain the correct coecients. The results, both in Q(x1 , . . . , xn1 )[z]/(m (z))[x0 ] and
Zp (x1 , . . . , xn1 )[z]/(m
(z))[x0 ], are veried by a fraction free trial division.
Apart from the above GCD computation some GCDs in Q()[x1 , . . . , xn1 ] have to be calculated, because treating the polynomials as univariate ones can result in a spurious
content of the GCD. For this func field modgcd is called recursively.
Parameters f, g : PolyElement
polynomials in Q()[x0 , . . . , xn1 ]
Returns h : PolyElement
monic GCD of the polynomials f and g
c : PolyElement
cofactor of f , i.e.
f
h
cfg : PolyElement
cofactor of g, i.e.
g
h
References
1243
>>> h == x + sqrt(2)*y
True
>>> cff * h == f
True
>>> cfg * h == g
True
>>> f = x + sqrt(2)*y
>>> g = x + y
>>> h, cff, cfg = func_field_modgcd(f, g)
>>> h == R.one
True
>>> cff * h == f
True
>>> cfg * h == g
True
Manipulation of power series Functions in this module carry the prex rs , standing for
ring series. They manipulate nite power series in the sparse representation provided by
polys.ring.ring.
sympy.polys.ring series.rs trunc(p1, x, prec)
truncate the series in the x variable with precision prec, that is modulo O(x**prec)
Examples
>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_trunc
>>> R, x = ring(x, QQ)
>>> p = x**10 + x**5 + x + 1
>>> rs_trunc(p, x, 12)
x**10 + x**5 + x + 1
>>> rs_trunc(p, x, 10)
x**5 + x + 1
1244
1245
Examples
>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_series_from_list, rs_trunc
>>> R, x = ring(x, QQ)
>>> p = x**2 + x + 1
>>> c = [1, 2, 3]
>>> rs_series_from_list(p, c, x, 4)
6*x**3 + 11*x**2 + 8*x + 6
>>> rs_trunc(1 + 2*p + 3*p**2, x, 4)
6*x**3 + 11*x**2 + 8*x + 6
>>> pc = R.from_list(list(reversed(c)))
>>> rs_trunc(pc.compose(x, p), x, 4)
6*x**3 + 11*x**2 + 8*x + 6
1246
A. Bostan, P. Flajolet, B. Salvy and E. Schost Fast Computation with Two Algebraic Numbers, (2002) Research Report 4579, Institut National de Recherche en Informatique et
en Automatique
Examples
>>>
>>>
>>>
>>>
>>>
>>>
1247
>>> rs_compose_add(f, g)
x**4 - 10*x**2 + 1
Undocumented
Many parts of the polys module are still undocumented, and even where there is documentation it is scarce. Please contribute!
Literature
The following is a non-comprehensive list of publications that were used as a theoretical
foundation for implementing polynomials manipulation module.
1248
Basic
|
Atom
|
Number
|
Rational
then, for expr=Rational(...), in order to dispatch, we will try calling printer methods as shown in the gure below:
p. print(expr)
|
|-- p. print Rational(expr)
|
|-- p. print Number(expr)
|
|-- p. print Atom(expr)
|
-- p. print Basic(expr)
if . print Rational method exists in the printer, then it is called, and the result is
returned back.
otherwise, we proceed with trying Rational bases in the inheritance order.
3. As fall-back use the emptyPrinter method for the printer.
As fall-back self.emptyPrinter will be called with the expression. If not dened
in the Printer subclass this will be the same as str(expr).
The main class responsible for printing is Printer (see also its source code):
class sympy.printing.printer.Printer(settings=None)
Generic printer
Its job is to provide infrastructure for implementing new printers easily.
Basically, if you want to implement a printer, all you have to do is:
1.Subclass Printer.
2.Dene Printer.printmethod in your subclass. If a object has a method with that name,
this method will be used for printing.
3.In your subclass, dene print <CLASS> methods
For each class you want to provide printing to, dene an appropriate method how
to do it. For example if you want a class FOO to be printed in its own way, dene
print FOO:
def _print_FOO(self, e):
...
1249
On the other hand, a good printer will probably have to dene separate routines for
Symbol, Atom, Number, Integral, Limit, etc...
4.If convenient, override self.emptyPrinter
This callable will be called to obtain printing result as a last resort, that is when no
appropriate print method was found for an expression.
Examples of overloading StrPrinter:
from sympy import Basic, Function, Symbol
from sympy.printing.str import StrPrinter
class CustomStrPrinter(StrPrinter):
Examples of how to customize the StrPrinter for both a SymPy class and a
user defined class subclassed from the SymPy Basic class.
or
s =
i = 0
for char in expr.s:
if i % 2 == 0:
s += char.lower()
else:
s += char.upper()
i += 1
return s
# Override the __str__ method of to use CustromStrPrinter
Basic.__str__ = lambda self: CustomStrPrinter().doprint(self)
# Demonstration of CustomStrPrinter:
t = Symbol(t)
x = Function(x)(t)
# dxdt is a Derivative instance
dxdt = x.diff(t)
d2xdt2 = dxdt.diff(t)
# dxdt2 is a Derivative instance
ex = MyClass(I like both lowercase and upper case)
1250
print dxdt
print d2xdt2
print ex
By overriding Basic. str , we can customize the printing of anything that is subclassed
from Basic.
Attributes
printmethod
printmethod = None
doprint(expr)
Returns printers representation for expr (as a string)
print(expr, *args, **kwargs)
Internal dispatcher
Tries the following concepts to print an expression:
1. Let the object print itself if it knows how.
2. Take the best tting method dened in the printer.
3. As fall-back use the emptyPrinter method for the printer.
classmethod set global settings(**settings)
Set system-wide printing settings.
1251
5.17.3 CCodePrinter
This class implements C code printing (i.e. it converts Python expressions to strings of C
code).
Usage:
>>> from sympy.printing import print_ccode
>>> from sympy.functions import sin, cos, Abs
>>> from sympy.abc import x
>>> print_ccode(sin(x)**2 + cos(x)**2)
pow(sin(x), 2) + pow(cos(x), 2)
>>> print_ccode(2*x + cos(x), assign_to=result)
result = 2*x + cos(x);
>>> print_ccode(Abs(x**2))
fabs(pow(x, 2))
sympy.printing.ccode.known functions = {sinh: sinh, asin: asin, cos: cos, log: log, atan
class sympy.printing.ccode.CCodePrinter(settings={})
A printer to convert python expressions to strings of c code
printmethod = ccode
indent code(code)
Accepts a string of code or a list of code lines
sympy.printing.ccode.ccode(expr, assign to=None, **settings)
Converts an expr to a string of c code
Parameters expr : Expr
A sympy expression to be converted.
assign to : optional
1252
Custom printing can be dened for certain types by passing a dictionary of type :
function to the user functions kwarg. Alternatively, the dictionary value can be a list
of tuples i.e. [(argument test, cfunction string)].
>>> custom_functions = {
...
ceiling: CEIL,
...
Abs: [(lambda x: not x.is_integer, fabs),
...
(lambda x: x.is_integer, ABS)]
... }
>>> ccode(Abs(x) + ceiling(x), user_functions=custom_functions)
fabs(x) + CEIL(x)
1253
Piecewise expressions are converted into conditionals. If an assign to variable is provided an if statement is created, otherwise the ternary operator is used. Note that if
the Piecewise lacks a default term, represented by (expr, True) then an error will be
thrown. This is to prevent generating an expression that may not evaluate to anything.
>>> from sympy import Piecewise
>>> expr = Piecewise((x + 1, x > 0), (x, True))
>>> print(ccode(expr, tau))
if (x > 0) {
tau = x + 1;
}
else {
tau = x;
}
Support for loops is provided through Indexed types. With contract=True these expressions will be turned into loops, whereas contract=False will just print the assignment
expression that should be looped over:
>>> from sympy import Eq, IndexedBase, Idx
>>> len_y = 5
>>> y = IndexedBase(y, shape=(len_y,))
>>> t = IndexedBase(t, shape=(len_y,))
>>> Dy = IndexedBase(Dy, shape=(len_y-1,))
>>> i = Idx(i, len_y-1)
>>> e=Eq(Dy[i], (y[i+1]-y[i])/(t[i+1]-t[i]))
>>> ccode(e.rhs, assign_to=e.lhs, contract=False)
Dy[i] = (y[i + 1] - y[i])/(t[i + 1] - t[i]);
Matrices are also supported, but a MatrixSymbol of the same dimensions must be provided to assign to. Note that any expression that can be generated normally can also
exist inside a Matrix:
>>> from sympy import Matrix, MatrixSymbol
>>> mat = Matrix([x**2, Piecewise((x + 1, x > 0), (x, True)), sin(x)])
>>> A = MatrixSymbol(A, 3, 1)
>>> print(ccode(mat, A))
A[0] = pow(x, 2);
if (x > 0) {
A[1] = x + 1;
}
else {
A[1] = x;
}
A[2] = sin(x);
1254
>>>
1255
Custom printing can be dened for certain types by passing a dictionary of type :
function to the user functions kwarg. Alternatively, the dictionary value can be a list
of tuples i.e. [(argument test, cfunction string)].
>>> custom_functions = {
...
ceiling: CEIL,
...
floor: [(lambda x: not x.is_integer, FLOOR1),
...
(lambda x: x.is_integer, FLOOR2)]
... }
>>> fcode(floor(x) + ceiling(x), user_functions=custom_functions)
CEIL(x) + FLOOR1(x)
Piecewise expressions are converted into conditionals. If an assign to variable is provided an if statement is created, otherwise the ternary operator is used. Note that if
the Piecewise lacks a default term, represented by (expr, True) then an error will be
thrown. This is to prevent generating an expression that may not evaluate to anything.
>>> from sympy import Piecewise
>>> expr = Piecewise((x + 1, x > 0), (x, True))
>>> print(fcode(expr, tau))
if (x > 0) then
tau = x + 1
else
tau = x
end if
Support for loops is provided through Indexed types. With contract=True these expressions will be turned into loops, whereas contract=False will just print the assignment
expression that should be looped over:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
Matrices are also supported, but a MatrixSymbol of the same dimensions must be provided to assign to. Note that any expression that can be generated normally can also
exist inside a Matrix:
>>>
>>>
>>>
>>>
class sympy.printing.fcode.FCodePrinter(settings={})
A printer to convert sympy expressions to strings of Fortran code
printmethod = fcode
indent code(code)
Accepts a string of code or a list of code lines
Two basic examples:
>>>
>>>
>>>
>>>
In case of line wrapping, it is handy to include the assignment so that lines are wrapped
properly when the assignment part is added.
>>> print(fcode(expr, assign_to=var))
var = -715.0d0/65536.0d0*x**18 - 429.0d0/32768.0d0*x**16 - 33.0d0/
@ 2048.0d0*x**14 - 21.0d0/1024.0d0*x**12 - 7.0d0/256.0d0*x**10 @ 5.0d0/128.0d0*x**8 - 1.0d0/16.0d0*x**6 - 1.0d0/8.0d0*x**4 - 1.0d0
@ /2.0d0*x**2 + 1
Note that by default only top-level piecewise functions are supported due to the lack of a
conditional operator in Fortran 77. Inline conditionals can be supported using the merge
function introduced in Fortran 95 by setting of the kwarg standard=95:
>>> print(fcode(Piecewise((x,x<1),(x**2,True)), standard=95))
merge(x, x**2, x < 1)
Loops are generated if there are Indexed objects in the expression. This also requires use of
the assign to option.
>>>
>>>
>>>
>>>
1257
Repeated indices in an expression with Indexed objects are interpreted as summation. For
instance, code for the trace of a matrix can be generated with
>>> print(fcode(A[i, i], assign_to=x))
x = 0
do i = 1, m
x = x + A(i, i)
end do
By default, number symbols such as pi and E are detected and dened as Fortran parameters. The precision of the constants can be tuned with the precision argument. Parameter
denitions are easily avoided using the N function.
>>> print(fcode(x - pi**2 - E))
parameter (E = 2.71828182845905d0)
parameter (pi = 3.14159265358979d0)
x - pi**2 - E
>>> print(fcode(x - pi**2 - E, precision=25))
parameter (E = 2.718281828459045235360287d0)
parameter (pi = 3.141592653589793238462643d0)
x - pi**2 - E
>>> print(fcode(N(x - pi**2, 25)))
x - 9.869604401089358618834491d0
When some functions are not part of the Fortran standard, it might be desirable to introduce
the names of user-dened functions in the Fortran expression.
>>> print(fcode(1 - gamma(x)**2, user_functions={gamma: mygamma}))
-mygamma(x)**2 + 1
However, when the user functions argument is not provided, fcode attempts to use a reasonable default and adds a comment to inform the user of the issue.
>>> print(fcode(1 - gamma(x)**2))
C
Not supported in Fortran:
C
gamma
-gamma(x)**2 + 1
By default the output is human readable code, ready for copy and paste. With the option
human=False, the return value is suitable for post-processing with source code generators
that write routines with multiple instructions. The return value is a three-tuple containing:
(i) a set of number symbols that must be dened as Fortran parameters, (ii) a list functions
that can not be translated in pure Fortran and (iii) a string of Fortran code. A few examples:
>>> fcode(1 - gamma(x)**2, human=False)
(set(), set([gamma(x)]),
-gamma(x)**2 + 1)
>>> fcode(1 - sin(x)**2, human=False)
(set(), set(),
-sin(x)**2 + 1)
>>> fcode(x - pi**2, human=False)
(set([(pi, 3.14159265358979d0)]), set(),
x - pi**2)
1258
printmethod = mcode
doprint(expr)
Returns printers representation for expr (as a string)
sympy.printing.mathematica.mathematica code(expr, **settings)
Converts an expr to a string of the Wolfram Mathematica code
Examples
>>> from sympy import mathematica_code as mcode, symbols, sin
>>> x = symbols(x)
>>> mcode(sin(x).series(x).removeO())
(1/120)*x^5 - 1/6*x^3 + x
5.17.6 Gtk
You can print to a grkmathview widget using the function print gtk located in
sympy.printing.gtk (it requires to have installed gtkmatmatview and libgtkmathview-bin
in some systems).
GtkMathView accepts MathML, so this rendering depends on the MathML representation of
the expression.
Usage:
from sympy import *
print_gtk(x**2 + 2*exp(x**3))
5.17.7 LambdaPrinter
This classes implements printing to strings that can
sympy.utilities.lambdify.lambdify() (page 1573) function.
be
used
by
the
class sympy.printing.lambdarepr.LambdaPrinter(settings=None)
This printer converts expressions into strings that can be used by lambdify.
printmethod = sympystr
sympy.printing.lambdarepr.lambdarepr(expr, **settings)
Returns a string usable for lambdifying.
5.17.8 LatexPrinter
This class implements LaTeX printing. See sympy.printing.latex.
1259
printmethod = latex
sympy.printing.latex.latex(expr, **settings)
Convert the given expression to LaTeX representation.
>>> from sympy import latex, pi, sin, asin, Integral, Matrix, Rational
>>> from sympy.abc import x, y, mu, r, tau
>>> print(latex((2*tau)**Rational(7,2)))
8 \sqrt{2} \tau^{\frac{7}{2}}
order: Any of the supported monomial orderings (currently lex, grlex, or grevlex),
old, and none. This parameter does nothing for Mul objects. Setting order to old
uses the compatibility ordering for Add dened in Printer. For very large expressions,
set the order keyword to none if speed is a concern.
mode: Species how the generated code will be delimited. mode can be one of plain,
inline, equation or equation*. If mode is set to plain, then the resulting code will
not be delimited at all (this is the default). If mode is set to inline then inline LaTeX
$ $ will be used. If mode is set to equation or equation*, the resulting code will be
enclosed in the equation or equation* environment (remember to import amsmath
for equation*), unless the itex option is set. In the latter case, the $$ $$ syntax is used.
>>> print(latex((2*mu)**Rational(7,2), mode=plain))
8 \sqrt{2} \mu^{\frac{7}{2}}
>>> print(latex((2*tau)**Rational(7,2), mode=inline))
$8 \sqrt{2} \tau^{\frac{7}{2}}$
>>> print(latex((2*mu)**Rational(7,2), mode=equation*))
\begin{equation*}8 \sqrt{2} \mu^{\frac{7}{2}}\end{equation*}
>>> print(latex((2*mu)**Rational(7,2), mode=equation))
\begin{equation}8 \sqrt{2} \mu^{\frac{7}{2}}\end{equation}
fold frac powers: Emit {p/q} instead of {frac{p}{q}} for fractional powers.
>>> print(latex((2*tau)**Rational(7,2), fold_frac_powers=True))
8 \sqrt{2} \tau^{7/2}
fold short frac: Emit p / q instead of frac{p}{q} when the denominator is simple
enough (at most two terms and no powers). The default value is T rue for inline mode,
False otherwise.
>>> print(latex(3*x**2/y))
\frac{3 x^{2}}{y}
1260
long frac ratio: The allowed ratio of the width of the numerator to the width of the denominator before we start breaking o long fractions. The default value is 2.
>>> print(latex(Integral(r, r)/2/pi, long_frac_ratio=2))
\frac{\int r\, dr}{2 \pi}
>>> print(latex(Integral(r, r)/2/pi, long_frac_ratio=0))
\frac{1}{2 \pi} \int r\, dr
mul symbol: The symbol to use for multiplication. Can be one of None, ldot, dot, or
times.
>>> print(latex((2*tau)**sin(Rational(7,2)), mul_symbol=times))
\left(2 \times \tau\right)^{\sin{\left (\frac{7}{2} \right )}}
inv trig style: How inverse trig functions should be displayed. Can be one of abbreviated, full, or power. Defaults to abbreviated.
>>> print(latex(asin(Rational(7,2))))
\operatorname{asin}{\left (\frac{7}{2} \right )}
>>> print(latex(asin(Rational(7,2)), inv_trig_style=full))
\arcsin{\left (\frac{7}{2} \right )}
>>> print(latex(asin(Rational(7,2)), inv_trig_style=power))
\sin^{-1}{\left (\frac{7}{2} \right )}
mat str: Which matrix environment string to emit. smallmatrix, matrix, array,
etc. Defaults to smallmatrix for inline mode, matrix for matrices of no more than 10
columns, and array otherwise.
>>> print(latex(Matrix(2, 1, [x, y])))
\left[\begin{matrix}x\\y\end{matrix}\right]
>>> print(latex(Matrix(2, 1, [x, y]), mat_str = array))
\left[\begin{array}{c}x\\y\end{array}\right]
mat delim: The delimiter to wrap around matrices. Can be one of [, (, or the empty
string. Defaults to [.
>>> print(latex(Matrix(2, 1, [x, y]), mat_delim=())
\left(\begin{matrix}x\\y\end{matrix}\right)
symbol names: Dictionary of symbols and the custom strings they should be emitted as.
>>> print(latex(x**2, symbol_names={x:x_i}))
x_i^{2}
latex also supports the builtin container types list, tuple, and dictionary.
>>> print(latex([2/x, y], mode=inline))
$\left [ 2 / x, \quad y\right ]$
1261
5.17.9 MathMLPrinter
This class is responsible for MathML printing. See sympy.printing.mathml.
More info on mathml content: http://www.w3.org/TR/MathML2/chapter4.html
class sympy.printing.mathml.MathMLPrinter(settings=None)
Prints an expression to the MathML markup language
Whenever possible tries to use Content markup and not Presentation markup.
References: http://www.w3.org/TR/MathML2/
printmethod = mathml
doprint(expr)
Prints the expression as MathML.
mathml tag(e)
Returns the MathML tag for an expression.
sympy.printing.mathml.mathml(expr, **settings)
Returns the MathML representation of expr
sympy.printing.mathml.print mathml(expr, **settings)
Prints a pretty representation of the MathML code for expr
Examples
>>> ##
>>> from sympy.printing.mathml import print_mathml
>>> from sympy.abc import x
>>> print_mathml(x+1)
<apply>
<plus/>
<ci>x</ci>
<cn>1</cn>
</apply>
5.17.10 PythonPrinter
This class implements Python printing. Usage:
>>> from sympy import print_python, sin
>>> from sympy.abc import x
>>> print_python(5*x**3 + sin(x))
x = Symbol(x)
e = 5*x**3 + sin(x)
5.17.11 ReprPrinter
This printer generates executable code. This code satises the identity eval(srepr(expr))
== expr.
class sympy.printing.repr.ReprPrinter(settings=None)
1262
printmethod = sympyrepr
emptyPrinter(expr)
The fallback printer.
reprify(args, sep)
Prints each item in args and joins them with sep.
sympy.printing.repr.srepr(expr, **settings)
return expr in repr form
5.17.12 StrPrinter
This module generates readable representations of SymPy expressions.
class sympy.printing.str.StrPrinter(settings=None)
printmethod = sympystr
sympy.printing.str.sstrrepr(expr, **settings)
return expr in mixed str/repr form
i.e. strings are returned in repr form with quotes, and everything else is returned in str
form.
This function could be useful for hooking into sys.displayhook
sympy.printing.tree.print node(node)
Returns information about the node.
This includes class name, string representation and assumptions.
sympy.printing.tree.tree(node)
Returns a tree representation of node as a string.
It uses print node() together with pprint nodes() on node.args recursively.
See also: print tree()
sympy.printing.tree.print tree(node)
Prints a tree representation of node.
1263
Examples
>>> from sympy.printing import print_tree
>>> from sympy import Symbol
>>> x = Symbol(x, odd=True)
>>> y = Symbol(y, even=True)
>>> print_tree(y**x)
Pow: y**x
+-Symbol: y
| algebraic: True
| commutative: True
| complex: True
| even: True
| hermitian: True
| imaginary: False
| integer: True
| irrational: False
| noninteger: False
| odd: False
| rational: True
| real: True
| transcendental: False
+-Symbol: x
algebraic: True
commutative: True
complex: True
even: False
hermitian: True
imaginary: False
integer: True
irrational: False
noninteger: False
nonzero: True
odd: True
rational: True
real: True
transcendental: False
zero: False
5.17.14 Preview
A useful function is preview:
sympy.printing.preview.preview(expr, output=png, viewer=None, euler=True,
packages=(), lename=None, outputbuer=None,
preamble=None, dvioptions=None, outputTexFile=None, **latex settings)
View expression or LaTeX markup in PNG, DVI, PostScript or PDF form.
If the expr argument is an expression, it will be exported to LaTeX and then compiled
using the available TeX distribution. The rst argument, expr, may also be a LaTeX
string. The function will then run the appropriate viewer for the given output format or
use the user dened one. By default png output is generated.
By default pretty Euler fonts are used for typesetting (they were used to typeset the
well known Concrete Mathematics book). For that to work, you need the eulervm.sty
1264
LaTeX style (in Debian/Ubuntu, install the texlive-fonts-extra package). If you prefer
default AMS fonts or your system lacks eulervm LaTeX package then unset the euler
keyword argument.
To use viewer auto-detection, lets say for png output, issue
>>> from sympy import symbols, preview, Symbol
>>> x, y = symbols(x,y)
>>> preview(x + y, output=png)
The png format is considered special. For all other formats the rules are slightly dierent. As an example we will take dvi output format. If you would run
>>> preview(x + y, output=dvi)
then view will look for available dvi viewers on your system (predened in the function,
so it will try evince, rst, then kdvi and xdvi). If nothing is found you will need to set the
viewer explicitly.
>>> preview(x + y, output=dvi, viewer=superior-dvi-viewer)
This will skip auto-detection and will run user specied superior-dvi-viewer. If view
fails to nd it on your system it will gracefully raise an exception.
You may also enter le for the viewer argument. Doing so will cause this function to
return a le object in read-only mode, if lename is unset. However, if it was set, then
preview writes the genereted le to this lename instead.
There is also support for writing to a BytesIO like object, which needs to be passed to
the outputbuer argument.
>>> from io import BytesIO
>>> obj = BytesIO()
>>> preview(x + y, output=png, viewer=BytesIO,
...
outputbuffer=obj)
The LaTeX preamble can be customized by setting the preamble keyword argument.
This can be used, e.g., to set a dierent font size, use a custom documentclass or import
certain set of LaTeX packages.
>>> preamble = \\documentclass[10pt]{article}\n \
...
\\usepackage{amsmath,amsfonts}\\begin{document}
>>> preview(x + y, output=png, preamble=preamble)
If the value of output is dierent from dvi then command line options can be set (dvioptions argument) for the execution of the dvi+output conversion tool. These options
have to be in the form of a list of strings (see subprocess.Popen).
Additional keyword args will be passed to the latex call, e.g., the symbol names ag.
>>> phidd = Symbol(phidd)
>>> preview(phidd, symbol_names={phidd:r\ddot{\varphi}})
For post-processing the generated TeX File can be written to a le by passing the desired
lename to the outputTexFile keyword argument. To write the TeX code to a le named
sample.tex and run the default png viewer to display the resulting bitmap, do
5.17. Printing System
1265
CodePrinter
This class is a base class for other classes that implement code-printing functionality, and
additionally lists a number of functions that cannot be easily translated to C or Fortran.
class sympy.printing.codeprinter.CodePrinter(settings=None)
The base class for code-printing subclasses.
printmethod = sympystr
exception sympy.printing.codeprinter.AssignmentError
Raised if an assignment variable for a loop is missing.
Precedence
sympy.printing.precedence.PRECEDENCE = {And: 30, Add: 40, Pow: 60, Xor: 10, Mul: 50, No
Default precedence values for some basic types.
sympy.printing.precedence.PRECEDENCE VALUES = {And: 30, Xor: 10, Sub: 40, factorial: 60, Po
A dictionary assigning precedence values to certain classes. These values are treated
like they were inherited, so not every single class has to be named here.
1266
sympy.printing.pretty.pretty symbology.frac = {(1, 3): u\u2153, (5, 6): u\u215a, (1, 4): u\xb
The following constants/functions are for rendering atoms and symbols.
sympy.printing.pretty.pretty symbology.xsym(sym)
get symbology for a character
sympy.printing.pretty.pretty symbology.atoms table = {Integers: u\u2124, NegativeInnity:
sympy.printing.pretty.pretty symbology.pretty atom(atom name, default=None)
return pretty representation of an atom
sympy.printing.pretty.pretty symbology.pretty symbol(symb name)
return pretty representation of a symbol
sympy.printing.pretty.pretty symbology.annotated(letter)
Return a stylised drawing of the letter letter, together with information on how to put
annotations (super- and subscripts to the left and to the right) on it.
See pretty.py functions print meijerg, print hyper on how to use this information.
5.17. Printing System
1267
TODO:
Allow left/center/right alignment options for above/below and top/center/bottom
alignment options for left/right
height()
The height of the picture in characters.
left(*args)
Put pictures (left to right) at left. Returns string, baseline arguments for stringPict.
leftslash()
Precede object by a slash of the proper size.
static next(*args)
Put a string of stringPicts next to each other. Returns string, baseline arguments
for stringPict.
parens(left=(, right=), ifascii nougly=False)
Put parentheses around self. Returns string, baseline arguments for stringPict.
left or right can be None or empty string which means no paren from that side
render(*args, **kwargs)
Return the string form of self.
Unless the argument line break is set to False, it will break the expression in a form
that can be printed on the terminal without being broken up.
right(*args)
Put pictures next to this one. Returns string, baseline arguments for stringPict.
(Multiline) strings are allowed, and are given a baseline of 0.
1268
Examples
>>> from sympy.printing.pretty.stringpict import stringPict
>>> print(stringPict(10).right( + ,stringPict(1\r-\r2,1))[0])
1
10 + 2
root(n=None)
Produce a nice root symbol. Produces ugly results for big n inserts.
static stack(*args)
Put pictures on top of each other, from top to bottom. Returns string, baseline arguments for stringPict. The baseline is the baseline of the second picture. Everything
is centered. Baseline is the baseline of the second picture. Strings are allowed. The
special value stringPict.LINE is a row of - extended to the width.
terminal width()
Return the terminal width if possible, otherwise return 0.
width()
The width of the picture in characters.
class sympy.printing.pretty.stringpict.prettyForm(s, baseline=0, binding=0,
unicode=None)
Extension of the stringPict class that knows about basic math applications, optimizing
double minus signs.
Binding is interpreted as follows:
ATOM
FUNC
DIV
POW
MUL
ADD
NEG
5.17.17 dotprint
sympy.printing.dot.dotprint(expr,
styles=[(<class
sympy.core.basic.Basic>,
{color:
blue,
shape:
ellipse}),
(<class
sympy.core.expr.Expr>,
{color:
black})],
atom=<function
<lambda>
at
0x1997fe9c>,
maxdepth=None,
repeat=True,
labelfunc=<type
str>, **kwargs)
DOT description of a SymPy expression tree
Options are
styles: Styles for dierent classes. The default is:
1269
The above functions are only for convenience and ease of use. It is possible to plot any plot
by passing the corresponding Series class to Plot as argument.
1271
legend : bool
xscale : {linear, log}
yscale : {linear, log}
axis : bool
axis center : tuple of two oats or {center, auto}
xlim : tuple of two oats
ylim : tuple of two oats
aspect ratio : tuple of two oats or {auto}
autoscale : bool
margin : oat in [0, 1]
The per data series options and aesthetics are: There are none in the base series. See
below for options for subclasses.
Some data series support additional aesthetics or options:
ListSeries, LineOver1DRangeSeries, Parametric2DLineSeries, Parametric3DLineSeries
support the following:
Aesthetics:
line color : function which returns a oat.
options:
label : str
steps : bool
integers only : bool
append(arg)
Adds an element from a plots series to an existing plot.
See Also:
extend (page 1272)
Examples
Consider two Plot objects, p1 and p2. To add the second plots rst series object to
the rst, use the append method, like so:
>>> from sympy import symbols
>>> from sympy.plotting import plot
>>> x = symbols(x)
>>> p1 = plot(x*x)
>>> p2 = plot(x)
>>> p1.append(p2[0])
>>> p1
Plot object containing:
[0]: cartesian line: x**2 for x over (-10.0, 10.0)
[1]: cartesian line: x for x over (-10.0, 10.0)
1272
extend(arg)
Adds all series from another plot.
Examples
Consider two Plot objects, p1 and p2. To add the second plot to the rst, use the
extend method, like so:
>>> from sympy import symbols
>>> from sympy.plotting import plot
>>> x = symbols(x)
>>> p1 = plot(x*x)
>>> p2 = plot(x)
>>> p1.extend(p2)
>>> p1
Plot object containing:
[0]: cartesian line: x**2 for x over (-10.0, 10.0)
[1]: cartesian line: x for x over (-10.0, 10.0)
Single Plot
>>> plot(x**2, (x, -5, 5))
Plot object containing:
[0]: cartesian line: x**2 for x over (-5.0, 5.0)
1273
No adaptive sampling.
>>> plot(x**2, adaptive=False, nb_of_points=400)
Plot object containing:
[0]: cartesian line: x**2 for x over (-10.0, 10.0)
Usage
Single Plot
plot(expr, range, **kwargs)
If the range is not specied, then a default range of (-10, 10) is used.
Multiple plots with same range.
plot(expr1, expr2, ..., range, **kwargs)
If the range is not specied, then a default range of (-10, 10) is used.
Multiple plots with dierent ranges.
plot((expr1, range), (expr2, range), ..., **kwargs)
Range has to be specied for every expression.
Default range may change in the future if a more advanced default range detection algorithm is implemented.
Arguments
1274
line color: oat. Species the color for the plot. See Plot to see how to set color for
the plots.
If there are multiple plots, then the same series series are applied to all the plots. If you
want to set these options separately, you can index the Plot object returned and set it.
Arguments for Plot class:
title : str. Title of the plot. It is set to the latex representation of the expression, if the
plot has only one expression.
xlabel : str. Label for the x-axis.
ylabel : str. Label for the y-axis.
xscale: {linear, log} Sets the scaling of the x-axis.
yscale: {linear, log} Sets the scaling if the y-axis.
axis center: tuple of two oats denoting the coordinates of the center or {center,
auto}
xlim : tuple of two oats, denoting the x-axis limits.
ylim : tuple of two oats, denoting the y-axis limits.
sympy.plotting.plot.plot parametric(*args, **kwargs)
Plots a 2D parametric plot.
The plotting uses an adaptive algorithm which samples recursively to accurately plot the
plot. The adaptive algorithm uses a random point near the midpoint of two points that
has to be further sampled. Hence the same plots can appear slightly dierent.
See Also:
Plot (page 1271), Parametric2DLineSeries (page 1282)
Examples
>>> from sympy import symbols, cos, sin
>>> from sympy.plotting import plot_parametric
>>> u = symbols(u)
1275
Usage
Single plot.
plot parametric(expr x, expr y, range, **kwargs)
If the range is not specied, then a default range of (-10, 10) is used.
Multiple plots with same range.
plot parametric((expr1 x, expr1 y), (expr2 x, expr2 y), range, **kwargs)
If the range is not specied, then a default range of (-10, 10) is used.
Multiple plots with dierent ranges.
plot parametric((expr x, expr y, range), ..., **kwargs)
Range has to be specied for every expression.
Default range may change in the future if a more advanced default range detection algorithm is implemented.
Arguments
See
If there are multiple plots, then the same Series arguments are applied to all the plots.
If you want to set these options separately, you can index the returned Plot object and
set it.
Arguments for Plot class:
xlabel : str. Label for the x-axis.
ylabel : str. Label for the y-axis.
xscale: {linear, log} Sets the scaling of the x-axis.
yscale: {linear, log} Sets the scaling if the y-axis.
1276
axis center: tuple of two oats denoting the coordinates of the center or {center,
auto}
xlim : tuple of two oats, denoting the x-axis limits.
ylim : tuple of two oats, denoting the y-axis limits.
sympy.plotting.plot.plot3d(*args, **kwargs)
Plots a 3D surface plot.
See Also:
Plot (page 1271), SurfaceOver2DRangeSeries (page 1283)
Examples
>>> from sympy import symbols
>>> from sympy.plotting import plot3d
>>> x, y = symbols(x y)
Single plot
>>> plot3d(x*y, (x, -5, 5), (y, -5, 5))
Plot object containing:
[0]: cartesian surface: x*y for x over (-5.0, 5.0) and y over (-5.0, 5.0)
Usage
Single plot
plot3d(expr, range x, range y, **kwargs)
If the ranges are not specied, then a default range of (-10, 10) is used.
Multiple plot with the same range.
plot3d(expr1, expr2, range x, range y, **kwargs)
If the ranges are not specied, then a default range of (-10, 10) is used.
Multiple plots with dierent ranges.
plot3d((expr1, range x, range y), (expr2, range x, range y), ..., **kwargs)
Ranges have to be specied for every expression.
1277
Default range may change in the future if a more advanced default range detection algorithm is implemented.
Arguments
Single plot.
>>> plot3d_parametric_line(cos(u), sin(u), u, (u, -5, 5))
Plot object containing:
[0]: 3D parametric cartesian line: (cos(u), sin(u), u) for u over (-5.0, 5.0)
Multiple plots.
>>> plot3d_parametric_line((cos(u), sin(u), u, (u, -5, 5)),
...
(sin(u), u**2, u, (u, -5, 5)))
Plot object containing:
[0]: 3D parametric cartesian line: (cos(u), sin(u), u) for u over (-5.0, 5.0)
[1]: 3D parametric cartesian line: (sin(u), u**2, u) for u over (-5.0, 5.0)
1278
Usage
Single plot:
plot3d parametric line(expr x, expr y, expr z, range, **kwargs)
If the range is not specied, then a default range of (-10, 10) is used.
Multiple plots.
plot3d parametric line((expr x, expr y, expr z, range), ..., **kwargs)
Ranges have to be specied for every expression.
Default range may change in the future if a more advanced default range detection algorithm is implemented.
Arguments
See
If there are multiple plots, then the same series arguments are applied to all the plots.
If you want to set these options separately, you can index the returned Plot object and
set it.
Arguments for Plot class.
title : str. Title of the plot.
sympy.plotting.plot.plot3d parametric surface(*args, **kwargs)
Plots a 3D parametric surface plot.
See Also:
Plot (page 1271), ParametricSurfaceSeries (page 1283)
Examples
>>> from sympy import symbols, cos, sin
>>> from sympy.plotting import plot3d_parametric_surface
>>> u, v = symbols(u v)
Single plot.
1279
Usage
Single plot.
plot3d parametric surface(expr x, expr y, expr z, range u, range v, **kwargs)
If the ranges is not specied, then a default range of (-10, 10) is used.
Multiple plots.
plot3d parametric surface((expr x, expr y, expr z, range u, range v), ...,
**kwargs)
Ranges have to be specied for every expression.
Default range may change in the future if a more advanced default range detection algorithm is implemented.
Arguments
1280
y var=None,
Arguments
If neither x var nor y var are given then the free symbols in the expression will be assigned in the order they are sorted.
The following keyword arguments can also be used:
adaptive. Boolean. The default value is set to True. It has to be set to False
if you want to use a mesh grid.
depth integer. The depth of recursion for adaptive mesh grid. Default value
is 0. Takes value in the range (0, 4).
points integer. The number of points if adaptive mesh grid is not used. Default value is 200.
title string .The title for the plot.
xlabel string. The label for the x-axis
ylabel string. The label for the y-axis
plot implicit, by default, uses interval arithmetic to plot functions. If the expression cannot be plotted using interval arithmetic, it defaults to a generating a contour using a mesh
grid of xed number of points. By setting adaptive to False, you can force plot implicit to
use the mesh grid. The mesh grid method can be eective when adaptive plotting using
interval arithmetic, fails to plot with small line width.
Examples:
Plot expressions:
>>> from sympy import plot_implicit, cos, sin, symbols, Eq, And
>>> x, y = symbols(x y)
1281
Plotting regions.
>>> p6 = plot_implicit(y > x**2)
When plotting an expression with a single variable (y - 1, for example), specify the x or
the y variable explicitly:
>>> p8 = plot_implicit(y - 1, y_var=y)
>>> p9 = plot_implicit(x - 1, x_var=x)
1282
Henrique
Henrique
class sympy.plotting.plot.Line3DBaseSeries
A base class for 3D lines.
Most of the stu is derived from Line2DBaseSeries.
class sympy.plotting.plot.Parametric3DLineSeries(expr x,
expr y,
expr z,
var start end, **kwargs)
Representation for a 3D line consisting of two parametric sympy expressions and a range.
class sympy.plotting.plot.SurfaceBaseSeries
A base class for 3D surfaces.
class sympy.plotting.plot.SurfaceOver2DRangeSeries(expr,
var start end x,
var start end y, **kwargs)
Representation for a 3D surface consisting of a sympy expression and 2D range.
class sympy.plotting.plot.ParametricSurfaceSeries(expr x,
expr y,
expr z,
var start end u,
var start end v, **kwargs)
Representation for a 3D surface consisting of three parametric sympy expressions and
a range.
class sympy.plotting.plot implicit.ImplicitSeries(expr,
var start end x,
var start end y, has equality,
use interval math,
depth,
nb of points)
Representation for Implicit plot
1283
To see lots of plotting examples, see examples/pyglet plotting.py and try running it in
interactive mode (python -i plotting.py):
$ python -i examples/pyglet plotting.py
Keys
SHIFT
R and F, Page Up and Down, Numpad + and Arrow Keys, A,S,D,W, Numpad 4,6,8,2
Q and E, Numpad 7 and 9
Z and C, Numpad 1 and 3
F1
F2
F3
F4
X, Numpad 5
Keys
F5
F6
Keys
ESCAPE
F8
The mouse can be used to rotate, zoom, and translate by dragging the left, middle, and right
mouse buttons respectively.
1284
Note that function parameters are given as option strings of the form key1=value1; key2 =
value2 (spaces are truncated). Keyword arguments given directly to plot apply to the plot
itself.
fz = x**2-y**2
Fx, Fy, Fz = fz.diff(x), fz.diff(y), 0
p[1] = fz, style=solid
p[1].color = (Fx**2 + Fy**2 + Fz**2)**(0.5)
1285
The other way to specify a color scheme is to give a separate function for each component r,
g, b. With this syntax, the default color scheme is dened:
>>> p[1].color = z,y,x, (0.4,0.4,0.4), (0.9,0.9,0.9)
This maps z->red, y->green, and x->blue. In some cases, you might prefer to use the following
alternative syntax:
>>> p[1].color = z,(0.4,0.9), y,(0.4,0.9), x,(0.4,0.9)
You can still use multi-step gradients with three-function color schemes.
Plotting polygons (Polygon, RegularPolygon, Triangle) are not supported directly. However a
polygon can be plotted through a loop as follows.
In [6]: p = Plot(axes=label axes=True)
In [7]: t = RegularPolygon(Point(0,0), 1, 5)
In [8]: for i in range(len(t.sides)):
....:
p[i] = t.sides[i]
1286
con-
Syntax
ask(proposition)
ask(proposition, assumptions)
Remarks Relations in assumptions are not implemented (yet), so the following will not
give a meaningful result.
>>> ask(Q.positive(x), Q.is_true(x > 0))
assumptions,
1287
...
# Mersenne numbers are in the form 2**n + 1, n integer
...
@staticmethod
...
def Integer(expr, assumptions):
...
import math
...
return ask(Q.integer(math.log(expr + 1, 2)))
>>> register_handler(mersenne, MersenneHandler)
>>> ask(Q.mersenne(7))
True
arg
Return the expression used by this assumption.
Examples
>>>
>>>
>>>
>>>
x +
class sympy.assumptions.assume.AssumptionsContext
Set representing assumptions.
This is used to represent global assumptions, but you can also use this class to create
your own local assumptions contexts. It is basically a thin wrapper to Pythons set, so
see its documentation for advanced usage.
Examples
>>> from sympy import AppliedPredicate, Q
>>> from sympy.assumptions.assume import global_assumptions
>>> global_assumptions
AssumptionsContext()
>>> from sympy.abc import x
>>> global_assumptions.add(Q.real(x))
1288
>>> global_assumptions
AssumptionsContext([Q.real(x)])
>>> global_assumptions.remove(Q.real(x))
>>> global_assumptions
AssumptionsContext()
>>> global_assumptions.clear()
add(*assumptions)
Add an assumption.
class sympy.assumptions.assume.Predicate
A predicate is a function that returns a boolean value.
Predicates merely wrap their argument and remain unevaluated:
>>> from sympy import Q, ask, Symbol, S
>>> x = Symbol(x)
>>> Q.prime(7)
Q.prime(7)
To obtain the truth value of an expression containing predicates, use the function ask:
>>> ask(Q.prime(7))
True
The tautological predicate Q.ist rue can be used to wrap other objects:
>>> Q.is_true(x > 1)
Q.is_true(x > 1)
>>> Q.is_true(S(1) < x)
Q.is_true(1 < x)
eval(expr, assumptions=True)
Evaluate self(expr) under the given assumptions.
This uses only direct resolution methods, not logical inference.
sympy.assumptions.assume.assuming(*args, **kwds)
Context manager for assumptions
Examples
>>> from sympy.assumptions import assuming, Q, ask
>>> from sympy.abc import x, y
>>> print(ask(Q.integer(x + y)))
None
>>> with assuming(Q.integer(x), Q.integer(y)):
...
print(ask(Q.integer(x + y)))
True
Rene
sympy.assumptions.refine.refine(expr, assumptions=True)
Simplify an expression using assumptions.
1289
Gives the form of expr that would be obtained if symbols in it were replaced by explicit
numerical expressions satisfying the assumptions.
Examples
>>> from sympy import refine, sqrt, Q
>>> from sympy.abc import x
>>> refine(sqrt(x**2), Q.real(x))
Abs(x)
>>> refine(sqrt(x**2), Q.positive(x))
x
1290
Handlers
Contents
Calculus This module contains query handlers responsible for calculus queries: innitesimal, bounded, etc.
class sympy.assumptions.handlers.calculus.AskBoundedHandler
Handler for key bounded.
Test that an expression is bounded respect to all its variables.
Examples of usage:
>>> from sympy import Symbol, Q
>>> from sympy.assumptions.handlers.calculus import AskBoundedHandler
>>> from sympy.abc import x
>>> a = AskBoundedHandler()
>>> a.Symbol(x, Q.positive(x)) == None
True
>>> a.Symbol(x, Q.bounded(x))
True
B
+
-
U
x
?
?
?
U
+
U
U
U
?
?
?
?
?
?
+
?
U
U
?
?
B = Bounded
U = Unbounded
? = unknown boundedness
+ = positive sign
- = negative sign
x = sign unknown
1291
When the signs are not the same you can have an undened result as in oo oo, hence bounded is also undened.
static Mul(expr, assumptions)
Return True if expr is bounded, False if not and None if unknown.
Truth Table:
B U ?
s
B B U ?
U
U U
?
?
/s
?
B = Bounded
U = Unbounded
? = unknown boundedness
s = signed (hence nonzero)
/s = not signed
class sympy.assumptions.handlers.calculus.AskInfinitesimalHandler
Handler for key innitesimal Test that a given expression is equivalent to an innitesimal number
static Add(expr, assumptions)
Innitesimal*Bounded -> Innitesimal
static Mul(expr, assumptions)
Innitesimal*Bounded -> Innitesimal
1292
class sympy.assumptions.handlers.sets.AskAlgebraicHandler
Handler for Q.algebraic key.
class sympy.assumptions.handlers.sets.AskAntiHermitianHandler
Handler for Q.antihermitian Test that an expression belongs to the eld of anti-Hermitian
operators, that is, operators in the form x*I, where x is Hermitian
static Add(expr, assumptions)
Antihermitian + Antihermitian -> Antihermitian Antihermitian + !Antihermitian ->
!Antihermitian
static Mul(expr, assumptions)
As long as there is at most only one noncommutative term: Hermitian*Hermitian
1293
->
Antihermitian
Antihermi-
1294
con-
Syntax
ask(proposition)
ask(proposition, assumptions)
Remarks Relations in assumptions are not implemented (yet), so the following will not
give a meaningful result.
>>> ask(Q.positive(x), Q.is_true(x > 0))
1295
5.20.2 Querying
asks optional second argument should be a boolean expression involving assumptions about
objects in expr. Valid values include:
Q.integer(x)
Q.positive(x)
Q.integer(x) & Q.positive(x)
etc.
commutative
Test that objects are commutative. By default, symbols in SymPy are considered commutative
except otherwise stated.
Examples:
>>> from sympy import *
>>> x, y = symbols(x,y)
>>> ask(Q.commutative(x))
True
>>> ask(Q.commutative(x), ~Q.commutative(x))
False
1296
complex
Test that expression belongs to the eld of complex numbers.
Examples:
>>> from sympy import *
>>> ask(Q.complex(2))
True
>>> ask(Q.complex(I))
True
>>> x, y = symbols(x,y)
>>> ask(Q.complex(x+I*y), Q.real(x) & Q.real(y))
True
even
Test that expression represents an even number, that is, an number that can be written in the
form 2*n, n integer.
Examples:
>>> from sympy import *
>>> ask(Q.even(2))
True
>>> n = Symbol(n)
>>> ask(Q.even(2*n), Q.integer(n))
True
extended real
Test that an expression belongs to the eld of extended real numbers, that is, real numbers
union {Innity, -Innity}.
Examples:
>>> from sympy import *
>>> ask(Q.extended_real(oo))
True
>>> ask(Q.extended_real(2))
True
>>> ask(Q.extended_real(x), Q.real(x))
True
imaginary
Test that an expression belongs to the set of imaginary numbers, that is, it can be
written as x*I, where x is real and I is the imaginary unit.
Examples:
1297
innitesimal
Test that an expression is equivalent to an innitesimal number.
Examples:
>>> from sympy import *
>>> ask(Q.infinitesimal(1/oo))
True
>>> x, y = symbols(x,y)
>>> ask(Q.infinitesimal(2*x), Q.infinitesimal(x))
True
>>> ask(Q.infinitesimal(x*y), Q.infinitesimal(x) & Q.bounded(y))
True
integer
Test that an expression belongs to the set of integer numbers.
Examples:
>>> from sympy import *
>>> ask(Q.integer(2))
True
>>> ask(Q.integer(sqrt(2)))
False
>>> x = Symbol(x)
>>> ask(Q.integer(x/2), Q.even(x))
True
irrational
Test that an expression represents an irrational number.
Examples:
>>> from sympy import *
>>> ask(Q.irrational(pi))
True
>>> ask(Q.irrational(sqrt(2)))
True
>>> ask(Q.irrational(x*sqrt(2)), Q.rational(x))
True
rational
Test that an expression represents a rational number.
1298
Examples:
>>> from sympy import *
>>> ask(Q.rational(Rational(3, 4)))
True
>>> x, y = symbols(x,y)
>>> ask(Q.rational(x/2), Q.integer(x))
True
>>> ask(Q.rational(x/y), Q.integer(x) & Q.integer(y))
True
negative
Test that an expression is less (strict) than zero.
Examples:
>>> from sympy import *
>>> ask(Q.negative(0.3))
False
>>> x = Symbol(x)
>>> ask(Q.negative(-x), Q.positive(x))
True
Remarks
negative numbers are dened as real numbers that are not zero nor positive, so complex
numbers (with nontrivial imaginary coecients) will return False for this predicate. The
same applies to Q.positive.
positive
Test that a given expression is greater (strict) than zero.
Examples:
>>> from sympy import *
>>> ask(Q.positive(0.3))
True
>>> x = Symbol(x)
>>> ask(Q.positive(-x), Q.negative(x))
True
Remarks
1299
odd
Test that an expression represents an odd number.
Examples:
>>> from sympy import *
>>> ask(Q.odd(3))
True
>>> n = Symbol(n)
>>> ask(Q.odd(2*n + 1), Q.integer(n))
True
nonzero
Test that an expression is not zero.
Examples:
>>> from sympy import *
>>> x = Symbol(x)
>>> ask(Q.nonzero(x), Q.positive(x) | Q.negative(x))
True
5.20.4 Design
Each time ask is called, the appropriate Handler for the current key is called. This is always a
subclass of sympy.assumptions.AskHandler. Its classmethods have the names of the classes
it supports. For example, a (simplied) AskHandler for the ask positive would look like this:
class AskPositiveHandler(CommonHandler):
def Mul(self):
# return True if all arguments in self.expr.args are positive
...
1300
def Add(self):
for arg in self.expr.args:
if not ask(arg, positive, self.assumptions):
break
else:
# if all arguments are positive
return True
...
The .Mul() method is called when self.expr is an instance of Mul, the Add method would be
called when self.expr is an instance of Add and so on.
5.20.5 Extensibility
You can dene new queries or support new types by subclassing sympy.assumptions.AskHandler
and registering that handler for a particular key by calling register handler:
sympy.assumptions.ask.register handler(key, handler)
Register a handler in the ask system. key must be a string and handler a class inheriting
from AskHandler:
>>> from sympy.assumptions import register_handler, ask, Q
>>> from sympy.assumptions.handlers import AskHandler
>>> class MersenneHandler(AskHandler):
...
# Mersenne numbers are in the form 2**n + 1, n integer
...
@staticmethod
...
def Integer(expr, assumptions):
...
import math
...
return ask(Q.integer(math.log(expr + 1, 2)))
>>> register_handler(mersenne, MersenneHandler)
>>> ask(Q.mersenne(7))
True
New type must inherit from Basic, otherwise an exception will be raised. This is a bug and should be xed.
1301
5.20.7 Misc
You can nd more examples
sympy/assumptions/tests/
in
the
in
the
form
of
test
under
directory
5.21.1 Expanding
The simplest rewrite rule is expanding expressions into a sparse form. Expanding has several avors and include expanding complex valued expressions, arithmetic expand of products and powers but also expanding functions in terms of more general functions is possible.
Below are listed all currently available expand rules.
Expanding of arithmetic expressions involving products and powers:
>>> from sympy import *
>>> x, y, z = symbols(x,y,z)
>>> ((x + y)*(x - y)).expand(basic=True)
x**2 - y**2
>>> ((x + y + z)**2).expand(basic=True)
x**2 + 2*x*y + 2*x*z + y**2 + 2*y*z + z**2
Arithmetic expand is done by default in expand() so the keyword basic can be omitted. However you can set basic=False to avoid this type of expand if you use rules described below.
This give complete control on what is done with the expression.
Another type of expand rule is expanding complex valued expressions and putting them into
a normal form. For this complex keyword is used. Note that it will always perform arithmetic
expand to obtain the desired normal form:
>>> (x + I*y).expand(complex=True)
re(x) + I*re(y) + I*im(x) - im(y)
>>> sin(x + I*y).expand(complex=True)
sin(re(x) - im(y))*cosh(re(y) + im(x)) + I*cos(re(x) - im(y))*sinh(re(y) + im(x))
1302
Note also that the same behavior can be obtained by using as real imag() method. However
it will return a tuple containing the real part in the rst place and the imaginary part in the
other. This can be also done in a two step process by using collect function:
>>> (x + I*y).as_real_imag()
(re(x) - im(y), re(y) + im(x))
>>> collect((x + I*y).expand(complex=True), I, evaluate=False)
{1: re(x) - im(y), I: re(y) + im(x)}
There is also possibility for expanding expressions in terms of expressions of dierent kind.
This is very general type of expanding and usually you would use rewrite() to do specic
type of rewrite:
>>> GoldenRatio.expand(func=True)
1/2 + sqrt(5)/2
________
[], \ sin(x)
>>> pprint(cse(sqrt(sin(x)+5)*sqrt(sin(x)+4)), use_unicode=True)
________
________
[(x, sin(x))], \ x + 4 \ x + 5
>>> pprint(cse(sqrt(sin(x+1) + 5 + cos(y))*sqrt(sin(x+1) + 4 + cos(y))),
...
use_unicode=True)
________
________
[(x, sin(x + 1) + cos(y))], \ x + 4 \ x + 5
>>> pprint(cse((x-y)*(z-y) + sqrt((x-y)*(z-y))), use_unicode=True)
____
____
However, these optimizations can be very slow for large expressions. Moreover, if speed is a
concern, one can pass the option order=none. Order of terms will then be dependent on
hashing algorithm implementation, but speed will be greatly improved.
More information:
1303
5.22.1 Limits
The main purpose of this module is the computation of limits.
sympy.series.limits.limit(e, z, z0, dir=+)
Compute the limit of e(z) at the point z0.
z0 can be any expression, including oo and -oo.
For dir=+ (default) it calculates the limit from the right (z->z0+) and for dir=- the
limit from the left (z->z0-). For innite z0 (oo or -oo), the dir argument is determined
from the direction of the innity (i.e., dir=- for oo).
Notes
First we try some heuristics for easy and frequent cases like x, 1/x, x**2 and similar, so that its fast. For all other cases, we use the Gruntz algorithm (see the gruntz()
function).
Examples
>>>
>>>
>>>
1
>>>
oo
>>>
-oo
>>>
0
class sympy.series.limits.Limit
Represents an unevaluated limit.
Examples
>>> from sympy import Limit, sin, Symbol
>>> from sympy.abc import x
>>> Limit(sin(x)/x, x, 0)
Limit(sin(x)/x, x, 0)
>>> Limit(1/x, x, 0, dir=-)
Limit(1/x, x, 0, dir=-)
doit(**hints)
Evaluates limit
As is explained above, the workhorse for limit computations is the function gruntz() which
implements Gruntz algorithm for computing limits.
1304
ex emx
x
ee ex
xm xn
1
ex+ x ex+log x ex .
Using these results yields the following strategy for computing limx f (x):
1. Find the set of most rapidly varying subexpressions (MRV set) of f (x). That is, from the
set of all subexpressions of f (x), nd the elements that are maximal under the relation
.
2. Choose a function that is in the same comparability class as the elements in the MRV
set, such that limx = 0.
3. Expand f (x) as a series in in such a way that the antecedents of the above theorem are
satised.
4. Apply the theorem and conclude the computation of limx f (x), possibly by recursively
working on g1 (x).
Notes
This exposition glossed over several details. Many are described in the le gruntz.py, and all
can be found in Gruntz very readable thesis. The most important points that have not been
explained are:
1. Given f(x) and g(x), how do we determine if f (x) g(x), g(x) f (x) or g(x) f (x)?
5.22. Series Expansions
1305
Here we can do e1, e2, e3, e4 or e1, e2, e4, e3. To do this we assemble the nodes into a
tree, and sort them by height.
This function builds the tree, rewrites then sorts the nodes.
sympy.series.gruntz.mrv leadterm(*args, **kwargs)
Returns (c0, e0) for e.
sympy.series.gruntz.calculate series(e, x, logx=None)
Calculates at least one term of the series of e in x.
This is a place that fails most often, so it is in its own function.
sympy.series.gruntz.limitinf(*args, **kwargs)
Limit e(x) for x-> oo
sympy.series.gruntz.sign(*args, **kwargs)
Returns a sign of an expression e(x) for x->oo.
e > 0 for x sufficiently large ... 1
e == 0 for x sufficiently large ... 0
e < 0 for x sufficiently large ... -1
1306
The result of this function is currently undened if e changes sign arbitarily often for
arbitrarily large x (e.g. sin(x)).
Note that this returns zero only if e is constantly zero for x suciently large. [If e is
constant, of course, this is just the same thing as the sign of e.]
sympy.series.gruntz.mrv(e, x)
Returns a SubsSet of most rapidly varying (mrv) subexpressions of e, and e rewritten
in terms of these
sympy.series.gruntz.mrv max1(f, g, exps, x)
Computes the maximum of two sets of expressions f and g, which are in the same comparability class, i.e. mrv max1() compares (two elements of) f and g and returns the set,
which is in the higher comparability class of the union of both, if they have the same
order of variation. Also returns exps, with the appropriate substitutions made.
sympy.series.gruntz.mrv max3(f, expsf, g, expsg, union, expsboth, x)
Computes the maximum of two sets of expressions f and g, which are in the same comparability class, i.e. max() compares (two elements of) f and g and returns either (f, expsf)
[if f is larger], (g, expsg) [if g is larger] or (union, expsboth) [if f, g are of the same class].
class sympy.series.gruntz.SubsSet
Stores (expr, dummy) pairs, and how to rewrite expr-s.
The gruntz algorithm needs to rewrite certain expressions in term of a new variable w.
We cannot use subs, because it is just too smart for us. For example:
> Omega=[exp(exp( p - exp(- p))/(1 - 1/ p)), exp(exp( p))]
> O2=[exp(-exp( p) + exp(-exp(- p))*exp( p)/(1 - 1/ p))/ w, 1/ w]
> e = exp(exp( p - exp(- p))/(1 - 1/ p)) - exp(exp( p))
> e.subs(Omega[0],O2[0]).subs(Omega[1],O2[1])
-1/w + exp(exp(p)*exp(-exp(-p))/(1 - 1/p))
The mrv set is {exp(x), exp(-x), exp(x - exp(-x))}. We introduce corresponding dummy
variables d1, d2, d3 and rewrite:
d3 + d1 + x.
This class rst of all keeps track of the mapping expr->variable, i.e. will at this stage be
a dictionary:
{exp(x): d1, exp(-x): d2, exp(x - exp(-x)): d3}.
[It turns out to be more convenient this way round.] But sometimes expressions in the
mrv set have other expressions from the mrv set as subexpressions, and we need to keep
track of that as well. In this case, d3 is really exp(x - d2), so rewrites at this stage is:
{d3: exp(x-d2)}.
The function rewrite uses all this information to correctly rewrite our expression in terms
of w. In this case w can be choosen to be exp(-x), i.e. d2. The correct rewriting then is:
exp(-w)/w + 1/w + x.
1307
meets(s2)
Tell whether or not self and s2 have non-empty intersection
union(s2, exps=None)
Compute the union of self and s2, adjusting exps
Reference
sympy.series.series.series(expr, x=None, x0=0, n=6, dir=+)
Series expansion of expr around point x = x0.
See the doctring of Expr.series() for complete details of this wrapper.
Reference
class sympy.series.order.Order
Represents the limiting behavior of some function
The order of a function characterizes the function based on the limiting behavior of the
function as it goes to some limit. Only taking the limit point to be a number is currently
supported. This is expressed in big O notation [R345] (page 1912).
The formal denition for the order of a function g(x) about a point a is such that g(x) =
O(f (x)) as x a if and only if for any > 0 there exists a M > 0 such that |g(x)| M |f (x)|
for |x a| < . This is equivalent to limxa sup |g(x)/f (x)| < .
1308
Lets illustrate it on the following example by taking the expansion of sin(x) about 0:
sin(x) = x x3 /3! + O(x5 )
where in this case O(x5 ) = x5 /5! x7 /7! + . By the denition of O, for any > 0 there is
an M such that:
|x5 /5! x7 /7! + ....| <= M |x5 | for |x| <
x0
x0
to
O(f(x,
In the multivariate case, it is assumed the limits w.r.t. the various symbols commute.
If no symbols are passed then all symbols in the expression are used and the limit point
is assumed to be zero.
References
1309
+ x**2)
+ x**2, (x, 0))
+ x**2, (x, oo))
(x, oo))
O(1, x)
in O(1)
O(1, x)
in O(x)
>>> O(x)*x
O(x**2)
>>> O(x) - O(x)
O(x)
>>> O(cos(x))
O(1)
>>> O(cos(x), (x, pi/2))
O(x - pi/2, (x, pi/2))
contains(*args, **kwargs)
Return True if expr belongs to Order(self.expr, *self.variables). Return False if self
belongs to expr. Return None if the inclusion relation cannot be determined (e.g.
when self and expr have dierent symbols).
1310
Richardson extrapolation with 11 appropriately chosen terms gives a value that is accurate to the indicated precision:
>>> from sympy import E
>>> from sympy.series.acceleration import richardson
>>> print(round(richardson(e, n, 10, 20).evalf(), 10))
2.7182818285
>>> print(round(E.evalf(), 10))
2.7182818285
sympy.series.acceleration.shanks(A, k, n, m=1)
Calculate an approximation for lim k->oo A(k) using the n-term Shanks transformation S(A)(n). With m > 1, calculate the m-fold recursive Shanks transformation
S(S(...S(A)...))(n).
The Shanks transformation is useful for summing Taylor series that converge slowly near
a pole or singularity, e.g. for log(2):
>>> from sympy.abc import k, n
>>> from sympy import Sum, Integer
>>> from sympy.series.acceleration import shanks
>>> A = Sum(Integer(-1)**(k+1) / k, (k, 1, n))
>>> print(round(A.subs(n, 100).doit().evalf(), 10))
0.6881721793
>>> print(round(shanks(A, n, 25).evalf(), 10))
0.6931396564
>>> print(round(shanks(A, n, 25, 5).evalf(), 10))
0.6931471806
5.22.5 Residues
TODO
1311
Reference
sympy.series.residues.residue(expr, x, x0)
Finds the residue of expr at the point x=x0.
The residue is dened as the coecient of 1/(x-x0) in the power series expansion about
x=x0.
References
1.http://en.wikipedia.org/wiki/Residue theorem
Examples
>>>
>>>
>>>
1
>>>
0
>>>
2
5.23 Sets
5.23.1 Set
class sympy.sets.sets.Set
The base class for any kind of set.
This is not meant to be used directly as a container of items. It does not behave like the
builtin set; see FiniteSet (page 1319) for that.
Real intervals are represented by the Interval (page 1317) class and unions of sets by
the Union (page 1320) class. The empty set is represented by the EmptySet (page 1323)
class and available as a singleton as S.EmptySet.
Attributes
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
boundary
The boundary or frontier of a set
A point x is on the boundary of a set S if
1.x is in the closure of S. I.e. Every neighborhood of x contains a point in S.
1312
2.x is not in the interior of S. I.e. There does not exist an open set centered on x
contained entirely within S.
There are the points on the outer rim of S. If S is open then these points need not
actually be contained within S.
For example, the boundary of an interval is its start and end points. This is true
regardless of whether or not the interval is open.
Examples
>>>
>>>
{0,
>>>
{0,
complement(universe)
The complement of self w.r.t the given the universe.
Examples
>>> from sympy import Interval, S
>>> Interval(0, 1).complement(S.Reals)
(-oo, 0) U (1, oo)
>>> Interval(0, 1).complement(S.UniversalSet)
UniversalSet() \ [0, 1]
contains(other)
Returns True if other is contained in self as an element.
As a shortcut it is possible to use the in operator:
Examples
>>> from sympy import Interval
>>> Interval(0, 1).contains(0.5)
True
>>> 0.5 in Interval(0, 1)
True
inf
The inmum of self
Examples
>>> from sympy import Interval, Union
>>> Interval(0, 1).inf
0
>>> Union(Interval(0, 1), Interval(2, 3)).inf
0
5.23. Sets
1313
intersect(other)
Returns the intersection of self and other.
>>> from sympy import Interval
>>> Interval(1, 3).intersect(Interval(1, 2))
[1, 2]
intersection(other)
Alias for intersect() (page 1313)
is disjoint(other)
Returns True if self and other are disjoint
References
is proper subset(other)
Returns True if self is a proper subset of other.
Examples
>>> from sympy import Interval
>>> Interval(0, 0.5).is_proper_subset(Interval(0, 1))
True
>>> Interval(0, 1).is_proper_subset(Interval(0, 1))
False
is proper superset(other)
Returns True if self is a proper superset of other.
Examples
>>> from sympy import Interval
>>> Interval(0, 1).is_proper_superset(Interval(0, 0.5))
True
>>> Interval(0, 1).is_proper_superset(Interval(0, 1))
False
is subset(other)
Returns True if self is a subset of other.
1314
Examples
>>> from sympy import Interval
>>> Interval(0, 0.5).is_subset(Interval(0, 1))
True
>>> Interval(0, 1).is_subset(Interval(0, 1, left_open=True))
False
is superset(other)
Returns True if self is a superset of other.
Examples
>>> from sympy import Interval
>>> Interval(0, 0.5).is_superset(Interval(0, 1))
False
>>> Interval(0, 1).is_superset(Interval(0, 1, left_open=True))
True
isdisjoint(other)
Alias for is disjoint() (page 1314)
issubset(other)
Alias for is subset() (page 1314)
issuperset(other)
Alias for is superset() (page 1315)
measure
The (Lebesgue) measure of self
Examples
>>> from sympy import Interval, Union
>>> Interval(0, 1).measure
1
>>> Union(Interval(0, 1), Interval(2, 3)).measure
2
powerset()
Find the Power set of self.
References
5.23. Sets
1315
subset(*args, **kwargs)
Returns True if other is a subset of self.
sup
The supremum of self
Examples
>>> from sympy import Interval, Union
>>> Interval(0, 1).sup
1
>>> Union(Interval(0, 1), Interval(2, 3)).sup
3
union(other)
Returns the union of self and other.
Examples
Interval(0, 2) - Interval(0, 1)
2]
Interval(1, 3) - FiniteSet(2)
2) U (2, 3]
sympy.sets.sets.imageset(*args)
Image of set under transformation f.
If this function cant compute the image, it returns an unevaluated ImageSet object.
f (x)|x self
See Also:
sympy.sets.fancysets.ImageSet (page 1326)
Examples
1316
Elementary Sets
5.23.2 Interval
class sympy.sets.sets.Interval
Represents a real interval as a Set.
Usage: Returns an interval with end points start and end.
For left open=True (default left open is False) the interval will be open on the left.
Similarly, for right open=True the interval will be open on the right.
Notes
5.23. Sets
1317
Attributes
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
as relational(symbol)
Rewrite an interval in terms of inequalities and logic operators.
end
The right end point of self.
This property takes the same value as the sup property.
Examples
>>> from sympy import Interval
>>> Interval(0, 1).end
1
is left unbounded
Return True if the left endpoint is negative innity.
is right unbounded
Return True if the right endpoint is positive innity.
left
The left end point of self.
This property takes the same value as the inf property.
Examples
>>> from sympy import Interval
>>> Interval(0, 1).start
0
left open
True if self is left-open.
Examples
>>> from sympy import Interval
>>> Interval(0, 1, left_open=True).left_open
True
>>> Interval(0, 1, left_open=False).left_open
False
right
The right end point of self.
This property takes the same value as the sup property.
1318
Examples
>>> from sympy import Interval
>>> Interval(0, 1).end
1
right open
True if self is right-open.
Examples
>>> from sympy import Interval
>>> Interval(0, 1, right_open=True).right_open
True
>>> Interval(0, 1, right_open=False).right_open
False
start
The left end point of self.
This property takes the same value as the inf property.
Examples
>>> from sympy import Interval
>>> Interval(0, 1).start
0
5.23.3 FiniteSet
class sympy.sets.sets.FiniteSet
Represents a nite set of discrete numbers
References
5.23. Sets
1319
Attributes
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
as relational(symbol)
Rewrite a FiniteSet in terms of equalities and logic operators.
Compound Sets
5.23.4 Union
class sympy.sets.sets.Union
Represents a union of sets as a Set (page 1312).
See Also:
Intersection (page 1321)
References
The Union constructor will always try to merge overlapping intervals, if possible. For
example:
>>> Union(Interval(1, 2), Interval(2, 3))
[1, 3]
Attributes
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
as relational(symbol)
Rewrite a Union in terms of equalities and logic operators.
static reduce(args)
Simplify a Union (page 1320) using known rules
We rst start with global rules like Merge all FiniteSets
Then we iterate through all pairs and ask the constituent sets if they can simplify
themselves with any other constituent
1320
5.23.5 Intersection
class sympy.sets.sets.Intersection
Represents an intersection of sets as a Set (page 1312).
See Also:
Union (page 1320)
References
Attributes
is Complement
is EmptySet
is UniversalSet
as relational(symbol)
Rewrite an Intersection in terms of equalities and logic operators
static reduce(args)
Simplify an intersection using known rules
We rst start with global rules like if any empty sets return empty set and distribute
any unions
Then we iterate through all pairs and ask the constituent sets if they can simplify
themselves with any other constituent
5.23.6 ProductSet
class sympy.sets.sets.ProductSet
Represents a Cartesian Product of Sets.
Returns a Cartesian product given several sets as either an iterable or individual arguments.
Can use * operator on any sets for convenient shorthand.
5.23. Sets
1321
Notes
Attributes
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
5.23.7 Complement
class sympy.sets.sets.Complement
Represents the set dierence or relative complement of a set with another set.
A B = {x A|x
/ B}
See Also:
Intersection (page 1321), Union (page 1320)
References
http://mathworld.wolfram.com/SetComplement.html
1322
Examples
>>> from sympy import Complement, FiniteSet
>>> Complement(FiniteSet(0, 1, 2), FiniteSet(1))
{0, 2}
Attributes
is EmptySet
is Intersection
is UniversalSet
static reduce(A, B)
Simplify a Complement (page 1322).
Singleton Sets
5.23.8 EmptySet
class sympy.sets.sets.EmptySet
Represents the empty set. The empty set is available as a singleton as S.EmptySet.
See Also:
UniversalSet (page 1324)
References
Attributes
is Complement
is Intersection
is UniversalSet
5.23. Sets
1323
5.23.9 UniversalSet
class sympy.sets.sets.UniversalSet
Represents the set of all things.
S.UniversalSet
See Also:
EmptySet (page 1323)
References
Attributes
is Complement
is EmptySet
is Intersection
Special Sets
5.23.10 Naturals
class sympy.sets.fancysets.Naturals
Represents the natural numbers (or counting numbers) which are all positive integers
starting from 1. This set is also available as the Singleton, S.Naturals.
See Also:
Naturals0 (page 1325) non-negative integers (i.e. includes 0, too)
Integers (page 1325) also includes negative integers
Examples
>>> from sympy import S, Interval, pprint
>>> 5 in S.Naturals
True
>>> iterable = iter(S.Naturals)
>>> next(iterable)
1324
1
>>>
2
>>>
3
>>>
{1,
next(iterable)
next(iterable)
pprint(S.Naturals.intersect(Interval(0, 10)))
2, ..., 10}
Attributes
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
5.23.11 Naturals0
class sympy.sets.fancysets.Naturals0
Represents the whole numbers which are all the non-negative integers, inclusive of zero.
See Also:
Naturals (page 1324) positive integers; does not include 0
Integers (page 1325) also includes the negative integers
Attributes
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
5.23.12 Integers
class sympy.sets.fancysets.Integers
Represents all integers: positive, negative and zero. This set is also available as the
Singleton, S.Integers.
See Also:
Naturals0 (page 1325) non-negative integers
Integers (page 1325) positive and negative integers and zero
Examples
5.23. Sets
1325
Attributes
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
5.23.13 ImageSet
class sympy.sets.fancysets.ImageSet
Image of a set under a mathematical function
Examples
>>> from sympy import Symbol, S, ImageSet, FiniteSet, Lambda
>>> x = Symbol(x)
>>> N = S.Naturals
>>> squares = ImageSet(Lambda(x, x**2), N) # {x**2 for x in N}
>>> 4 in squares
True
>>> 5 in squares
False
>>> FiniteSet(0, 1, 2, 3, 4, 5, 6, 7, 9, 10).intersect(squares)
{1, 4, 9}
>>> square_iterable = iter(squares)
>>> for i in range(4):
...
next(square_iterable)
1
4
9
16
1326
Attributes
is
is
is
is
Complement
EmptySet
Intersection
UniversalSet
5.24 Simplify
5.24.1 simplify
sympy.simplify.simplify.simplify(expr, ratio=1.7, measure=<function count ops
at 0x9db2b54>, fu=False)
Simplies the given expression.
Simplication is not a well dened term and the exact strategies this function tries can
change in the future versions of SymPy. If your algorithm relies on simplication
(whatever it is), try to determine what you need exactly - is it powsimp()?, radsimp()?,
together()?, logcombine()?, or something else? And use this particular function directly,
because those are well dened and thus your algorithm will be robust.
Nonetheless, especially for interactive use, or when you dont know anything about the
structure of the expression, simplify() tries to apply intelligent heuristics to make the
input expression simpler. For example:
>>> from sympy import simplify, cos, sin
>>> from sympy.abc import x, y
>>> a = (x + x**2)/(x*sin(y)**2 + x*cos(y)**2)
>>> a
(x**2 + x)/(x*sin(y)**2 + x*cos(y)**2)
>>> simplify(a)
x + 1
Note that we could have obtained the same result by using specic simplication functions:
>>> from sympy import trigsimp, cancel
>>> trigsimp(a)
(x**2 + x)/x
>>> cancel(_)
x + 1
In some cases, applying simplify() (page 1327) may actually result in some more complicated expression. The default ratio=1.7 prevents more extreme cases: if (result
length)/(input length) > ratio, then input is returned unmodied. The measure parameter lets you specify the function used to determine how complex an expression is. The
function should take a single argument as an expression and return a number such that
if expression a is more complex than expression b, then measure(a) > measure(b). The
default measure function is count ops(), which returns the total number of operations
in the expression.
For example, if ratio=1, simplify output cant be longer than input.
>>> from sympy import sqrt, simplify, count_ops, oo
>>> root = 1/(sqrt(2)+3)
5.24. Simplify
1327
Since simplify(root) would result in a slightly longer expression, root is returned unchanged instead:
>>> simplify(root, ratio=1) == root
True
Note that the shortest expression is not necessary the simplest, so setting ratio to 1 may
not be a good idea. Heuristically, the default value ratio=1.7 seems like a reasonable
choice.
You can easily dene your own measure function based on what you feel should represent
the size or complexity of the input expression. Note that some choices, such as
lambda expr: len(str(expr)) may appear to be good metrics, but have other problems
(in this case, the measure function may slow down simplify too much for very large
expressions). If you dont know what a good metric would be, the default, count ops, is
a good one.
For example:
>>> from sympy import symbols, log
>>> a, b = symbols(a b, positive=True)
>>> g = log(a) + log(b) + log(a)*log(1/b)
>>> h = simplify(g)
>>> h
log(a*b**(-log(a) + 1))
>>> count_ops(g)
8
>>> count_ops(h)
5
So you can see that h is simpler than g using the count ops metric. However, we may not
like how simplify (in this case, using logcombine) has created the b**(log(1/a) + 1)
term. A simple way to reduce this would be to give more weight to powers as operations
in count ops. We can do this by using the visual=True option:
>>> print(count_ops(g, visual=True))
2*ADD + DIV + 4*LOG + MUL
>>> print(count_ops(h, visual=True))
2*LOG + MUL + POW + SUB
>>> from sympy import Symbol, S
>>> def my_measure(expr):
...
POW = Symbol(POW)
...
# Discourage powers by giving POW a weight of 10
...
count = count_ops(expr, visual=True).subs(POW, 10)
...
# Every other operation gets a weight of 1 (the default)
...
count = count.replace(Symbol, type(S.One))
...
return count
>>> my_measure(g)
8
>>> my_measure(h)
14
>>> 15./8 > 1.7 # 1.7 is the default ratio
True
1328
Note that because simplify() internally tries many dierent simplication strategies
and then compares them using the measure function, we get a completely dierent result
that is still dierent from the input expression by doing this.
5.24.2 collect
sympy.simplify.simplify.collect(expr, syms, func=None, evaluate=None,
act=False, distribute order term=True)
Collect additive terms of an expression.
ex-
This function collects additive terms of an expression with respect to a list of expression
up to powers with rational exponents. By the term symbol here are meant arbitrary
expressions, which can contain powers, products, sums etc. In other words symbol is a
pattern which will be searched for in the expressions terms.
The input expression is not expanded by collect() (page 1329), so user is expected
to provide an expression is an appropriate form. This makes collect() (page 1329)
more predictable as there is no magic happening behind the scenes. However, it is
important to note, that powers of products are converted to products of powers using
the expand power base() function.
There are two possible types of output. First, if evaluate ag is set, this function will
return an expression with collected terms or else it will return a dictionary with expressions up to rational powers as keys and collected coecients as values.
See Also:
collect const (page 1341), collect sqrt (page 1340), rcollect (page 1331)
Examples
>>> from sympy import S, collect, expand, factor, Wild
>>> from sympy.abc import a, b, c, x, y, z
You can also work with multivariate polynomials. However, remember that this function
is greedy so it will care only about a single symbol at time, in specication order:
5.24. Simplify
1329
It is also possible to work with symbolic powers, although it has more complicated behavior, because in this case powers base and symbolic part of the exponent are treated
as a single symbol:
>>> collect(a*x**c + b*x**c, x)
a*x**c + b*x**c
>>> collect(a*x**c + b*x**c, x**c)
x**c*(a + b)
However if you incorporate rationals to the exponents, then you will get well known
behavior:
>>> collect(a*x**(2*c) + b*x**(2*c), x**c)
x**(2*c)*(a + b)
Note also that all previously stated facts about collect() (page 1329) function apply to
the exponential function, so you can get:
>>> from sympy import exp
>>> collect(a*exp(2*x) + b*exp(2*x), exp(x))
(a + b)*exp(2*x)
If you are interested only in collecting specic powers of some symbols then set exact
ag in arguments:
>>> collect(a*x**7 + b*x**7, x, exact=True)
a*x**7 + b*x**7
>>> collect(a*x**7 + b*x**7, x**7, exact=True)
x**7*(a + b)
You can also apply this function to dierential equations, where derivatives of arbitrary
order can be collected. Note that if you collect with respect to a function or a derivative
of a function, all derivatives of that function will also be collected. Use exact=True to
prevent this from happening:
>>> from sympy import Derivative as D, collect, Function
>>> f = Function(f) (x)
>>> collect(a*D(f,x) + b*D(f,x), D(f,x))
(a + b)*Derivative(f(x), x)
1330
Or you can even match both derivative order and exponent at the same time:
>>> collect(a*D(D(f,x),x)**2 + b*D(D(f,x),x)**2, D(f,x))
(a + b)*Derivative(f(x), x, x)**2
Finally, you can apply a function to each of the collected coecients. For example you
can factorize symbolic coecients of polynomial:
>>> f = expand((x + a + 1)**3)
>>> collect(f, x, factor)
x**3 + 3*x**2*(a + 1) + 3*x*(a + 1)**2 + (a + 1)**3
Note: Arguments are expected to be in expanded form, so you might have to call
expand() prior to calling this function.
sympy.simplify.simplify.rcollect(expr, *vars)
Recursively collect sums in an expression.
See Also:
collect (page 1329), collect const (page 1341), collect sqrt (page 1340)
Examples
>>> from sympy.simplify import rcollect
>>> from sympy.abc import x, y
>>> expr = (x**2*y + x*y + x + y)/(x + y)
>>> rcollect(expr, y)
(x + y*(x**2 + x + 1))/(x + y)
5.24.3 separatevars
sympy.simplify.simplify.separatevars(expr, symbols=[], dict=False, force=False)
Separates variables in an expression, if possible. By default, it separates with respect to
all symbols in an expression and collects constant coecients that are independent of
symbols.
If dict=True then the separated terms will be returned in a dictionary keyed to their
corresponding symbols. By default, all symbols in the expression will appear as keys; if
symbols are provided, then all those symbols will be used as keys, and any terms in the
expression containing other symbols or non-symbols will be returned keyed to the string
5.24. Simplify
1331
coe. (Passing None for symbols will return the expression in a dictionary keyed to
coe.)
If force=True, then bases of powers will be separated regardless of assumptions on the
symbols involved.
Notes
The order of the factors is determined by Mul, so that the separated expressions may
not necessarily be grouped together.
Although factoring is necessary to separate variables in some expressions, it is not necessary in all cases, so one should not count on the returned factors being factored.
Examples
>>> from sympy.abc import x, y, z, alpha
>>> from sympy import separatevars, sin
>>> separatevars((x*y)**y)
(x*y)**y
>>> separatevars((x*y)**y, force=True)
x**y*y**y
>>> e = 2*x**2*z*sin(y)+2*z*x**2
>>> separatevars(e)
2*x**2*z*(sin(y) + 1)
>>> separatevars(e, symbols=(x, y), dict=True)
{coeff: 2*z, x: x**2, y: sin(y) + 1}
>>> separatevars(e, [x, y, alpha], dict=True)
{coeff: 2*z, alpha: 1, x: x**2, y: sin(y) + 1}
If the expression is not really separable, or is only partially separable, separatevars will
do the best it can to separate it by using factoring.
>>> separatevars(x + x*y - 3*x**2)
-x*(3*x - y - 1)
If the expression is not separable then expr is returned unchanged or (if dict=True) then
None is returned.
>>> eq = 2*x + y*sin(x)
>>> separatevars(eq) == eq
True
>>> separatevars(2*x + y*sin(x), symbols=(x, y), dict=True) == None
True
5.24.4 nthroot
sympy.simplify.simplify.nthroot(expr, n, max len=4, prec=15)
compute a real nth-root of a sum of surds
Parameters expr : sum of surds
n : integer
max len : maximum number of surds passed as constants to nsimplify
1332
Examples
>>> from sympy.simplify.simplify import nthroot
>>> from sympy import Rational, sqrt
>>> nthroot(90 + 34*sqrt(7), 3)
sqrt(7) + 3
Algorithm
First nsimplify is used to get a candidate root; if it is not a root the minimal polynomial
is computed; the answer is one of its roots.
5.24.6 radsimp
sympy.simplify.simplify.radsimp(expr, symbolic=True, max terms=4)
Rationalize the denominator by removing square roots.
Note: the expression returned from radsimp must be used with caution since if the denominator contains symbols, it will be possible to make substitutions that violate the assumptions of the simplication process: that for a denominator matching a + b*sqrt(c),
a != +/-b*sqrt(c). (If there are no symbols, this assumptions is made valid by collecting
terms of sqrt(c) so the match variable a does not contain sqrt(c).) If you do not want
the simplication to occur for symbolic denominators, set symbolic to False.
If there are more than max terms radical terms then the expression is returned unchanged.
Examples
>>>
>>>
>>>
>>>
from
from
from
from
5.24. Simplify
1333
No simplication beyond removal of the gcd is done. One might want to polish the result
a little, however, by collecting square root terms:
>>> r2 = sqrt(2)
>>> r5 = sqrt(5)
>>> ans = radsimp(1/(y*r2 + x*r2 + a*r5 + b*r5)); pprint(ans)
___
___
___
___
\/ 5 *a + \/ 5 *b - \/ 2 *x - \/ 2 *y
-----------------------------------------2
2
2
2
5*a + 10*a*b + 5*b - 2*x - 4*x*y - 2*y
>>> n, d = fraction(ans)
>>> pprint(factor_terms(signsimp(collect_sqrt(n))/d, radical=True))
___
___
\/ 5 *(a + b) - \/ 2 *(x + y)
-----------------------------------------2
2
2
2
5*a + 10*a*b + 5*b - 2*x - 4*x*y - 2*y
Results with symbols will not always be valid for all substitutions:
>>> eq = 1/(a + b*sqrt(c))
>>> eq.subs(a, b*sqrt(c))
1/(2*b*sqrt(c))
>>> radsimp(eq).subs(a, b*sqrt(c))
nan
If symbolic=False, symbolic denominators will not be transformed (but numeric denominators will still be processed):
>>> radsimp(eq, symbolic=False)
1/(a + b*sqrt(c))
5.24.7 ratsimp
sympy.simplify.simplify.ratsimp(expr)
Put an expression over a common denominator, cancel and reduce.
1334
Examples
>>> from sympy import ratsimp
>>> from sympy.abc import x, y
>>> ratsimp(1/x + 1/y)
(x + y)/(x*y)
5.24.8 fraction
sympy.simplify.simplify.fraction(expr, exact=False)
Returns a pair with expressions numerator and denominator. If the given expression is
not a fraction then this function will return the tuple (expr, 1).
This function will not make any attempt to simplify nested fractions or to do any term
rewriting at all.
If only one of the numerator/denominator pair is needed then use numer(expr) or denom(expr) functions respectively.
>>> from sympy import fraction, Rational, Symbol
>>> from sympy.abc import x, y
>>>
(x,
>>>
(x,
fraction(x/y)
y)
fraction(x)
1)
>>> fraction(1/y**2)
(1, y**2)
>>> fraction(x*y/2)
(x*y, 2)
>>> fraction(Rational(1, 2))
(1, 2)
If we know nothing about sign of some exponent and exact ag is unset, then structure
this exponents structure will be analyzed and pretty fraction will be returned:
>>> from sympy import exp
>>> fraction(2*x**(-y))
(2, x**y)
>>> fraction(exp(-x))
(1, exp(x))
>>> fraction(exp(-x), exact=True)
(exp(-x), 1)
5.24. Simplify
1335
5.24.9 trigsimp
sympy.simplify.simplify.trigsimp(expr, **opts)
reduces expression by using known trig identities
Notes
method: - Determine the method to use. Valid choices are matching (default), groebner, combined, and fu. If matching, simplify the expression recursively by targeting
common patterns. If groebner, apply an experimental groebner basis algorithm. In this
case further options are forwarded to trigsimp groebner, please refer to its docstring.
If combined, rst run the groebner basis algorithm with small default parameters, then
run the matching algorithm. fu runs the collection of trigonometric transformations
described by Fu, et al. (see the f u docstring).
Examples
>>>
>>>
>>>
>>>
2
5.24.10 besselsimp
sympy.simplify.simplify.besselsimp(expr)
Simplify bessel-type functions.
This routine tries to simplify bessel-type functions. Currently it only works on the Bessel J
and I functions, however. It works by looking at all such functions in turn, and eliminating
factors of I and -1 (actually their polar equivalents) in front of the argument. Then,
functions of half-integer order are rewritten using trigonometric functions and functions
of integer order (> 1) are rewritten using functions of low order. Finally, if the expression
was changed, compute factorization of the result with factor().
1336
5.24.11 powsimp
sympy.simplify.simplify.powsimp(expr, deep=False, combine=all, force=False,
measure=<function count ops at 0x9db2b54>)
reduces expression by combining powers with similar bases and exponents.
Notes
If deep is True then powsimp() will also simplify arguments of functions. By default deep
is set to False.
If force is True then bases will be combined without checking for assumptions, e.g.
sqrt(x)*sqrt(y) -> sqrt(x*y) which is not true if x and y are both negative.
You can make powsimp() only combine bases or only combine exponents by changing
combine=base or combine=exp. By default, combine=all, which does both. combine=base will only combine:
a
a
x * y =>
a
(x*y)
2x
as well as things like 2
=>
x
4
(a + b)
x
combine=exp will strictly only combine exponents in the way that used to be automatic.
Also use deep=True if you need the old behavior.
When combine=all, exp is evaluated rst. Consider the rst example below for when
there could be an ambiguity relating to this. This is done so things like the second
example can be completely combined. If you want base combined rst, do something
like powsimp(powsimp(expr, combine=base), combine=exp).
Examples
>>> from sympy import powsimp, exp, log, symbols
>>> from sympy.abc import x, y, z, n
>>> powsimp(x**y*x**z*y**z, combine=all)
x**(y + z)*y**z
>>> powsimp(x**y*x**z*y**z, combine=exp)
x**(y + z)*y**z
5.24. Simplify
1337
Two radicals are automatically joined through Mul: >>> a=sqrt(x*sqrt(y)) >>> a*a**3
== a**4 True
But if an integer power of that radical has been autoexpanded then Mul does not join the
resulting factors: >>> a**4 # auto expands to a Mul, no longer a Pow x**2*y >>> *a
# so Mul doesnt combine them x**2*y*sqrt(x*sqrt(y)) >>> powsimp( ) # but powsimp
will (x*sqrt(y))**(5/2) >>> powsimp(x*y*a) # but wont when doing so would violate
assumptions x*y*sqrt(x*sqrt(y))
5.24.12 combsimp
sympy.simplify.simplify.combsimp(expr)
Simplify combinatorial expressions.
This function takes as input an expression containing factorials, binomials, Pochhammer
symbol and other combinatorial functions, and tries to minimize the number of those
functions and reduce the size of their arguments. The result is be given in terms of
binomials and factorials.
The algorithm works by rewriting all combinatorial functions as expressions involving
rising factorials (Pochhammer symbols) and applies recurrence relations and other transformations applicable to rising factorials, to reduce their arguments, possibly letting the
resulting rising factorial to cancel. Rising factorials with the second argument being
an integer are expanded into polynomial forms and nally all other rising factorial are
rewritten in terms more familiar functions. If the initial expression contained any combinatorial functions, the result is expressed using binomial coecients and gamma functions. If the initial expression consisted of gamma functions alone, the result is expressed
in terms of gamma functions.
If the result is expressed using gamma functions, the following three additional steps
are performed:
1.Reduce the number of gammas
gamma(x)*gamma(1-x) == pi/sin(pi*x).
1338
by
applying
the
reection
theorem
theorem
3.Reduce the number of prefactors by absorbing them into gammas, where possible.
All transformation rules can be found (or was derived from) here:
1.http://functions.wolfram.com/GammaBetaErf/Pochhammer/17/01/02/
2.http://functions.wolfram.com/GammaBetaErf/Pochhammer/27/01/0005/
Examples
>>> from sympy.simplify import combsimp
>>> from sympy import factorial, binomial
>>> from sympy.abc import n, k
>>> combsimp(factorial(n)/factorial(n - 3))
n*(n - 2)*(n - 1)
>>> combsimp(binomial(n+1, k+1)/binomial(n, k))
(n + 1)/(k + 1)
5.24.13 hypersimp
sympy.simplify.simplify.hypersimp(f, k)
Given combinatorial term f(k) simplify its consecutive term ratio i.e. f(k+1)/f(k). The
input term can be composed of functions and integer sequences which have equivalent
representation in terms of gamma special function.
The algorithm performs three basic steps:
1.Rewrite all functions in terms of gamma, if possible.
2.Rewrite all occurrences of gamma in terms of products of gamma and rising factorial
with integer, absolute constant exponent.
3.Perform simplication of nested fractions, powers and if the resulting expression is
a quotient of polynomials, reduce their total degree.
If f(k) is hypergeometric then as result we arrive with a quotient of polynomials of minimal degree. Otherwise None is returned.
For more information on the implemented algorithm refer to:
1.W. Koepf, Algorithms for m-fold Hypergeometric Summation, Journal of Symbolic
Computation (1995) 20, 399-417
5.24.14 hypersimilar
sympy.simplify.simplify.hypersimilar(f, g, k)
Returns True if f and g are hyper-similar.
Similarity in hypergeometric sense means that a quotient of f(k) and g(k) is a rational
function in k. This procedure is useful in solving recurrence relations.
For more information see hypersimp().
5.24. Simplify
1339
5.24.15 nsimplify
sympy.simplify.simplify.nsimplify(expr,
constants=[],
tolerance=None,
full=False, rational=None)
Find a simple representation for a number or, if there are free symbols or if rational=True, then replace Floats with their Rational equivalents. If no change is made
and rational is not False then Floats will at least be converted to Rationals.
For numerical expressions, a simple formula that numerically matches the given numerical expression is sought (and the input should be possible to evalf to a precision of at
least 30 digits).
Optionally, a list of (rationally independent) constants to include in the formula may be
given.
A lower tolerance may be set to nd less exact matches. If no tolerance is given then the
least precise value will set the tolerance (e.g. Floats default to 15 digits of precision, so
would be tolerance=10**-15).
With full=True, a more extensive search is performed (this is useful to nd simpler numbers when the tolerance is set low).
See Also:
sympy.core.function.nfloat (page 181)
Examples
>>> from sympy import nsimplify, sqrt, GoldenRatio, exp, I, exp, pi
>>> nsimplify(4/(1+sqrt(5)), [GoldenRatio])
-2 + 2*GoldenRatio
>>> nsimplify((1/(exp(3*pi*I/5)+1)))
1/2 - I*sqrt(sqrt(5)/10 + 1/4)
>>> nsimplify(I**I, [pi])
exp(-pi/2)
>>> nsimplify(pi, tolerance=0.01)
22/7
1340
Examples
>>> from sympy import sqrt
>>> from sympy.simplify.simplify import collect_sqrt
>>> from sympy.abc import a, b
>>> r2, r3, r5 = [sqrt(i) for i in [2, 3, 5]]
>>> collect_sqrt(a*r2 + b*r2)
sqrt(2)*(a + b)
>>> collect_sqrt(a*r2 + b*r2 + a*r3 + b*r3)
sqrt(2)*(a + b) + sqrt(3)*(a + b)
>>> collect_sqrt(a*r2 + b*r2 + a*r3 + b*r5)
sqrt(3)*a + sqrt(5)*b + sqrt(2)*(a + b)
If evaluate is False then the arguments will be sorted and returned as a list and a count
of the number of sqrt-containing terms will be returned:
>>> collect_sqrt(a*r2 + b*r2 + a*r3 + b*r5, evaluate=False)
((sqrt(3)*a, sqrt(5)*b, sqrt(2)*(a + b)), 3)
>>> collect_sqrt(a*sqrt(2) + b, evaluate=False)
((b, sqrt(2)*a), 1)
>>> collect_sqrt(a + b, evaluate=False)
((a + b,), 0)
5.24. Simplify
1341
>>> collect_const(x - y - z)
x - (y + z)
>>> collect_const(-y - z)
-(y + z)
>>> collect_const(2*x - 2*y - 2*z, 2)
2*(x - y - z)
>>> collect_const(2*x - 2*y - 2*z, -2)
2*x - 2*(y + z)
5.24.18 posify
sympy.simplify.simplify.posify(eq)
Return eq (with generic symbols made positive) and a restore dictionary.
Any symbol that has positive=None will be replaced with a positive dummy symbol having the same name. This replacement will allow more symbolic processing of expressions, especially those involving powers and logarithms.
A dictionary that can be sent to subs to restore eq to its original symbols is also returned.
>>>
>>>
>>>
(_x
5.24.19 powdenest
sympy.simplify.simplify.powdenest(eq, force=False, polar=False)
Collect exponents on powers as assumptions allow.
Given (bb**be)**e, this can be simplied as follows:
if bb is positive, or
e is an integer, or
|be| < 1 then this simplies to bb**(be*e)
Given a product of powers raised to a power, (bb1**be1 * bb2**be2...)**e, simplication can be done as follows:
if e is positive, the gcd of all bei can be joined with e;
all non-negative bb can be separated from those that are negative and their gcd can
be joined with e; autosimplication already handles this separation.
integer factors from powers that have integers in the denominator of the exponent
can be removed from any term and the gcd of such integers can be joined with e
1342
Setting force to True will make symbols that are not explicitly negative behave as though
they are positive, resulting in more denesting.
Setting polar to True will do simplications on the Riemann surface of the logarithm,
also resulting in more denestings.
When there are sums of logs in exp() then a product of powers may be obtained e.g.
exp(3*(log(a) + 2*log(b))) - > a**3*b**6.
Examples
>>> from sympy.abc import a, b, x, y, z
>>> from sympy import Symbol, exp, log, sqrt, symbols, powdenest
>>> powdenest((x**(2*a/3))**(3*x))
(x**(2*a/3))**(3*x)
>>> powdenest(exp(3*x*log(2)))
2**(3*x)
But exp() will be denested by moving all non-log terms outside of the function; this may
result in the collapsing of the exp to a power with a dierent base:
>>> powdenest(exp(3*y*log(x)))
x**(3*y)
>>> powdenest(exp(y*(log(a) + log(b))))
(a*b)**y
>>> powdenest(exp(3*(log(a) + log(b))))
a**3*b**3
5.24. Simplify
1343
5.24.20 logcombine
sympy.simplify.simplify.logcombine(expr, force=False)
Takes logarithms and combines them using the following rules:
log(x) + log(y) == log(x*y) if both are not negative
a*log(x) == log(x**a) if x is positive and a is real
If force is True then the assumptions above will be assumed to hold if there is no assumption already in place on a quantity. For example, if a is imaginary or the argument
negative, force will not perform a combination but if a is a symbol with no assumptions
the change will take place.
See Also:
posify (page 1342) replace all symbols with symbols having positive assumptions
Examples
>>> from sympy import Symbol, symbols, log, logcombine, I
>>> from sympy.abc import a, x, y, z
>>> logcombine(a*log(x) + log(y) - log(z))
a*log(x) + log(y) - log(z)
>>> logcombine(a*log(x) + log(y) - log(z), force=True)
log(x**a*y/z)
>>> x,y,z = symbols(x,y,z, positive=True)
>>> a = Symbol(a, real=True)
>>> logcombine(a*log(x) + log(y) - log(z))
log(x**a*y/z)
The transformation is limited to factors and/or terms that contain logs, so the result
depends on the initial state of expansion:
>>> eq = (2 + 3*I)*log(x)
>>> logcombine(eq, force=True) == eq
True
>>> logcombine(eq.expand(), force=True)
log(x**2) + I*log(x**3)
See Also:
sympy.solvers.solvers.unrad
References
[1] http://researcher.watson.ibm.com/researcher/les/us-fagin/symb85.pdf
[2] D. J. Jerey and A. D. Rich, Symplifying Square Roots of Square Roots by Denesting
(available at http://www.cybertester.com/data/denest.pdf)
Examples
>>> from sympy.simplify.sqrtdenest import sqrtdenest
>>> from sympy import sqrt
>>> sqrtdenest(sqrt(5 + 2 * sqrt(6)))
sqrt(2) + sqrt(3)
1345
tree cse
sympy.simplify.cse main.tree cse(exprs,
symbols,
opt subs=None,
der=canonical)
Perform raw CSE on expression tree, taking opt subs into account.
or-
1346
5.24. Simplify
1347
literal
number
type
attribute
all
slice
range
query
selector
path
::=
::=
::=
::=
::=
::=
::=
::=
::=
::=
select(expr)
Retrieve parts of an expression selected by a path.
Examples
>>> from sympy.simplify.epathtools import EPath
>>> from sympy import sin, cos, E
>>> from sympy.abc import x, y, z, t
>>> path = EPath(/*/[0]/Symbol)
>>> expr = [((x, 1), 2), ((3, y), z)]
>>> path.select(expr)
[x, y]
>>> path = EPath(/*/*/Symbol)
>>> expr = t + sin(x + 1) + cos(x + y + E)
1348
>>> path.select(expr)
[x, x, y]
epath
sympy.simplify.epathtools.epath(path, expr=None,
kwargs=None)
Manipulate parts of an expression selected by a path.
func=None,
args=None,
This function allows to manipulate large nested expressions in single line of code, utilizing techniques to those applied in XML processing standards (e.g. XPath).
If func is None, epath() (page 1349) retrieves elements selected by the path. Otherwise
it applies func to each matching element.
Note that it is more ecient to create an EPath object and use the select and apply
methods of that object, since this will compile the path string only once. This function
should only be used as a convenient shortcut for interactive use.
This is the supported syntax:
select all: /* Equivalent of for arg in args:.
select slice: /[0] or /[1:5] or /[1:5:2] Supports standard Pythons slice syntax.
select by type: /list or /list|tuple Emulates isinstance().
select by attribute: / iter ? Emulates hasattr().
5.24. Simplify
1349
epath(path, expr)
x, y]
epath(path, expr, lambda expr: 2*expr)
sin(2*x + 1) + cos(2*x + 2*y + E)
(a1 )n . . . (ap )n z n
a1 , . . . , ap
.
z
=
p Fq
b1 , . . . , bq
(b1 )n . . . (bq )n n!
n=0
It turns out that there are certain dierential operators that can change the ap and pq parameters by integers. If a sequence of such operators is known that converts the set of indices
a0r and b0s into ap and bq , then we shall say the pair ap , bq is reachable from a0r , b0s . Our general
strategy is thus as follows: given a set ap , bq of parameters, try to look up an origin a0r , b0s for
which we know an expression, and then apply the sequence of dierential operators to the
known expression to nd an expression for the Hypergeometric function we are interested
in.
Notation
In the following, the symbol a will always denote a numerator parameter and the symbol b
will always denote a denominator parameter. The subscripts p, q, r, s denote vectors of that
length, so e.g. ap denotes a vector of p numerator parameters. The subscripts i and j denote
running indices, so they should usually be used in conjuction with a for all i. E.g. ai < 4
for all i. Uppercase subscripts I and J denote a chosen, xed index. So for example aI > 0 is
true if the inequality holds for the one index I we are currently interested in.
1350
z d
ai dz
(
+ 1. It is then easy to show that A(ai )p Fq
ap
= p Fq
bq z
d
z
bj 1 dz + 1
ap +ei
bq z
and nd
where ei is the i-th unit vector. Similarly for bj 6= 1 we set B(bj ) =
)
( )
(
p
B(bj )p Fq abqp z = p Fq bqae
z . Thus we can increment upper and decrement lower indices
i
at will, as long as we dont go through zero. The A(ai ) and B(bj ) are called shift operators.
)
( )
(
a1 ...ap
ap
ap +1
d
It is also easy to show that dz
p Fq bq z = b1 ...bq p Fq bq +1 z , where ap +1 is the vector a1 +1, a2 +
1, . . . and similarly for bq + 1. Combining this[ with the shift operators, we arrive at] one(form
) of
q
p
a1 ...ap
ap
d
the Hypergeometric dierential equation: dz j=1 B(bj ) (b1 1)...(bq 1) i=1 A(ai ) p Fq bq z =
0. This holds if all shift operators are dened, i.e. if no ai = 0 and no bj = 1.
Clearing
denominators
multiplying)]through
[
) z we arrive at the following equation:
) and
( by
q ( d
p ( d
ap
d
z dz j=1 z dz + bj 1 z i=1 z dz + ai p Fq bq z = 0. Even though our derivation does not
show it, it can be checked that this equation holds whenever the p Fq is dened.
d
Notice that, under suitable conditions on aI , bJ , each of the operators A(ai ), B(bj ) and z dz
can be expressed in terms of A(aI ) or B(bJ ). Our
) aim is to write the Hypergeometric
( next
ap
dierential equation as follows: [XA(aI ) r]p Fq bq z = 0, for some operator X and some
)
(
( )
ap +eI
constant r to be determined. If r 6= 0, then we can write this as 1
= p Fq abqp z ,
r X p Fq
bq z
and so
1
r X
d
Now A(aI ) exists if aI 6= 0, and then z dz
= aI A(aI ) a)I . Observe
also
that ))
all the operators
(
(
p ( d
p
d
d
aI A(aI ), so this
A(ai ), B(bj ) and z dz commute. We have i=1 z dz + ai =
i=1,i6=I z dz + ai
1
=
(a
A(a
)
a
)
j
I
I
I
j=1
j=1 (aI A(aI ) aI + bj 1). Since the rst half had no
dz
q
constant term, we infer r = aI j=1 (bj 1 aI ).
This tells us under which conditions we can un-shift A(aI ), namely when aI 6= 0 and r 6= 0.
Substituting aI 1 for aI then tells us under what conditions we can decrement the index aI .
Doing a similar analysis for B(aJ ), we arrive at the following rules:
An index aI can be decremented if aI 6= 1 and aI 6= bj for all bj .
An index bJ can be incremented if bJ 6= 1 and bJ 6= ai for all ai .
Combined with the conditions (stated above) for the existence of shift operators, we have thus
established the rules of the game!
Reduction of Order
(
Notice that, quite trivially, if aI = bJ , we have p Fq
ap
bq z
(
=
p1 Fq1
a
p
z
b
q
, where ap means ap
d k n
) z
(z dz
(aI )n
(bJ )n
is actually a
k n
1351
The above reasoning shows that ap , bq is reachable from a0p , b0q if and only if the invariants
r , r , all agree. Thus in particular being reachable from is a symmetric relation on suitable
parameters without zeros.
Applying the Operators
If all goes well then for a given set of parameters we nd an origin in our database for which
we have a nice formula. We now have to apply (potentially) many dierential operators to it. If
we do this blindly then the result will be very messy. This is because with Hypergeometric type
functions, the derivative is usually expressed as a sum of two contiguous functions. Hence
if we compute N derivatives, then the answer will involve 2N contiguous functions! This is
clearly undesirable. In fact we know from the Hypergeometric dierential equation that we
need at most max(p, q + 1) contiguous functions to express all derivatives.
Hence instead of dierentiating blindly, we will work with a C(z)-module basis: for an origin
a0r , b0s we either store (for particularly pretty answers) or compute a set of N functions (typically N = max(r, s + 1)) with the property that the derivative of any of them is a C(z)-linear
combination of them. In formulae, we store a vector B of N functions, a matrix M and a vector
C (the latter two with entries in C(z)), with the following properties:
1352
r Fs
a0r
b0s z
= CB
d
z dz
B = M B.
Then we can compute as many derivatives as we want and we will always end up with C(z)linear combination of at most N special functions.
As hinted above, B, M and C can either all be stored (for particularly pretty answers) or
computed from a single p Fq formula.
Loose Ends
This describes the bulk of the hypergeometric function algorithm. There a few further tricks,
described in the hyperexpand.py source le. The extension to Meijer G-functions is also described there.
1
j=1 (1 aj + s)
j=1 (bj s)
G(z) =
z s ds,
2i L qj=m+1 (1 bj + s) pj=n+1 (aj s)
where L is a contour starting and ending at +, enclosing all of the poles of (bj s) for
j = 1, . . . , n once in the negative direction, and no other poles. Also the integral is assumed
absolutely convergent.
In what follows, for any complex numbers a, b, we write a b (mod 1) if and only if there
exists an integer k such that a b = k. Thus there are double poles i ai aj (mod 1) for some
i 6= j n.
We now assume that whenever bj ai (mod 1) for i m, j > n then bj < ai . This means that
no quotient of the relevant gamma functions is a polynomial, and can always be achieved by
reduction of order. Fix a complex number c such that {bi |bi c (mod 1), i m} is not empty.
Enumerate this set as b, b + k1 , . . . , b + ku , with ki non-negative integers. Enumerate similarly
{aj |aj c (mod 1), j > n} as b + l1 , . . . , b + lv . Then li > kj for all i, j. For nite conuence, we
need to assume v u for all such c.
Let c1 , . . . , cw be distinct (mod 1) and exhaust the congruence classes of the bi . I claim
G(z) =
1353
where Fj (z) is a hypergeometric function and Rj (z) is a nite sum, both to be specied later.
Indeed corresponding to every cj there is a sequence of poles, at mostly nitely many of them
multiple poles. This is where the j-th term comes from.
Hence x again c, enumerate the relevant bi as b, b + k1 , . . . , b + ku . We will look at the aj
corresponding to a + l1 , . . . , a + lu . The other ai are not treated specially. The corresponding
gamma functions have poles at (potentially) s = b + r for r = 0, 1, . . . . For r lu , pole of the
integrand is simple. We thus set
R(z) =
l
u 1
ress=r+b .
r=0
(bj lu b)
,
(1)t (lu + b + 1 bj )t
(1 aj + lu + b + t) = (1 aj + lu + b)(1 aj + lu + b)t
and
ress=b+lu +t (b s) =
Hence
ress=b+lu +t
(1)lu +t
(1)lu (1)t
=
.
(lu + t)!
lu ! (lu + 1)t
m
n
u
(1)i
(1)lu
j=1 (bj lu b)
j=1 (1 aj + lu + b)
p
=z
q
lu ! i=1 (lu ki + 1)i j=n+1 (aj lu b) j=m+1 (1 bj + lu + b)
n
p
u
t
t
(lu li + 1)t j=1 (1 aj + lu + b)t j=n+1 (1) (lu + b + 1 aj )t
t (1)
m
z
,
q
(lu + 1)t i=1 (lu ki + 1)t j=1 (1)t (lu + b + 1 bj )t j=m+1 (1 bj + lu + b)t
b+lu
)
1, (1 + lu li ), (1 + lu + b ai )
pmn
(1)
z
,
1 + lu , (1 + lu ki ), (1 + lu + b bi )
where C designates the factor in the residue independent of t. (This result can also be written
in slightly simpler form by converting all the lu etc back to a b , but doing so is going to
require more notation still and is not helpful for computation.)
1354
nz
the well-known formula 0 (a)
= (1 z)a is declared by the following line: add((-a, ),
n!
(), (1-z)**a).
From the information provided, the matrices B, C and M will be computed, and the
formula is now available when expanding hypergeometric functions.
Next the test
le sympy/simplify/tests/test hyperexpand.py should be run, in particular the test
test formulae(). This will test the newly added formula numerically. If it fails, there is
(presumably) a typo in what was entered.
Since all newly-added formulae are probably relatively complicated, chances are that the
automatically computed basis is rather suboptimal (there is no good way of testing this, other
than observing very messy output). In this case the matrices B, C and M should be computed
by hand. Then the helper addb can be used to declare a hypergeometric formula with handcomputed basis.
An example
Because this explanation so far might be very theoretical and dicult to understand, we walk
through an explicit example now. We take the Fresnel function C(z) which obeys the following
hypergeometric representation:
( 1
)
2 z4
4
C(z) = z 1 F2 1 5
.
16
2, 4
First we try to add this formula to the lookup table by using the (simpler) function add(ap,
bq, res). The rst two arguments are simply the lists containing the parameter sets of 1 F2 .
The res argument is a little bit more complicated. We only know C(z) in terms of 1 F2 (. . . |f (z))
with f a function of z, in our case
f (z) =
2 z4
.
16
What we need is a formula where the hypergeometric function has only z as argument
We introduce the new complex symbol w and search for a function g(w) such that
1 F2 (. . . |z).
f (g(w)) = w
holds. Then we can replace every z in C(z) by g(w). In the case of our example the function g
could look like
( )
1
i
2
w4 .
g(w) = exp
4
1355
We get these functions mainly by guessing and testing the result. Hence we proceed by
computing f (g(w)) (and simplifying naively)
f (g(w)) =
=
=
2 g(w)4
16
(
( ) 1 )4
2
4
g 2 exp i
4 w
4
2 24
16
( )4 1 4
exp i
w4
4
16
= exp (i) w
=w
and indeed get back w. (In case of branched functions we have to be aware of branch cuts. In
that case we take w to be a positive real number and check the formula. If what we have found
works for positive w, then just replace exp() inside any branched function by exp polar()
and what we get is right for all w.) Hence we can write the formula as
( 1 )
C(g(w)) = g(w) 1 F2 1 4 5 w .
2, 4
and trivially
(
1 F2
)
C
C(g(w))
=
1 5 w =
g(w)
2, 4
1
4
( ) 1)
4
exp i
4 w
( i ) 1
exp 4 w 4
which is exactly what is needed for the third paramenter, res, in add. Finally, the whole
function call to add this rule to the table looks like:
add([S(1)/4],
[S(1)/2, S(5)/4],
fresnelc(exp(pi*I/4)*root(z,4)*2/sqrt(pi)) / (exp(pi*I/4)*root(z,4)*2/sqrt(pi))
)
Using this rule we will nd that it works but the results are not really nice in terms of simplicity
and number of special function instances included. We can obtain much better results by
adding the formula to the lookup table in another way. For this we use the (more complicated)
function addb(ap, bq, B, C, M). The rst two arguments are again the lists containing the
parameter sets of 1 F2 . The remaining three are the matrices mentioned earlier on this page.
We know that the n = max (p, q + 1)-th derivative can be expressed as a linear combination of
lower order derivatives. The matrix B contains the basis {B0 , B1 , . . .} and is of shape n 1. The
best way to get Bi is to take the rst n = max(p, q + 1) derivatives of the expression for p Fq
and take out usefull pieces. In our case we nd that n = max (1, 2 + 1) = 3. For computing the
d
. The rst basis element B0 is set to the expression
derivatives, we have to use the operator z dz
for 1 F2 from above:
(
( ) 1)
) ( 2
exp z 4
exp
C
4
4
B0 =
1
2z 4
d
B0 . For this we can directly use SymPy!
Next we compute z dz
1356
>>> from sympy import Symbol, sqrt, exp, I, pi, fresnelc, root, diff, expand
>>> z = Symbol(z)
>>> B0 = sqrt(pi)*exp(-I*pi/4)*fresnelc(2*root(z,4)*exp(I*pi/4)/sqrt(pi))/\
...
(2*root(z,4))
>>> z * diff(B0, z)
z*(cosh(2*sqrt(z))/(4*z) - sqrt(pi)*exp(-I*pi/4)*fresnelc(2*z**(1/4)*exp(I*pi/4)/sqrt(pi))/(8*z**(5/4
>>> expand(_)
cosh(2*sqrt(z))/4 - sqrt(pi)*exp(-I*pi/4)*fresnelc(2*z**(1/4)*exp(I*pi/4)/sqrt(pi))/(8*z**(1/4))
( ) ( 2
( ) 1)
exp z 4
exp
C
4
4
1
2z
1
4
( )
1
cosh 2 z
4
>>> from sympy import (Symbol, cosh, sqrt, pi, exp, I, fresnelc, root,
...
diff, expand)
>>> z = Symbol(z)
>>> B1prime = cosh(2*sqrt(z))/4 - sqrt(pi)*exp(-I*pi/4)*\
...
fresnelc(2*root(z,4)*exp(I*pi/4)/sqrt(pi))/(8*root(z,4))
>>> z * diff(B1prime, z)
z*(-cosh(2*sqrt(z))/(16*z) + sinh(2*sqrt(z))/(4*sqrt(z)) + sqrt(pi)*exp(-I*pi/4)*fresnelc(2*z**(1/4)*
>>> expand(_)
sqrt(z)*sinh(2*sqrt(z))/4 - cosh(2*sqrt(z))/16 + sqrt(pi)*exp(-I*pi/4)*fresnelc(2*z**(1/4)*exp(I*pi/4
B20 =
1
16
(
) ( 2
( ) 1)
exp z 4
exp
C
4
4
2z
1
4
( ) 1
( )
1
cosh 2 z + sinh 2 z z
16
4
We see the common pattern and can collect the pieces. Hence it makes sense to choose B1
and B2 as follows
(
1)
2 exp( )z 4
exp(
4 )C
4
B0
1
2z 4
B = B1 =
cosh (2
z)
B2
sinh (2 z) z
(This is in contrast to the basis B = (B0 , B10 , B20 ) that would have been computed automatically
if we used just add(ap, bq, res).)
Because it must hold that p Fq ( |z) = CB the entries of C are obviously
1
C = 0
0
d
Finally we have to compute the entries of the 3 3 matrix M such that z dz
B = M B holds. This
d
is easy. We already computed the rst part z dz B0 above. This gives us the rst row of M . For
the second row we have:
1357
4 4 0
0 1
M = 0
0
z 21
Note that the entries of C and M should typically be rational functions in z, with rational
coecients. This is all we need to do in order to add a new formula to the lookup table for
hyperexpand.
1 F0
2 F1
(
a, a
2a
2 F1
1
2 z
1358
= 22a1
(
)2a+1
z + 1 + 1
( )
1
1, 1
z = log (z + 1)
2
z
(1
2 F1
( )
az = (z + 1)a
2 , 1z
3
2
( )
1
= atanh z
z
(1
1
2 , 2 z
3
2
2 F1
2 F1
( )
1
= asin z
z
)
(
)2a 1 (
)2a
1 (
a, a + 21
z+1
+
z+1
1
z = 2
2
2
)
(
(
( ))
a, a
= cos 2a asin z
2 F1
1 z
2
(
2 F1
asin ( z)
1, 1
=
3 z
z z + 1
2
(1
2 F1
2 F1
3 F2
1
2 , 2 z
2K (z)
( 1 1 )
2E (z)
2 , 2
z =
1
)
( 1
( ) 2
2 z
1
2 , 1, 1
z
=
atanh z +
log (z + 1)
1
,
2
3
3
3z
2
) (
)
(
)
( 1
4 16
4
1
1
16
2 , 1, 1
z =
z + 1 +
log
z + 1 +
+
3 F2
2, 2
9 9z
3z
2
2
9z
( )
1
z = z b+1 (b 1) ez (b 1, z)
1 F1
b
)
)
(z ) (
1
a
a 12 a+ 12 z2
a+
z
e Ia 12
z =4
2a
2
2
(
1 F1
(
1 F1
)
)
(
)a (
a
a, zei
z = a zei
a+1
1359
1 F1
( 1 )
( )
2
= zi erf zi + ez
1 z
2
(
1 F2
) i (
(
)
(
))
( )
( )
e 4
2 4 z i
2 4 z i
1
4
4
i sinh 2 z S
e
+ cosh 2 z C
e
=
3 5 z
24z
4, 4
(
2 F2
(
)a
)
ai z1
( ) a zei
(
)
z
=
erf
zi
a, zei
3
2a 1
2a 1
2, a + 1
1
2, a
2 F2
( )
1
1, 1
z = ( log (z) + Ei (z))
2, 2
z
z
0 F1
( )
( )
= cosh 2 z
1 z
2
0 F1
)
( )
( ))
1 (
a
= 22a z 2 + 4 I2a1 4 4 z + J2a1 4 4 z (2a)
1 z
(
0 F3
1
2 , a, a
(
0 F3
) (
)2a+1
( i )
( i )
4
4
z = 2 ze i
2
4
I
2
2
ze
J
2 (2a)
2a1
2a1 2 2 ze 4
)
) (
)
)
(
(
( )
( )
( ) 2
1
1
1
a1 a+1
a 12 a+ 12 2
3
1
z
I
z
=
2
4
z
I
a
+
4
z
I
z
a
+
1
a 2
a 2
a 2
a 21 , 2a
2
2
2
(
1 F2
a, a + 12 , 2a
( )
( )
z = z 2b + 12 Ib1 2 z (b)
b
z = Ib+1 ( z) Ib1 ( z) (b + 1)
b, b + 2
sin (b)
(
1 F2
1
2
(
1 F2
1360
)
( )
1
= Shi 2 z
3 3 z
2 z
2, 2
1
2
)
(
)
3 3 i
2 4 z i
4 S
4
e
z
=
e
3 7
3
4z 4
2, 4
(
1 F2
3
4
) i (
)
2 4 z i
e 4
4
C e
=
1 5 z
24z
2, 4
1
4
) ( )2a+1
( )
( )
z
a, a + 12
z =
I2ab
z Ib1
z (b)(2a b + 1)
2a, b, 2a b + 1
2
(
2 F3
)
( )
( ))
1(
1, 1
=
log 2 z + Chi 2 z
3 z
2, 2, 2
z
z
(
2 F3
)
a
a (z)
a
aez
1, 1, a
z
=
((a)
(a,
z))
+
(a
+
1)
(log
(z)
+
E
(z)
+
)
+
1
2
2, 2, a + 1
z (a2 2a + 1)
z (a2 2a + 1) z
(a 1)
(
3 F3
5.25.5 References
5.26 Stats
SymPy statistics module
Introduces a random variable type into the SymPy language.
Random variables may be declared using prebuilt functions such as Normal, Exponential,
Coin, Die, etc... or built with functions like FiniteRV.
Queries on random expressions can be made using the functions
Expression
P(condition)
E(expression)
variance(expression)
density(expression)
sample(expression)
where(condition)
Meaning
Probability
Expected value
Variance
Probability Density Function
Produce a realization
Where the condition is true
5.26.1 Examples
>>>
>>>
>>>
>>>
>>>
5.26. Stats
1361
1/2
>>> E(X+Y) # Expectation of the sum of two dice
7
>>> variance(X+Y) # Variance of the sum of two dice
35/6
>>> simplify(P(Z>1)) # Probability of Z being greater than 1
-erf(sqrt(2)/2)/2 + 1/2
sympy.stats.Die(name, sides=6)
Create a Finite Random Variable representing a fair die.
Returns a RandomSymbol.
>>> from sympy.stats import Die, density
>>> D6 = Die(D6, 6) # Six sided Die
>>> density(D6).dict
{1: 1/6, 2: 1/6, 3: 1/6, 4: 1/6, 5: 1/6, 6: 1/6}
>>> D4 = Die(D4, 4) # Four sided Die
>>> density(D4).dict
{1: 1/4, 2: 1/4, 3: 1/4, 4: 1/4}
1362
sympy.stats.Coin(name, p=1/2)
Create a Finite Random Variable representing a Coin toss.
Probability p is the chance of gettings Heads. Half by default
Returns a RandomSymbol.
>>> from sympy.stats import Coin, density
>>> from sympy import Rational
>>> C = Coin(C) # A fair coin toss
>>> density(C).dict
{H: 1/2, T: 1/2}
>>> C2 = Coin(C2, Rational(3, 5)) # An unfair coin
>>> density(C2).dict
{H: 3/5, T: 2/5}
sympy.stats.Hypergeometric(name, N, m, n)
Create a Finite Random Variable representing a hypergeometric distribution.
Returns a RandomSymbol.
Examples
>>> from sympy.stats import Hypergeometric, density
>>> from sympy import S
>>> X = Hypergeometric(X, 10, 5, 3) # 10 marbles, 5 white (success), 3 draws
>>> density(X).dict
{0: 1/12, 1: 5/12, 2: 5/12, 3: 1/12}
sympy.stats.FiniteRV(name, density)
Create a Finite Random Variable given a dict representing the density.
5.26. Stats
1363
Returns a RandomSymbol.
>>> from sympy.stats import FiniteRV, P, E
>>> density = {0: .1, 1: .2, 2: .3, 3: .4}
>>> X = FiniteRV(X, density)
>>> E(X)
2.00000000000000
>>> P(X>=2)
0.700000000000000
Discrete Types
sympy.stats.Geometric(name, p)
Create a discrete random variable with a Geometric distribution.
The density of the Geometric distribution is given by
f (k) := p(1 p)k1
sympy.stats.Poisson(name, lamda)
Create a discrete random variable with a Poisson distribution.
1364
k e
k!
Continuous Types
sympy.stats.Arcsin(name, a=0, b=1)
Create a Continuous Random Variable with an arcsin distribution.
The density of the arcsin distribution is given by
f (x) :=
(x a)(b x)
1365
Examples
>>> from sympy.stats import Arcsin, density
>>> from sympy import Symbol, simplify
>>> a = Symbol(a, real=True)
>>> b = Symbol(b, real=True)
>>> z = Symbol(z)
>>> X = Arcsin(x, a, b)
>>> density(X)(z)
1/(pi*sqrt((-a + z)*(b - z)))
1366
2/ z \
|-----|
\sigma/
f (x) :=
x1 (1 + x)
B(, )
with x > 0.
5.26. Stats
1367
1368
>>> x0 = Symbol(x0)
>>> gamma = Symbol(gamma, positive=True)
>>> z = Symbol(z)
>>> X = Cauchy(x, x0, gamma)
>>> density(X)(z)
1/(pi*gamma*(1 + (-x0 + z)**2/gamma**2))
sympy.stats.Chi(name, k)
Create a continuous random variable with a Chi distribution.
The density of the Chi distribution is given by
f (x) :=
21k/2 xk1 ex
(k/2)
/2
with x 0.
Parameters k : A positive Integer, k > 0, the number of degrees of freedom
Returns A RandomSymbol. :
References
sympy.stats.ChiNoncentral(name, k, l)
Create a continuous random variable with a non-central Chi distribution.
The density of the non-central Chi distribution is given by
e(x + )/2 xk
f (x) :=
Ik/21 (x)
(x)k/2
2
with x 0. Here, I (x) is the modied Bessel function of the rst kind (page 410).
Parameters k : A positive Integer, k > 0, the number of degrees of freedom
l : Shift parameter
Returns A RandomSymbol. :
5.26. Stats
1369
References
sympy.stats.ChiSquared(name, k)
Create a continuous random variable with a Chi-squared distribution.
The density of the Chi-squared distribution is given by
f (x) :=
x
k
1
( k ) x 2 1 e 2
2 2
k
2
with x 0.
Parameters k : A positive Integer, k > 0, the number of degrees of freedom
Returns A RandomSymbol. :
References
1370
>>> simplify(expand_func(variance(X)))
2*k
sympy.stats.Dagum(name, p, a, b)
Create a continuous random variable with a Dagum distribution.
The density of the Dagum distribution is given by
(
)
( x )ap
ap
b
f (x) :=
x (( x )a + 1)p+1
b
with x > 0.
Parameters p : Real number, p > 0, a shape
a : Real number, a > 0, a shape
b : Real number, b > 0, a scale
Returns A RandomSymbol. :
References
p
b
a
z
=
=
=
=
Symbol(p, positive=True)
Symbol(b, positive=True)
Symbol(a, positive=True)
Symbol(z)
>>> X = Dagum(x, p, a, b)
>>> density(X)(z)
a*p*(z/b)**(a*p)*((z/b)**a + 1)**(-p - 1)/z
sympy.stats.Erlang(name, k, l)
Create a continuous random variable with an Erlang distribution.
The density of the Erlang distribution is given by
f (x) :=
k xk1 ex
(k 1)!
with x [0, ].
Parameters k : Integer
l : Real number, > 0, the rate
Returns A RandomSymbol. :
5.26. Stats
1371
References
sympy.stats.Exponential(name, rate)
Create a continuous random variable with an Exponential distribution.
The density of the exponential distribution is given by
f (x) := exp(x)
1372
Examples
>>> from sympy.stats import Exponential, density, cdf, E
>>> from sympy.stats import variance, std, skewness
>>> from sympy import Symbol
>>> l = Symbol(lambda, positive=True)
>>> z = Symbol(z)
>>> X = Exponential(x, l)
>>> density(X)(z)
lambda*exp(-lambda*z)
>>> cdf(X)(z)
Piecewise((1 - exp(-lambda*z), z >= 0), (0, True))
>>> E(X)
1/lambda
>>> variance(X)
lambda**(-2)
>>> skewness(X)
2
>>> X = Exponential(x, 10)
>>> density(X)(z)
10*exp(-10*z)
>>> E(X)
1/10
>>> std(X)
1/10
f (x) :=
(d1 x)d1 d2 2
(d1 x+d2 )d1 +d2
xB
( d1
2
, d22
with x > 0.
Parameters d1 : d1 > 0 a parameter
d2 : d2 > 0 a parameter
Returns A RandomSymbol. :
5.26. Stats
1373
References
f (x) :=
2d11 d22
ed 1 z
B(d1 /2, d2 /2) (d1 e2z + d2 )(d1 +d2 )/2
1374
xm
s
)1
e(
xm
s )
with x m.
Parameters a : Real number, a (0, ) the shape
s : Real number, s (0, ) the scale
m : Real number, m (, ) the minimum
Returns A RandomSymbol. :
References
a
s
m
z
=
=
=
=
Symbol(a, positive=True)
Symbol(s, positive=True)
Symbol(m, real=True)
Symbol(z)
>>> X = Frechet(x, a, s, m)
>>> density(X)(z)
a*((-m + z)/s)**(-a - 1)*exp(-((-m + z)/s)**(-a))/s
sympy.stats.Gamma(name, k, theta)
Create a continuous random variable with a Gamma distribution.
5.26. Stats
1375
x
1
xk1 e
(k)k
for z >= 0
otherwise
>>> E(X)
theta*gamma(k + 1)/gamma(k)
>>> V = simplify(variance(X))
>>> pprint(V, use_unicode=False)
2
k*theta
1376
sympy.stats.GammaInverse(name, a, b)
Create a continuous random variable with an inverse Gamma distribution.
The density of the inverse Gamma distribution is given by
(
)
1
f (x) :=
x
exp
()
x
with x > 0.
Parameters a : Real number, a > 0 a shape
b : Real number, b > 0 a scale
Returns A RandomSymbol. :
References
sympy.stats.Kumaraswamy(name, a, b)
Create a Continuous Random Variable with a Kumaraswamy distribution.
The density of the Kumaraswamy distribution is given by
f (x) := abxa1 (1 xa )b1
5.26. Stats
1377
References
sympy.stats.Laplace(name, mu, b)
Create a continuous random variable with a Laplace distribution.
The density of the Laplace distribution is given by
(
)
1
|x |
f (x) :=
exp
2b
b
1378
sympy.stats.Logistic(name, mu, s)
Create a continuous random variable with a logistic distribution.
The density of the logistic distribution is given by
f (x) :=
e(x)/s
(
)2
s 1 + e(x)/s
with x 0.
Parameters mu : Real number, the log-scale
sigma : Real number, 2 > 0 a shape
Returns A RandomSymbol. :
References
5.26. Stats
1379
Examples
>>> from sympy.stats import LogNormal, density
>>> from sympy import Symbol, simplify, pprint
>>> mu = Symbol(mu, real=True)
>>> sigma = Symbol(sigma, positive=True)
>>> z = Symbol(z)
>>> X = LogNormal(x, mu, sigma)
>>> D = density(X)(z)
>>> pprint(D, use_unicode=False)
2
-(-mu + log(z))
----------------2
___
2*sigma
\/ 2 *e
-----------------------____
2*\/ pi *sigma*z
>>> X = LogNormal(x, 0, 1) # Mean 0, standard deviation 1
>>> density(X)(z)
sqrt(2)*exp(-log(z)**2/2)/(2*sqrt(pi)*z)
sympy.stats.Maxwell(name, a)
Create a continuous random variable with a Maxwell distribution.
The density of the Maxwell distribution is given by
2
2
2 x2 ex /(2a )
f (x) :=
a3
with x 0.
Parameters a : Real number, a > 0
Returns A RandomSymbol. :
References
1380
>>> X = Maxwell(x, a)
>>> density(X)(z)
sqrt(2)*z**2*exp(-z**2/(2*a**2))/(sqrt(pi)*a**3)
>>> E(X)
2*sqrt(2)*a/sqrt(pi)
>>> simplify(variance(X))
a**2*(-8 + 3*pi)/pi
with x > 0.
Parameters mu : Real number,
1
2
a shape
5.26. Stats
1381
(x)2
1
e 22
2
1382
>>> E(2*X + 1)
1
>>> simplify(std(2*X + 1))
2
x
m
x+1
with x [xm , ].
Parameters xm : Real number, xm > 0, a scale
alpha : Real number, > 0, a shape
Returns A RandomSymbol. :
References
sympy.stats.QuadraticU(name, a, b)
Create a Continuous Random Variable with a U-quadratic distribution.
The density of the U-quadratic distribution is given by
f (x) := (x )2
5.26. Stats
1383
References
sympy.stats.RaisedCosine(name, mu, s)
Create a Continuous Random Variable with a raised cosine distribution.
The density of the raised cosine distribution is given by
(
(
))
1
x
f (x) :=
1 + cos
2s
s
with x [ s, + s].
Parameters mu : Real number
s : Real number, s > 0
Returns A RandomSymbol. :
References
1384
sympy.stats.Rayleigh(name, sigma)
Create a continuous random variable with a Rayleigh distribution.
The density of the Rayleigh distribution is given by
f (x) :=
x x2 /22
e
2
with x > 0.
Parameters sigma : Real number, > 0
Returns A RandomSymbol. :
References
5.26. Stats
1385
sympy.stats.StudentT(name, nu)
Create a continuous random variable with a students t distribution.
The density of the students t distribution is given by
(
) (
) +1
2
+1
x2
2( )
f (x) :=
1+
sympy.stats.Triangular(name, a, b, c)
Create a continuous random variable with a triangular distribution.
The density of the triangular distribution is given by
0
for x < a,
2(xa)
2(bx)
for c < x b,
(ba)(bc)
0
for b < x.
1386
a
b
c
z
=
=
=
=
Symbol(a)
Symbol(b)
Symbol(c)
Symbol(z)
5.26. Stats
1387
References
sympy.stats.UniformSum(name, n)
Create a continuous random variable with an Irwin-Hall distribution.
The probability distribution function depends on a single parameter n which is an integer.
The density of the Irwin-Hall distribution is given by
f (x) :=
( )
bxc
1
n
(1)k
(x k)n1
(n 1)!
k
k=0
1388
sympy.stats.VonMises(name, mu, k)
Create a Continuous Random Variable with a von Mises distribution.
The density of the von Mises distribution is given by
f (x) :=
e cos(x)
2I0 ()
5.26. Stats
1389
x0
x<0
sympy.stats.WignerSemicircle(name, R)
Create a continuous random variable with a Wigner semicircle distribution.
The density of the Wigner semicircle distribution is given by
f (x) :=
2 2
R x2
R2
1390
References
5.26.3 Interface
sympy.stats.P(condition, given condition=None, numsamples=None, evaluate=True,
**kwargs)
Probability that a condition is true, optionally given a second condition
Parameters expr : Relational containing RandomSymbols
5.26. Stats
1391
1392
>>> E(2*X + 1)
8
>>> E(X, X>3) # Expectation of X given that it is above 3
5
5.26. Stats
1393
Following convention, if the condition is a random symbol then that symbol is considered
xed.
>>> from sympy.stats import Normal
>>> from sympy import pprint
>>> from sympy.abc import z
>>> X = Normal(X, 0, 1)
>>> Y = Normal(Y, 0, 1)
>>> pprint(density(X + Y, Y)(z), use_unicode=False)
2
-(-Y + z)
----------___
2
\/ 2 *e
-----------------____
2*\/ pi
1394
>>> variance(2*X)
35/3
>>> simplify(variance(B))
p*(-p + 1)
5.26. Stats
1395
5.26.4 Mechanics
SymPy Stats employs a relatively complex class hierarchy.
RandomDomains are a mapping of variables to possible values. For example we might say that
the symbol Symbol(x) can take on the values {1, 2, 3, 4, 5, 6}.
class sympy.stats.rv.RandomDomain
A PSpace, or Probability Space, combines a RandomDomain with a density to provide probabilistic information. For example the above domain could be enhanced by a nite density
{1:1/6, 2:1/6, 3:1/6, 4:1/6, 5:1/6, 6:1/6} to fully dene the roll of a fair die named
x.
class sympy.stats.rv.PSpace
A RandomSymbol represents the PSpaces symbol x inside of SymPy expressions.
class sympy.stats.rv.RandomSymbol
The RandomDomain and PSpace classes are almost never directly instantiated. Instead they
are subclassed for a variety of situations.
RandomDomains and PSpaces must be suciently general to represent domains and spaces
of several variables with arbitrarily complex densities. This generality is often unnecessary. Instead we often build SingleDomains and SinglePSpaces to represent single, univariate
events and processes such as a single die or a single normal variable.
class sympy.stats.rv.SinglePSpace
class sympy.stats.rv.SingleDomain
Another common case is to collect together a set of such univariate random variables. A
collection of independent SinglePSpaces or SingleDomains can be brought together to form
a ProductDomain or ProductPSpace. These objects would be useful in representing three
dice rolled together for example.
class sympy.stats.rv.ProductDomain
class sympy.stats.rv.ProductPSpace
The Conditional adjective is added whenever we add a global condition to a RandomDomain
or PSpace. A common example would be three independent dice where we know their sum
to be greater than 12.
class sympy.stats.rv.ConditionalDomain
We specialize further into Finite and Continuous versions of these classes to represent nite
(such as dice) and continuous (such as normals) random variables.
class sympy.stats.frv.FiniteDomain
class sympy.stats.frv.FinitePSpace
class sympy.stats.crv.ContinuousDomain
class sympy.stats.crv.ContinuousPSpace
Additionally there are a few specialized classes that implement certain common random variable types. There is for example a DiePSpace that implements SingleFinitePSpace and a
NormalPSpace that implements SingleContinuousPSpace.
class sympy.stats.frv types.DiePSpace
class sympy.stats.crv types.NormalPSpace
1396
RandomVariables can be extracted from these objects using the PSpace.values method.
As previously mentioned SymPy Stats employs a relatively complex class structure. Inheritance is widely used in the implementation of end-level classes. This tactic was chosen to
balance between the need to allow SymPy to represent arbitrarily dened random variables
and optimizing for common cases. This complicates the code but is structured to only be
important to those working on extending SymPy Stats to other random variable types.
Users will not use this class structure. Instead these mechanics are exposed through variable
creation functions Die, Coin, FiniteRV, Normal, Exponential, etc.... These build the appropriate SinglePSpaces and return the corresponding RandomVariable. Conditional and Product
spaces are formed in the natural construction of SymPy expressions and the use of interface
functions E, Given, Density, etc....
sympy.stats.Die()
sympy.stats.Normal()
There are some additional functions that may be useful. They are largely used internally.
sympy.stats.rv.random symbols(expr)
Returns all RandomSymbols within a SymPy Expression.
sympy.stats.rv.pspace(expr)
Returns the underlying Probability Space of a random expression.
For internal use.
Examples
>>> from sympy.stats import pspace, Normal
>>> from sympy.stats.rv import ProductPSpace
>>> X = Normal(X, 0, 1)
>>> pspace(2*X + 1) == X.pspace
True
sympy.stats.rv.rs swap(a, b)
Build a dictionary to swap RandomSymbols based on their underlying symbol.
i.e. if X = (x, pspace1) and Y = (x, pspace2) then X and Y match and the key,
value pair {X:Y} will appear in the result
Inputs: collections a and b of random variables which share common symbols Output:
dict mapping RVs in a to RVs in b
5.27 ODE
5.27.1 User Functions
These are functions that are imported into the global namespace with from sympy import *.
These functions (unlike Hint Functions (page 1405), below) are intended for use by ordinary
users of SymPy.
dsolve()
sympy.solvers.ode.dsolve(eq, func=None, hint=default, simplify=True, ics=None,
xi=None, eta=None, x0=0, n=6, **kwargs)
5.27. ODE
1397
Solves any (supported) kind of ordinary dierential equation and system of ordinary dierential equations.
Examples
>>> from sympy import Function, dsolve, Eq, Derivative, sin, cos, symbols
>>> from sympy.abc import x
>>> f = Function(f)
>>> dsolve(Derivative(f(x), x, x) + 9*f(x), f(x))
f(x) == C1*sin(3*x) + C2*cos(3*x)
all Integral: This is the same as all, except if a hint also has a corresponding Integral hint, it only returns the Integral hint. This is useful if all
causes dsolve() (page 1397) to hang because of a dicult or impossible
integral. This meta-hint will also be much faster than all, because integrate() (page 114) is an expensive routine.
best: To have dsolve() (page 1397) try all methods and return the simplest
one. This takes into account whether the solution is solvable in the function,
whether it contains any Integral classes (i.e. unevaluatable integrals), and
which one is the shortest in size.
See also the classify ode() (page 1400) docstring for more info on hints, and
the ode (page 1457) docstring for a list of all supported hints.
Tips
5.27. ODE
1399
Derivative
is the independent variable
a function of x
of f with respect to x
See test ode.py for many tests, which serves also as a set of examples for how to
use dsolve() (page 1397).
dsolve() (page 1397) always returns an Equality (page 148) class (except for the
case when the hint is all or all Integral). If possible, it solves the solution explicitly for the function being solved for. Otherwise, it returns an implicit solution.
Arbitrary constants are symbols named C1, C2, and so on.
Because all solutions should be mathematically equivalent, some hints may return
the exact same result for an ODE. Often, though, two dierent hints will return the
same solution formatted dierently. The two should be equivalent. Also note that
sometimes the values of the arbitrary constants in two dierent solutions may not
be the same, because one constant may have absorbed other constants into it.
Do help(ode.ode <hintname>) to get help more information on a specic hint,
where <hintname> is the name of a hint without Integral.
For System Of Ordinary Dierential Equations
Usage
dsolve(eq, func) -> Solve a system of ordinary dierential equations eq for
func being list of functions including x(t), y(t), z(t) where number of functions
in the list depends upon the number of equations provided in eq.
Details
eq can be any supported system of ordinary dierential equations This can
either be an Equality (page 148), or an expression, which is assumed to be
equal to 0.
func holds x(t) and y(t) being functions of one variable which together
with some of their derivatives make up the system of ordinary dierential
equation eq. It is not necessary to provide this; it will be autodetected (and
an error raised if it couldnt be detected).
Hints
The hints are formed by parameters returned by classify sysode, combining
them give hints name used later for forming method name.
classify ode()
sympy.solvers.ode.classify ode(eq, func=None, dict=False, ics=None, **kwargs)
Returns a tuple of possible dsolve() (page 1397) classications for an ODE.
The tuple is ordered so that rst item is the classication that dsolve() (page 1397)
uses to solve the ODE by default. In general, classications at the near the beginning
of the list will produce better solutions faster than those near the end, thought there
are always exceptions. To make dsolve() (page 1397) use a dierent classication, use
1400
5.27. ODE
1401
The word coeff in a hint refers to the coecients of something in the ODE,
usually of the derivative terms. See the docstring for the individual methods
for more info (help(ode)). This is contrast to coefficients, as in undetermined coefficients, which refers to the common name of a method.
best
Methods that have more than one fundamental way to solve will have a hint for
each sub-method and a best meta-classication. This will evaluate all hints and
return the best, using the same considerations as the normal best meta-hint.
Examples
>>> from sympy import Function, classify_ode, Eq
>>> from sympy.abc import x
>>> f = Function(f)
>>> classify_ode(Eq(f(x).diff(x), 0), f(x))
(separable, 1st_linear, 1st_homogeneous_coeff_best,
1st_homogeneous_coeff_subs_indep_div_dep,
1st_homogeneous_coeff_subs_dep_div_indep,
1st_power_series, lie_group,
nth_linear_constant_coeff_homogeneous,
separable_Integral, 1st_linear_Integral,
1st_homogeneous_coeff_subs_indep_div_dep_Integral,
1st_homogeneous_coeff_subs_dep_div_indep_Integral)
>>> classify_ode(f(x).diff(x, 2) + 3*f(x).diff(x) + 2*f(x) - 4)
(nth_linear_constant_coeff_undetermined_coefficients,
nth_linear_constant_coeff_variation_of_parameters,
nth_linear_constant_coeff_variation_of_parameters_Integral)
checkodesol()
sympy.solvers.ode.checkodesol(ode,
sol,
func=None,
solve for func=True)
Substitutes sol into ode and checks that the result is 0.
order=auto,
This only works when func is one function, like f (x). sol can be a single solution or a list
of solutions. Each solution may be an Equality (page 148) that the solution satises,
e.g. Eq(f(x), C1), Eq(f(x) + C1, 0); or simply an Expr (page 103), e.g. f(x) C1. In most cases it will not be necessary to explicitly identify the function, but if the
function cannot be inferred from the original equation it can be supplied through the
func argument.
If a sequence of solutions is passed, the same sort of container will be used to return the
result for each solution.
It tries the following methods, in order, until it nds zero equivalence:
1.Substitute the solution for f in the original equation. This only works if ode is solved
for f . It will attempt to solve it rst unless solve for func == False.
2.Take n derivatives of the solution, where n is the order of ode, and check to see if
that is equal to the solution. This only works on exact ODEs.
3.Take the 1st, 2nd, ..., nth derivatives of the solution, each time solving for the derivative of f of that order (this will always be possible because f is a linear operator).
Then back substitute each derivative into ode in reverse order.
1402
This function returns a tuple. The rst item in the tuple is True if the substitution results
in 0, and False otherwise. The second item in the tuple is what the substitution results
in. It should always be 0 if the rst item is True. Note that sometimes this function
will False, but with an expression that is identically equal to 0, instead of returning
True. This is because simplify() (page 1327) cannot reduce the expression to 0. If an
expression returned by this function vanishes identically, then sol really is a solution to
ode.
If this function seems to hang, it is probably because of a hard simplication.
To use this function to test, test the rst item of the tuple.
Examples
>>> from sympy import Eq, Function, checkodesol, symbols
>>> x, C1 = symbols(x,C1)
>>> f = Function(f)
>>> checkodesol(f(x).diff(x), Eq(f(x), C1))
(True, 0)
>>> assert checkodesol(f(x).diff(x), C1)[0]
>>> assert not checkodesol(f(x).diff(x), x)[0]
>>> checkodesol(f(x).diff(x, 2), x**2)
(False, 2)
homogeneous order()
sympy.solvers.ode.homogeneous order(eq, *symbols)
Returns the order n if g is homogeneous and None if it is not homogeneous.
Determines if a function is homogeneous and if so of what order. A function f (x, y, ) is
homogeneous of order n if f (tx, ty, ) = tn f (x, y, ).
If the function is of two variables, F (x, y), then f being homogeneous of any order is
equivalent to being able to rewrite F (x, y) as G(x/y) or H(y/x). This fact is used to solve
1st order ordinary dierential equations whose coecients are homogeneous of the
same order (see the docstrings of ode 1st homogeneous coeff subs dep div indep()
and ode 1st homogeneous coeff subs indep div dep()).
Symbols can be functions, but every argument of the function must be a symbol, and the
arguments of the function that appear in the expression must match those given in the
list of symbols. If a declared function appears with dierent arguments than given in
the list of symbols, None is returned.
Examples
>>> from sympy import Function, homogeneous_order, sqrt
>>> from sympy.abc import x, y
>>> f = Function(f)
>>> homogeneous_order(f(x), f(x)) is None
True
>>> homogeneous_order(f(x,y), f(y, x), x, y) is None
True
>>> homogeneous_order(f(x), f(x), x)
1
5.27. ODE
1403
infinitesimals()
sympy.solvers.ode.infinitesimals(eq, func=None, order=None, hint=default,
match=None)
The innitesimal functions of an ordinary dierential equation, (x, y) and (x, y), are the
innitesimals of the Lie group of point transformations for which the dierential equation
is invariant. So, the ODE y 0 = f (x, y) would admit a Lie group x = X(x, y; ) = x + (x, y),
y = Y (x, y; ) = y + (x, y) such that (y )0 = f (x , y ). A change of coordinates, to r(x, y)
and s(x, y), can be performed so this Lie group becomes the translation group, r = r and
s = s + . They are tangents to the coordinate curves of the new system.
Consider the transformation (x, y) (X, Y ) such that the dierential equation remains
invariant. and are the tangents to the transformed coordinates X and Y , at = 0.
(
)
(
)
X(x, y; )
Y (x, y; )
|=0 = ,
|=0 = ,
Solving the above mentioned PDE is not trivial, and can be solved only by making intelligent assumptions for and (heuristics). Once an innitesimal is found, the attempt
to nd more heuristics stops. This is done to optimise the speed of solving the dierential equation. If a list of all the innitesimals is needed, hint should be agged as
all, which gives the complete list of innitesimals. If the innitesimals for a particular
heuristic needs to be found, it can be passed as a ag to hint.
References
1404
Examples
>>> from sympy import Function, diff
>>> from sympy.solvers.ode import infinitesimals
>>> from sympy.abc import x
>>> f = Function(f)
>>> eq = f(x).diff(x) - x**2*f(x)
>>> infinitesimals(eq)
[{eta(x, f(x)): exp(x**3/3), xi(x, f(x)): 0}]
checkinfsol()
sympy.solvers.ode.checkinfsol(eq, innitesimals, func=None, order=None)
This function is used to check if the given innitesimals are the actual innitesimals of
the given rst order dierential equation. This method is specic to the Lie Group Solver
of ODEs.
As of now, it simply checks, by substituting the innitesimals in the partial dierential
equation.
(
)
h
h
+
h
h2
=0
x
y
x
y
x
y
dy
dx
The innitesimals should be given in the form of a list of dicts [{xi(x, y): inf,
eta(x, y): inf}], corresponding to the output of the function innitesimals. It returns
a list of values of the form [(True/False, sol)] where sol is the value obtained after
substituting the innitesimals in the PDE. If it is True, then sol would be 0.
1405
odesimp
sympy.solvers.ode.odesimp(*args, **kwargs)
Simplies ODEs, including trying to solve for func and running constantsimp()
(page 1407).
It may use knowledge of the type of solution that the hint returns to apply additional
simplications.
It also attempts to integrate any Integral (page 615)s in the expression, if the hint is
not an Integral hint.
This function should have no eect on expressions returned by dsolve() (page 1397),
as dsolve() (page 1397) already calls odesimp() (page 1406), but the individual hint
functions do not call odesimp() (page 1406) (because the dsolve() (page 1397) wrapper
does). Therefore, this function is designed for mainly internal use.
Examples
>>>
>>>
>>>
>>>
>>>
...
...
>>>
1406
constant renumber
sympy.solvers.ode.constant renumber(expr, symbolname, startnumber, endnumber)
Renumber arbitrary constants in expr to have numbers 1 through N where N is endnumber - startnumber + 1 at most. In the process, this reorders expression terms in a
standard way.
This is a simple function that goes through and renumbers any Symbol (page 122) with
a name in the form symbolname + num where num is in the range from startnumber to
endnumber.
Symbols are renumbered based on .sort key(), so they should be numbered roughly
in the order that they appear in the nal, printed expression. Note that this ordering is
based in part on hashes, so it can produce dierent results on dierent machines.
The structure of this function is very similar to that of constantsimp() (page 1407).
Examples
>>> from sympy import symbols, Eq, pprint
>>> from sympy.solvers.ode import constant_renumber
>>> x, C0, C1, C2, C3, C4 = symbols(x,C:5)
Only constants in the given range (inclusive) are renumbered; the renumbering always
starts from 1:
>>> constant_renumber(C1 + C3 +
C1 + C2 + C4
>>> constant_renumber(C0 + C1 +
C0 + 2*C1 + C2
>>> constant_renumber(C0 + 2*C1
C1 + 3*C2
>>> pprint(C2 + C1*x + C3*x**2)
2
C1*x + C2 + C3*x
>>> pprint(constant_renumber(C2
2
C1 + C2*x + C3*x
C4, C, 1, 3)
C3 + C4, C, 2, 4)
+ C2, C, 0, 1)
constantsimp
sympy.solvers.ode.constantsimp(*args, **kwargs)
Simplies an expression with arbitrary constants in it.
This function is written specically to work with dsolve() (page 1397), and is not intended for general use.
Simplication is done by absorbing the arbitrary constants into other arbitrary constants, numbers, and symbols that they are not independent of.
The symbols must all have the same name with numbers after it, for example, C1, C2,
C3. The symbolname here would be C, the startnumber would be 1, and the endnumber
would be 3. If the arbitrary constants are independent of the variable x, then the independent symbol would be x. There is no need to specify the dependent function, such as
f(x), because it already has the independent symbol, x, in it.
5.27. ODE
1407
Because terms are absorbed into arbitrary constants and because constants are
renumbered after simplifying, the arbitrary constants in expr are not necessarily equal
to the ones of the same name in the returned result.
If two or more arbitrary constants are added, multiplied, or raised to the power of each
other, they are rst absorbed together into a single arbitrary constant. Then the new
constant is combined into other terms if necessary.
Absorption of constants is done with limited assistance:
1.terms of Add (page 144)s are collected to try join constants so ex (C1 cos(x)+C2 cos(x))
will simplify to ex C1 cos(x);
2.powers with exponents that are Add (page 144)s are expanded so eC1 +x will be simplied to C1 ex .
Use constant renumber() (page 1407) to renumber constants after simplication or else
arbitrary numbers on constants may appear, e.g. C1 + C3 x.
In rare cases, a single constant can be simplied into two constants. Every dierential
equation solution should have as many arbitrary constants as the order of the dierential
equation. The result here will be technically correct, but it may, for example, have C1
and C2 in an expression, when C1 is actually equal to C2 . Use your discretion in such
situations, and also take advantage of the ability to use hints in dsolve() (page 1397).
Examples
>>> from sympy import symbols
>>> from sympy.solvers.ode import constantsimp
>>> C1, C2, C3, x, y = symbols(C1, C2, C3, x, y)
>>> constantsimp(2*C1*x, set([C1, C2, C3]))
C1*x
>>> constantsimp(C1 + 2 + x, set([C1, C2, C3]))
C1 + x
>>> constantsimp(C1*C2 + 2 + C2 + C3*x, set([C1, C2, C3]))
C1 + C3*x
sol simplicity
sympy.solvers.ode.ode sol simplicity(sol, func, trysolving=True)
Returns an extended integer representing how simple a solution to an ODE is.
The following things are considered, in order from most simple to least:
sol is solved for func.
sol is not solved for func, but can be if passed to solve (e.g., a solution returned by
dsolve(ode, func, simplify=False).
If sol is not solved for func, then base the result on the length of sol, as computed
by len(str(sol)).
If sol has any unevaluated Integral (page 615)s, this will automatically be considered less simple than any of the above.
This function returns an integer such that if solution A is simpler than solution B by above
metric, then ode sol simplicity(sola, func) < ode sol simplicity(solb, func).
Currently, the following are the numbers returned, but if the heuristic is ever improved,
this may change. Only the ordering is guaranteed.
1408
Simplicity
sol solved for func
sol not solved for func but can be
sol is not solved nor solvable for func
sol contains an Integral (page 615)
Return
-2
-1
len(str(sol))
oo
oo here means the SymPy innity, which should compare greater than any integer.
If you already know solve() (page 1469) cannot solve sol, you can use trysolving=False to skip that step, which is the only potentially slow step. For example,
dsolve() (page 1397) with the simplify=False ag should do this.
If sol is a list of solutions, if the worst solution in the list returns oo it returns that,
otherwise it returns len(str(sol)), that is, the length of the string representation of
the whole list.
Examples
from sympy import symbols, Function, Eq, tan, cos, sqrt, Integral
from sympy.solvers.ode import ode_sol_simplicity
x, C1, C2 = symbols(x, C1, C2)
f = Function(f)
1st exact
sympy.solvers.ode.ode 1st exact(eq, func, order, match)
Solves 1st order exact ordinary dierential equations.
A 1st order dierential equation is called exact if it is the total dierential of a function.
That is, the dierential equation
P (x, y) x + Q(x, y) y = 0
is exact if there is some function F (x, y) such that P (x, y) = F /x and Q(x, y) = F /y. It
can be shown that a necessary and sucient condition for a rst order ODE to be exact
is that P /y = Q/x. Then, the solution will be as given below:
5.27. ODE
1409
>>>
>>>
>>>
>>>
...
Where the rst partials of P and Q exist and are continuous in a simply connected region.
A note: SymPy currently has no way to represent inert substitution on an expression, so
the hint 1st exact Integral will return an integral with dy. This is supposed to represent the function that you are solving for.
References
# indirect doctest
Examples
>>> from sympy import Function, dsolve, cos, sin
>>> from sympy.abc import x
>>> f = Function(f)
>>> dsolve(cos(f(x)) - (x*sin(f(x)) - f(x)**2)*f(x).diff(x),
... f(x), hint=1st_exact)
x*cos(f(x)) + f(x)**3/3 == C1
1412)
docis no
References
1410
# indirect doctest
Examples
>>>
>>>
>>>
>>>
...
such that P and Q are homogeneous and of the same order. A function F (x, y) is homogeneous of order n if F (xt, yt) = tn F (x, y). Equivalently, F (x, y) can be rewritten as G(y/x)
or H(x/y). See also the docstring of homogeneous order() (page 1403).
If the coecients P and Q in the dierential equation above are homogeneous functions
of the same order, then it can be shown that the substitution y = u1 x (i.e. u1 = y/x) will
turn the dierential equation into an equation separable in the variables x and u. If h(u1 )
is the function that results from making the substitution u1 = f (x)/x on P (x, f (x)) and g(u2 )
is the function that results from the substitution on Q(x, f (x)) in the dierential equation
P (x, f (x)) + Q(x, f (x))f 0 (x) = 0, then the general solution is:
>>> from sympy import Function, dsolve, pprint
>>> from sympy.abc import x
>>> f, g, h = map(Function, [f, g, h])
>>> genform = g(f(x)/x) + h(f(x)/x)*f(x).diff(x)
>>> pprint(genform)
/f(x)\
/f(x)\ d
g|----| + h|----|*--(f(x))
\ x /
\ x / dx
>>> pprint(dsolve(genform, f(x),
... hint=1st_homogeneous_coeff_subs_dep_div_indep_Integral))
f(x)
---x
/
|
5.27. ODE
1411
|
|
|
|
log(x) = C1 +
-h(u1)
---------------- d(u1)
u1*h(u1) + g(u1)
# indirect doctest
Examples
>>>
>>>
>>>
>>>
...
such that P and Q are homogeneous and of the same order. A function F (x, y) is homogeneous of order n if F (xt, yt) = tn F (x, y). Equivalently, F (x, y) can be rewritten as G(y/x)
or H(x/y). See also the docstring of homogeneous order() (page 1403).
If the coecients P and Q in the dierential equation above are homogeneous functions
of the same order, then it can be shown that the substitution x = u2 y (i.e. u2 = x/y) will
turn the dierential equation into an equation separable in the variables y and u2 . If
h(u2 ) is the function that results from making the substitution u2 = x/f (x) on P (x, f (x))
1412
and g(u2 ) is the function that results from the substitution on Q(x, f (x)) in the dierential
equation P (x, f (x)) + Q(x, f (x))f 0 (x) = 0, then the general solution is:
>>> from sympy import Function, dsolve, pprint
>>> from sympy.abc import x
>>> f, g, h = map(Function, [f, g, h])
>>> genform = g(x/f(x)) + h(x/f(x))*f(x).diff(x)
>>> pprint(genform)
/ x \
/ x \ d
g|----| + h|----|*--(f(x))
\f(x)/
\f(x)/ dx
>>> pprint(dsolve(genform, f(x),
... hint=1st_homogeneous_coeff_subs_indep_div_dep_Integral))
x
---f(x)
/
|
|
-g(u2)
| ---------------- d(u2)
| u2*g(u2) + h(u2)
|
/
f(x) = C1*e
# indirect doctest
Examples
>>>
>>>
>>>
>>>
...
...
5.27. ODE
1413
1st linear
sympy.solvers.ode.ode 1st linear(eq, func, order, match)
Solves 1st order linear dierential equations.
These are dierential equations of the form
dy/dx + P (x)y = Q(x).
These kinds
of dierential equations can be solved in a general way. The integrating
factor e P (x) dx will turn the equation into a separable equation. The general solution is:
>>>
>>>
>>>
>>>
>>>
References
# indirect doctest
Examples
>>> f = Function(f)
>>> pprint(dsolve(Eq(x*diff(f(x), x) - f(x), x**2*sin(x)),
... f(x), 1st_linear))
f(x) = x*(C1 - cos(x))
Bernoulli
sympy.solvers.ode.ode Bernoulli(eq, func, order, match)
Solves Bernoulli dierential equations.
1414
The substitution w = 1/y 1n will transform an equation of this form into one that is linear
(see the docstring of ode 1st linear() (page 1414)). The general solution is:
>>>
>>>
>>>
>>>
>>>
Note that the equation is separable when n = 1 (see the docstring of ode separable()
(page 1421)).
>>> pprint(dsolve(Eq(f(x).diff(x) + P(x)*f(x), Q(x)*f(x)), f(x),
... hint=separable_Integral))
f(x)
/
|
/
| 1
|
| - dy = C1 + | (-P(x) + Q(x)) dx
| y
|
|
/
/
References
# indirect doctest
5.27. ODE
1415
Examples
>>> from sympy import Function, dsolve, Eq, pprint, log
>>> from sympy.abc import x
>>> f = Function(f)
>>> pprint(dsolve(Eq(x*f(x).diff(x) + f(x), log(x)*f(x)**2),
... f(x), hint=Bernoulli))
1
f(x) = ------------------/
log(x)
1\
x*|C1 + ------ + -|
\
x
x/
Liouville
sympy.solvers.ode.ode Liouville(eq, func, order, match)
Solves 2nd order Liouville dierential equations.
The general form of a Liouville ODE is
( )2
d2 y
dy
dy
+ g(y)
+ h(x) .
2
dx
dx
dx
References
Goldstein and Braun, Advanced Methods for the Solution of Dierential Equations,
pp. 98
1416
http://www.maplesoft.com/support/help/Maple/view.aspx?path=odeadvisor/Liouville
# indirect doctest
Examples
>>>
>>>
>>>
>>>
...
While it does not have a general solution [1], the special form, dy/dx = ay 2 bxc , does
have solutions in many cases [2]. This routine returns a solution for a(dy/dx) = by 2 +cy/x+
d/x2 that is obtained by using a suitable change of variables to reduce it to the special
form and is valid when neither a nor b are zero and either c or d is zero.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
References
1.http://www.maplesoft.com/support/help/Maple/view.aspx?path=odeadvisor/Riccati
2.http://eqworld.ipmnet.ru/en/solutions/ode/ode0106.pdf - http://eqworld.ipmnet.ru/en/solutions/ode
5.27. ODE
1417
These equations can be solved in a general manner, by taking the roots of the characteristic equation an mn + an1 mn1 + + a1 m + a0 = 0. The solution will then be the sum of
Cn xi erx terms, for each where Cn is an arbitrary constant, r is a root of the characteristic
equation and i is one of each from 0 to the multiplicity of the root - 1 (for example, a
root 3 of multiplicity 2 would create the terms C1 e3x + C2 xe3x ). The exponential is usually
expanded for complex roots using Eulers equation eIx = cos(x) + I sin(x). Complex roots
always come in conjugate pairs in polynomials with real coecients, so the two roots
will be represented (after simplifying the constants) as eax (C1 cos(bx) + C2 sin(bx)).
If SymPy cannot nd exact roots to the characteristic equation, a RootOf (page 1119)
instance will be return instead.
>>> from sympy import Function, dsolve, Eq
>>> from sympy.abc import x
>>> f = Function(f)
>>> dsolve(f(x).diff(x, 5) + 10*f(x).diff(x) - 2*f(x), f(x),
... hint=nth_linear_constant_coeff_homogeneous)
...
f(x) == C1*exp(x*RootOf(_x**5 + 10*_x - 2, 0)) +
C2*exp(x*RootOf(_x**5 + 10*_x - 2, 1)) +
C3*exp(x*RootOf(_x**5 + 10*_x - 2, 2)) +
C4*exp(x*RootOf(_x**5 + 10*_x - 2, 3)) +
C5*exp(x*RootOf(_x**5 + 10*_x - 2, 4))
integration,
there
is
no
section:
Nonhomoge-
M. Tenenbaum & H. Pollard, Ordinary Dierential Equations, Dover 1963, pp. 211
1418
# indirect doctest
Examples
>>>
>>>
>>>
>>>
...
...
where P (x) is a function that has a nite number of linearly independent derivatives.
Functions that t this requirement are nite sums functions of the form axi ebx sin(cx + d)
or axi ebx cos(cx + d), where i is a non-negative integer and a, b, c, and d are constants.
For example any polynomial in x, functions like x2 e2x , x sin(x), and ex cos(x) can all be
used. Products of sins and coss have a nite number of derivatives, because they can
be expanded into sin(ax) and cos(bx) terms. However, SymPy currently cannot do that
expansion, so you will need to manually rewrite the expression in terms of the above
to use this method. So, for example, you will need to manually convert sin2 (x) into (1 +
cos(2x))/2 to properly apply the method of undetermined coecients on it.
This method works by creating a trial function from the expression and all of its linear
independent derivatives and substituting them into the original ODE. The coecients for
each term will be a system of linear equations, which are be solved for and substituted,
giving the solution. If any of the trial functions are linearly dependent on the solution
to the homogeneous equation, they are multiplied by sucient x to make them linearly
independent.
References
# indirect doctest
5.27. ODE
1419
Examples
>>>
>>>
>>>
>>>
...
...
This method works by assuming that the particular solution takes the form
n
ci (x)yi (x),
x=1
where yi is the ith solution to the homogeneous equation. The solution is then solved
using Wronskians and Cramers Rule. The particular solution is given by
)
n (
Wi (x)
dx yi (x),
W (x)
x=1
where W (x) is the Wronskian of the fundamental system (the system of n linearly independent solutions to the homogeneous equation), and Wi (x) is the Wronskian of the
fundamental system with the ith column replaced with [0, 0, , 0, P (x)].
This method is general enough to solve any nth order inhomogeneous linear dierential equation with constant coecients, but sometimes SymPy cannot simplify the Wronskian well enough to integrate it.
If this method hangs,
try
using
the
nth linear constant coeff variation of parameters Integral
hint
and
simplifying
the
integrals
manually.
Also,
prefer
using
nth linear constant coeff undetermined coefficients when it applies, because
it doesnt use integration, making it faster and more reliable.
Warning, using simplify=False with nth linear constant coe variation of parameters
in dsolve() (page 1397) may cause it to hang, because it will not attempt to simplify the
1420
Wronskian before integrating. It is recommended that you only use simplify=False with
nth linear constant coe variation of parameters Integral for this method, especially if
the solution to the homogeneous equation has trigonometric functions in it.
References
http://en.wikipedia.org/wiki/Variation of parameters
http://planetmath.org/VariationOfParameters
M. Tenenbaum & H. Pollard, Ordinary Dierential Equations, Dover 1963, pp. 233
# indirect doctest
Examples
>>>
>>>
>>>
>>>
...
...
separable
sympy.solvers.ode.ode separable(eq, func, order, match)
Solves separable 1st order dierential equations.
dy
This is any dierential equation that can be written as P (y)
dx = Q(x). The solution can
then just be found by rearranging terms and integrating: P (y) dy = Q(x) dx. This hint
uses sympy.simplify.simplify.separatevars() (page 1331) as its back end, so if a
separable equation is not caught by this solver, it is most likely the fault of that function. separatevars() (page 1331) is smart enough to do most expansion and factoring
necessary to convert a separable equation F (x, y) into the proper form P (x) Q(y). The
general solution is:
>>>
>>>
>>>
>>>
>>>
5.27. ODE
1421
|
|
d(y)
| a(x)
|
/
References
# indirect doctest
Examples
>>> from sympy import Function, dsolve, Eq
>>> from sympy.abc import x
>>> f = Function(f)
>>> pprint(dsolve(Eq(f(x)*f(x).diff(x) + x, 3*x*f(x)**2), f(x),
... hint=separable, simplify=False))
/
2
\
2
log\3*f (x) - 1/
x
---------------- = C1 + -6
2
almost linear
sympy.solvers.ode.ode almost linear(eq, func, order, match)
Solves an almost-linear dierential equation.
The general form of an almost linear dierential equation is
f (x)g(y)y + k(x)l(y) + m(x) = 0wherel0 (y) = g(y).
This can be solved by substituting l(y) = u(y). Making the given substitution reduces it
to a linear dierential equation of the form u0 + P (x)u + Q(x) = 0.
The general solution is
>>>
>>>
>>>
>>>
>>>
1422
|
|
\
||-------------||
k(x)
\\
otherwise
||
||
//
See Also:
sympy.solvers.ode.ode 1st linear() (page 1414)
References
linear coefficients
sympy.solvers.ode.ode linear coefficients(eq, func, order, match)
Solves a dierential equation with linear coecients.
The general form of a dierential equation with linear coecients is
(
)
a1 x + b1 y + c 1
0
y +F
= 0,
a2 x + b2 y + c 2
where a1 , b1 , c1 , a2 , b2 , c2 are constants and a1 b2 a2 b1 6= 0.
This can be solved by substituting:
b2 c1 b1 c2
a2 b1 a1 b2
a1 c2 a2 c1
.
y = y0 +
a2 b1 a1 b2
x = x0 +
5.27. ODE
1423
References
separable reduced
sympy.solvers.ode.ode separable reduced(eq, func, order, match)
Solves a dierential equation that can be reduced to the separable form.
The general form of this equation is
y 0 + (y/x)H(xn y) = 0.
This can be solved by substituting u(y) = xn y. The equation then reduces to the separable
u0
form u(powerH(u))
x1 = 0.
The general solution is:
>>>
>>>
>>>
>>>
>>>
1424
See Also:
sympy.solvers.ode.ode separable() (page 1421)
References
lie group
sympy.solvers.ode.ode lie group(eq, func, order, match)
This hint implements the Lie group method of solving rst order dierential equations.
The aim is to convert the given dierential equation from the given coordinate given system into another coordinate system where it becomes invariant under the one-parameter
Lie group of translations. The converted ODE is quadrature and can be solved easily.
It makes use of the sympy.solvers.ode.infinitesimals() (page 1404) function which
returns the innitesimals of the transformation.
The coordinates r and s can be found by solving the following Partial Dierential Equations.
r
r
+
=0
x
y
s
s
+
=1
x
y
5.27. ODE
s
x
r
x
s
+ h(x, y) y
r
+ h(x, y) y
1425
After nding the solution by integration, it is then converted back to the original coordinate system by subsituting r and s in terms of x and y again.
References
y(x) = y(x0 ) +
Fn (x0 , b)(x x0 )n
,
n!
n=1
where y(x0 ) = b is the value of y at the initial value of x0 . To compute the values of
the Fn (x0 , b) the following algorithm is followed, until the required number of terms are
generated.
1.F1 = h(x0 , b)
2.Fn+1 =
Fn
x
Fn
y F1
References
Travis W. Walker, Analytic power series technique for solving rst-order dierential
equations, p.p 17, 18
Examples
1426
>>>
>>>
>>>
>>>
>>>
>>>
d2 y
dy
+ R(x) = 0
+ Q(x)
dx2
dx
For simplicity it is assumed that P (x), Q(x) and R(x) are polynomials, it is sucient that
Q(x)
R(x)
n
n=0 an x ,
P (x) and P (x) exists at x0 . A recurrence relation is obtained by substituting y as
in the dierential equation, and equating the nth term. Using this relation various terms
can be generated.
References
http://tutorial.math.lamar.edu/Classes/DE/SeriesSolutions.aspx
George E. Simmons, Dierential Equations with Applications and Historical Notes,
p.p 176 - 184
Examples
>>>
>>>
>>>
>>>
>>>
5.27. ODE
1427
polynomial coecients at a regular point. A second order homogenous dierential equation is of the form
P (x)
d2 y
dy
+ Q(x)
+ R(x) = 0
dx2
dx
2 R(x)
A point is said to regular singular at x0 if x x0 Q(x)
P (x) and (x x0) P (x) are analytic at x0. For
simplicity P (x), Q(x) and R(x) are assumed to be polynomials. The algorithm for nding
the power series solutions is:
1.Try expressing (x x0)P (x) and ((x x0)2 )Q(x) as power series solutions about x0.
Find p0 and q0 which are the constants of the power series expansions.
2.Solve the indicial equation f (m) = m(m 1) + m p0 + q0, to obtain the roots m1 and
m2 of the indicial equation.
3.If m1 m2 is a non integer there exists two series solutions. If m1 = m2, there exists
only one solution. If m1 m2 is an integer, then the existence of one solution is
conrmed. The other solution may or may not exist.
The power series solution is of the form xm n=0 an xn . The coecients are determined
n1
+(m+k)p
nk
by the following recurrence relation. an = k=0 nk
. For the case in which
f (m+n)
m1 m2 is an integer, it can be seen from the recurrence relation that for the lower root
m, when n equals the dierence of both the roots, the denominator becomes zero. So if
the numerator is not equal to zero, a second series solution exists.
References
1428
abaco1 simple
sympy.solvers.ode.lie heuristic abaco1 simple(match, comp=False)
The rst heuristic uses the following four sets of assumptions on and
= 0, = f (x)
= 0, = f (y)
= f (x), = 0
= f (y), = 0
The success of this heuristic is determined by algebraic factorisation. For the rst assumption = 0 and to be a function of x, the PDE
h
h
+(
)h
h2
=0
x
y
x
y
x
y
h
reduces to f 0 (x)f h
y = 0 If y is a function of x, then this can usually be integrated easily.
A similar idea is applied to the other 3 assumptions as well.
References
E.S Cheb-Terrab, L.G.S Duarte and L.A,C.P da Mota, Computer Algebra Solving of
First Order ODEs Using Symmetry Methods, pp. 8
abaco1 product
sympy.solvers.ode.lie heuristic abaco1 product(match, comp=False)
The second heuristic uses the following two assumptions on and
= 0, = f (x) g(y)
= f (x) g(y), = 0
2
provided f x
1
f h
1
f x
( f h
) dy
)
is a function of y only.
dy
dy
1
The second assumption holds good if dx
= h(x, y) is rewritten as dx
= h(y,x)
and the same
properties of the rst assumption satisifes. After obtaining f (x) and g(y), the coordinates
are again interchanged, to get as f (x) g(y)
5.27. ODE
1429
References
E.S. Cheb-Terrab, A.D. Roche, Symmetries and First Order ODE Patterns, pp. 7 pp. 8
bivariate
sympy.solvers.ode.lie heuristic bivariate(match, comp=False)
The third heuristic assumes the innitesimals and to be bi-variate polynomials in x
and y. The assumption made here for the logic below is that h is a rational function in x
and y though that may not be necessary for the innitesimals to be bivariate polynomials.
The coecients of the innitesimals are found out by substituting them in the PDE and
grouping similar terms that are polynomials and since they form a linear system, solve
and check for non trivial solutions. The degree of the assumed bivariates are increased
till a certain maximum value.
References
chi
sympy.solvers.ode.lie heuristic chi(match, comp=False)
The aim of the fourth heuristic is to nd the function (x, y) that satisies the PDE
h
h d
dx y = 0.
d
dx
E.S Cheb-Terrab, L.G.S Duarte and L.A,C.P da Mota, Computer Algebra Solving of
First Order ODEs Using Symmetry Methods, pp. 8
abaco2 similar
sympy.solvers.ode.lie heuristic abaco2 similar(match, comp=False)
This heuristic uses the following two assumptions on and
= g(x), = f (x)
= f (y), = g(y)
For the rst assumption,
1430
1.First
h
y
2 h
yy
2.If this is constant, then h is matched to the form A(x) + B(x)e C then,
f (x) and A(x) f (x) gives g(x)
3.Otherwise
A
X
A
Y
A(x)
dx
C
B(x)
gives
= is calculated. If
a] is a function of x alone
h 0 (x) h
x
h+
b] y
g(x)
G dx
dy
dy
1
The second assumption holds good if dx
= h(x, y) is rewritten as dx
= h(y,x)
and the same
properties of the rst assumption satisifes. After obtaining f (x) and g(x), the coordinates
are again interchanged, to get as f (x ) and as g(y )
References
E.S. Cheb-Terrab, A.D. Roche, Symmetries and First Order ODE Patterns, pp. 10 pp. 12
function sum
sympy.solvers.ode.lie heuristic function sum(match, comp=False)
This heuristic uses the following two assumptions on and
= 0, = f (x) + g(y)
= f (x) + g(y), = 0
2
[(h 2 (h1 ))1 ]
y
x
is separable in x and y,
1.The separated factors containing y is
g
y .
00
1
3.h x
) equals
2 (h
f 00 (x)
f (x)+g(y) .
dy
dy
1
The second assumption holds good if dx
= h(x, y) is rewritten as dx
= h(y,x)
and the same
properties of the rst assumption satisifes. After obtaining f (x) and g(y), the coordinates
are again interchanged, to get as f (x) + g(y).
For both assumptions, the constant factors are separated among g(y) and f 00 (x), such
that f 00 (x) obtained from 3] is the same as that obtained from 2]. If not possible, then
this heuristic fails.
5.27. ODE
1431
References
E.S. Cheb-Terrab, A.D. Roche, Symmetries and First Order ODE Patterns, pp. 7 pp. 8
f
x
f
x
=R
R
X
1
and = X
satisfy the PDE. If yes, then return and
E.S. Cheb-Terrab, A.D. Roche, Symmetries and First Order ODE Patterns, pp. 10 pp. 12
E.S. Cheb-Terrab, A.D. Roche, Symmetries and First Order ODE Patterns, pp. 10 pp. 12
linear
sympy.solvers.ode.lie heuristic linear(match, comp=False)
This heuristic assumes
1. = ax + by + c and
2. = f x + gy + h
1432
h
h
(f x + gy + c)
x
y
Solving the reduced PDE obtained, using the method of characteristics, becomes impractical. The method followed is grouping similar terms and solving the system of linear
equations obtained. The dierence between the bivariate heuristic is that h need not be
a rational function in this case.
References
E.S. Cheb-Terrab, A.D. Roche, Symmetries and First Order ODE Patterns, pp. 10 pp. 12
y 0 = cx + dy
5.27. ODE
1433
y = c1 (1 a)e1 t + c2 (2 a)e2 t
a+d
C2
+ C2 t)e 2 t
ad
a+d
2 t
1434
The general solution og this system is given by sum of its particular solution and the
general solution of the corresponding homogeneous system is obtained from type1.
1. When ad bc 6= 0. The particular solution will be x = x0 and y = y0 where x0 and y0 are
determined by solving linear system of equations
ax0 + by0 + k1 = 0, cx0 + dy0 + k2 = 0
2.When ad bc = 0 and a2 + b2 > 0. In this case, the system of equation becomes
x0 = ax + by + k1 , y 0 = k(ax + by) + k2
2.1 If = a + bk 6= 0, particular solution is given by
x = b 1 (c1 k c2 )t 2 (ac1 + bc2 )
y = kx + (c2 c1 k)t
1
b(c2 c1 k)t2 + c1 t
2
y = kx + (c2 c1 k)t
y 0 = g(t)x + f (t)y
5.27. ODE
1435
y 0 = g(t)x + f (t)y
The solution is given by
x = F (C1 cos(G) + C2 sin(G)), y = F (C1 sin(G) + C2 cos(G))
where C1 and C2 are arbitary constants, and
The transformation of
x=e
f (t) dt
u, y = e
f (t) dt
v, T =
g(t) dt
1436
h(t) dt
and on substituing the value of y in rst equation give rise to rst order ODEs. After
solving for x, we can obtain y by substituting the value of x in second equation.
system of odes linear 2eq order1 type7
sympy.solvers.ode. linear 2eq order1 type7(x, y, t, r)
The equations of this type of ode are .
x0 = f (t)x + g(t)y
y 0 = h(t)x + p(t)y
Dierentiating the rst equation and substituting the value of y from second equation
will give a second-order linear equation
gx00 (f g + gp + g 0 )x0 + (f gp g 2 h + f g 0 f 0 g)x = 0
This above equation can be easily integrated if following conditions are satised.
1.f gp g 2 h + f g 0 f 0 g = 0
2.f gp g 2 h + f g 0 f 0 g = ag, f g + gp + g 0 = bg
If rst condition is satised then it is solved by current dsolve solver and in second case it
becomes a constant cocient dierential equation which is also solved by current solver.
Otherwise if the above condition fails then, a particular solution is assumed as x = x0 (t)
and y = y0 (t) Then the general solution is expressed as
5.27. ODE
1437
y = C1 y0 (t) + C2 [
F (t)P (t)
+ y0 (t)
x0 (t)
F (t) = e
f (t) dt
, P (t) = e
p(t) dt
y 00 = cx + dy
kt
kt
kt
kt
kt
2bk
2bk
)e 2 + 2C2 (bt +
)e 2 + 2bC3 te 2 + 2bC4 te 2
ad
ad
y = C1 (d a)te 2 + C2 (d a)te
kt
2
kt
1438
kt
2
2(a + d)
x = 2 aC1 e at + 2 aC2 e at
y = cC1 te
at
cC2 te
at
+ C3 e
at
+ C4 e
at
x = bC1 te
at
bC2 te
at
+ C3 e
at
+ C4 e
at
y = 2 aC1 e at + 2 aC2 e at
y 00 = k(ax + by)
2.1. If a + bk 6= 0:
x = C1 et
y = C1 ket
a+bk
a+bk
+ C2 et
a+bk
+ C2 ket
+ C3 bt + C4 b
a+bk
C3 at C4 a
2.2. If a + bk = 0:
x = C1 bt3 + C2 bt2 + C3 t + C4
y = kx + 6C1 t + 2C2
5.27. ODE
1439
y 00 = a2 x + b2 y + c2
The general solution of this system is given by the sum of its particular solution and the
general solution of the homogeneous system. The general solution is given by the linear
system of 2 equation of order 2 and type 1
1. If a1 b2 a2 b1 6= 0. A particular solution will be x = x0 and y = y0 where the constants x0
and y0 are determined by solving the linear algebraic system
a1 x0 + b1 y0 + c1 = 0, a2 x0 + b2 y0 + c2 = 0
2.If a1 b2 a2 b1 = 0 and a21 + b21 > 0. In this case, the system in question becomes
x00 = ax + by + c1 , y 00 = k(ax + by) + c2
2.1. If = a + bk 6= 0, the particular solution will be
x=
1 1
b (c1 k c2 )t2 2 (ac1 + bc2 )
2
1
y = kx + (c2 c1 k)t2
2
2.2. If = a + bk = 0, the particular solution will be
x=
1
1
b(c2 c1 k)t4 + c1 t2
24
2
1
y = kx + (c2 c1 k)t2
2
1440
1 2
1 2
1
1
a+
a + 4b, = a
a + 4b
2
2
2
2
y 00 + a2 x0 + b2 y 0 + c2 x + d2 y = k2 eit
The general solution of this linear nonhomogeneous system of constant-coecient differential equations is given by the sum of its particular solution and the general solution
of the corresponding homogeneous system (with k1 = k2 = 0)
1.A particular solution is obtained by the method of undetermined coecients:
x = A eit , y = B eit
On substituting these expressions into the original system of dierential equations, one
arrive at a linear nonhomogeneous system of algebraic equations for the coecients A
and B.
2. The general solution of the homogeneous system of dierential equations is determined by a linear combination of linearly independent particular solutions determined
by the method of undetermined coecients in the form of exponentials:
x = Aet , y = Bet
On substituting these expressions into the original system and colleting the coecients
of the unknown A and B, one obtains
(2 + a1 + c1 )A + (b1 + d1 )B = 0
(a2 + c2 )A + (2 + b2 + d2 )B = 0
The determinant of this system must vanish for nontrivial solutions A, B to exist. This
requirement results in the following characteristic equation for
(2 + a1 + c1 )(2 + b2 + d2 ) (b1 + d1 )(a2 + c2 ) = 0
If all roots k1 , ..., k4 of this equation are distict, the general solution of the original system
of the dierential equations has the form
x = C1 (b1 1 + d1 )e1 t C2 (b1 2 + d1 )e2 t C3 (b1 3 + d1 )e3 t C4 (b1 4 + d1 )e4 t
5.27. ODE
1441
y 00 = b(tx0 x)
The transformation
u = tx0 x, b = ty 0 y
u = C1 ae 2
abt2
+ C2 ae 2
abt2
2
2
1
1
v = C1 abe 2 abt C2 abe 2 abt
If ab < 0:
u = C1 a cos(
v = C1
1
1
|ab|t2 ) + C2 a sin(
|ab|t2 )
2
2
1
1
|ab| sin(
|ab|t2 ) + C2 |ab| cos(
|ab|t2 )
2
2
where C1 and C2 are arbitary constants. On substituting the value of u and v in above
equations and integrating the resulting expressions, the general solution will become
u
u
dt, y = C4 t + t
dt
x = C3 t + t
t2
t2
1442
y 00 = f (t)(a2 x + b2 y)
Solving the equations will give the values of x and y after obtaining the value of z1 and
z2 by solving the dierential equation and substuting the result.
system of odes linear 2eq order2 type7
sympy.solvers.ode. linear 2eq order2 type7(x, y, t, r)
The equations are given as
x00 = f (t)(a1 x0 + b1 y 0 )
y 00 = f (t)(a2 x0 + b2 y 0 )
Then the system can be reduced by adding together the two equations multiplied by
appropriate constants give following two independent equations:
z100 = k1 f (t)z10 , z1 = a2 x + (k1 a1 )y
5.27. ODE
1443
a2 x + (k2 a1 )y = C3
ek2 F (t) dt + C4
f (t) dt
y 00 = bf (t)(tx0 x)
The transformation
u = tx0 x, v = ty 0 y
ab tf (t) dt
+ C2 ae
ab
tf (t) dt
If ab < 0:
u = C1 a cos(
1444
v = C1
|ab| sin( |ab| tf (t) dt) + C2 |ab| cos( |ab| tf (t) dt)
where C1 and C2 are arbitary constants. On substituting the value of u and v in above
equations and integrating the resulting expressions, the general solution will become
u
u
x = C3 t + t
dt,
y
=
C
t
+
t
dt
4
t2
t2
t2 y 00 + a2 tx0 + b2 ty 0 + c2 x + d2 y = 0
y 00 + a2 x0 + (b2 1)y 0 + c2 x + d2 y = 0
On substituting these expressions into the original system and colleting the coecients
of the unknown A and B, one obtains
(2 + (a1 1) + c1 )A + (b1 + d1 )B = 0
(a2 + c2 )A + (2 + (b2 1) + d2 )B = 0
5.27. ODE
1445
The determinant of this system must vanish for nontrivial solutions A, B to exist. This
requirement results in the following characteristic equation for
(2 + (a1 1) + c1 )(2 + (b2 1) + d2 ) (b1 + d1 )(a2 + c2 ) = 0
If all roots k1 , ..., k4 of this equation are distict, the general solution of the original system
of the dierential equations has the form
x = C1 (b1 1 + d1 )e1 t C2 (b1 2 + d1 )e2 t C3 (b1 3 + d1 )e3 t C4 (b1 4 + d1 )e4 t
y = C1 (21 + (a1 1)1 + c1 )e1 t + C2 (22 + (a1 1)2 + c1 )e2 t + C3 (23 + (a1 1)3 + c1 )e3 t + C4 (24 + (a1 1)4 +
(t2 + t + )2 y 00 = cx + dy
The transformation
t2
x
1
y
dt, u =
,v =
2
2
+ t +
|t + t + |
|t + t + |
1
v 00 = cu + (d + 2 )v
4
These system of equations obtained can be solved by type1 of System of two constantcoecient second-order linear homogeneous dierential equations.
system of odes linear 2eq order2 type11
sympy.solvers.ode. linear 2eq order2 type11(x, y, t, r)
The equations which comes under this type are
x00 = f (t)(tx0 x) + g(t)(ty 0 y)
1446
y 00 = h(t)(tx0 x) + p(t)(ty 0 y)
The transformation
u = tx0 x, v = ty 0 y
u
v
x = C3 t + t
dt,
y
=
C
t
+
t
dt.
4
2
t
t2
y 0 = bx + cy
z 0 = dx + ky + pz
Solution of such equations are forward substitution. Solving rst equations gives the
value of x, substituting it in second and third equation and solving second equation gives
y and similarly substituting y in third equation give z.
x = C1 eat
y=
z=
bC1 at
e + C2 ect
ac
C1
bk
kC2 ct
(d +
)eat +
e + C3 ept
ap
ac
cp
1447
y 0 = az cx
z 0 = bx ay
1.First integral:
ax + by + cz = A
(1)
x2 + y 2 + z 2 = B 2
(2)
where A and B are arbitrary constants. It follows from these integrals that the integral
lines are circles formed by the intersection of the planes (1) and sphere (2)
2.Solution:
x = aC0 + kC1 cos(kt) + (cC2 bC3 ) sin(kt)
1448
by 0 = ac(z x)
cz 0 = ab(x y)
1.First integral:
a2 x + b2 y + c 2 z = A
where A is an arbitary constant. It follows that the integral lines are plane curves.
2.Solution:
x = C0 + kC1 cos(kt) + a1 bc(C2 C3 ) sin(kt)
The transformation
x=e
5.27. ODE
g(t) dt
u, y = e
g(t) dt
v, z = e
g(t) dt
w, =
f (t) dt
1449
v 0 = b1 u + b2 v + b3 w
w0 = c1 u + c2 v + c3 w
These system of equations are solved by homogeneous linear system of constant coefcients of n equations of rst order. Then substituting the value of u, v and w in transformed equation gives value of x, y and z.
system of odes linear neq order1 type1
sympy.solvers.ode. linear neq order1 type1(match )
System of n rst-order constant-coecient linear nonhomogeneous dierential equation
yk0 = ak1 y1 + ak2 y2 + ... + akn yn ; k = 1, 2, ..., n
or that can be written as y~0 = A.~y where ~y is matrix of yk for k = 1, 2, ...n and A is a n n
matrix.
Since these equations are equivalent to a rst order homogeneous linear dierential
equation. So the general solution will contain n linearly independent parts and solution
will consist some type of exponential functions. Assuming y = ~v ert is a solution of the
system where ~v is a vector of coecients of y1 , ..., yn . Substituting y and y 0 = rvert into the
equation y~0 = A.~y , we get
r~v ert = A~v ert
r~v = A~v
where r comes out to be eigenvalue of A and vector ~v is the eigenvector of A corresponding to r. There are three possiblities of eigenvalues of A
n distinct real eigenvalues
complex conjugate eigenvalues
eigenvalues with multiplicity k
1. When all eigenvalues r1 , .., rn are distinct with n dierent eigenvectors v1 , ...vn then the
solution is given by
~y = C1 er1 t v~1 + C2 er2 t v~2 + ... + Cn ern t v~n
2. When some eigenvalues are complex then in order to make the solution real, we
take a llinear combination: if r = a + bi has an eigenvector ~v = w~1 + iw~2 then to obtain
real-valued solutions to the system, replace the complex-valued solutions erx~v with realvalued solution eax (w~1 cos(bx) w~2 sin(bx)) and for r = a bi replace the solution erx~v with
eax (w~1 sin(bx) + w~2 cos(bx))
3. If some eigenvalues are repeated. Then we get fewer than n linearly independent
eigenvectors, we miss some of the solutions and need to construct the missing ones. We
do this via generalized eigenvectors, vectors which are not eigenvectors but are close
enough that we can use to write down the remaining solutions. For a eigenvalue r with
eigenvector w
~ we obtain w~2 , ..., w~k using
(A rI).w~2 = w
~
(A rI).w~3 = w~2
..
.
(A rI).w~k = wk1
~
~ + tw~2 +
Then the solutions to the system for the eigenspace are ert [w],
~ ert [tw
~ + w~2 ], ert [ t2 w
k1
k2
t
rt t
w~3 ], ..., e [ (k1)! w
~ + (k2)! w~2 + ... + twk1
~ + w~k ]
So, If y~1 , ..., y~n are n solution of obtained from three categories of A, then general solution
to the system y~0 = A.~y
~y = C1 y~1 + C2 y~2 + + Cn y~n
y 0 = g(y)F (x, y)
Solution:
x = (y),
5.27. ODE
1
dy = t + C2
g(y)F ((y), y)
1451
where
if n 6= 1
= [C1 + (1 n)
1
1
dy] 1n
g(y)
if n = 1
= C1 e
1
g(y)
dy
y 0 = g(y)F (x, y)
Solution:
x = (y),
1
dy = t + C2
g(y)F ((y), y)
where
if 6= 0
1
= log(C1
if = 0
= C1 +
1
dy)
g(y)
1
dy
g(y)
1452
y 0 = G(x, y)
Then the general solution of the original system of equations has the form
1
dx = t + C1
F (x, y(x, C1 ))
y 0 = f2 (x)g2 (y)(x, y, t)
First integral:
f2 (x)
dx
f1 (x)
g1 (y)
dy = C
g2 (y)
y = ty 0 + G(x0 , y 0 )
5.27. ODE
1453
First Integrals:
ax2 + by 2 + cz 2 = C1
a2 x2 + b2 y 2 + c2 z 2 = C2
where C1 and C2 are arbitrary constants. On solving the integrals for y and z and on
substituting the resulting expressions into the rst equation of the system, we arrives at
a separable rst-order equation on x. Similarly doing that for other two equations, we
will arrive at rst order equation on y and z too.
References
-http://eqworld.ipmnet.ru/en/solutions/sysode/sode0401.pdf
system of odes nonlinear 3eq order1 type2
sympy.solvers.ode. nonlinear 3eq order1 type2(x, y, z, t, eq)
Equations:
ax0 = (b c)yzf (x, y, z, t)
by 0 = (c a)zxf (x, y, z, t)
cz 0 = (a b)xyf (x, y, z, t)
1454
First Integrals:
ax2 + by 2 + cz 2 = C1
a2 x2 + b2 y 2 + c2 z 2 = C2
where C1 and C2 are arbitrary constants. On solving the integrals for y and z and on
substituting the resulting expressions into the rst equation of the system, we arrives at
a rst-order dierential equations on x. Similarly doing that for other two equations we
will arrive at rst order equation on y and z.
References
-http://eqworld.ipmnet.ru/en/solutions/sysode/sode0402.pdf
system of odes nonlinear 3eq order1 type3
sympy.solvers.ode. nonlinear 3eq order1 type3(x, y, z, t, eq)
Equations:
x0 = cF2 bF3 , y 0 = aF3 cF1 , z 0 = bF1 aF2
-http://eqworld.ipmnet.ru/en/solutions/sysode/sode0404.pdf
5.27. ODE
1455
where Fn = Fn (x, y, z, t)
1.First integral:
ax2 + by 2 + cz 2 = C1
where z =
1
c (C1
ax2 by 2 )
References
-http://eqworld.ipmnet.ru/en/solutions/sysode/sode0405.pdf
system of odes nonlinear 3eq order1 type5
sympy.solvers.ode. nonlinear 3eq order1 type5(x, y, t, eq)
x0 = x(cF2 bF3 ), y 0 = y(aF3 cF1 ), z 0 = z(bF1 aF2 )
where C is an arbitrary constant. If the function Fn is independent of t, then, by eliminating t and z from the rst two equations of the system, one arrives at a rst-order
equation.
References
-http://eqworld.ipmnet.ru/en/solutions/sysode/sode0406.pdf
1456
These are the non-solver helper functions that are for internal use. The user should
use the various options to dsolve() (page 1397) to obtain the functionality provided
by these functions:
odesimp() (page 1406) - Does all forms of ODE simplication.
ode sol simplicity() (page 1408) - A key function for comparing solutions by
simplicity.
constantsimp() (page 1407) - Simplies arbitrary constants.
constant renumber() (page 1407) - Renumber arbitrary constants.
handle Integral() - Evaluate unevaluated Integrals.
5.27. ODE
1457
Power series solutions for second order dierential equations at ordinary and regular
singular points.
nth order linear homogeneous dierential equation with constant coecients.
nth order linear inhomogeneous dierential equation with constant coecients using
the method of undetermined coecients.
nth order linear inhomogeneous dierential equation with constant coecients using
the method of variation of parameters.
1458
undetermined coecients generally returns cleaner results for the ODEs that it can solve
than variation of parameters does, and it does not require integration, so it is much faster.
Next, you need to have a match expression or a function that matches the type of the ODE,
which you should put in classify ode() (page 1400) (if the match function is more than just a
few lines, like undetermined coefficients match(), it should go outside of classify ode()
(page 1400)). It should match the ODE without solving for it as much as possible, so that
classify ode() (page 1400) remains fast and is not hindered by bugs in solving code. Be
sure to consider corner cases. For example, if your solution method involves dividing by
something, make sure you exclude the case where that division will be 0.
In most cases, the matching of the ODE will also give you the various parts that you need to
solve it. You should put that in a dictionary (.match() will do this for you), and add that as
matching hints[hint] = matchdict in the relevant part of classify ode() (page 1400).
classify ode() (page 1400) will then send this to dsolve() (page 1397), which will send it to
your function as the match argument. Your function should be named ode <hint>(eq, func,
order, match). If you need to send more information, put it in the match
dictionary. For example, if you had to substitute in a dummy variable in classify ode()
(page 1400) to match the ODE, you will need to pass it to your function using the match dict to
access it. You can access the independent variable using func.args[0], and the dependent
variable (the function you are trying to solve for) as func.func. If, while trying to solve the
ODE, you nd that you cannot, raise NotImplementedError. dsolve() (page 1397) will catch
this error with the all meta-hint, rather than causing the whole routine to fail.
Add a docstring to your function that describes the method employed. Like with anything
else in SymPy, you will need to add a doctest to the docstring, in addition to real tests in
test ode.py. Try to maintain consistency with the other hint functions docstrings. Add
your method to the list at the top of this docstring. Also, add your method to ode.rst in
the docs/src directory, so that the Sphinx docs will pull its docstring into the main SymPy
documentation. Be sure to make the Sphinx documentation by running make html from within
the doc directory to verify that the docstring formats correctly.
If your solution method involves integrating, use C.Integral() instead of integrate()
(page 114). This allows the user to bypass hard/slow integration by using the Integral
variant of your hint. In most cases, calling sympy.core.basic.Basic.doit() (page 93)
will integrate your solution. If this is not the case, you will need to write special code in
handle Integral(). Arbitrary constants should be symbols named C1, C2, and so on. All
solution methods should return an equality instance. If you need an arbitrary number of arbitrary constants, you can use constants = numbered symbols(prefix=C, cls=Symbol,
start=1). If it is possible to solve for the dependent function in a general way, do so. Otherwise, do as best as you can, but do not call solve in your ode <hint>() function. odesimp()
(page 1406) will attempt to solve the solution for you, so you do not need to do that. Lastly,
if your ODE has a common simplication that can be applied to your solutions, you can add
a special case in odesimp() (page 1406) for it. For example, solutions returned from the
1st homogeneous coeff hints often have many log() terms, so odesimp() (page 1406) calls
logcombine() (page 1344) on them (it also helps to write the arbitrary constant as log(C1)
instead of C1 in this case). Also consider common ways that you can rearrange your solution
to have constantsimp() (page 1407) take better advantage of it. It is better to put simplication in odesimp() (page 1406) than in your method, because it can then be turned o with
the simplify ag in dsolve() (page 1397). If you have any extraneous simplication in your
function, be sure to only run it using if match.get(simplify, True):, especially if it can
be slow or if it can reduce the domain of the solution.
Finally, as with every contribution to SymPy, your method will need to be tested. Add a
test for each method in test ode.py. Follow the conventions there, i.e., test the solver using dsolve(eq, f(x), hint=your hint), and also test the solution using checkodesol()
(page 1402) (you can put these in a separate tests and skip/XFAIL if it runs too slow/doesnt
5.27. ODE
1459
work). Be sure to call your hint specically in dsolve() (page 1397), that way the test wont be
broken simply by the introduction of another matching hint. If your method works for higher
order (>1) ODEs, you will need to run sol = constant renumber(sol, C, 1, order)
for each solution, where order is the order of the ODE. This is because constant renumber
renumbers the arbitrary constants by printing order, which is platform dependent. Try to test
every corner case of your solver, including a range of orders if it is a nth order solver, but if
your solver is slow, such as if it involves hard integration, try to keep the test run time down.
Feel free to refactor existing hints to avoid duplicating code or creating inconsistencies. If you
can show that your method exactly duplicates an existing method, including in the simplicity
and speed of obtaining the solutions, then you can remove the old, less general method. The
existing code is tested extensively in test ode.py, so if anything is broken, one of those tests
will surely fail.
5.28 PDE
5.28.1 User Functions
These are functions that are imported into the global namespace with from sympy import *.
They are intended for user use.
pde separate()
sympy.solvers.pde.pde separate(eq, fun, sep, strategy=mul)
Separate variables in partial dierential equation either by additive or multiplicative
separation approach. It tries to rewrite an equation so that one of the specied variables
occurs on a dierent side of the equation than the others.
Parameters
eq Partial dierential equation
fun Original function F(x, y, z)
sep List of separated functions [X(x), u(y, z)]
strategy Separation strategy. You can choose between additive separation (add) and multiplicative separation (mul) which is default.
See Also:
pde separate add, pde separate mul
Examples
>>> from sympy import E, Eq, Function, pde_separate, Derivative as D
>>> from sympy.abc import x, t
>>> u, X, T = map(Function, uXT)
>>> eq = Eq(D(u(x, t), x), E**(u(x, t))*D(u(x, t), t))
>>> pde_separate(eq, u(x, t), [X(x), T(t)], strategy=add)
[exp(-X(x))*Derivative(X(x), x), exp(T(t))*Derivative(T(t), t)]
1460
pdsolve()
sympy.solvers.pde.pdsolve(eq, func=None, hint=default,
fun=None, **kwargs)
Solves any (supported) kind of partial dierential equation.
dict=False,
solve-
Usage
5.28. PDE
1461
pdsolve(eq, f(x,y), hint) -> Solve partial dierential equation eq for function
f(x,y), using method hint.
Details
eq can be any supported partial dierential equation (see the pde docstring for supported methods). This can either be an Equality, or an expression, which is assumed to be equal to 0.
f(x,y) is a function of two variables whose derivatives in that variable
make up the partial dierential equation. In many cases it is not necessary
to provide this; it will be autodetected (and an error raised if it couldnt be
detected).
hint is the solving method that you want pdsolve to use. Use
classify pde(eq, f(x,y)) to get all of the possible hints for a PDE. The default
hint, default, will use whatever hint is returned rst by classify pde(). See
Hints below for more options that you can use for hint.
solvefun is the convention used for arbitrary functions returned by the
PDE solver. If not set by the user, it is set by default to be F.
Hints
Aside from the various solving methods, there are also some meta-hints that you
can pass to pdsolve():
default: This uses whatever hint is returned rst by classify pde(). This is
the default argument to pdsolve().
all: To make pdsolve apply all relevant classication hints, use pdsolve(PDE,
func, hint=all). This will return a dictionary of hint:solution terms. If a
hint causes pdsolve to raise the NotImplementedError, value of that hints
key will be the exception object raised. The dictionary will also include some
special keys:
order: The order of the PDE. See also ode order() in deutils.py
default: The solution that would be returned by default. This is the one
produced by the hint that appears rst in the tuple returned by classify pde().
all Integral: This is the same as all, except if a hint also has a corresponding Integral hint, it only returns the Integral hint. This is useful if all
causes pdsolve() to hang because of a dicult or impossible integral. This
meta-hint will also be much faster than all, because integrate() is an expensive routine.
See also the classify pde() docstring for more info on hints, and the pde docstring for a list of all supported hints.
Tips
You can declare the derivative of an unknown function this way:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1462
See test pde.py for many tests, which serves also as a set of examples for how
to use pdsolve().
pdsolve always returns an Equality class (except for the case when the hint is
all or all Integral). Note that it is not possible to get an explicit solution for
f(x, y) as in the case of ODEs
Do help(pde.pde hintname) to get help more information on a specic hint
Examples
>>> from sympy.solvers.pde import pdsolve
>>> from sympy import Function, diff, Eq
>>> from sympy.abc import x, y
>>> f = Function(f)
>>> u = f(x, y)
>>> ux = u.diff(x)
>>> uy = u.diff(y)
>>> eq = Eq(1 + (2*(ux/u)) + (3*(uy/u)))
>>> pdsolve(eq)
f(x, y) == F(3*x - 2*y)*exp(-2*x/13 - 3*y/13)
classify pde()
sympy.solvers.pde.classify pde(eq, func=None, dict=False, **kwargs)
Returns a tuple of possible pdsolve() classications for a PDE.
The tuple is ordered so that rst item is the classication that pdsolve() uses to solve the
PDE by default. In general, classications near the beginning of the list will produce better solutions faster than those near the end, though there are always exceptions. To make
pdsolve use a dierent classication, use pdsolve(PDE, func, hint=<classication>). See
also the pdsolve() docstring for dierent meta-hints you can use.
If dict is true, classify pde() will return a dictionary of hint:match expression terms.
This is intended for internal use by pdsolve(). Note that because dictionaries are ordered
arbitrarily, this will most likely not be in the same order as the tuple.
You can get help on dierent hints by doing help(pde.pde hintname), where hintname is
the name of the hint without Integral.
See sympy.pde.allhints or the sympy.pde docstring for a list of all supported hints that
can be returned from classify pde.
Examples
>>> from sympy.solvers.pde import classify_pde
>>> from sympy import Function, diff, Eq
>>> from sympy.abc import x, y
>>> f = Function(f)
>>> u = f(x, y)
>>> ux = u.diff(x)
>>> uy = u.diff(y)
>>> eq = Eq(1 + (2*(ux/u)) + (3*(uy/u)))
>>> classify_pde(eq)
(1st_linear_constant_coeff_homogeneous,)
5.28. PDE
1463
checkpdesol()
sympy.solvers.pde.checkpdesol(pde, sol, func=None, solve for func=True)
Checks if the given solution satises the partial dierential equation.
pde is the partial dierential equation which can be given in the form of an equation or
an expression. sol is the solution for which the pde is to be checked. This can also be
given in an equation or an expression form. If the function is not provided, the helper
function preprocess from deutils is used to identify the function.
If a sequence of solutions is passed, the same sort of container will be used to return the
result for each solution.
The following methods are currently being implemented to check if the solution satises
the PDE:
1.Directly substitute the solution in the PDE and check. If the solution hasnt been
solved for f, then it will solve for f provided solve for func hasnt been set to False.
If the solution satises the PDE, then a tuple (True, 0) is returned. Otherwise a tuple
(False, expr) where expr is the value obtained after substituting the solution in the PDE.
However if a known solution returns False, it may be due to the inability of doit() to
simplify it to zero.
Examples
1464
df (x, y)
df (x, y)
+b
+ cf (x, y) = 0
dx
dy
References
Viktor Grigoryan, Partial Dierential Equations Math 124A - Fall 2010, pp.7
Examples
>>> from sympy.solvers.pde import (
... pde_1st_linear_constant_coeff_homogeneous)
>>> from sympy import pdsolve
>>> from sympy import Function, diff, pprint
>>> from sympy.abc import x,y
>>> f = Function(f)
>>> pdsolve(f(x,y) + f(x,y).diff(x) + f(x,y).diff(y))
f(x, y) == F(x - y)*exp(-x/2 - y/2)
>>> pprint(pdsolve(f(x,y) + f(x,y).diff(x) + f(x,y).diff(y)))
x
y
- - - 2
2
f(x, y) = F(x - y)*e
5.28. PDE
df (x, y)
df (x, y)
+b
+ cf (x, y) = G(x, y)
dx
dy
1465
where a, b and c are constants and G(x, y) can be an arbitrary function in x and y.
The general solution of the PDE is:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
References
Viktor Grigoryan, Partial Dierential Equations Math 124A - Fall 2010, pp.7
1466
Examples
>>> from sympy.solvers.pde import pdsolve
>>> from sympy import Function, diff, pprint, exp
>>> from sympy.abc import x,y
>>> f = Function(f)
>>> eq = -2*f(x,y).diff(x) + 4*f(x,y).diff(y) + 5*f(x,y) - exp(x + 3*y)
>>> pdsolve(eq)
f(x, y) == (F(4*x + 2*y) + exp(x/2 + 4*y)/15)*exp(x/2 - y)
df (x, y)
df (x, y)
+ a(x, y)
+ c(x, y)f (x, y) G(x, y)
dx
dy
where a(x, y), b(x, y), c(x, y) and G(x, y) are arbitrary functions in x and y. This PDE is
converted into an ODE by making the following transformation.
1] as x
2] as the constant in the solution to the dierential equation
dy
dx
= ab
du
+ c(, )u d(, ) = 0
d
References
Viktor Grigoryan, Partial Dierential Equations Math 124A - Fall 2010, pp.7
5.28. PDE
1467
Examples
>>> from sympy.solvers.pde import pdsolve
>>> from sympy import Function, diff, pprint, exp
>>> from sympy.abc import x,y
>>> f = Function(f)
>>> eq = x*(u.diff(x)) - y*(u.diff(y)) + y**2*u - y**2
>>> pdsolve(eq)
f(x, y) == F(x*y)*exp(y**2/2) + 1
5.29 Solvers
The solvers module in SymPy implements methods for solving equations.
1468
The rst argument for solve() is an equation (equaled to zero) and the second argument is
the symbol that we want to solve the equation for.
sympy.solvers.solvers.solve(f, *symbols, **ags)
Algebraically solves equations and systems of equations.
Currently supported are:
univariate polynomial,
transcendental
piecewise combinations of the above
systems of linear and polynomial equations
sytems containing relational expressions.
5.29. Solvers
1469
If check=False then a solution to the numerator being zero is found: x = 0. In this case,
this is a spurious solution since sin(x)/x has the well known limit (without dicontinuity)
of 1 at x = 0:
>>> solve(sin(x)/x, check=False)
[0, pi]
In the following case, however, the limit exists and is equal to the the value of x = 0 that
is excluded when check=True:
>>>
>>>
[]
>>>
[0]
>>>
0
>>>
0
eq = x**2*(1/x - z**2/x)
solve(eq, x)
solve(eq, x, check=False)
limit(eq, x, 0, -)
limit(eq, x, 0, +)
Examples
The output varies according to the input and can be seen by example:
1470
In this case, all free symbols will be selected as potential symbols to solve
for. If the equation is univariate then a list of solutions is returned; otherwise
as is the case when symbols are given as an iterable of length > 1 a list
of mappings will be returned.
>>> solve(x - 3)
[3]
>>> solve(x**2 - y**2)
[{x: -y}, {x: y}]
>>> solve(z**2*x**2 - z**2*y**2)
[{x: -y}, {x: y}, {z: 0}]
>>> solve(z**2*x - z**2*y**2)
[{x: y**2}, {z: 0}]
5.29. Solvers
1471
Nothing heroic is done in this implicit solving so you may end up with a
symbol still in the solution:
>>>
>>>
{y:
>>>
{x:
if you attempt to solve for a number remember that the number you have
obtained does not necessarily mean that the value is equivalent to the
expression obtained:
>>> solve(sqrt(2) - 1, 1)
[sqrt(2)]
>>> solve(x - y + 1, 1) # /!\ -1 is targeted, too
[x/(y - 1)]
>>> [_.subs(z, -1) for _ in solve((x - y + 1).subs(-1, z), 1)]
[-x + y]
if there is no linear solution then the rst successful attempt for a nonlinear
solution will be returned
>>> solve(x**2 - y**2, x, y)
[{x: -y}, {x: y}]
>>> solve(x**2 - y**2/exp(x), x, y)
[{x: 2*LambertW(y/2)}]
>>> solve(x**2 - y**2/exp(x), y, x)
[{y: -x*sqrt(exp(x))}, {y: x*sqrt(exp(x))}]
solve([x - 3], x)
3}
solve((x + 5*y - 2,
-3, y: 1}
solve((x + 5*y - 2,
-3, y: 1}
solve((x + 5*y - 2,
-5*y + 2, z: 21*y -
*without a solution
>>> solve([x + 3, x - 3])
[]
5.29. Solvers
1473
if no symbols are given, all free symbols will be selected and a list of mappings
returned
>>> solve([x - 2, x**2 + y])
[{x: 2, y: -4}]
>>> solve([x - 2, x**2 + f(x)], set([f(x), x]))
[{x: 2, f(x): -4}]
if any equation doesnt depend on the symbol(s) given it will be eliminated from
the equation set and an answer may be given implicitly in terms of variables that
were not of interest
>>> solve([x - y, y - 3], x)
{x: y}
solve_linear(x + y**2)
-y**2)
solve_linear(1/x - y**2)
y**(-2))
When not linear in x or y then the numerator and denominator are returned.
>>> solve_linear(x**2/y**2 - 3)
(x**2 - 3*y**2, y**2)
1474
If the numerator is a symbol then (0, 0) is returned if the solution for that symbol would
have set any denominator to 0:
>>>
(0,
>>>
x
>>>
(x,
solve_linear(1/(1/x - 2))
0)
1/(1/x) # to SymPy, this looks like x ...
solve_linear(1/(1/x)) # so a solution is given
0)
If x is allowed to cancel, then this appears linear, but this sort of cancellation is not done
so the solution will always satisfy the original expression without causing a division by
zero error.
>>> solve_linear(x**2*(1/x - z**2/x))
(x**2*(-z**2 + 1), x)
You can also indicate what variables you dont want to consider:
>>> solve_linear(x + y + z, exclude=[x, z])
(y, -x - z)
5.29. Solvers
1475
solve_linear_system_LU(Matrix([
[1, 2, 0, 1],
[3, 2, 2, 1],
[2, 0, 0, 1]]), [x, y, z])
1/2, y: 1/4, z: -1/2}
sympy.solvers.solvers.nsolve(*args, **kwargs)
Solve a nonlinear equation system numerically:
nsolve(f, [args,] x0, modules=[mpmath], **kwargs)
f is a vector function of symbolic expressions representing the system. args are the
variables. If there is only one variable, this argument can be omitted. x0 is a starting
vector close to a solution.
Use the modules keyword to specify which modules should be used to evaluate the function and the Jacobian matrix. Make sure to use a module that supports matrices. For
more information on the syntax, please see the docstring of lambdify.
1476
5.29. Solvers
1477
Input can be either a single symbol and corresponding value or a dictionary of symbols
and values. When given as a dictionary and ag simplify=True, the values in the dictionary will be simplied. f can be a single equation or an iterable of equations. A solution
must satisfy all equations in f to be considered valid; if a solution does not satisfy any
equation, False is returned; if one or more checks are inconclusive (and none are False)
then None is returned.
Examples
>>> from sympy import symbols
>>> from sympy.solvers import checksol
>>> x, y = symbols(x,y)
>>> checksol(x**4 - 1, x, 1)
True
>>> checksol(x**4 - 1, x, 0)
False
>>> checksol(x**2 + y**2 - 5**2, {x: 3, y: 4})
True
To check if an expression is zero using checksol, pass it as f and send an empty dictionary
for symbol:
>>> checksol(x**2 + x - x*(x + 1), {})
True
1478
Examples
>>>
>>>
>>>
>>>
>>>
...
2
>>>
2
>>>
3
where ai (n), for i = 0, . . . , k, are polynomials or rational functions in n, and f is a hypergeometric function or a sum of a xed number of pairwise dissimilar hypergeometric terms
in n, nds all solutions or returns None, if none were found.
Initial conditions can be given as a dictionary in two forms:
1.{ n 0 : v 0, n 1 : v 1, ..., n m : v m }
2.{ y(n 0) : v 0, y(n 1) : v 1, ..., y(n m) : v m }
or as a list L of values:
L = [ v 0, v 1, ..., v m ]
where L[i] = v i, for i = 0, . . . , m, maps to y(ni ).
See Also:
rsolve poly (page 1480), rsolve ratio (page 1480), rsolve hyper (page 1481)
Examples
5.29. Solvers
1479
References
1480
2.Construct new linear dierence equation by substitution y(n) = u(n)/v(n) and solve
it for u(n) nding all its polynomial solutions. Return None if none were found.
Algorithm implemented here is a revised version of the original Abramovs algorithm,
developed in 1989. The new approach is much simpler to implement and has better
overall eciency. This method can be easily adapted to q-dierence equations case.
Besides nding rational solutions alone, this functions is an important part of Hyper algorithm were it is used to nd particular solution of inhomogeneous part of a recurrence.
See Also:
rsolve hyper (page 1481)
References
5.29. Solvers
1481
References
1482
>>> solve_triangulated(F, x, y, z)
[(0, 0, 1), (0, 1, 0), (1, 0, 0)]
5.29.8 Inequalities
See Inequality Solvers (page 1505)
5.30 Diophantine
5.30.1 Diophantine equations
The word Diophantine comes with the name Diophantus, a mathematician lived in the great
city of Alexandria sometime around 250 AD. Often referred to as the father of Algebra, Diophantus in his famous work Arithmetica presented 150 problems that marked the early
beginnings of number theory, the eld of study about integers and their properties. Diophantine equations play a central and an important part in number theory.
We call a Diophantine equation to an equation of the form, f (x1 , x2 , . . . xn ) = 0 where n 2 and
x1 , x2 , . . . xn are integer variables. If we can nd n integers a1 , a2 , . . . an such that x1 = a1 , x2 =
a2 , . . . xn = an satises the above equation, we say that the equation is solvable. You can read
more about Diophantine equations in 5 and 6 .
Currently, following ve types of Diophantine equations can be solved using diophantine()
(page 1487) and other helper functions of the Diophantine module.
Linear Diophantine equations: a1 x1 + a2 x2 + . . . + an xn = b.
General binary quadratic equation: ax2 + bxy + cy 2 + dx + ey + f = 0
Homogeneous ternary quadratic equation: ax2 + by 2 + cz 2 + dxy + eyz + f zx = 0
Extended Pythagorean equation: a1 x21 + a2 x22 + . . . + an x2n = an+1 x2n+1
General sum of squares: x21 + x22 + . . . + x2n = k
5.30. Diophantine
1483
5.30.3 Tutorial
First, lets import the highest API of the Diophantine module.
>>> from sympy.solvers.diophantine import diophantine
Lets start by solving the easiest type of Diophantine equations, i.e. linear Diophantine equations. Lets solve 2x + 3y = 5. Note that although we write the equation in the above form,
when we input the equation to any of the functions in Diophantine module, it needs to be in
the form eq = 0.
>>> diophantine(2*x + 3*y - 5)
set([(3*t - 5, -2*t + 5)])
Note that stepping one more level below the highest API, we can solve the very same equation
by calling diop solve() (page 1488).
>>> from sympy.solvers.diophantine import diop_solve
>>> diop_solve(2*x + 3*y - 5)
(3*t - 5, -2*t + 5)
Note that it returns a tuple rather than a set. diophantine() (page 1487) always return
a set of tuples. But diop solve() (page 1488) may return a single tuple or a set of tuples
depending on the type of the equation given.
We can also solve this equation by calling diop linear() (page 1490), which is what
diop solve() (page 1488) calls internally.
1484
If the given equation has no solutions then the outputs will look like below.
>>> diophantine(2*x + 4*y - 3)
set()
>>> diop_solve(2*x + 4*y - 3)
(None, None)
>>> diop_linear(2*x + 4*y - 3)
(None, None)
Note that except for the highest level API, in case of no solutions, a tuple of N one are returned. Size of the tuple is the same as the number of variables. Also, one can specically
set the parameter to be used in the solutions by passing a customized parameter. Consider
the following example.
>>> m = symbols(m, integer=True)
>>> diop_solve(2*x + 3*y - 5, m)
(3*m - 5, -2*m + 5)
Please note that for the moment, user can set the parameter only for linear Diophantine
equations and binary quadratic equations.
Lets try solving a binary quadratic equation which is an equation with two variables and has a
degree of two. Before trying to solve these equations, an idea about various cases associated
with the equation would help a lot. Please refer 7 and 8 for detailed analysis of dierent
cases and the nature of the solutions. Let us dene = b2 4ac w.r.t. the binary quadratic
ax2 + bxy + cy 2 + dx + ey + f = 0.
When < 0, there are either no solutions or only a nite number of solutions.
>>> diophantine(x**2 - 4*x*y + 8*y**2 - 3*x + 7*y - 5)
set([(2, 1), (5, 1)])
In the above equation = (4)2 4 1 8 = 16 and hence only a nite number of solutions
exist.
When = 0 we might have either no solutions or parameterized solutions.
>>> diophantine(3*x**2 - 6*x*y + 3*y**2 - 3*x + 7*y - 5)
set()
>>> diophantine(x**2 - 4*x*y + 4*y**2 - 3*x + 7*y - 5)
set([(-2*t**2 - 7*t + 10, -t**2 - 3*t + 5)])
>>> diophantine(x**2 + 2*x*y + y**2 - 3*x - 3*y)
set([(t, -t), (t, -t + 3)])
The most interesting case is when > 0 and it is not a perfect square. In this case, the
equation has either no solutions or an innte number of solutions. Consider the below cases
where = 8.
>>> diophantine(x**2 - 4*x*y + 2*y**2 - 3*x + 7*y - 5)
set()
>>> from sympy import expand
>>> n = symbols(n, integer=True)
7
Methods to solve Ax2 + Bxy + Cy2 + Dx + Ey + F = 0,[online],
Available:
http://www.alpertron.com.ar/METHODS.HTM
8 Solving the equation ax2+ bxy + cy2 + dx + ey + f= 0, [online], Available: http://www.jpr2718.org/ax2p.pdf
5.30. Diophantine
1485
Here n is an integer. Although x n and y n may not look like integers, substituting in specic
values for n (and simplifying) shows that they are. For example consider the following example
where we set n equal to 9.
>>> from sympy import simplify
>>> simplify(x_n.subs({n: 9}))
-9369318
So, the above equation is equivalent to the equation X 2 5Y 2 = 920 after a linear transformation. If we want to nd the linear transformation, we can use transformation to DN()
(page 1494)
>>> A, B = transformation_to_DN(x**2 - 3*x*y + y**2 - 7*x + 5*y - 3)
1486
If you are only interested about a base solution rather than the parameterized general solution
(to be more precise, one of the general solutions), you can use diop ternary quadratic()
(page 1495).
>>> from sympy.solvers.diophantine import diop_ternary_quadratic
>>> diop_ternary_quadratic(3*x**2 + 4*y**2 - 5*z**2 + 4*x*y - 7*y*z + 7*z*x)
(-4, 5, 1)
diop ternary quadratic() (page 1495) rst converts the given equation to an equivalent
equation of the form w2 = AX 2 + BY 2 and then it uses descent() (page 1496) to solve the
latter equation. You can refer to the docs of transformation to normal() to nd more on
this. The equation w2 = AX 2 + BY 2 can be solved more easily by using the Aforementioned
descent() (page 1496).
>>> from sympy.solvers.diophantine import descent
>>> descent(3, 1) # solves the equation w**2 = 3*Y**2 + Z**2
(1, 0, 1)
function diop general pythagorean() (page 1497) can also be called directly to solve the
same equation. This is true about the general sum of squares too. Either you can call
diop general pythagorean() (page 1497) or use the high level API.
>>> diophantine(a**2 + b**2 + c**2 + d**2 + e**2 + f**2 - 112)
set([(8, 4, 4, 4, 0, 0)])
If you want to get a more thorough idea about the the Diophantine module please refer to the
following blog.
http://thilinaatsympy.wordpress.com/
5.30.4 References
5.30.5 User Functions
These are functions that are imported into the global namespace with from sympy import *.
These functions are intended for use by ordinary users of SymPy.
diophantine()
sympy.solvers.diophantine.diophantine(eq, param=t)
Simplify the solution procedure of diophantine equation eq by converting it into a product
of terms which should equal zero.
For example, when solving, x2 y 2 = 0 this is treated as (x + y)(x y) = 0 and x + y = 0
and x y = 0 are solved independently and combined. Each term is solved by calling
diop solve().
5.30. Diophantine
1487
Output of diophantine() is a set of tuples. Each tuple represents a solution of the input
equation. In a tuple, solution for each variable is listed according to the alphabetic order
of input variables. i.e. if we have an equation with two variables a and b, rst element of
the tuple will give the solution for a and the second element will give the solution for b.
See Also:
diop solve
Examples
>>> from sympy.solvers.diophantine import diophantine
>>> from sympy.abc import x, y, z
>>> diophantine(x**2 - y**2)
set([(-t, -t), (t, -t)])
#>>> diophantine(x*(2*x + 3*y - z)) #set([(0, n1, n2), (3*t - z, -2*t + z, z)]) #>>> diophantine(x**2 + 3*x*y + 4*x) #set([(0, n1), (3*t - 4, -t)])
Usage
diophantine(eq, t): Solve the diophantine equation eq. t is the parameter to be used
by diop solve().
Details
1488
Usage
Usage
5.30. Diophantine
1489
diop linear()
sympy.solvers.diophantine.diop linear(eq, param=t)
Solves linear diophantine equations.
A linear diophantine equation is an equation of the form a1 x1 + a2 x2 + .. + an xn = 0 where
a1 , a2 , ..an are integer constants and x1 , x2 , ..xn are integer variables.
See Also:
diop quadratic,
diop ternary quadratic,
diop general sum of squares
Examples
>>> from sympy.solvers.diophantine import diop_linear
>>> from sympy.abc import x, y, z, t
>>> from sympy import Integer
>>> diop_linear(2*x - 3*y - 5) #solves equation 2*x - 3*y -5 = 0
(-3*t - 5, -2*t - 5)
Usage
diop linear(eq): Returns a tuple containing solutions to the diophantine equation eq.
Values in the tuple is arranged in the same order as the sorted variables.
Details
1490
Usage
References
Usage
5.30. Diophantine
1491
diop DN()
sympy.solvers.diophantine.diop DN(D, N, t=t)
Solves the equation x2 Dy 2 = N .
Mainly concerned in the case D > 0, D is not a perfect square, which is the same as
generalized Pell equation. To solve the generalized Pell equation this function Uses LMM
algorithm. Refer [R357] (page 1914) for more details on the algorithm. Returns one
solution for each class of the solutions. Other solutions of the class can be constructed
according to the values of D and N. Returns a list containing the solution tuples (x, y).
See Also:
find DN, diop bf DN
References
The output can be interpreted as follows: There are three fundamental solutions to the
equation x2 13y 2 = 4 given by (3, 1), (393, 109) and (36, 10). Each tuple is in the form
(x, y), i. e solution (3, 1) means that x = 3 and y = 1.
>>> diop_DN(986, 1) # Solves equation x**2 - 986*y**2 = 1
[(49299, 1570)]
Usage
1492
References
diop bf DN()
sympy.solvers.diophantine.diop bf DN(D, N, t=t)
Uses brute force to solve the equation, x2 Dy 2 = N .
Mainly concerned with the generalized Pell equation which is the case when D > 0, D is
not a perfect square. For more information on the case refer [R360] (page 1914). Let
2
2
(t, u) be the
minimal positive solution of the equation x Dy = 1. Then this method
requires
|N |(t1)
2D
to be small.
See Also:
diop DN
References
Usage
5.30. Diophantine
1493
transformation to DN()
sympy.solvers.diophantine.transformation to DN(eq)
This function transforms general quadratic, ax2 + bxy + cy 2 + dx + ey + f = 0 to more easy
to deal with X 2 DY 2 = N form.
This is used to solve the general quadratic equation by transforming it to the latter form.
Refer [R361] (page 1914) for more detailed information on the transformation. This
function returns a tuple (A, B) where A is a 2 X 2 matrix and B is a 2 X 1 matrix such
that,
Transpose([x y]) = A * Transpose([X Y]) + B
See Also:
find DN
References
By multiplying the denominator appropriately, we can get a Pell equation in the standard
form.
1494
>>> eq * 676
X**2 - 13*Y**2 + 884
Interpretation of the output is that we get X 2 13Y 2 = 884 after transforming x2 3xy
y 2 2y + 1 using the transformation returned by transformation to DN().
Usage
5.30. Diophantine
1495
Examples
>>> from sympy.abc import x, y, z
>>> from sympy.solvers.diophantine import diop_ternary_quadratic
>>> diop_ternary_quadratic(x**2 + 3*y**2 - z**2)
(1, 0, 1)
>>> diop_ternary_quadratic(4*x**2 + 5*y**2 - z**2)
(1, 0, 2)
>>> diop_ternary_quadratic(45*x**2 - 7*y**2 - 8*x*y - z**2)
(28, 45, 105)
>>> diop_ternary_quadratic(x**2 - 49*y**2 - z**2 + 13*z*y -8*x*y)
(9, 1, 5)
Usage
eq should be an homogeneous expression of degree two in three variables and it is assumed to be zero.
square factor()
sympy.solvers.diophantine.square factor(a)
Returns an integer c s.t. a = c2 k, c, k Z. Here k is square free.
Examples
>>>
>>>
2
>>>
6
>>>
1
descent()
sympy.solvers.diophantine.descent(A, B)
Lagranges descent() with lattice-reduction to nd solutions to x2 = Ay 2 + Bz 2 .
Here A and B should be square free and pairwise prime. Always should be called with
suitable A and B so that the above equation has solutions.
This is more faster than the normal Lagranges descent algorithm because the gaussian
reduction is used.
1496
References
+ 15*m4**2, 15*m
Usage
5.30. Diophantine
1497
Examples
>>> from sympy.solvers.diophantine import diop_general_sum_of_squares
>>> from sympy.abc import a, b, c, d, e, f
>>> diop_general_sum_of_squares(a**2 + b**2 + c**2 + d**2 + e**2 - 2345)
set([(0, 48, 5, 4, 0)])
Usage
partition()
sympy.solvers.diophantine.partition(n, k=None, zeros=False)
Returns a generator that can be used to generate partitions of an integer n.
A partition of n is a set of positive integers which add upto n. For example, partitions of
3 are 3 , 1 + 2, 1 + 1+ 1. A partition is returned as a tuple. If k equals None, then all
possible partitions are returned irrespective of their size, otherwise only the partitions
of size k are returned. If there are no partions of n with size k then an empty tuple is
returned. If the zero parameter is set to True then a suitable number of zeros are added
at the end of every partition of size less than k.
zero parameter is considered only if k is not None. When the partitions are over, the
last next() call throws the StopIteration exception, so this function should always be
used inside a try - except block.
Examples
>>>
>>>
>>>
(1,
>>>
(1,
>>>
>>>
(3,
>>>
(2,
1498
Details
partition(n, k): Here n is a positive integer and k is the size of the partition which is
also positive integer.
Reference
Usage
5.30. Diophantine
1499
Usage
Usage
1500
PQa
sympy.solvers.diophantine.PQa(P 0, Q 0, D)
Returns useful information needed to solve the Pell equation.
There are six
sequences of integers dened related to the continued fraction represen
P+ D
tation of Q , namely {Pi }, {Qi }, {ai },{Ai }, {Bi }, {Gi }. PQa() Returns these values as
a 6-tuple in the same order as mentioned above. Refer [R368] (page 1915) for more
detailed information.
References
Usage
5.30. Diophantine
1501
Usage
equivalent(u, v, r, s, D, N): (u, v) and (r, s) are two solutions of the equation
x2 Dy 2 = N and all parameters involved are integers.
simplified
sympy.solvers.diophantine.simplified(x, y, z)
Simplify the solution (x, y, z).
parametrize ternary quadratic
sympy.solvers.diophantine.parametrize ternary quadratic(eq)
Returns the parametrized general solution for the ternary quadratic equation eq which
has the form ax2 + by 2 + cz 2 + f xy + gyz + hxz = 0.
References
Examples
>>>
>>>
>>>
(1,
>>>
(1,
>>>
(4,
Usage
diop ternary quadratic normal(eq): where eq is an equation of the form ax2 +by 2 +cz 2 =
0.
ldescent
sympy.solvers.diophantine.ldescent(A, B)
Uses Lagranges method to nd a non trivial solution to w2 = Ax2 + By 2 .
Here, A 6= 0 and B 6= 0 and A and B are square free. Output a tuple (w0 , x0 , y0 ) which is a
solution to the above equation.
References
gaussian reduce
sympy.solvers.diophantine.gaussian reduce(w, a, b)
Returns a reduced solution (x, z) to the congruence X 2 aZ 2 0 (mod b) so that x2 + |a|z 2
is minimal.
References
1503
Details
Reference
pairwise prime
sympy.solvers.diophantine.pairwise prime(a, b, c)
Transform ax2 + by 2 + cz 2 = 0 into an equivalent equation a0 x2 + b0 y 2 + c0 z 2 = 0 where a0 , b0 , c0
are pairwise relatively prime.
Returns a tuple containing a0 , b0 , c0 . gcd(a, b, c) should equal 1 for this to work. The solutions for ax2 + by 2 + cz 2 = 0 can be recovered from the solutions of a0 x2 + b0 y 2 + c0 z 2 = 0.
See Also:
make prime, reocnstruct
Examples
>>> from sympy.solvers.diophantine import pairwise_prime
>>> pairwise_prime(6, 15, 10)
(5, 2, 3)
make prime
sympy.solvers.diophantine.make prime(a, b, c)
Transform the equation ax2 + by 2 + cz 2 = 0 to an equivalent equation a0 x2 + b0 y 2 + c0 z 2 = 0
with gcd(a0 , b0 ) = 1.
Returns a tuple (a0 , b0 , c0 ) which satises above conditions. Note that in the returned tuple
gcd(a0 , c0 ) and gcd(b0 , c0 ) can take any value.
1504
See Also:
pairwaise prime, reconstruct
Examples
>>> from sympy.solvers.diophantine import make_prime
>>> make_prime(4, 2, 7)
(2, 1, 14)
reconstruct
sympy.solvers.diophantine.reconstruct(a, b, z)
Reconstruct the z value of an equivalent solution of ax2 + by 2 + cz 2 from the z value of a
solution of a transformed version of the above equation.
1505
Examples
>>> from sympy import Poly
>>> from sympy.abc import x
>>> from sympy.solvers.inequalities import solve_poly_inequality
>>> solve_poly_inequality(Poly(x, x, domain=ZZ), ==)
[{0}]
>>> solve_poly_inequality(Poly(x**2 - 1, x, domain=ZZ), !=)
[(-oo, -1), (-1, 1), (1, oo)]
>>> solve_poly_inequality(Poly(x**2 - 1, x, domain=ZZ), ==)
[{-1}, {1}]
rela-
Examples
>>> from sympy import Poly, Symbol
>>> from sympy.solvers.inequalities import reduce_rational_inequalities
>>> x = Symbol(x, real=True)
>>> reduce_rational_inequalities([[x**2 <= 0]], x)
x == 0
>>> reduce_rational_inequalities([[x + 2 > 0]], x)
And(-2 < x, x < oo)
>>> reduce_rational_inequalities([[(x + 2, >)]], x)
And(-2 < x, x < oo)
>>> reduce_rational_inequalities([[x + 2]], x)
x == -2
1506
rela-
Examples
>>> from sympy.solvers.inequalities import solve_univariate_inequality
>>> from sympy.core.symbol import Symbol
>>> x = Symbol(x, real=True)
>>> solve_univariate_inequality(x**2 >= 4, x)
Or(And(-oo < x, x <= -2), And(2 <= x, x < oo))
>>> solve_univariate_inequality(x**2 >= 4, x, relational=False)
(-oo, -2] U [2, oo)
1507
5.32.1 Contents
Indexed Objects
Module that denes indexed objects
The classes IndexedBase, Indexed and Idx would represent a matrix element M[i, j] as in the
following graph:
1) The Indexed class represents the entire indexed object.
|
|
M[i, j]
/
\ \
|
|
|
|
|
2) The Idx class represent indices and each Idx can
|
optionally contain information about its range.
|
3) IndexedBase represents the stem of an indexed object, here M.
The stem used by itself is usually taken to represent the entire
array.
There can be any number of indices on an Indexed object. No transformation properties are
implemented in these Base objects, but implicit contraction of repeated indices is supported.
Note that the support for complicated (i.e. non-atomic) integer expressions as indices is
limited. (This should be improved in future releases.)
Examples
If the indexed objects will be converted to component based arrays, e.g. with the code printers
or the autowrap framework, you also need to provide (symbolic or numerical) dimensions.
This can be done by passing an optional shape parameter to IndexedBase upon construction:
1508
If an IndexedBase object has no shape information, it is assumed that the array is as large as
the ranges of its indices:
>>> n, m = symbols(n m, integer=True)
>>> i = Idx(i, m)
>>> j = Idx(j, n)
>>> M[i, j].shape
(m, n)
>>> M[i, j].ranges
[(0, m - 1), (0, n - 1)]
To analyze the structure of indexed expressions, you can use the methods get indices() and
get contraction structure():
>>> from sympy.tensor import get_indices, get_contraction_structure
>>> get_indices(A[i, j, j])
(set([i]), {})
>>> get_contraction_structure(A[i, j, j])
{(j,): set([A[i, j, j]])}
Note: the Idx constructor is rather pedantic in that it only accepts integer arguments.
The only exception is that you can use oo and -oo to specify an unbounded range. For all
other cases, both label and bounds must be declared as integers, e.g. if n is given as an
argument then n.is integer must return True.
For convenience, if the label is given as a string it is automatically converted to an integer
symbol. (Note: this conversion is not done for range or dimension arguments.)
1509
Examples
>>> from sympy.tensor import IndexedBase, Idx
>>> from sympy import symbols, oo
>>> n, i, L, U = symbols(n i L U, integer=True)
If a string is given for the label an integer Symbol is created and the bounds are both
None:
>>> idx = Idx(qwerty); idx
qwerty
>>> idx.lower, idx.upper
(None, None)
When only a single bound is given it is interpreted as the dimension and the lower bound
defaults to 0:
>>>
(0,
>>>
(0,
>>>
(0,
idx
n idx
3)
idx
oo)
label
Returns the label (Integer or integer expression) of the Idx object.
Examples
>>>
>>>
2
>>>
>>>
j
>>>
j +
lower
Returns the lower bound of the Index.
1510
Examples
>>> from sympy import Idx
>>> Idx(j, 2).lower
0
>>> Idx(j, 5).lower
0
>>> Idx(j).lower is None
True
upper
Returns the upper bound of the Index.
Examples
>>> from sympy import Idx
>>> Idx(j, 2).upper
1
>>> Idx(j, 5).upper
4
>>> Idx(j).upper is None
True
class sympy.tensor.indexed.Indexed
Represents a mathematical object with indices.
>>> from sympy.tensor import Indexed, IndexedBase, Idx
>>> from sympy import symbols
>>> i, j = symbols(i j, cls=Idx)
>>> Indexed(A, i, j)
A[i, j]
base
Returns the IndexedBase of the Indexed object.
Examples
>>> from sympy.tensor import Indexed, IndexedBase, Idx
>>> from sympy import symbols
>>> i, j = symbols(i j, cls=Idx)
>>> Indexed(A, i, j).base
A
>>> B = IndexedBase(B)
>>> B == B[i, j].base
True
indices
Returns the indices of the Indexed object.
1511
Examples
>>>
>>>
>>>
>>>
(i,
ranges
Returns a list of tuples with lower and upper range of each index.
If an index does not dene the data members upper and lower, the corresponding
slot in the list contains None instead of a tuple.
Examples
>>> from sympy import Indexed,Idx, symbols
>>> Indexed(A, Idx(i, 2), Idx(j, 4), Idx(k, 8)).ranges
[(0, 1), (0, 3), (0, 7)]
>>> Indexed(A, Idx(i, 3), Idx(j, 3), Idx(k, 3)).ranges
[(0, 2), (0, 2), (0, 2)]
>>> x, y, z = symbols(x y z, integer=True)
>>> Indexed(A, x, y, z).ranges
[None, None, None]
rank
Returns the rank of the Indexed object.
Examples
>>> from sympy.tensor import Indexed, Idx
>>> from sympy import symbols
>>> i, j, k, l, m = symbols(i:m, cls=Idx)
>>> Indexed(A, i, j).rank
2
>>> q = Indexed(A, i, j, k, l, m)
>>> q.rank
5
>>> q.rank == len(q.indices)
True
shape
Returns a list with dimensions of each index.
Dimensions is a property of the array, not of the indices. Still, if the IndexedBase
does not dene a shape attribute, it is assumed that the ranges of the indices correspond to the shape of the array.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1512
>>>
(n,
>>>
(m,
A[i, j].shape
n)
B[i, j].shape
m)
class sympy.tensor.indexed.IndexedBase
Represent the base or stem of an indexed object
The IndexedBase class represent an array that contains elements. The main purpose
of this class is to allow the convenient creation of objects of the Indexed class. The
getitem method of IndexedBase returns an instance of Indexed. Alone, without indices, the IndexedBase class can be used as a notation for e.g. matrix equations, resembling what you could do with the Symbol class. But, the IndexedBase class adds
functionality that is not available for Symbol instances:
An IndexedBase object can optionally store shape information. This can be used in
to check array conformance and conditions for numpy broadcasting. (TODO)
An IndexedBase object implements syntactic sugar that allows easy symbolic representation of array operations, using implicit summation of repeated indices.
The IndexedBase object symbolizes a mathematical structure equivalent to arrays,
and is recognized as such for code generation and automatic compilation and wrapping.
>>> from sympy.tensor import IndexedBase, Idx
>>> from sympy import symbols
>>> A = IndexedBase(A); A
A
>>> type(A)
<class sympy.tensor.indexed.IndexedBase>
When an IndexedBase object receives indices, it returns an array with named axes, represented by an Indexed object:
>>> i, j = symbols(i j, integer=True)
>>> A[i, j, 2]
A[i, j, 2]
>>> type(A[i, j, 2])
<class sympy.tensor.indexed.Indexed>
m, n, o, p = symbols(m n o p, integer=True)
i = Idx(i, m)
j = Idx(j, n)
A[i, j].shape
n)
B = IndexedBase(B, shape=(o, p))
B[i, j].shape
p)
args
Returns the arguments used to create this IndexedBase object.
1513
Examples
>>>
>>>
>>>
(A,
label
Returns the label of the IndexedBase object.
Examples
>>> from sympy import IndexedBase
>>> from sympy.abc import x, y
>>> IndexedBase(A, shape=(x, y)).label
A
shape
Returns the shape of the IndexedBase object.
Examples
>>>
>>>
>>>
(x,
Note: If the shape of the IndexedBase is specied, it will override any shape information given by the indices.
>>>
>>>
>>>
>>>
>>>
(x,
>>>
(2,
Methods
Module with functions operating on IndexedBase, Indexed and Idx objects
Check shape conformance
Determine indices in resulting expression
etc.
Methods in this module could be implemented by calling methods on Expr objects instead.
When things stabilize this could be a useful refactoring.
sympy.tensor.index methods.get contraction structure(expr)
Determine dummy indices of expr and describe its structure
By dummy we mean indices that are summation indices.
1514
Examples
>>> from sympy.tensor.index_methods import get_contraction_structure
>>> from sympy import symbols, default_sort_key
>>> from sympy.tensor import IndexedBase, Idx
>>> x, y, A = map(IndexedBase, [x, y, A])
>>> i, j, k, l = map(Idx, [i, j, k, l])
>>> get_contraction_structure(x[i]*y[i] + A[j, j])
{(i,): set([x[i]*y[i]]), (j,): set([A[j, j]])}
>>> get_contraction_structure(x[i]*y[j])
{None: set([x[i]*y[j]])}
A parenthesized Add object is also returned as a nested dictionary. The term containing
the parenthesis is a Mul with a contraction among the arguments, so it will be found as
a key in the result. It stores the dictionary resulting from a recursive call on the Add
expression.
1515
Powers with contractions in either base or exponent will also be found as keys in the
dictionary, mapping to a list of results from recursive calls:
>>> d = get_contraction_structure(A[j, j]**A[i, i])
>>> d[None]
set([A[j, j]**A[i, i]])
>>> nested_contractions = d[A[j, j]**A[i, i]]
>>> nested_contractions[0]
{(j,): set([A[j, j]])}
>>> nested_contractions[1]
{(i,): set([A[i, i]])}
The description of the contraction structure may appear complicated when represented
with a string in the above examples, but it is easy to iterate over:
>>> from sympy import Expr
>>> for key in d:
...
if isinstance(key, Expr):
...
continue
...
for term in d[key]:
...
if term in d:
...
# treat deepest contraction first
...
pass
...
# treat outermost contactions here
The indices of the total expression is determined, Repeated indices imply a summation,
for instance the trace of a matrix A:
>>> get_indices(A[i, i])
(set(), {})
In the case of many terms, the terms are required to have identical outer indices. Else
an IndexConformanceException is raised.
1516
Exceptions
An IndexConformanceException means that the terms ar not compatible, e.g.
>>> get_indices(x[i] + y[j])
(...)
IndexConformanceException: Indices are not consistent: x(i) + y(j)
Warning: The concept of outer indices applies recursively, starting on the deepest
level. This implies that dummies inside parenthesis are assumed to be summed rst,
so that the following expression is handled gracefully:
>>> get_indices((x[i] + A[i, j]*y[j])*x[j])
(set([i, j]), {})
This is correct and may appear convenient, but you need to be careful with this as
SymPy will happily .expand() the product, if requested. The resulting expression
would mix the outer j with the dummies inside the parenthesis, which makes it a
dierent expression. To be on the safe side, it is best to avoid such ambiguities by
using unique indices for all contractions that should be held separate.
Tensor
class sympy.tensor.tensor. TensorManager
Class to manage tensor properties.
Notes
Tensors belong to tensor commutation groups; each group has a label comm; there are
predened labels:
0 tensors commuting with any other tensor
1 tensors anticommuting among themselves
2 tensors not commuting, apart with those with comm=0
Other groups can be dened using set comm; tensors in those groups commute with those
with comm=0; by default they do not commute with any other group.
clear()
Clear the TensorManager.
comm i2symbol(i)
Returns the symbol corresponding to the commutation group number.
comm symbols2i(i)
get the commutation group number corresponding to i
i can be a symbol or a number or a string
If i is not already dened its commutation group number is set.
1517
get comm(i, j)
Return the commutation parameter for commutation group numbers i, j
see TensorManager.set comm
set comm(i, j, c)
set the commutation parameter c for commutation groups i, j
Parameters i, j : symbols representing commutation groups
c : group commutation number
Notes
i, j can be symbols, strings or numbers, apart from 0, 1 and 2 which are reserved
respectively for commuting, anticommuting tensors and tensors not commuting with
any other group apart with the commuting tensors. For the remaining cases, use
this method to set the commutation rules; by default c=None.
The group commutation number c is assigned in correspondence to the group commutation symbols; it can be
0 commuting
1 anticommuting
None no commutation property
Examples
G and GH do not commute with themselves and commute with each other; A is commuting.
set comms(*args)
set the commutation group numbers c for symbols i, j
Parameters args : sequence of (i, j, c)
class sympy.tensor.tensor.TensorIndexType
A TensorIndexType is characterized by its name and its metric.
Parameters name : name of the tensor type
metric : metric symmetry or metric object or None
dim : dimension, it can be a symbol or an integer or None
eps dim : dimension of the epsilon tensor
1518
The metric parameter can be: metric = False symmetric metric (in Riemannian geometry)
metric = True antisymmetric metric (for spinor calculus)
metric = None there is no metric
metric can be an object having name and antisym attributes.
If there is a metric the metric is used to raise and lower indices.
In the case of antisymmetric metric, the following raising and lowering conventions will
be adopted:
psi(a) = g(a, b)*psi(-b); chi(-a) = chi(b)*g(-b, -a)
g(-a, b) = delta(-a, b); g(b, -a) = -delta(a, -b)
where delta(-a, b) = delta(b, -a) is the Kronecker delta (see TensorIndex for
the conventions on indices).
If there is no metric it is not possible to raise or lower indices; e.g. the index of the
dening representation of SU(N) is covariant and the conjugate representation is contravariant; for N > 2 they are linearly independent.
eps dim is by default equal to dim, if the latter is an integer; else it can be assigned (for
use in naive dimensional regularization); if eps dim is not an integer epsilon is None.
Examples
>>> from sympy.tensor.tensor import TensorIndexType
>>> Lorentz = TensorIndexType(Lorentz, dummy_fmt=L)
>>> Lorentz.metric
metric(Lorentz,Lorentz)
Examples with metric components data added, this means it is working on a xed basis:
>>> Lorentz.data = [1, -1, -1, -1]
>>> Lorentz
TensorIndexType(Lorentz, 0)
>>> Lorentz.data
[[1 0 0 0]
[0 -1 0 0]
[0 0 -1 0]
[0 0 0 -1]]
1519
Attributes
name
metric name
metric antisym
metric
delta
epsilon
dim
dim eps
dummy fmt
data
it is metric or metric.name
the metric tensor
Kronecker delta
the Levi-Civita epsilon tensor
class sympy.tensor.tensor.TensorIndex
Represents an abstract tensor index.
Parameters name : name of the index, or True if you want it to be automatically assigned
tensortype : TensorIndexType of the index
is up : ag for contravariant index
Notes
If you want the index name to be automatically assigned, just put True in the name eld,
it will be generated using the reserved character in front of its name, in order to avoid
conicts with possible existing indices:
>>> i0 = TensorIndex(True, Lorentz)
>>> i0
_i0
>>> i1 = TensorIndex(True, Lorentz)
>>> i1
_i1
>>> A(i0)*B(-i1)
A(_i0)*B(-_i1)
1520
>>> A(i0)*B(-i0)
A(L_0)*B(-L_0)
Attributes
name
tensortype
is up
sympy.tensor.tensor.tensor indices(s, typ)
Returns list of tensor indices given their names and their types
Parameters s : string of comma separated names of indices
typ : list of TensorIndexType of the indices
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices
>>> Lorentz = TensorIndexType(Lorentz, dummy_fmt=L)
>>> a, b, c, d = tensor_indices(a,b,c,d, Lorentz)
class sympy.tensor.tensor.TensorSymmetry
Monoterm symmetry of a tensor
Parameters bsgs : tuple (base, sgs) BSGS of the symmetry of the tensor
See Also:
sympy.combinatorics.tensor can.get symmetric group sgs (page 275)
Notes
A tensor can have an arbitrary monoterm symmetry provided by its BSGS. Multiterm
symmetries, like the cyclic symmetry of the Riemann tensor, are not covered.
Examples
Attributes
base
generators
rank
1521
sympy.tensor.tensor.tensorsymmetry(*args)
Return a TensorSymmetry object.
One can represent a tensor with any monoterm slot symmetry group using a BSGS.
args can be a BSGS args[0] base args[1] sgs
Usually tensors are in (direct products of) representations of the symmetric group; args
can be a list of lists representing the shapes of Young tableaux
Notes
For instance: [[1]] vector [[1]*n] symmetric tensor of rank n [[n]] antisymmetric
tensor of rank n [[2, 2]] monoterm slot symmetry of the Riemann tensor [[1],[1]]
vector*vector [[2],[1],[1] (antisymmetric tensor)*vector*vector
Notice that with the shape [2, 2] we associate only the monoterm symmetries of the
Riemann tensor; this is an abuse of notation, since the shape [2, 2] corresponds usually
to the irreducible representation characterized by the monoterm symmetries and by the
cyclic symmetry.
Examples
class sympy.tensor.tensor.TensorType
Class of tensor types.
Parameters index types : list of TensorIndexType of the tensor indices
symmetry : TensorSymmetry of the tensor
Examples
1522
Attributes
index types
symmetry
types
class sympy.tensor.tensor.TensorHead
Tensor head of the tensor
Parameters name : name of the tensor
typ : list of TensorIndexType
comm : commutation group number
Notes
Examples with ndarray values, the components data assigned to the TensorHead object
are assumed to be in a fully-contravariant representation. In case it is necessary to
assign components data which represents the values of a non-fully covariant tensor, see
the other examples.
>>>
>>>
>>>
>>>
in order to retrieve data, it is also necessary to specify abstract indices enclosed by round
brackets, then numerical indices inside square brackets.
>>> A(i0, i1)[0, 0]
0
>>> A(i0, i1)[2, 3] == 3+2*2
True
1523
[4 5 6 7]
[6 7 8 9]]
Turning to a tensor expression, covariant indices get the corresponding components data
corrected by the metric:
>>>
[[0
[2
[4
[6
A(i0,
-1 -2
-3 -4
-5 -6
-7 -8
-i1).data
-3]
-5]
-7]
-9]]
while if all indices are contravariant, the ndarray remains the same
>>> A(i0, i1).data
[[0 1 2 3]
[2 3 4 5]
[4 5 6 7]
[6 7 8 9]]
When all indices are contracted and components data are added to the tensor, accessing
the data will return a scalar, no numpy object. In fact, numpy ndarrays are dropped to
scalars if they contain only one element.
>>> A(i0, -i0)
A(L_0, -L_0)
>>> A(i0, -i0).data
-18
It is also possible to assign components data to an indexed tensor, i.e. a tensor with
specied covariant and contravariant components. In this example, the covariant components data of the Electromagnetic tensor are injected into A:
>>>
>>>
>>>
>>>
...
...
...
...
1524
Still notice, in this last example, that accessing components data from a tensor without
specifying the indices is equivalent to assume that all indices are contravariant.
It is also possible to store symbolic components data inside a tensor, for example, dene
a four-momentum-like tensor:
>>>
>>>
>>>
>>>
Attributes
name
index types
rank
types
symmetry
comm
equal to typ.types
equal to typ.symmetry
commutation group
commutes with(other)
Returns 0 if self and other commute, 1 if they anticommute.
Returns None if self and other neither commute nor anticommute.
5.32. Tensor Module
1525
class sympy.tensor.tensor.TensExpr
Abstract base class for tensor expressions
Notes
class sympy.tensor.tensor.TensAdd
Sum of tensors
1526
Sum of more than one tensor are put automatically in canonical form.
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensorhead, tensor_indices
>>> Lorentz = TensorIndexType(Lorentz, dummy_fmt=L)
>>> a, b = tensor_indices(a,b, Lorentz)
>>> p, q = tensorhead(p,q, [Lorentz], [[1]])
>>> t = p(a) + q(a); t
p(a) + q(a)
>>> t(b)
p(b) + q(b)
Attributes
args
rank
free args
tuple of addends
rank of the tensor
list of the free indices in sorted order
canon bp()
canonicalize using the Butler-Portugal algorithm for canonicalization under
monoterm symmetries.
contract metric(g)
Raise or lower indices with the metric g
Parameters g : metric
contract all : if True, eliminate all g which are contracted
1527
Notes
1528
class sympy.tensor.tensor.TensMul
Product of tensors
Parameters coe : SymPy coecient of the tensor
args :
Notes
components
types
free
dum
ext rank
rank
coeff
free args
is canon bp
canon bp()
Canonicalize using the Butler-Portugal algorithm for canonicalization under
monoterm symmetries.
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead
>>> Lorentz = TensorIndexType(Lorentz, dummy_fmt=L)
>>> m0, m1, m2 = tensor_indices(m0,m1,m2, Lorentz)
>>> A = tensorhead(A, [Lorentz]*2, [[2]])
>>> t = A(m0,-m1)*A(m1,-m0)
>>> t.canon_bp()
-A(L_0, L_1)*A(-L_0, -L_1)
>>> t = A(m0,-m1)*A(m1,-m2)*A(m2,-m0)
1529
>>> t.canon_bp()
0
contract metric(g)
Raise or lower indices with the metric g
Parameters g : metric
Notes
get indices()
Returns the list of indices of the tensor
The indices are listed in the order in which they appear in the component tensors.
The dummy indices are given a name which does not collide with the names of the
free indices.
Examples
1530
sympy.tensor.tensor.canon bp(p)
Butler-Portugal canonicalization
5.32. Tensor Module
1531
sympy.tensor.tensor.tensor mul(*a)
product of tensors
sympy.tensor.tensor.riemann cyclic replace(t r)
replace Riemann tensor with an equivalent expression
R(m,n,p,q) -> 2/3*R(m,n,p,q) - 1/3*R(m,q,n,p) + 1/3*R(m,p,n,q)
sympy.tensor.tensor.riemann cyclic(t2)
replace each Riemann tensor with an equivalent expression satisfying the cyclic identity.
This trick is discussed in the reference guide to Cadabra.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
0
5.33 Utilities
This module contains some general purpose utilities that are used across SymPy.
Contents:
Because the code printers treat Indexed objects with repeated indices as a summation, the
above equality instance will be translated to low-level code for a matrix vector product. This
is how you tell SymPy to generate the code, compile it and wrap it as a python function:
>>> matvec = autowrap(instruction)
Thats it. Now lets test it with some numpy arrays. The default wrapper backend is f2py. The
wrapper function it provides is set up to accept python lists, which it will silently convert to
numpy arrays. So we can test the matrix vector product like this:
1532
Implementation details
The autowrap module is implemented with a backend consisting of CodeWrapper objects.
The base class CodeWrapper takes care of details about module name, lenames and options.
It also contains the driver routine, which runs through all steps in the correct order, and also
takes care of setting up and removing the temporary working directory.
The actual compilation and wrapping is done by external resources, such as the system installed f2py command. The Cython backend runs a distutils setup script in a subprocess.
Subclasses of CodeWrapper takes care of these backend-dependent details.
API Reference
Module for compiling codegen output, and wrap the binary for use in python.
Note: To use the autowrap module it must rst be imported
>>> from sympy.utilities.autowrap import autowrap
This module provides a common interface for dierent external backends, such as f2py, fwrap,
Cython, SWIG(?) etc. (Currently only f2py and Cython are implemented) The goal is to provide
access to compiled binaries of acceptable performance with a one-button user interface, i.e.
>>> from sympy.abc import x,y
>>> expr = ((x - y)**(25)).expand()
>>> binary_callable = autowrap(expr)
>>> binary_callable(1, 2)
-1.0
The callable returned from autowrap() is a binary python function, not a SymPy object. If
it is desired to use the compiled function in symbolic expressions, it is better to use binary function() which returns a SymPy Function object. The binary callable is attached as
the imp attribute and invoked when a numerical evaluation is requested with evalf(), or
with lambdify().
>>> from sympy.utilities.autowrap import binary_function
>>> f = binary_function(f, expr)
>>> 2*f(x, y) + y
y + 2*f(x, y)
>>> (2*f(x, y) + y).evalf(2, subs={x: 1, y:2})
0.e-110
The idea is that a SymPy user will primarily be interested in working with mathematical
expressions, and should not have to learn details about wrapping tools in order to evaluate
expressions numerically, even if they are computationally expensive.
When is this useful?
5.33. Utilities
1533
1. For computations on large arrays, Python iterations may be too slow, and depending on
the mathematical expression, it may be dicult to exploit the advanced index operations
provided by NumPy.
2. For really long expressions that will be called repeatedly, the compiled binary should be
signicantly faster than SymPys .evalf()
3. If you are generating code with the codegen utility in order to use it in another project,
the automatic python wrappers let you test the binaries immediately from within SymPy.
4. To create customized ufuncs for use with numpy arrays. See ufuncify.
When is this module NOT the best approach?
1. If you are really concerned about speed or memory optimizations, you will probably
get better results by working directly with the wrapper tools and the low level code.
However, the les generated by this utility may provide a useful starting point and
reference code. Temporary les will be left intact if you supply the keyword tempdir=path/to/les/.
2. If the array computation can be handled easily by numpy, and you dont need the binaries
for another project.
class sympy.utilities.autowrap.CodeWrapper(generator, lepath=None, ags=[],
verbose=False)
Base Class for code wrappers
class sympy.utilities.autowrap.CythonCodeWrapper(generator,
lepath=None,
ags=[], verbose=False)
Wrapper that uses Cython
dump pyx(routines, f, prex)
Write a Cython le with python wrappers
This le contains all the denitions of the routines in c code and refers to the header
le.
Arguments
1534
Arguments
5.33. Utilities
1535
sympy.utilities.autowrap.ufuncify(*args, **kwargs)
Generates a binary function that supports broadcasting on numpy arrays.
Parameters args : iterable
Either a Symbol or an iterable of symbols. Species the argument
sequence for the function.
expr :
A SymPy expression that denes the element wise operation.
language : string, optional
If supplied, (options: C or F95), species the language of the generated code. If None [default], the language is inferred based upon
the specied backend.
backend : string, optional
Backend used to wrap the generated code. Either numpy [default],
cython, or f2py.
tempdir : string, optional
Path to directory for temporary les. If this argument is supplied,
the generated code and the wrapper input les are left intact in the
specied path.
ags : iterable, optional
Additional option ags that will be passed to the backend
verbose : bool, optional
If True, autowrap will not mute the command line backends. This can
be helpful for debugging.
helpers : iterable, optional
Used to dene auxillary expressions needed for the main expr. If the
main expression needs to call a specialized function it should be put
in the helpers iterable. Autowrap will then make sure that the compiled main expression can link to the helper routine. Items should be
tuples with (<funtion name>, <sympy expression>, <arguments>).
It is mandatory to supply an argument sequence to helper routines.
1536
References
[1] http://docs.scipy.org/doc/numpy/reference/ufuncs.html
Examples
>>> from sympy.utilities.autowrap import ufuncify
>>> from sympy.abc import x, y
>>> import numpy as np
>>> f = ufuncify((x, y), y + x**2)
>>> type(f)
numpy.ufunc
>>> f([1, 2, 3], 2)
array([ 3., 6., 11.])
>>> f(np.arange(5), 3)
array([ 3., 4., 7., 12., 19.])
For the F2Py and Cython backends, inputs are required to be equal length 1-dimensional
arrays. The F2Py backend will perform type conversion, but the Cython backend will
error if the inputs are not of the expected type.
>>> f fortran = ufuncify((x, y), y + x**2, backend=F2Py)
>>> f fortran(1, 2)
3
>>> f fortran(numpy.array([1, 2, 3]), numpy.array([1.0, 2.0, 3.0]))
array([2., 6., 12.])
>>> f cython = ufuncify((x, y), y + x**2, backend=Cython)
>>> f cython(1, 2)
Traceback (most recent call last):
File <stdin>, line 1, in <module>
TypeError: Argument x has incorrect type (expected numpy.ndarray, got int)
>>> f cython(numpy.array([1.0]), numpy.array([2.0]))
array([ 3.])
Note
The default backend (numpy) will create actual instances of numpy.ufunc. These support ndimensional broadcasting, and implicit type conversion. Use of the other backends
will result in a ufunc-like function, which requires equal length 1-dimensional arrays
for all arguments, and will not perform any type conversions.
5.33.2 Codegen
This module provides functionality to generate directly compilable code from SymPy expressions. The codegen function is the user interface to the code generation functionality in
SymPy. Some details of the implementation is given below for advanced users that may want
to use the framework directly.
Note: The codegen callable is not in the sympy namespace automatically, to use it you must
rst execute
5.33. Utilities
1537
Implementation Details
Here we present the most important pieces of the internal structure, as advanced users may
want to use it directly, for instance by subclassing a code generator for a specialized application. It is very likely that you would prefer to use the codegen() function documented
above.
Basic assumptions:
A generic Routine data structure describes the routine that must be translated into
C/Fortran/... code. This data structure covers all features present in one or more of
the supported languages.
Descendants from the CodeGen class transform multiple Routine instances into compilable code. Each derived class translates into a specic language.
In many cases, one wants a simple workow. The friendly functions in the last part are
a simple api on top of the Routine/CodeGen stu. They are easier to use, but are less
powerful.
Routine
The Routine class is a very important piece of the codegen module. Viewing the codegen
utility as a translator of mathematical expressions into a set of statements in a programming
language, the Routine instances are responsible for extracting and storing information about
how the math can be encapsulated in a function call. Thus, it is the Routine constructor that
decides what arguments the routine will need and if there should be a return value.
API Reference
module for generating C, C++, Fortran77, Fortran90 and Octave/Matlab routines that evaluate sympy expressions. This module is work in progress. Only the milestones with a +
character in the list below have been completed.
How is sympy.utilities.codegen dierent from sympy.printing.ccode?
We considered the idea to extend the printing routines for sympy functions in such a way that
it prints complete compilable code, but this leads to a few unsurmountable issues that can
only be tackled with dedicated code generator:
For C, one needs both a code and a header le, while the printing routines generate just
one string. This code generator can be extended to support .pyf les for f2py.
SymPy functions are not concerned with programming-technical issues, such as input,
output and input-output arguments. Other examples are contiguous or non-contiguous
arrays, including headers of other libraries such as gsl or others.
It is highly interesting to evaluate several sympy functions in one C routine, eventually
sharing common intermediate results with the help of the cse routine. This is more than
just printing.
From the programming perspective, expressions with constants should be evaluated in
the code generator as much as possible. This is dierent for printing.
1538
Basic assumptions
A generic Routine data structure describes the routine that must be translated into
C/Fortran/... code. This data structure covers all features present in one or more of
the supported languages.
Descendants from the CodeGen class transform multiple Routine instances into compilable code. Each derived class translates into a specic language.
In many cases, one wants a simple workow. The friendly functions in the last part are
a simple api on top of the Routine/CodeGen stu. They are easier to use, but are less
powerful.
Milestones
First working version with scalar input arguments, generating C code, tests
Friendly functions that are easier to use than the rigorous Routine/CodeGen workow.
Integer and Real numbers as input and output
Output arguments
InputOutput arguments
Sort input/output arguments properly
Contiguous array arguments (numpy matrices)
Also generate .pyf code for f2py (in autowrap module)
Isolate constants and evaluate them beforehand in double precision
Fortran 90
Octave/Matlab
Common Subexpression Elimination
User dened comments in the generated code
Optional extra include lines for libraries/objects that can eval special functions
Test other C compilers and libraries: gcc, tcc, libtcc, gcc+gsl, ...
Contiguous array arguments (sympy matrices)
Non-contiguous array arguments (sympy matrices)
ccode must raise an error when it encounters something that can not be translated into
c. ccode(integrate(sin(x)/x, x)) does not make sense.
Complex numbers as input and output
A default complex datatype
Include extra information in the header: date, user, hostname, sha1 hash, ...
Fortran 77
C++
Python
...
5.33. Utilities
1539
language. For example, multiple return values are possible in Python, but not in C or
Fortran. Another example: Fortran and Python support complex numbers, while C does
not.
result variables
Returns a list of OutputArgument, InOutArgument and Result.
If return values are present, they are at the end ot the list.
variables
Returns a set of all variables possibly used in the routine.
For routines with unnamed return values, the dummies that may or may not be used
will be included in the set.
class sympy.utilities.codegen.DataType(cname, fname, pyname, octname)
Holds strings for a certain datatype in dierent languages.
sympy.utilities.codegen.get default datatype(expr)
Derives an appropriate datatype based on the expression.
class sympy.utilities.codegen.Argument(name, datatype=None, dimensions=None,
precision=None)
An abstract Argument data structure: a name and a data type.
This structure is rened in the descendants below.
class sympy.utilities.codegen.Result(expr,
name=None,
result var=None,
datatype=None, dimensions=None, precision=None)
An expression for a return value.
The name result is used to avoid conicts with the reserved word return in the python
language. It is also shorter than ReturnValue.
These may or may not need a name in the destination (e.g., return(x*y) might return
a value without ever naming it).
class sympy.utilities.codegen.CodeGen(project=project)
Abstract class for the code generators.
dump code(routines, f, prex, header=True, empty=True)
Write the code by calling language specic methods.
The generated le contains all the denitions of the routines in low-level code and
refers to the header le if appropriate.
Parameters routines : list
A list of Routine instances.
f : le-like
Where to write the le.
prex : string
The lename prex, used to refer to the proper header le. Only the
basename of the prex is used.
header : bool, optional
When True, a header comment is included on top of each source le.
[default : True]
empty : bool, optional
1540
When True, empty lines are included to structure the source les.
[default : True]
routine(name, expr, argument sequence)
Creates an Routine object that is appropriate for this language.
This implementation is appropriate for at least C/Fortran. Subclasses can override
this if necessary.
Here, we assume at most one return value (the l-value) which must be scalar. Additional outputs are OutputArguments (e.g., pointers on right-hand-side or passby-reference). Matrices are always returned via OutputArguments. If argument sequence is None, arguments will be ordered alphabetically, but with all InputArguments rst, and then OutputArgument and InOutArguments.
write(routines, prex, to les=False, header=True, empty=True)
Writes all the source code les for the given routines.
The generated source is returned as a list of (lename, contents) tuples, or is written
to les (see below). Each lename consists of the given prex, appended with an
appropriate extension.
Parameters routines : list
A list of Routine instances to be written
prex : string
The prex for the output les
to les : bool, optional
When True, the output is written to les. Otherwise, a list of (lename, contents) tuples is returned. [default: False]
header : bool, optional
When True, a header comment is included on top of each source le.
[default: True]
empty : bool, optional
When True, empty lines are included to structure the source les.
[default: True]
class sympy.utilities.codegen.CCodeGen(project=project)
Generator for C code.
The .write() method inherited from CodeGen will output a code le and an interface le,
<prex>.c and <prex>.h respectively.
dump c(routines, f, prex, header=True, empty=True)
Write the code by calling language specic methods.
The generated le contains all the denitions of the routines in low-level code and
refers to the header le if appropriate.
Parameters routines : list
A list of Routine instances.
f : le-like
Where to write the le.
prex : string
5.33. Utilities
1541
The lename prex, used to refer to the proper header le. Only the
basename of the prex is used.
header : bool, optional
When True, a header comment is included on top of each source le.
[default : True]
empty : bool, optional
When True, empty lines are included to structure the source les.
[default : True]
dump h(routines, f, prex, header=True, empty=True)
Writes the C header le.
This le contains all the function declarations.
Parameters routines : list
A list of Routine instances.
f : le-like
Where to write the le.
prex : string
The lename prex, used to construct the include guards. Only the
basename of the prex is used.
header : bool, optional
When True, a header comment is included on top of each source le.
[default : True]
empty : bool, optional
When True, empty lines are included to structure the source les.
[default : True]
get prototype(routine)
Returns a string for the function prototype of the routine.
If the routine has multiple result objects, an CodeGenError is raised.
See: http://en.wikipedia.org/wiki/Function prototype
class sympy.utilities.codegen.FCodeGen(project=project)
Generator for Fortran 95 code
The .write() method inherited from CodeGen will output a code le and an interface le,
<prex>.f90 and <prex>.h respectively.
dump f95(routines, f, prex, header=True, empty=True)
Write the code by calling language specic methods.
The generated le contains all the denitions of the routines in low-level code and
refers to the header le if appropriate.
Parameters routines : list
A list of Routine instances.
f : le-like
Where to write the le.
prex : string
1542
The lename prex, used to refer to the proper header le. Only the
basename of the prex is used.
header : bool, optional
When True, a header comment is included on top of each source le.
[default : True]
empty : bool, optional
When True, empty lines are included to structure the source les.
[default : True]
dump h(routines, f, prex, header=True, empty=True)
Writes the interface to a header le.
This le contains all the function declarations.
Parameters routines : list
A list of Routine instances.
f : le-like
Where to write the le.
prex : string
The lename prex.
header : bool, optional
When True, a header comment is included on top of each source le.
[default : True]
empty : bool, optional
When True, empty lines are included to structure the source les.
[default : True]
get interface(routine)
Returns a string for the function interface.
The routine should have a single result object, which can be None. If the routine
has multiple result objects, a CodeGenError is raised.
See: http://en.wikipedia.org/wiki/Function prototype
class sympy.utilities.codegen.OctaveCodeGen(project=project)
Generator for Octave code.
The .write() method inherited from CodeGen will output a code le <prex>.m.
Octave .m les usually contain one function. That function name should match the lename (prefix). If you pass multiple name expr pairs, the latter ones are presumed to be
private functions accessed by the primary function.
You should only pass inputs to argument sequence: outputs are ordered according to
their order in name expr.
dump m(routines, f, prex, header=True, empty=True, inline=True)
Write the code by calling language specic methods.
The generated le contains all the denitions of the routines in low-level code and
refers to the header le if appropriate.
Parameters routines : list
A list of Routine instances.
5.33. Utilities
1543
f : le-like
Where to write the le.
prex : string
The lename prex, used to refer to the proper header le. Only the
basename of the prex is used.
header : bool, optional
When True, a header comment is included on top of each source le.
[default : True]
empty : bool, optional
When True, empty lines are included to structure the source les.
[default : True]
routine(name, expr, argument sequence)
Specialized Routine creation for Octave.
sympy.utilities.codegen.codegen(name expr,
language,
prex=None,
project=project, to les=False, header=True,
empty=True, argument sequence=None)
Generate source code for expressions in a given language.
Parameters name expr : tuple, or list of tuples
A single (name, expression) tuple or a list of (name, expression) tuples. Each tuple corresponds to a routine. If the expression is an
equality (an instance of class Equality) the left hand side is considered
an output argument. If expression is an iterable, then the routine will
have multiple outputs.
language : string
A string that indicates the source code language. This is case insensitive. Currently, C, F95 and Octave are supported. Octave
generates code compatible with both Octave and Matlab.
prex : string, optional
A prex for the names of the les that contain the source code.
Language-dependent suxes will be appended. If omitted, the name
of the rst name expr tuple is used.
project : string, optional
A project name, used for making unique preprocessor instructions.
[default: project]
to les : bool, optional
When True, the code will be written to one or more les with the
given prex, otherwise strings with the names and contents of these
les are returned. [default: False]
header : bool, optional
When True, a header is written on top of each source le. [default:
True]
empty : bool, optional
When True, empty lines are used to structure the code. [default:
True]
1544
Another example using Equality objects to give named outputs. Here the lename (prex) is taken from the rst (name, expr) pair.
>>> from sympy.abc import f, g
>>> from sympy import Eq
>>> [(c_name, c_code), (h_name, c_header)] = codegen(
...
[(myfcn, x + y), (fcn2, [Eq(f, 2*x), Eq(g, y)])],
...
C, header=False, empty=False)
>>> print(c_name)
myfcn.c
>>> print(c_code)
#include myfcn.h
#include <math.h>
double myfcn(double x, double y) {
double myfcn_result;
myfcn_result = x + y;
return myfcn_result;
}
void fcn2(double x, double y, double *f, double *g) {
(*f) = 2*x;
(*g) = y;
}
1545
Another more complicated example with a mixture of specied and automaticallyassigned names. Also has Matrix output.
>>> from sympy import Matrix
>>> r = make_routine(fcn, [x*y, Eq(f, 1), Eq(g, x + g), Matrix([[x, 2]])])
>>> [arg.result_var for arg in r.results]
[result_5397460570204848505]
>>> [arg.expr for arg in r.results]
1546
[x*y]
>>> [arg.name for arg in r.arguments]
[x, y, f, g, out_8598435338387848786]
5.33.3 Decorator
Useful utility decorators.
sympy.utilities.decorator.conserve mpmath dps(func)
After the function nishes, resets the value of mpmath.mp.dps to the value it had before
the function was run.
sympy.utilities.decorator.doctest depends on(exe=None, modules=None, disable viewers=None)
Adds metadata about the depenencies which need to be met for doctesting the docstrings
of the decorated objects.
sympy.utilities.decorator.no attrs in subclass
Dont inherit certain attributes from a base class
>>> from sympy.utilities.decorator import no_attrs_in_subclass
>>> class A(object):
...
x = test
>>> A.x = no_attrs_in_subclass(A, A.x)
>>> class B(A):
...
pass
>>> hasattr(A, x)
True
>>> hasattr(B, x)
False
sympy.utilities.decorator.public(obj)
Append objs name to global all variable (call site).
By using this decorator on functions or classes you achieve the same goal as by lling
all variables manually, you just dont have to repeat your self (objects name). You
5.33. Utilities
1547
also know if object is public at denition site, not at some random location (where all
was set).
Note that in multiple decorator setup, in almost all cases, @public decorator must be
applied before any other decorators, because it relies on the pointer to objects global
namespace. If you apply other decorators rst, @public may end up modifying wrong
namespace.
Example:
>>> from sympy.utilities.decorator import public
>>> __all__
Traceback (most
...
NameError: name
Traceback (most
...
NameError: name
>>> @public
... def some_function():
...
pass
>>> __all__
[some_function]
sympy.utilities.decorator.threaded(func)
Apply func to subelements of an object, including Add.
This decorator is intended to make it uniformly possible to apply a function to all elements
of composite objects, e.g. matrices, lists, tuples and other iterable containers, or just
expressions.
This version of threaded() (page 1548) decorator allows threading over elements of Add
class. If this behavior is not desirable use xthreaded() (page 1548) decorator.
Functions using this decorator must have the following signature:
@threaded
def function(expr, *args, **kwargs):
1548
5.33.4 Enumerative
This module includes functions and classes for enumerating and counting multiset partitions.
sympy.utilities.enumerative.multiset partitions taocp(multiplicities)
Enumerates partions of a multiset.
Parameters multiplicities :
list of integer multiplicities of the components of the multiset.
See Also:
sympy.utilities.iterables.multiset partititions Takes a multiset as input and directly yields multiset partitions. It dispatches to a number of functions, including
this one, for implementation. Most users will nd it more convenient to use than
multiset partitions taocp.
Examples
>>> from sympy.utilities.enumerative import list_visitor
>>> from sympy.utilities.enumerative import multiset_partitions_taocp
>>> # variables components and multiplicities represent the multiset abb
>>> components = ab
>>> multiplicities = [1, 2]
>>> states = multiset_partitions_taocp(multiplicities)
>>> list(list_visitor(state, components) for state in states)
[[[a, b, b]],
[[a, b], [b]],
[[a], [b, b]],
[[a], [b], [b]]]
Yields
state Internal data structure which encodes a particular partition. This output is then
usually processed by a vistor function which combines the information from this data
structure with the components themselves to produce an actual partition.
Unless they wish to create their own visitor function, users will have little need to
look inside this data structure. But, for reference, it is a 3-element list with components:
f is a frame array, which is used to divide pstack into parts.
lpart points to the base of the topmost part.
pstack is an array of PartComponent objects.
The state output oers a peek into the internal data structures of the enumeration
function. The client should treat this as read-only; any modication of the data
structure will cause unpredictable (and almost certainly incorrect) results. Also, the
components of state are modied in place at each iteration. Hence, the visitor must
be called at each loop iteration. Accumulating the state instances and processing
them later will not work.
5.33. Utilities
1549
To enumerate the factorings of a number we can think of the elements of the partition
as being the prime factors and the multiplicities as being their exponents.
>>> from sympy.utilities.enumerative import factoring_visitor
>>> from sympy.utilities.enumerative import multiset_partitions_taocp
>>> from sympy import factorint
>>> primes, multiplicities = zip(*factorint(24).items())
>>> primes
(2, 3)
>>> multiplicities
(3, 1)
>>> states = multiset_partitions_taocp(multiplicities)
>>> list(factoring_visitor(state, primes) for state in states)
[[24], [8, 3], [12, 2], [4, 6], [4, 2, 3], [6, 2, 2], [2, 2, 2, 3]]
The approach of the function multiset partitions taocp is extended and generalized by the
class MultisetPartitionTraverser.
class sympy.utilities.enumerative.MultisetPartitionTraverser
Has methods to enumerate and count the partitions of a multiset.
This implements a refactored and extended version of Knuths algorithm 7.1.2.5M
[AOCP] (page 1915).
The enumeration methods of this class are generators and return data structures
which can be interpreted by the same visitor functions used for the output of multiset partitions taocp.
See Also:
multiset partitions taocp (page 1549), sympy.utilities.iterables.multiset partititions
1550
References
count partitions(multiplicities)
Returns the number of partitions of a multiset whose components have the multiplicities given in multiplicities.
For larger counts, this method is much faster than calling one of the enumerators
and counting the result. Uses dynamic programming to cut down on the number
of nodes actually explored. The dictionary used in order to accelerate the counting
process is stored in the MultisetPartitionTraverser object and persists across
calls. If the the user does not expect to call count partitions for any additional
multisets, the object should be cleared to save memory. On the other hand, the
cache built up from one count run can signicantly speed up subsequent calls to
count partitions, so it may be advantageous not to clear the object.
Notes
If one looks at the workings of Knuths algorithm M [AOCP] (page 1915), it can be
viewed as a traversal of a binary tree of parts. A part has (up to) two children, the left
child resulting from the spread operation, and the right child from the decrement
operation. The ordinary enumeration of multiset partitions is an in-order traversal of
this tree, and with the partitions corresponding to paths from the root to the leaves.
The mapping from paths to partitions is a little complicated, since the partition would
contain only those parts which are leaves or the parents of a spread link, not those
which are parents of a decrement link.
For counting purposes, it is sucient to count leaves, and this can be done with a
recursive in-order traversal. The number of leaves of a subtree rooted at a particular
part is a function only of that part itself, so memoizing has the potential to speed up
the counting dramatically.
This method follows a computational approach which is similar to the hypothetical
memoized recursive function, but with two dierences:
1.This method is iterative, borrowing its structure from the other enumerations
and maintaining an explicit stack of parts which are in the process of being
counted. (There may be multisets which can be counted reasonably quickly by
this implementation, but which would overow the default Python recursion limit
with a recursive implementation.)
2.Instead of using the part data structure directly, a more compact key is constructed. This saves space, but more importantly coalesces some parts which
would remain separate with physical keys.
5.33. Utilities
1551
enum all(multiplicities)
Enumerate the partitions of a multiset.
See Also:
multiset partitions taocp (page 1549) which provides the same result as this
method, but is about twice as fast. Hence, enum all is primarily useful for testing. Also see the function for a discussion of states and visitors.
Examples
>>> from sympy.utilities.enumerative import list_visitor
>>> from sympy.utilities.enumerative import MultisetPartitionTraverser
>>> m = MultisetPartitionTraverser()
>>> states = m.enum_all([2,2])
>>> list(list_visitor(state, ab) for state in states)
[[[a, a, b, b]],
[[a, a, b], [b]],
[[a, a], [b, b]],
[[a, a], [b], [b]],
[[a, b, b], [a]],
[[a, b], [a, b]],
[[a, b], [a], [b]],
[[a], [a], [b, b]],
[[a], [a], [b], [b]]]
1552
Examples
>>> from sympy.utilities.enumerative import list_visitor
>>> from sympy.utilities.enumerative import MultisetPartitionTraverser
>>> m = MultisetPartitionTraverser()
>>> states = m.enum_large([2,2], 2)
>>> list(list_visitor(state, ab) for state in states)
[[[a, a], [b], [b]],
[[a, b], [a], [b]],
[[a], [a], [b, b]],
[[a], [a], [b], [b]]]
5.33. Utilities
1553
The implementation is based, in part, on the answer given to exercise 69, in Knuth
[AOCP] (page 1915).
5.33.5 Iterables
cartes
Returns the cartesian product of sequences as a generator.
Examples::
>>> from sympy.utilities.iterables import cartes
>>> list(cartes([1,2,3], ab))
[(1, a), (1, b), (2, a), (2, b), (3, a), (3, b)]
variations
variations(seq, n) Returns all the variations of the list of size n.
Has an optional third argument. Must be a boolean value and makes the method return the
variations with repetition if set to True, or the variations without repetition if set to False.
Examples::
>>> from sympy.utilities.iterables import variations
>>> list(variations([1,2,3], 2))
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
>>> list(variations([1,2,3], 2, True))
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
partitions
Although the combinatorics module contains Partition and IntegerPartition classes for investigation and manipulation of partitions, there are a few functions to generate partitions that
can be used as low-level tools for routines: partitions and multiset partitions. The former gives integer partitions, and the latter gives enumerated partitions of elements. There
is also a routine kbins that will give a variety of permutations of partions.
partitions:
>>> from sympy.utilities.iterables import partitions
>>> [p.copy() for s, p in partitions(7, m=2, size=True) if s == 2]
[{1: 1, 6: 1}, {2: 1, 5: 1}, {3: 1, 4: 1}]
multiset partitions:
>>> from sympy.utilities.iterables import multiset_partitions
>>> [p for p in multiset_partitions(3, 2)]
[[[0, 1], [2]], [[0, 2], [1]], [[0], [1, 2]]]
>>> [p for p in multiset_partitions([1, 1, 1, 2], 2)]
[[[1, 1, 1], [2]], [[1, 1, 2], [1]], [[1, 1], [1, 2]]]
1554
kbins:
>>> from sympy.utilities.iterables import kbins
>>> def show(k):
...
rv = []
...
for p in k:
...
rv.append(,.join([.join(j) for j in p]))
...
return sorted(rv)
...
>>> show(kbins(ABCD, 2))
[A,BCD, AB,CD, ABC,D]
>>> show(kbins(ABC, 2))
[A,BC, AB,C]
>>> show(kbins(ABC, 2, ordered=0)) # same as multiset_partitions
[A,BC, AB,C, AC,B]
>>> show(kbins(ABC, 2, ordered=1))
[A,BC, A,CB,
B,AC, B,CA,
C,AB, C,BA]
>>> show(kbins(ABC, 2, ordered=10))
[A,BC, AB,C, AC,B,
B,AC, BC,A,
C,AB]
>>> show(kbins(ABC, 2, ordered=11))
[A,BC, A,CB, AB,C, AC,B,
B,AC, B,CA, BA,C, BC,A,
C,AB, C,BA, CA,B, CB,A]
Docstring
sympy.utilities.iterables.binary partitions(n)
Generates the binary partition of n.
A binary partition consists only of numbers that are powers of two. Each step reduces a
2**(k+1) to 2**k and 2**k. Thus 16 is converted to 8 and 8.
Reference: TAOCP 4, section 7.2.1.5, problem 64
Examples
>>>
>>>
...
...
[4,
[2,
[2,
[1,
sympy.utilities.iterables.bracelets(n, k)
Wrapper to necklaces to return a free (unrestricted) necklace.
sympy.utilities.iterables.capture(func)
Return the printed output of func().
f unc should be a function without arguments that produces output with print statements.
5.33. Utilities
1555
sympy.utilities.iterables.common prefix(*seqs)
Return the subsequence that is a common start of sequences in seqs.
>>>
>>>
[0,
>>>
[0,
>>>
[1,
>>>
[1]
sympy.utilities.iterables.common suffix(*seqs)
Return the subsequence that is a common ending of sequences in seqs.
>>>
>>>
[0,
>>>
[]
>>>
[2,
>>>
[3]
sympy.utilities.iterables.dict merge(*dicts)
Merge dictionaries into a single dictionary.
sympy.utilities.iterables.filter symbols(iterator, exclude)
Only yield elements from iterator that do not occur in exclude.
Parameters iterator : iterable
iterator to take elements from :
exclude : iterable
elements to exclude :
Returns iterator : iterator
ltered iterator :
sympy.utilities.iterables.flatten(iterable, levels=None, cls=None)
Recursively denest iterable containers.
>>> from sympy.utilities.iterables import flatten
>>> flatten([1, 2, 3])
[1, 2, 3]
1556
If you want to denest only a specied number of levels of nested containers, then set
levels ag to the desired number of levels:
>>> ls = [[(-2, -1), (1, 2)], [(0, 0)]]
>>> flatten(ls, levels=1)
[(-2, -1), (1, 2), (0, 0)]
If cls argument is specied, it will only atten instances of that class, for example:
>>>
>>>
...
...
>>>
[1,
http://en.wikipedia.org/wiki/Method ringing
http://stackoverow.com/questions/4856615/recursive-permutation/4857018
http://programminggeeks.com/bell-algorithm-for-permutation/
http://en.wikipedia.org/wiki/Steinhaus%E2%80%93Johnson%E2%80%93Trotter algorithm
Generating involutions, derangements, and relatives by ECO Vincent Vajnovszki,
DMTCS vol 1 issue 12, 2010
Examples
>>> from itertools import permutations
>>> from sympy.utilities.iterables import generate_bell
>>> from sympy import zeros, Matrix
This is the sort of permutation used in the ringing of physical bells, and does not produce
permutations in lexicographical order. Rather, the permutations dier from each other
5.33. Utilities
1557
by exactly one inversion, and the position at which the swapping occurs varies periodically in a simple fashion. Consider the rst few permutations of 4 elements generated
by permutations and generate bell:
>>> list(permutations(range(4)))[:5]
[(0, 1, 2, 3), (0, 1, 3, 2), (0, 2, 1, 3), (0, 2, 3, 1), (0, 3, 1, 2)]
>>> list(generate_bell(4))[:5]
[(0, 1, 2, 3), (0, 1, 3, 2), (0, 3, 1, 2), (3, 0, 1, 2), (3, 0, 2, 1)]
Notice how the 2nd and 3rd lexicographical permutations have 3 elements out of place
whereas each bell permutation always has only two elements out of place relative to
the previous permutation (and so the signature (+/-1) of a permutation is opposite of the
signature of the previous permutation).
How the position of inversion varies across the elements can be seen by tracing out
where the largest number appears in the permutations:
>>> m = zeros(4, 24)
>>> for i, p in enumerate(generate_bell(4)):
...
m[:, i] = Matrix([j - 3 for j in list(p)])
>>> m.print_nonzero(X)
[XXX XXXXXX XXXXXX XXX]
[XX XX XXXX XX XXXX XX XX]
[X XXXX XX XXXX XX XXXX X]
[ XXXXXX XXXXXX XXXXXX ]
sympy.utilities.iterables.generate derangements(perm)
Routine to generate unique derangements.
TODO: This will be rewritten to use the ECO operator approach once the permutations
branch is in master.
See Also:
sympy.functions.combinatorial.factorials.subfactorial
Examples
>>> from sympy.utilities.iterables import generate_derangements
>>> list(generate_derangements([0, 1, 2]))
[[1, 2, 0], [2, 0, 1]]
>>> list(generate_derangements([0, 1, 2, 3]))
[[1, 0, 3, 2], [1, 2, 3, 0], [1, 3, 0, 2], [2, 0, 3, 1],
[2, 3, 0, 1], [2, 3, 1, 0], [3, 0,
>>> list(generate_derangements([0, 1, 1]))
[]
sympy.utilities.iterables.generate involutions(n)
Generates involutions.
An involution is a permutation that when multiplied by itself equals the identity permutation. In this implementation the involutions are generated using Fixed Points.
Alternatively, an involution can be considered as a permutation that does not contain any
cycles with a length that is greater than two.
Reference: http://mathworld.wolfram.com/PermutationInvolution.html
1558
Examples
>>> from sympy.utilities.iterables import generate_involutions
>>> list(generate_involutions(3))
[(0, 1, 2), (0, 2, 1), (1, 0, 2), (2, 1, 0)]
>>> len(list(generate_involutions(4)))
10
sympy.utilities.iterables.group(seq, multiple=True)
Splits a sequence into a list of lists of equal, adjacent elements.
See Also:
multiset (page 1562)
Examples
>>> from sympy.utilities.iterables import group
>>> group([1, 1, 1, 2, 2, 3])
[[1, 1, 1], [2, 2], [3]]
>>> group([1, 1, 1, 2, 2, 3], multiple=False)
[(1, 3), (2, 2), (3, 1)]
>>> group([1, 1, 3, 2, 2, 1], multiple=False)
[(1, 2), (3, 1), (2, 2), (1, 1)]
sympy.utilities.iterables.has dups(seq)
Return True if there are any duplicate elements in seq.
Examples
>>> from sympy.utilities.iterables import has_dups
>>> from sympy import Dict, Set
5.33. Utilities
1559
sympy.utilities.iterables.has variety(seq)
Return True if there are any dierent elements in seq.
Examples
>>> from sympy.utilities.iterables import has_variety
>>> has_variety((1, 2, 1))
True
>>> has_variety((1, 1, 1))
False
bits = 2
for i in ibin(2, all):
print(i)
0)
1)
0)
1)
1560
1101111000
>>> list(ibin(3, all, str=True))
[000, 001, 010, 011, 100, 101, 110, 111]
sympy.utilities.iterables.interactive traversal(expr)
Traverse a tree asking a user which branch to choose.
sympy.utilities.iterables.kbins(l, k, ordered=None)
Return sequence l partitioned into k bins.
See Also:
partitions (page 1566), multiset partitions (page 1563)
Examples
>>> from sympy.utilities.iterables import kbins
The default is to give the items in the same order, but grouped into k partitions without
any reordering:
>>> from __future__ import print_function
>>> for p in kbins(list(range(5)), 2):
...
print(p)
...
[[0], [1, 2, 3, 4]]
[[0, 1], [2, 3, 4]]
[[0, 1, 2], [3, 4]]
[[0, 1, 2, 3], [4]]
The ordered ag which is either None (to give the simple partition of the the elements)
or is a 2 digit integer indicating whether the order of the bins and the order of the items
in the bins matters. Given:
A
B
C
D
=
=
=
=
means
means
means
means
A
A
A
A
==
==
==
==
B == C == D
B
D
A
5.33. Utilities
1561
ordered = 1
[[0], [1, 2]]
[[0], [2, 1]]
[[1], [0, 2]]
[[1], [2, 0]]
[[2], [0, 1]]
[[2], [1, 0]]
ordered = 10
[[0, 1], [2]]
[[2], [0, 1]]
[[0, 2], [1]]
[[1], [0, 2]]
[[0], [1, 2]]
[[1, 2], [0]]
ordered = 11
[[0], [1, 2]]
[[0, 1], [2]]
[[0], [2, 1]]
[[0, 2], [1]]
[[1], [0, 2]]
[[1, 0], [2]]
[[1], [2, 0]]
[[1, 2], [0]]
[[2], [0, 1]]
[[2, 0], [1]]
[[2], [1, 0]]
[[2, 1], [0]]
sympy.utilities.iterables.multiset(seq)
Return the hashable sequence in multiset form with values being the multiplicity of the
item in the sequence.
1562
See Also:
group (page 1559)
Examples
>>> from sympy.utilities.iterables import multiset
>>> multiset(mississippi)
{i: 4, m: 1, p: 2, s: 4}
The number of combinations depends on the number of letters; the number of unique
combinations depends on how the letters are repeated.
>>> s1 = abracadabra
>>> s2 = banana tree
>>> count(combinations, s1), count(multiset_combinations, s1)
(165, 23)
>>> count(combinations, s2), count(multiset_combinations, s2)
(165, 54)
When all the elements are the same in the multiset, the order of the returned partitions
is determined by the partitions routine. If one is counting partitions then it is better
to use the nT function.
Examples
5.33. Utilities
1563
Only unique partitions are returned and these will be returned in a canonical order regardless of the order of the input:
>>> a = [1, 2, 2, 1]
>>> ans = list(multiset_partitions(a, 2))
>>> a.sort()
>>> list(multiset_partitions(a, 2)) == ans
True
>>> a = range(3, 1, -1)
>>> (list(multiset_partitions(a)) ==
... list(multiset_partitions(sorted(a))))
True
Counting
The number of partitions of length k from a set of size n is given by the Stirling Number
of the 2nd kind:
>>> def S2(n, k):
...
from sympy import Dummy, binomial, factorial, Sum
...
if k > n:
...
return 0
...
j = Dummy()
...
arg = (-1)**(k-j)*j**n*binomial(k,j)
...
return 1/factorial(k)*Sum(arg,(j,0,k)).doit()
...
>>> S2(5, 2) == len(list(multiset_partitions(5, 2))) == 15
True
1564
Examples
>>> from sympy.utilities.iterables import multiset_permutations
>>> from sympy import factorial
>>> [.join(i) for i in multiset_permutations(aab)]
[aab, aba, baa]
>>> factorial(len(banana))
720
>>> len(list(multiset_permutations(banana)))
60
sympy.utilities.iterables.necklaces(n, k, free=False)
A routine to generate necklaces that may (free=True) or may not (free=False) be turned
over to be viewed. The necklaces returned are comprised of n integers (beads) with k
dierent values (colors). Only unique necklaces are returned.
References
http://mathworld.wolfram.com/Necklace.html
Examples
>>> from sympy.utilities.iterables import necklaces, bracelets
>>> def show(s, i):
...
return .join(s[j] for j in i)
The unrestricted necklace is sometimes also referred to as a bracelet (an object that
can be turned over, a sequence that can be reversed) and the term necklace is used to
imply a sequence that cannot be reversed. So ACB == ABC for a bracelet (rotate and
reverse) while the two are dierent for a necklace since rotation alone cannot make the
two sequences the same.
(mnemonic: Bracelets can be viewed Backwards, but Not Necklaces.)
>>> B = [show(ABC, i) for i in bracelets(3, 3)]
>>> N = [show(ABC, i) for i in necklaces(3, 3)]
>>> set(N) - set(B)
set([ACB])
>>> list(necklaces(4, 2))
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 1),
(0, 1, 0, 1), (0, 1, 1, 1), (1, 1, 1, 1)]
>>> [show(.o, i) for i in bracelets(4, 2)]
[...., ...o, ..oo, .o.o, .ooo, oooo]
5.33. Utilities
1565
187),
Examples
>>> from sympy.utilities.iterables import partitions
The numbers appearing in the partition (the key of the returned dict) are limited with k:
>>>
...
{2:
{1:
{1:
{1:
The maximum number of parts in the partion (the sum of the values in the returned dict)
are limited with m:
>>>
...
...
{6:
{1:
{2:
{3:
1566
Note that the same dictionary object is returned each time. This is for speed: generating each partition goes quickly, taking constant time, independent of n.
>>> [p for p in partitions(6, k=2)]
[{1: 6}, {1: 6}, {1: 6}, {1: 6}]
If you want to build a list of the returned dictionaries then make a copy of them:
>>> [p.copy() for p in partitions(6, k=2)]
[{2: 3}, {1: 2, 2: 2}, {1: 4, 2: 1}, {1: 6}]
>>> [(M, p.copy()) for M, p in partitions(6, k=2, size=True)]
[(3, {2: 3}), (4, {1: 2, 2: 2}), (5, {1: 4, 2: 1}), (6, {1: 6})]
Reference: modied from Tim Peters version to allow for k and m values:
code.activestate.com/recipes/218332-generator-for-integer-partitions/
sympy.utilities.iterables.postfixes(seq)
Generate all postxes of a sequence.
Examples
>>> from sympy.utilities.iterables import postfixes
>>> list(postfixes([1,2,3,4]))
[[4], [3, 4], [2, 3, 4], [1, 2, 3, 4]]
The nodes are returned in the order that they are encountered unless key is given; simply
passing key=True will guarantee that the traversal is unique.
>>>
[z,
>>>
[w,
list(postorder_traversal(w
y, x, x + y, z*(x + y), w,
list(postorder_traversal(w
z, x, y, x + y, z*(x + y),
5.33. Utilities
+
w
+
w
(x + y)*z))
+ z*(x + y)]
(x + y)*z, keys=True))
+ z*(x + y)]
1567
Yields
sympy.utilities.iterables.reshape(seq, how)
Reshape the sequence according to the template in how.
Examples
>>> from sympy.utilities import reshape
>>> seq = list(range(1, 9))
>>> reshape(seq, [4]) # lists of 4
[[1, 2, 3, 4], [5, 6, 7, 8]]
>>> reshape(seq, (4,)) # tuples of 4
[(1, 2, 3, 4), (5, 6, 7, 8)]
>>> reshape(seq, (2, 2)) # tuples of 4
[(1, 2, 3, 4), (5, 6, 7, 8)]
>>> reshape(seq, (2, [2])) # (i, i, [i, i])
[(1, 2, [3, 4]), (5, 6, [7, 8])]
>>> reshape(seq, ((2,), [2])) # etc....
[((1, 2), [3, 4]), ((5, 6), [7, 8])]
>>> reshape(seq, (1, [2], 1))
[(1, [2, 3], 4), (5, [6, 7], 8)]
>>> reshape(tuple(seq), ([[1], 1, (2,)],))
(([[1], 2, (3, 4)],), ([[5], 6, (7, 8)],))
>>> reshape(tuple(seq), ([1], 1, (2,)))
(([1], 2, (3, 4)), ([5], 6, (7, 8)))
>>> reshape(list(range(12)), [2, [3], set([2]), (1, (3,), 1)])
[[0, 1, [2, 3, 4], set([5, 6]), (7, (8, 9, 10), 11)]]
sympy.utilities.iterables.rotate left(x, y)
Left rotates a list x by the number of steps specied in y.
1568
Examples
>>>
>>>
>>>
[1,
sympy.utilities.iterables.rotate right(x, y)
Right rotates a list x by the number of steps specied in y.
Examples
>>>
>>>
>>>
[2,
sympy.utilities.iterables.sift(seq, keyfunc)
Sift the sequence, seq into a dictionary according to keyfunc.
OUTPUT: each element in expr is stored in a list keyed to the value of keyfunc for the
element.
See Also:
ordered
Examples
>>> from sympy.utilities import sift
>>> from sympy.abc import x, y
>>> from sympy import sqrt, exp
>>> sift(range(5), lambda x: x % 2)
{0: [0, 2, 4], 1: [1, 3]}
sift() returns a defaultdict() object, so any key that has no matches will give [].
>>> sift([x], lambda x: x.is_commutative)
{True: [x]}
5.33. Utilities
1569
>>> _[False]
[]
Sometimes you wont know how many keys you will get:
>>> sift([sqrt(x), exp(x), (y**x)**2],
...
lambda x: x.as_base_exp()[0])
{E: [exp(x)], x: [sqrt(x)], y: [y**(2*x)]}
If you need to sort the sifted items it might be better to use ordered which can economically apply multiple sort keys to a squence while sorting.
sympy.utilities.iterables.subsets(seq, k=None, repetition=False)
Generates all k-subsets (combinations) from an n-element set, seq.
A k-subset of an n-element set is any subset of length exactly k. The number of k-subsets
of an n-element set is given by binomial(n, k), whereas there are 2**n subsets all together.
If k is None then all 2**n subsets will be returned from shortest to longest.
Examples
>>> from sympy.utilities.iterables import subsets
subsets(seq, k) will return the n!/k!/(n - k)! k-subsets (combinations) without repetition,
i.e. once an item has been removed, it can no longer be taken:
>>> list(subsets([1,
[(1, 2)]
>>> list(subsets([1,
[(), (1,), (2,), (1,
>>> list(subsets([1,
[(1, 2), (1, 3), (2,
2], 2))
2]))
2)]
2, 3], 2))
3)]
If you ask for more items than are in the set you get the empty set unless you allow
repetitions:
>>> list(subsets([0, 1], 3, repetition=False))
[]
>>> list(subsets([0, 1], 3, repetition=True))
[(0, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1)]
sympy.utilities.iterables.take(iter, n)
Return n items from iter iterator.
sympy.utilities.iterables.topological sort(graph, key=None)
Topological sort of graphs vertices.
Parameters graph : tuple[list, list[tuple[T, T]]
A tuple consisting of a list of vertices and a list of edges of a graph to
be sorted topologically.
key : callable[T] (optional)
1570
Ordering key for vertices on the same level. By default the natural
(e.g. lexicographic) ordering is used (in this case the base type must
implement ordering relations).
Examples
Consider a graph:
+---+
+---+
+---+
| 7 |\
| 5 |
| 3 |
+---+ \
+---+
+---+
|
\ /
/ |
| / \ /
\ /
|
V V
V V
|
+----+
+---+ |
| 11 |
| 8 | |
+----+
+---+ |
/
|
| | \
| \
\ /
/ \ |
V \
V V
/ V V
+---+ \
+---+ | +----+
| 2 | | | 9 | | | 10 |
+---+ | +---+ | +----+
\
/
where vertices are integers. This graph can be encoded using elementary Pythons data
structures as follows:
>>> V = [2, 3, 5, 7, 8, 9, 10, 11]
>>> E = [(7, 11), (7, 8), (5, 11), (3, 8), (3, 10),
...
(11, 2), (11, 9), (11, 10), (8, 9)]
Only acyclic graphs can be sorted. If the input graph has a cycle, then ValueError will
be raised:
>>> topological_sort((V, E + [(10, 7)]))
Traceback (most recent call last):
...
ValueError: cycle detected
Traceback (most recent call last):
...
ValueError: cycle detected
See Also:
http://en.wikipedia.org/wiki/Topological sorting
5.33. Utilities
1571
sympy.utilities.iterables.unflatten(iter, n=2)
Group iter into tuples of length n. Raise an error if the length of iter is not a multiple
of n.
sympy.utilities.iterables.uniq(seq, result=None)
Yield unique elements from seq as an iterator. The second parameter result is used
internally; it is not necessary to pass anything for this.
Examples
>>> from sympy.utilities.iterables import uniq
>>> dat = [1, 4, 1, 5, 4, 2, 1, 2]
>>> type(uniq(dat)) in (list, tuple)
False
>>> list(uniq(dat))
[1, 4, 5, 2]
>>> list(uniq(x for x in dat))
[1, 4, 5, 2]
>>> list(uniq([[1], [2, 1], [1]]))
[[1], [2, 1]]
variations(seq, n, True) will return the N**n permutations obtained by allowing repetition of elements:
>>> list(variations([1, 2], 2, repetition=True))
[(1, 1), (1, 2), (2, 1), (2, 2)]
If you ask for more items than are in the set you get the empty set unless you allow
repetitions:
>>> list(variations([0, 1], 3, repetition=False))
[]
>>> list(variations([0, 1], 3, repetition=True))[:4]
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1)]
1572
5.33.6 Lambdify
This module provides convenient functions to transform sympy expressions to lambda functions which can be used to calculate numerical values very fast.
sympy.utilities.lambdify.implemented function(symfunc, implementation)
Add numerical implementation to function symfunc.
symfunc can be an UndefinedFunction instance, or a name string. In the latter case we
create an UndefinedFunction instance with that name.
Be aware that this is a quick workaround, not a general method to create special symbolic
functions. If you want to create a symbolic function to be used by all the machinery of
SymPy you should subclass the Function class.
Parameters symfunc : str or UndefinedFunction instance
If str, then create new UndefinedFunction with this as name. If
symf unc is a sympy function, attach implementation to it.
implementation : callable
numerical implementation to be called by evalf() or lambdify
Returns afunc : sympy.FunctionClass instance
function with attached implementation
Examples
>>>
>>>
>>>
>>>
>>>
>>>
5
Although tuples may not appear as arguments to lambda in Python 3, lambdastr will create a lambda function that will unpack the original arguments so that nested arguments
can be handled:
>>> lambdastr((x, (y, z)), x + y)
lambda _0,_1: (lambda x,y,z: (x + y))(*list(__flatten_args__([_0,_1])))
5.33. Utilities
1573
The default behavior is to substitute all arguments in the provided expression with
dummy symbols. This allows for applied functions (e.g. f(t)) to be supplied as arguments. Call the function with dummify=False if dummy substitution is unwanted (and
args is not a string). If you want to view the lambdied function or provide sympy as
the module, you should probably set dummify=False.
For functions involving large array calculations, numexpr can provide a signicant speedup over numpy.
Please note that the available functions for numexpr are more limited than numpy but can be expanded with implemented function
and user dened subclasses of Function.
If specied, numexpr may be the
only option in modules. The ocial list of numexpr functions can be found at:
https://github.com/pydata/numexpr#supported-functions
Examples
>>>
>>>
>>>
>>>
from
from
from
from
Tuple arguments are handled and the lambdied function should be called with the same
type of arguments as were used to create the function.:
>>> f = lambdify((x, (y, z)), x + y)
>>> f(1, (2, 4))
3
1574
A more robust way of handling this is to always work with attened arguments:
>>>
>>>
>>>
>>>
>>>
10
Functions present in expr can also carry their own numerical implementations, in a
callable attached to the imp attribute. Usually you attach this using the implemented function factory:
>>> f = implemented_function(Function(f), lambda x: x+1)
>>> func = lambdify(x, f(x))
>>> func(4)
5
lambdify always prefers imp implementations to implementations in other namespaces, unless the use imps input parameter is False.
Deprecation Warnings
Usage
Attention: Functions that are not in the math module will throw a name
error when the lambda function is evaluated! So this would be better:
>>> f = lambdify(x, sin(x)*gamma(x), (math, mpmath, sympy))
5.33. Utilities
1575
5.33.7 Memoization
sympy.utilities.memoization.assoc recurrence memo(base seq)
Memo decorator for associated sequences dened by recurrence starting from base
base seq(n) callable to get base sequence elements
XXX works only for Pn0 = base seq(0) cases XXX works only for m <= n cases
sympy.utilities.memoization.recurrence memo(initial)
Memo decorator for sequences dened by recurrence
See usage examples e.g. in the specfun/combinatorial module
5.33.8 Miscellaneous
Miscellaneous stu that doesnt really t anywhere else.
sympy.utilities.misc.debug(*args)
Print *args if SYMPY DEBUG is True, else do nothing.
sympy.utilities.misc.debug decorator(func)
If SYMPY DEBUG is True, it will print a nice execution tree with arguments and results
of all decorated functions, else do nothing.
sympy.utilities.misc.find executable(executable, path=None)
Try to nd executable in the directories listed in path (a string listing directories separated by os.pathsep; defaults to os.environ[PATH]). Returns the complete lename
or None if not found
sympy.utilities.misc.rawlines(s)
Return a cut-and-pastable string that, when printed, is equivalent to the input. The
string returned is formatted so it can be indented nicely within tests; in some cases it is
wrapped in the dedent function which has to be imported from textwrap.
1576
Examples
Note: because there are characters in the examples below that need to be escaped because they are themselves within a triple quoted docstring, expressions below look more
complicated than they would be if they were printed in an interpreter window.
>>>
>>>
>>>
>>>
(
)
>>> print(rawlines(this
... that))
dedent(\
this
that)
>>> print(rawlines(this
... that
... ))
dedent(\
this
that
)
>>> s = this
... is a triple
...
>>> print(rawlines(s))
dedent(\
this
is a triple
)
>>> print(rawlines(this
... that
...
))
(
this\n
that\n
5.33.9 PKGDATA
pkgdata is a simple, extensible way for a package to acquire data le resources.
The getResource function is equivalent to the standard idioms, such as the following minimal
implementation:
import sys, os
5.33. Utilities
1577
When a loader is present on the module given by name , it will defer getResource to its
get data implementation and return it as a le-like object (such as StringIO).
sympy.utilities.pkgdata.get resource(identier, pkgname=sympy.utilities.pkgdata)
Acquire a readable object for a given package name and identier. An IOError will be
raised if the resource can not be found.
For example:
mydata = get_resource(mypkgdata.jpg).read()
Note that the package name must be fully qualied, if given, such that it would be found
in sys.modules.
In some cases, getResource will return a real le object. In that case, it may be useful to
use its name attribute to get the path rather than use it as a le-like object. For example,
you may be handing data o to a C API.
5.33.10 pytest
py.test hacks to support XFAIL/XPASS
sympy.utilities.pytest.SKIP(reason)
Similar to skip(), but this is a decorator.
sympy.utilities.pytest.raises(expectedException, code=None)
Tests that code raises the exception expectedException.
code may be a callable, such as a lambda expression or function name.
If code is not given or None, raises will return a context manager for use in with statements; the code to execute then comes from the scope of the with.
raises() does nothing if the callable raises the expected exception, otherwise it raises
an AssertionError.
Examples
>>> from sympy.utilities.pytest import raises
>>> raises(ZeroDivisionError, lambda: 1/0)
>>> raises(ZeroDivisionError, lambda: 1/2)
Traceback (most recent call last):
...
AssertionError: DID NOT RAISE
Traceback (most recent call last):
...
AssertionError: DID NOT RAISE
>>> with raises(ZeroDivisionError):
...
n = 1/0
>>> with raises(ZeroDivisionError):
1578
...
n = 1/2
Traceback (most
...
AssertionError:
Traceback (most
...
AssertionError:
Note that you cannot test multiple statements via with raises:
>>> with raises(ZeroDivisionError):
...
n = 1/0
# will execute and raise, aborting the with
...
n = 9999/0 # never executed
This is just what with is supposed to do: abort the contained statement sequence at the
rst exception and let the context manager deal with the exception.
To test multiple statements, youll need a separate with for each:
>>> with raises(ZeroDivisionError):
...
n = 1/0
# will execute and raise
>>> with raises(ZeroDivisionError):
...
n = 9999/0 # will also execute and raise
5.33. Utilities
1579
1580
from the following object types: modules, functions, classes, methods, staticmethods,
classmethods, and properties.
Modied from doctests version by looking harder for code in the case that it looks like
the the code comes from a dierent module. In the case of decorated functions (e.g.
@vectorize) they appear to come from a dierent module (e.g. multidemensional) even
though their code is not there.
class sympy.utilities.runtests.SymPyDocTestRunner(checker=None,
verbose=None, optionags=0)
A class used to run DocTest test cases, and accumulate statistics. The run method is
used to process a single DocTest case. It returns a tuple (f, t), where t is the number
of test cases tried, and f is the number of test cases that failed.
Modied from the doctest version to not reset the sys.displayhook (see issue 5140).
See the docstring of the original DocTestRunner for more information.
run(test, compileags=None, out=None, clear globs=True)
Run the examples in test, and display the results using the writer function out.
The examples are run in the namespace test.globs. If clear globs is true (the
default), then this namespace will be cleared after the test runs, to help with garbage
collection. If you would like to examine the namespace after the test completes, then
use clear globs=False.
compileflags gives the set of ags that should be used by the Python compiler when
running the examples. If not specied, then it will default to the set of future-import
ags that apply to globs.
The output of each example is checked using SymPyDocTestRunner.check output,
and the results are formatted by the SymPyDocTestRunner.report * methods.
class sympy.utilities.runtests.SymPyOutputChecker
Compared to the OutputChecker from the stdlib our OutputChecker class supports numerical comparison of oats occuring in the output of the doctest examples
check output(want, got, optionags)
Return True i the actual output from an example (got) matches the expected output (want). These strings are always considered to match if they are identical; but
depending on what option ags the test runner is using, several non-exact match
types are also possible. See the documentation for T estRunner for more information
about option ags.
sympy.utilities.runtests.SymPyTestResults
alias of TestResults
sympy.utilities.runtests.convert to native paths(lst)
Converts a list of / separated paths into a list of native (os.sep separated) paths and
converts to lowercase if the system is case insensitive.
sympy.utilities.runtests.doctest(*paths, **kwargs)
Runs doctests in all *.py les in the sympy directory which match any of the given strings
in paths or all tests if paths=[].
Notes:
Paths can be entered in native system format or in unix, forward-slash format.
Files that are on the blacklist can be tested by providing their path; they are only
excluded if no paths are given.
5.33. Utilities
1581
Examples
>>> import sympy
The split option can be passed to split the test run into parts. The split currently only
splits the test les, though this may change in the future. split should be a string of
the form a/b, which will run part a of b. Note that the regular doctests and the Sphinx
doctests are split independently. For instance, to run the rst half of the test suite:
>>> sympy.doctest(split=1/2)
The subprocess and verbose options are the same as with the function test(). See the
docstring of that function for more information.
sympy.utilities.runtests.get sympy dir()
Returns the root sympy directory and set the global value indicating whether the system
is case sensitive or not.
sympy.utilities.runtests.run all tests(test args=(),
test kwargs={},
doctest args=(),
doctest kwargs={},
examples args=(),
examples kwargs={quiet: True})
Run all tests.
Right now, this runs the regular tests (bin/test), the doctests (bin/doctest), the examples
(examples/all.py), and the sage tests (see sympy/external/tests/test sage.py).
This is what setup.py test uses.
You can pass arguments and keyword arguments to the test functions that support them
(for now, test, doctest, and the examples). See the docstrings of those functions for a
description of the available options.
For example, to run the solvers tests with colors turned o:
>>> from sympy.utilities.runtests import run_all_tests
>>> run_all_tests(test_args=(solvers,),
... test_kwargs={colors:False})
1582
5.33. Utilities
1583
>>>
>>>
>>>
[0,
>>>
[3,
>>>
[6,
sympy.utilities.runtests.sympytestfile(lename,
module relative=True,
name=None,
package=None,
globs=None,
verbose=None,
report=True,
optionags=0,
extraglobs=None,
raise on error=False,
parser=<doctest.DocTestParser instance
at 0x9c7360c>, encoding=None)
Test examples in the given le. Return (#failures, #tests).
Optional keyword arg module relative species how lenames should be interpreted:
If module relative is True (the default), then filename species a module-relative
path. By default, this path is relative to the calling modules directory; but if the
package argument is specied, then it is relative to that package. To ensure osindependence, filename should use / characters to separate path segments, and
should not be an absolute path (i.e., it may not begin with /).
If module relative is False, then filename species an os-specic path. The path
may be absolute or relative (to the current working directory).
Optional keyword arg name gives the name of the test; by default use the les basename.
Optional keyword argument package is a Python package or the name of a Python package whose directory should be used as the base directory for a module relative lename.
If no package is specied, then the calling modules directory is used as the base directory for module relative lenames. It is an error to specify package if module relative
is False.
Optional keyword arg globs gives a dict to be used as the globals when executing examples; by default, use {}. A copy of this dict is actually used for each docstring, so that
each docstrings examples start with a clean slate.
Optional keyword arg extraglobs gives a dictionary that should be merged into the
globals that are used to execute examples. By default, no extra globals are used.
Optional keyword arg verbose prints lots of stu if true, prints only failures if false; by
default, its true i -v is in sys.argv.
Optional keyword arg report prints a summary at the end when true, else prints nothing
at the end. In verbose mode, the summary is detailed, else very brief (in fact, empty if
all tests passed).
Optional keyword arg optionflags ors together module constants, and defaults to 0.
Possible values (see the docs for details):
DONT ACCEPT TRUE FOR 1
DONT ACCEPT BLANKLINE
NORMALIZE WHITESPACE
ELLIPSIS
SKIP
1584
Optional keyword arg raise on error raises an exception on the rst unexpected exception or failure. This allows failures to be post-mortem debugged.
Optional keyword arg parser species a DocTestParser (or subclass) that should be used
to extract tests from the les.
Optional keyword arg encoding species an encoding that should be used to convert the
le to unicode.
Advanced tomfoolery: testmod runs methods of a local instance of class doctest.Tester,
then merges the results into (or creates) global Tester instance doctest.master. Methods
of doctest.master can be called directly too, if you want to do something unusual. Passing
report=0 to testmod is especially useful then, to delay displaying a summary. Invoke
doctest.master.summarize(verbose) when youre done ddling.
sympy.utilities.runtests.test(*paths, **kwargs)
Run tests in the specied test *.py les.
Tests in a particular test *.py le are run if any of the given strings in paths matches a
part of the test les path. If paths=[], tests in all test *.py les are run.
Notes:
If sort=False, tests are run in random order (not default).
Paths can be entered in native system format or in unix, forward-slash format.
Files that are on the blacklist can be tested by providing their path; they are only
excluded if no paths are given.
Meaning
passed
failed
XPassed (expected to fail but passed)
XFAILed (expected to fail and indeed failed)
skipped
slow
timeout (e.g., when --timeout is used)
KeyboardInterrupt (when running the slow tests with --slow, you can
interrupt one of them without killing the test runner)
Colors have no additional meaning and are used just to facilitate interpreting the output.
Examples
>>> import sympy
5.33. Utilities
1585
>>> sympy.test()
Turn o colors:
>>> sympy.test(colors=False)
Force colors, even when the output is not to a terminal (this is useful, e.g., if you are
piping to less -r and you still want colors)
>>> sympy.test(force_colors=False)
The split option can be passed to split the test run into parts. The split currently only
splits the test les, though this may change in the future. split should be a string of the
form a/b, which will run part a of b. For instance, to run the rst half of the test suite:
>>> sympy.test(split=1/2)
You can disable running the tests in a separate subprocess using subprocess=False.
This is done to support seeding hash randomization, which is enabled by default in the
Python versions where it is supported. If subprocess=False, hash randomization is enabled/disabled according to whether it has been enabled or not in the calling Python
1586
process. However, even if it is enabled, the seed cannot be printed unless it is called
from a new Python process.
Hash randomization was added in the minor Python versions 2.6.8, 2.7.3, 3.1.5, and
3.2.3, and is enabled by default in all Python versions after and including 3.3.0.
If hash randomization is not supported subprocess=False is used automatically.
>>> sympy.test(subprocess=False)
To set the hash randomization seed, set the environment variable PYTHONHASHSEED before
running the tests. This can be done from within Python using
>>> import os
>>> os.environ[PYTHONHASHSEED] = 42
sympy.utilities.source.source(object)
Prints the source code of a given object.
5.33. Utilities
1587
standard transformations,
im-
Examples
>>> from sympy.parsing.sympy_parser import parse_expr
>>> parse_expr(1/2)
1/2
>>> type(_)
<class sympy.core.numbers.Half>
>>> from sympy.parsing.sympy_parser import standard_transformations,\
... implicit_multiplication_application
>>> transformations = (standard_transformations +
...
(implicit_multiplication_application,))
>>> parse_expr(2x, transformations=transformations)
2*x
1588
In addition the order of the arguments will not be made canonical. This feature allows
one to tell exactly how the expression was entered:
>>> a = parse_expr(1 + x, evaluate=False)
>>> b = parse_expr(x + 1, evaluate=0)
>>> a == b
False
>>> a.args
(1, x)
>>> b.args
(x, 1)
1589
The generator produces 5-tuples with these members: the token type; the token string;
a 2-tuple (srow, scol) of ints specifying the row and column where the token begins in
the source; a 2-tuple (erow, ecol) of ints specifying the row and column where the token
ends in the source; and the line on which the token was found. The line passed is the
logical line; continuation lines are included.
sympy.parsing.sympy tokenize.group(*choices)
sympy.parsing.sympy tokenize.any(*choices)
sympy.parsing.sympy tokenize.maybe(*choices)
sympy.parsing.maxima.parse maxima(str, globals=None, name dict={})
sympy.parsing.mathematica.mathematica(s)
1590
...
return _token_splittable(symbol)
...
return False
...
>>> transformation = split_symbols_custom(can_split)
>>> parse_expr(unsplittable, transformations=standard_transformations +
... (transformation, implicit_multiplication))
unsplittable
local dict,
Use this before implicit application(), otherwise expressions like sin 2x will be
parsed as x * sin(2) rather than sin(2*x).
Example:
>>> from sympy.parsing.sympy_parser import (parse_expr,
... standard_transformations, implicit_multiplication)
>>> transformations = standard_transformations + (implicit_multiplication,)
>>> parse_expr(3 x y, transformations=transformations)
3*x*y
local dict,
Example:
>>> from sympy.parsing.sympy_parser import (parse_expr,
... standard_transformations, function_exponentiation)
>>> transformations = standard_transformations + (function_exponentiation,)
>>> parse_expr(sin**4(x), transformations=transformations)
sin(x)**4
Example:
1591
5.35 Calculus
Some calculus-related methods waiting to nd a better place in the SymPy modules tree.
sympy.calculus.euler.euler equations(L, funcs=(), vars=())
Find the Euler-Lagrange equations [R1] (page 1915) for a given Lagrangian.
Parameters L : Expr
The Lagrangian that should be a function of the functions listed in
the second argument and their derivatives.
For example, in the case of two functions f (x, y), g(x, y) and two independent variables x, y the Lagrangian would have the form:
(
)
f (x, y) f (x, y) g(x, y) g(x, y)
L f (x, y), g(x, y),
,
,
,
, x, y
x
y
x
y
In many cases it is not necessary to provide anything, except the Lagrangian, it will be autodetected (and an error raised if this couldnt
be done).
funcs : Function or an iterable of Functions
The functions that the Lagrangian depends on. The Euler equations
are dierential equations for each of these functions.
vars : Symbol or an iterable of Symbols
The Symbols that are the independent variables of the functions.
1592
sympy.calculus.singularities.singularities(expr, sym)
Finds singularities for a function. Currently supported functions are: - univariate real
rational functions
References
5.35. Calculus
also
1593
Order = 0 corresponds to interpolation. Only supply so many points you think makes
sense to around x0 when extracting the derivative (the function need to be well behaved
within that region). Also beware of Runges phenomenon.
References
we see that the example above only contain rounding errors. apply nite di can also
be used on more abstract objects:
1594
>>>
>>>
>>>
>>>
>>>
>>>
(-1
1594),
Examples
>>> from sympy import symbols, Function, exp, sqrt, Symbol, as_finite_diff
>>> x, h = symbols(x h)
>>> f = Function(f)
>>> as_finite_diff(f(x).diff(x))
-f(x - 1/2) + f(x + 1/2)
The default step size and number of points are 1 and order + 1 respectively. We can
change the step size by passing a symbol as a parameter:
>>> as_finite_diff(f(x).diff(x), h)
-f(-h/2 + x)/h + f(h/2 + x)/h
5.35. Calculus
1595
The algorithm is not restricted to use equidistant spacing, nor do we need to make the
approximation around x0, but we can get an expression estimating the derivative at an
oset:
If weights for a nite dierence approximation of the 3rd order derivative is wanted,
weights for 0th, 1st and 2nd order are calculated for free, so are formulae using fewer
and fewer of the parameters. This is something one can take advantage of to save computational cost.
References
1596
Examples
>>> from sympy import S
>>> from sympy.calculus import finite_diff_weights
>>> finite_diff_weights(1, [-S(1)/2, S(1)/2, S(3)/2, S(5)/2], 0)
[[[1, 0, 0, 0],
[1/2, 1/2, 0, 0],
[3/8, 3/4, -1/8, 0],
[5/16, 15/16, -5/16, 1/16]],
[[0, 0, 0, 0], [-1, 1, 0, 0], [-1, 1, 0, 0], [-23/24, 7/8, 1/8, -1/24]]]
the result is two subslists, the rst is for the 0:th derivative (interpolation) and the second
for the rst derivative (we gave 1 as the parameter of order so this is why we get no list
for a higher order derivative). Each sublist contains the most accurate formula in the
end (all points used).
Beware of the oset in the lower accuracy formulae when looking at a centered dierence:
>>> from sympy import S
>>> from sympy.calculus import finite_diff_weights
>>> finite_diff_weights(1, [-S(5)/2, -S(3)/2, -S(1)/2, S(1)/2,
...
S(3)/2, S(5)/2], 0)
[[[1, 0, 0, 0, 0, 0],
[-3/2, 5/2, 0, 0, 0, 0],
[3/8, -5/4, 15/8, 0, 0, 0],
[1/16, -5/16, 15/16, 5/16, 0, 0],
[3/128, -5/32, 45/64, 15/32, -5/128, 0],
[3/256, -25/256, 75/128, 75/128, -25/256, 3/256]],
[[0, 0, 0, 0, 0, 0],
[-1, 1, 0, 0, 0, 0],
[1, -3, 2, 0, 0, 0],
[1/24, -1/8, -7/8, 23/24, 0, 0],
[0, 1/24, -9/8, 9/8, -1/24, 0],
[-3/640, 25/384, -75/64, 75/64, -25/384, 3/640]]]
The capability to generate weights at arbitrary points can be used e.g. to minimize
Runges phenomenon by using Chebyshev nodes:
>>> from sympy import cos, symbols, pi, simplify
>>> from sympy.calculus import finite_diff_weights
>>> N, (h, x) = 4, symbols(h x)
>>> x_list = [x+h*cos(i*pi/(N)) for i in range(N,-1,-1)] # chebyshev nodes
>>> print(x_list)
[-h + x, -sqrt(2)*h/2 + x, x, sqrt(2)*h/2 + x, h + x]
>>> mycoeffs = finite_diff_weights(1, x_list, 0)[1][4]
>>> [simplify(c) for c in mycoeffs]
[(h**3/2 + h**2*x - 3*h*x**2 - 4*x**3)/h**4,
(-sqrt(2)*h**3 - 4*h**2*x + 3*sqrt(2)*h*x**2 + 8*x**3)/h**4,
6*x/h**2 - 8*x**3/h**4,
(sqrt(2)*h**3 - 4*h**2*x - 3*sqrt(2)*h*x**2 + 8*x**3)/h**4,
(-h**3/2 + h**2*x + 3*h*x**2 - 4*x**3)/h**4]
1597
5.36.1 Contents
Hydrogen Wavefunctions
sympy.physics.hydrogen.E nl(n, Z=1)
Returns the energy of the state (n, l) in Hartree atomic units.
The energy doesnt depend on l.
Examples
>>> from sympy import var
>>> from sympy.physics.hydrogen import E_nl
>>> var(n Z)
(n, Z)
>>> E_nl(n, Z)
-Z**2/(2*n**2)
>>> E_nl(1)
-1/2
>>> E_nl(2)
-1/8
>>> E_nl(3)
-1/18
>>> E_nl(3, 47)
-2209/18
Examples
>>> from sympy.physics.hydrogen import E_nl_dirac
>>> E_nl_dirac(1, 0)
-0.500006656595360
>>> E_nl_dirac(2, 0)
-0.125002080189006
>>> E_nl_dirac(2, 1)
-0.125000416028342
>>> E_nl_dirac(2, 1, False)
-0.125002080189006
>>> E_nl_dirac(3, 0)
-0.0555562951740285
>>> E_nl_dirac(3, 1)
-0.0555558020932949
1598
For Hydrogen atom, you can just use the default value of Z=1:
>>> R_nl(1, 0, r)
2*exp(-r)
>>> R_nl(2, 0, r)
sqrt(2)*(-r + 2)*exp(-r/2)/4
>>> R_nl(3, 0, r)
2*sqrt(3)*(2*r**2/9 - 2*r + 3)*exp(-r/3)/27
1599
Matrices
Known matrices related to physics
sympy.physics.matrices.mdft(n)
Returns an expression of a discrete Fourier transform as a matrix multiplication. It is an
n X n matrix.
References
sympy.physics.matrices.mgamma(mu, lower=False)
Returns a Dirac gamma matrix in the standard (Dirac) representation.
If you want , use gamma(mu, True).
We use a convention:
5 = i 0 1 2 3
5 = i 0 1 2 3 = 5
References
1600
[ 0, -1, 0, 0],
[-1, 0, 0, 0]])
sympy.physics.matrices.msigma(i)
Returns a Pauli matrix i with i = 1, 2, 3
References
To translate a body having a mass of 2 units a distance of 1 unit along the x-axis we get:
>>> from sympy.physics.matrices import pat_matrix
>>> pat_matrix(2, 1, 0, 0)
Matrix([
[0, 0, 0],
[0, 2, 0],
[0, 0, 2]])
Pauli Algebra
This module implements Pauli algebra by subclassing Symbol. Only algebraic properties of
Pauli matrices are used (we dont use the Matrix class).
See the documentation to the class Pauli for examples.
References
1601
Examples
>>> from sympy.physics.paulialgebra import Pauli, evaluate_pauli_product
>>> from sympy import I
>>> evaluate_pauli_product(I*Pauli(1)*Pauli(2))
-sigma3
>>> from sympy.abc import x,y
>>> evaluate_pauli_product(x**2*Pauli(2)*Pauli(1))
-I*x**2*sigma3
1602
1603
Second Quantization
Second quantization operators and states for bosons.
This follow the formulation of Fetter and Welecka, Quantum Theory of Many-Particle Systems.
class sympy.physics.secondquant.Dagger
Hermitian conjugate of creation/annihilation operators.
Examples
>>> from sympy import I
>>> from sympy.physics.secondquant import Dagger, B, Bd
>>> Dagger(2*I)
-2*I
>>> Dagger(B(0))
CreateBoson(0)
>>> Dagger(Bd(0))
AnnihilateBoson(0)
classmethod eval(arg)
Evaluates the Dagger instance.
Examples
>>> from sympy import I
>>> from sympy.physics.secondquant import Dagger, B, Bd
>>> Dagger(2*I)
-2*I
>>> Dagger(B(0))
CreateBoson(0)
>>> Dagger(Bd(0))
AnnihilateBoson(0)
1604
See Also:
eval
(page
(page 377)
1605),
sympy.functions.special.delta functions.DiracDelta
References
Symbolic indices:
>>> from sympy.abc import
>>> KroneckerDelta(i, j)
KroneckerDelta(i, j)
>>> KroneckerDelta(i, i)
1
>>> KroneckerDelta(i, i +
0
>>> KroneckerDelta(i, i +
KroneckerDelta(i, i + k +
i, j, k
1)
1 + k)
1)
classmethod eval(i, j)
Evaluates the discrete delta function.
Examples
>>> from sympy.functions.special.tensor_functions import KroneckerDelta
>>> from sympy.abc import i, j, k
>>> KroneckerDelta(i,
KroneckerDelta(i, j)
>>> KroneckerDelta(i,
1
>>> KroneckerDelta(i,
0
>>> KroneckerDelta(i,
KroneckerDelta(i, i +
j)
i)
i + 1)
i + 1 + k)
k + 1)
# indirect doctest
indices contain equal information
Returns True if indices are either both above or below fermi.
1605
Examples
>>> from sympy.functions.special.tensor_functions import KroneckerDelta
>>> from sympy import Symbol
>>> a = Symbol(a, above_fermi=True)
>>> i = Symbol(i, below_fermi=True)
>>> p = Symbol(p)
>>> q = Symbol(q)
>>> KroneckerDelta(p, q).indices_contain_equal_information
True
>>> KroneckerDelta(p, q+1).indices_contain_equal_information
True
>>> KroneckerDelta(i, p).indices_contain_equal_information
False
is above fermi
True if Delta can be non-zero above fermi
See Also:
is below fermi
(page
1606),
is only above fermi (page 1607)
(page
1607),
Examples
>>> from sympy.functions.special.tensor_functions import KroneckerDelta
>>> from sympy import Symbol
>>> a = Symbol(a, above_fermi=True)
>>> i = Symbol(i, below_fermi=True)
>>> p = Symbol(p)
>>> q = Symbol(q)
>>> KroneckerDelta(p, a).is_above_fermi
True
>>> KroneckerDelta(p, i).is_above_fermi
False
>>> KroneckerDelta(p, q).is_above_fermi
True
is below fermi
True if Delta can be non-zero below fermi
See Also:
is above fermi
(page
1606),
is only below fermi (page 1607)
(page
1607),
Examples
>>> from sympy.functions.special.tensor_functions import KroneckerDelta
>>> from sympy import Symbol
>>> a = Symbol(a, above_fermi=True)
>>> i = Symbol(i, below_fermi=True)
>>> p = Symbol(p)
>>> q = Symbol(q)
>>> KroneckerDelta(p, a).is_below_fermi
False
1606
killable index
Returns the index which is preferred to substitute in the nal expression.
The index to substitute is the index with less information regarding fermi level. If
indices contain same information, a is preferred before b.
See Also:
5.36. Physics Module
1607
preferred index
Returns the index which is preferred to keep in the nal expression.
The preferred index is the index with more information regarding fermi level. If
indices contain same information, a is preferred before b.
See Also:
killable index (page 1607)
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
i
>>>
a
>>>
i
class sympy.physics.secondquant.AnnihilateBoson
Bosonic annihilation operator.
Examples
>>> from sympy.physics.secondquant import B
>>> from sympy.abc import x
>>> B(x)
AnnihilateBoson(x)
apply operator(state)
Apply state to self if self is not symbolic and state is a FockStateKet, else multiply
self by state.
1608
Examples
>>> from sympy.physics.secondquant import B, BKet
>>> from sympy.abc import x, y, n
>>> B(x).apply_operator(y)
y*AnnihilateBoson(x)
>>> B(0).apply_operator(BKet((n,)))
sqrt(n)*FockStateBosonKet((n - 1,))
class sympy.physics.secondquant.CreateBoson
Bosonic creation operator.
apply operator(state)
Apply state to self if self is not symbolic and state is a FockStateKet, else multiply
self by state.
Examples
>>> from sympy.physics.secondquant import B, Dagger, BKet
>>> from sympy.abc import x, y, n
>>> Dagger(B(x)).apply_operator(y)
y*CreateBoson(x)
>>> B(0).apply_operator(BKet((n,)))
sqrt(n)*FockStateBosonKet((n - 1,))
class sympy.physics.secondquant.AnnihilateFermion
Fermionic annihilation operator.
apply operator(state)
Apply state to self if self is not symbolic and state is a FockStateKet, else multiply
self by state.
Examples
>>> from sympy.physics.secondquant import B, Dagger, BKet
>>> from sympy.abc import x, y, n
>>> Dagger(B(x)).apply_operator(y)
y*CreateBoson(x)
>>> B(0).apply_operator(BKet((n,)))
sqrt(n)*FockStateBosonKet((n - 1,))
is only q annihilator
Always destroy a quasi-particle? (annihilate hole or annihilate particle)
>>>
>>>
>>>
>>>
>>>
>>> F(a).is_only_q_annihilator
True
>>> F(i).is_only_q_annihilator
False
1609
>>> F(p).is_only_q_annihilator
False
is only q creator
Always create a quasi-particle? (create hole or create particle)
>>>
>>>
>>>
>>>
>>>
>>> F(a).is_only_q_creator
False
>>> F(i).is_only_q_creator
True
>>> F(p).is_only_q_creator
False
is q annihilator
Can we destroy a quasi-particle? (annihilate hole or annihilate particle) If so, would
that be above or below the fermi surface?
>>>
>>>
>>>
>>>
>>>
>>> F(a).is_q_annihilator
1
>>> F(i).is_q_annihilator
0
>>> F(p).is_q_annihilator
1
is q creator
Can we create a quasi-particle? (create hole or create particle) If so, would that be
above or below the fermi surface?
>>>
>>>
>>>
>>>
>>>
>>> F(a).is_q_creator
0
>>> F(i).is_q_creator
-1
>>> F(p).is_q_creator
-1
class sympy.physics.secondquant.CreateFermion
Fermionic creation operator.
apply operator(state)
Apply state to self if self is not symbolic and state is a FockStateKet, else multiply
self by state.
1610
Examples
>>> from sympy.physics.secondquant import B, Dagger, BKet
>>> from sympy.abc import x, y, n
>>> Dagger(B(x)).apply_operator(y)
y*CreateBoson(x)
>>> B(0).apply_operator(BKet((n,)))
sqrt(n)*FockStateBosonKet((n - 1,))
is only q annihilator
Always destroy a quasi-particle? (annihilate hole or annihilate particle)
>>>
>>>
>>>
>>>
>>>
>>> Fd(a).is_only_q_annihilator
False
>>> Fd(i).is_only_q_annihilator
True
>>> Fd(p).is_only_q_annihilator
False
is only q creator
Always create a quasi-particle? (create hole or create particle)
>>>
>>>
>>>
>>>
>>>
>>> Fd(a).is_only_q_creator
True
>>> Fd(i).is_only_q_creator
False
>>> Fd(p).is_only_q_creator
False
is q annihilator
Can we destroy a quasi-particle? (annihilate hole or annihilate particle) If so, would
that be above or below the fermi surface?
>>>
>>>
>>>
>>>
>>>
>>> Fd(a).is_q_annihilator
0
>>> Fd(i).is_q_annihilator
-1
>>> Fd(p).is_q_annihilator
-1
1611
is q creator
Can we create a quasi-particle? (create hole or create particle) If so, would that be
above or below the fermi surface?
>>>
>>>
>>>
>>>
>>>
>>> Fd(a).is_q_creator
1
>>> Fd(i).is_q_creator
0
>>> Fd(p).is_q_creator
1
class sympy.physics.secondquant.FockState
Many particle Fock state with a sequence of occupation numbers.
Anywhere you can have a FockState, you can also have S.Zero. All code must check for
this!
Base class to represent FockStates.
class sympy.physics.secondquant.FockStateBra
Representation of a bra.
class sympy.physics.secondquant.FockStateKet
Representation of a ket.
class sympy.physics.secondquant.FockStateBosonKet
Many particle Fock state with a sequence of occupation numbers.
Occupation numbers can be any integer >= 0.
Examples
>>> from sympy.physics.secondquant import BKet
>>> BKet([1, 2])
FockStateBosonKet((1, 2))
class sympy.physics.secondquant.FockStateBosonBra
Describes a collection of BosonBra particles.
Examples
>>> from sympy.physics.secondquant import BBra
>>> BBra([1, 2])
FockStateBosonBra((1, 2))
sympy.physics.secondquant.BBra
alias of FockStateBosonBra (page 1612)
sympy.physics.secondquant.BKet
alias of FockStateBosonKet (page 1612)
sympy.physics.secondquant.FBra
alias of FockStateFermionBra
1612
sympy.physics.secondquant.FKet
alias of FockStateFermionKet
sympy.physics.secondquant.F
alias of AnnihilateFermion (page 1609)
sympy.physics.secondquant.Fd
alias of CreateFermion (page 1610)
sympy.physics.secondquant.B
alias of AnnihilateBoson (page 1608)
sympy.physics.secondquant.Bd
alias of CreateBoson (page 1609)
sympy.physics.secondquant.apply operators(e)
Take a sympy expression with operators and states and apply the operators.
Examples
>>> from sympy.physics.secondquant import apply_operators
>>> from sympy import sympify
>>> apply_operators(sympify(3)+4)
7
class sympy.physics.secondquant.InnerProduct
An unevaluated inner product between a bra and ket.
Currently this class just reduces things to a product of Kronecker Deltas. In the future,
we could introduce abstract states like |a> and |b>, and leave the inner product unevaluated as <a|b>.
bra
Returns the bra part of the state
ket
Returns the ket part of the state
class sympy.physics.secondquant.BosonicBasis
Base class for a basis set of bosonic Fock states.
class sympy.physics.secondquant.VarBosonicBasis(n max)
A single state, variable particle number basis set.
Examples
>>> from sympy.physics.secondquant import VarBosonicBasis
>>> b = VarBosonicBasis(5)
>>> b
[FockState((0,)), FockState((1,)), FockState((2,)),
FockState((3,)), FockState((4,))]
index(state)
Returns the index of state in basis.
1613
Examples
>>> from sympy.physics.secondquant import VarBosonicBasis
>>> b = VarBosonicBasis(3)
>>> state = b.state(1)
>>> b
[FockState((0,)), FockState((1,)), FockState((2,))]
>>> state
FockStateBosonKet((1,))
>>> b.index(state)
1
state(i)
The state of a single basis.
Examples
>>> from sympy.physics.secondquant import VarBosonicBasis
>>> b = VarBosonicBasis(5)
>>> b.state(3)
FockStateBosonKet((3,))
index(state)
Returns the index of state in basis.
Examples
>>> from sympy.physics.secondquant import FixedBosonicBasis
>>> b = FixedBosonicBasis(2, 3)
>>> b.index(b.state(3))
3
state(i)
Returns the state that lies at index i of the basis
1614
Examples
>>> from sympy.physics.secondquant import FixedBosonicBasis
>>> b = FixedBosonicBasis(2, 3)
>>> b.state(3)
FockStateBosonKet((1, 0, 1))
class sympy.physics.secondquant.Commutator
The Commutator: [A, B] = A*B - B*A
The arguments are ordered according to . cmp ()
>>> from sympy import symbols
>>> from sympy.physics.secondquant import Commutator
>>> A, B = symbols(A,B, commutative=False)
>>> Commutator(B, A)
-Commutator(A, B)
>>> Commutator(Fd(a),Fd(i))
2*NO(CreateFermion(a)*CreateFermion(i))
But for more complicated expressions, the evaluation is triggered by a call to .doit()
>>> comm = Commutator(Fd(p)*Fd(q),F(i)); comm
Commutator(CreateFermion(p)*CreateFermion(q), AnnihilateFermion(i))
>>> comm.doit(wicks=True)
-KroneckerDelta(i, p)*CreateFermion(q) +
KroneckerDelta(i, q)*CreateFermion(p)
doit(**hints)
Enables the computation of complex expressions.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
0
classmethod eval(a, b)
The Commutator [A,B] is on canonical form if A < B.
5.36. Physics Module
1615
Examples
>>>
>>>
>>>
>>>
>>>
0
sympy.physics.secondquant.contraction(a, b)
Calculates contraction of Fermionic operators a and b.
Examples
>>>
>>>
>>>
>>>
>>>
from
from
p, q
a, b
i, j
For general indices a non-zero result restricts the indices to below/above the fermi surface:
>>> contraction(Fd(p),F(q))
KroneckerDelta(_i, q)*KroneckerDelta(p, q)
>>> contraction(F(p),Fd(q))
KroneckerDelta(_a, q)*KroneckerDelta(p, q)
1616
>>> contraction(Fd(p),Fd(q))
0
With the keyword keep only fully contracted=True, only fully contracted terms are returned.
By request, the result can be simplied in the following order: KroneckerDelta
functions are evaluated Dummy variables are substituted consistently across terms
>>> p, q, r = symbols(p q r, cls=Dummy)
>>> wicks(Fd(p)*(F(q)+F(r)), keep_only_fully_contracted=True)
KroneckerDelta(_i, _q)*KroneckerDelta(
_p, _q) + KroneckerDelta(_i, _r)*KroneckerDelta(_p, _r)
class sympy.physics.secondquant.NO
This Object is used to represent normal ordering brackets.
i.e. {abcd} sometimes written :abcd:
Applying the function NO(arg) to an argument means that all operators in the argument
will be assumed to anticommute, and have vanishing contractions. This allows an immediate reordering to canonical form upon object creation.
>>> from sympy import symbols
>>> from sympy.physics.secondquant import NO, F, Fd
>>> p,q = symbols(p,q)
>>> NO(Fd(p)*F(q))
NO(CreateFermion(p)*AnnihilateFermion(q))
>>> NO(F(q)*Fd(p))
-NO(CreateFermion(p)*AnnihilateFermion(q))
Note: If you want to generate a normal ordered equivalent of an expression, you should
use the function wicks(). This class only indicates that all operators inside the brackets
anticommute, and have vanishing contractions. Nothing more, nothing less.
doit(**kw args)
Either removes the brackets or enables complex computations in its arguments.
1617
Examples
>>> from sympy.physics.secondquant import NO, Fd, F
>>> from textwrap import fill
>>> from sympy import symbols, Dummy
>>> p,q = symbols(p,q, cls=Dummy)
>>> print(fill(str(NO(Fd(p)*F(q)).doit())))
KroneckerDelta(_a, _p)*KroneckerDelta(_a,
_q)*CreateFermion(_a)*AnnihilateFermion(_a) + KroneckerDelta(_a,
_p)*KroneckerDelta(_i, _q)*CreateFermion(_a)*AnnihilateFermion(_i) KroneckerDelta(_a, _q)*KroneckerDelta(_i,
_p)*AnnihilateFermion(_a)*CreateFermion(_i) - KroneckerDelta(_i,
_p)*KroneckerDelta(_i, _q)*AnnihilateFermion(_i)*CreateFermion(_i)
get subNO(i)
Returns a NO() without FermionicOperator at index i.
Examples
>>> from sympy import symbols
>>> from sympy.physics.secondquant import F, NO
>>> p,q,r = symbols(p,q,r)
>>> NO(F(p)*F(q)*F(r)).get_subNO(1)
NO(AnnihilateFermion(p)*AnnihilateFermion(r))
has q annihilators
Return 0 if the rightmost argument of the rst argument is a not a q annihilator, else
1 if it is above fermi or -1 if it is below fermi.
Examples
>>> from sympy import symbols
>>> from sympy.physics.secondquant import NO, F, Fd
>>>
>>>
>>>
-1
>>>
1
>>>
0
a = symbols(a, above_fermi=True)
i = symbols(i, below_fermi=True)
NO(Fd(a)*Fd(i)).has_q_annihilators
NO(F(i)*F(a)).has_q_annihilators
NO(Fd(a)*F(i)).has_q_annihilators
has q creators
Return 0 if the leftmost argument of the rst argument is a not a q creator, else 1 if
it is above fermi or -1 if it is below fermi.
Examples
>>> from sympy import symbols
>>> from sympy.physics.secondquant import NO, F, Fd
1618
>>>
>>>
>>>
1
>>>
-1
>>>
0
a = symbols(a, above_fermi=True)
i = symbols(i, below_fermi=True)
NO(Fd(a)*Fd(i)).has_q_creators
NO(F(i)*F(a)).has_q_creators
NO(Fd(i)*F(a)).has_q_creators
iter q annihilators()
Iterates over the annihilation operators.
Examples
>>>
>>>
>>>
>>>
>>>
from
i, j
a, b
from
no =
>>> no.iter_q_creators()
<generator object... at 0x...>
>>> list(no.iter_q_creators())
[0, 1]
>>> list(no.iter_q_annihilators())
[3, 2]
iter q creators()
Iterates over the creation operators.
Examples
>>>
>>>
>>>
>>>
>>>
from
i, j
a, b
from
no =
>>> no.iter_q_creators()
<generator object... at 0x...>
>>> list(no.iter_q_creators())
[0, 1]
>>> list(no.iter_q_annihilators())
[3, 2]
sympy.physics.secondquant.evaluate deltas(e)
We evaluate KroneckerDelta symbols in the expression assuming Einstein summation.
If one index is repeated it is summed over and in eect substituted with the other one.
If both indices are repeated we substitute according to what is the preferred index. this
is determined by KroneckerDelta.preferred index and KroneckerDelta.killable index.
In case there are no possible substitutions or if a substitution would imply a loss of
information, nothing is done.
1619
In case an index appears in more than one KroneckerDelta, the resulting substitution
depends on the order of the factors. Since the ordering is platform dependent, the literal
expression resulting from this function may be hard to predict.
Examples
The order of preference for these indices according to KroneckerDelta is (a, b, i, j, p, q).
Trivial cases:
>>> evaluate_deltas(KroneckerDelta(i,j)*f(i))
f(_j)
>>> evaluate_deltas(KroneckerDelta(i,j)*f(j))
f(_i)
>>> evaluate_deltas(KroneckerDelta(i,p)*f(p))
f(_i)
>>> evaluate_deltas(KroneckerDelta(q,p)*f(p))
f(_q)
>>> evaluate_deltas(KroneckerDelta(q,p)*f(q))
f(_p)
Finally, here are some cases where nothing is done, because that would imply a loss of
information:
>>> evaluate_deltas(KroneckerDelta(i,p)*f(q))
f(_q)*KroneckerDelta(_i, _p)
>>> evaluate_deltas(KroneckerDelta(i,p)*f(i))
f(_i)*KroneckerDelta(_i, _p)
class sympy.physics.secondquant.AntiSymmetricTensor
Stores upper and lower indices in separate Tuples.
Each group of indices is assumed to be antisymmetric.
Examples
1620
As you can see, the indices are automatically sorted to a canonical form.
doit(**kw args)
Returns self.
Examples
>>> from sympy import symbols
>>> from sympy.physics.secondquant import AntiSymmetricTensor
>>> i, j = symbols(i,j, below_fermi=True)
>>> a, b = symbols(a,b, above_fermi=True)
>>> AntiSymmetricTensor(v, (a, i), (b, j)).doit()
AntiSymmetricTensor(v, (a, i), (b, j))
lower
Returns the lower indices.
Examples
>>> from sympy import symbols
>>> from sympy.physics.secondquant import AntiSymmetricTensor
>>> i, j = symbols(i,j, below_fermi=True)
>>> a, b = symbols(a,b, above_fermi=True)
>>> AntiSymmetricTensor(v, (a, i), (b, j))
AntiSymmetricTensor(v, (a, i), (b, j))
>>> AntiSymmetricTensor(v, (a, i), (b, j)).lower
(b, j)
symbol
Returns the symbol of the tensor.
Examples
>>> from sympy import symbols
>>> from sympy.physics.secondquant import AntiSymmetricTensor
>>> i, j = symbols(i,j, below_fermi=True)
>>> a, b = symbols(a,b, above_fermi=True)
>>> AntiSymmetricTensor(v, (a, i), (b, j))
AntiSymmetricTensor(v, (a, i), (b, j))
>>> AntiSymmetricTensor(v, (a, i), (b, j)).symbol
v
upper
Returns the upper indices.
1621
Examples
>>> from sympy import symbols
>>> from sympy.physics.secondquant import AntiSymmetricTensor
>>> i, j = symbols(i,j, below_fermi=True)
>>> a, b = symbols(a,b, above_fermi=True)
>>> AntiSymmetricTensor(v, (a, i), (b, j))
AntiSymmetricTensor(v, (a, i), (b, j))
>>> AntiSymmetricTensor(v, (a, i), (b, j)).upper
(a, i)
sympy.physics.secondquant.substitute dummies(expr,
new indices=False,
pretty indices={})
Collect terms by substitution of dummy variables.
This routine allows simplication of Add expressions containing terms which dier only
due to dummy variables.
The idea is to substitute all dummy variables consistently depending on the structure of
the term. For each term, we obtain a sequence of all dummy variables, where the order is
determined by the index range, what factors the index belongs to and its position in each
factor. See get ordered dummies() for more inforation about the sorting of dummies.
The index sequence is then substituted consistently in each term.
Examples
>>>
>>>
>>>
>>>
>>>
Since a, b, c and d are equivalent summation indices, the expression can be simplied
to a single term (for which the dummy indices are still summed over)
>>> substitute_dummies(expr)
2*f(_a, _b)
Controlling output:
By default the dummy symbols that are already present in the expression will be reused in
a dierent permuation. However, if new indices=True, new dummies will be generated
and inserted. The keyword pretty indices can be used to control this generation of new
symbols.
By default the new dummies will be generated on the form i 1, i 2, a 1, etc. If you supply
a dictionary with key:value pairs in the form:
{ index group: string of letters }
The letters will be used as labels for the new dummy symbols. The index groups must
be one of above, below or general.
>>> expr = f(a,b,i,j)
>>> my_dummies = { above:st, below:uv }
1622
If we run out of letters, or if there is no keyword for some index group the default dummy
generator will be used as a fallback:
>>> p,q = symbols(p q, cls=Dummy) # general indices
>>> expr = f(p,q)
>>> substitute_dummies(expr, new_indices=True, pretty_indices=my_dummies)
f(_p_0, _p_1)
class sympy.physics.secondquant.PermutationOperator
Represents the index permutation operator P(ij).
P(ij)*f(i)*g(j) = f(i)*g(j) - f(j)*g(i)
get permuted(expr)
Returns -expr with permuted indices.
>>> from sympy import symbols, Function
>>> from sympy.physics.secondquant import PermutationOperator
>>> p,q = symbols(p,q)
>>> f = Function(f)
>>> PermutationOperator(p,q).get_permuted(f(p,q))
-f(q, p)
Wigner Symbols
Wigner, Clebsch-Gordan, Racah, and Gaunt coecients
1623
Collection of functions for calculating Wigner 3j, 6j, 9j, Clebsch-Gordan, Racah as well as
Gaunt coecients exactly, all evaluating to a rational number times the square root of a
rational number [Rasch03] (page 1915).
Please see the description of the individual functions for further details and examples.
References
Credits and Copyright
This code was taken from Sage with the permission of all authors:
https://groups.google.com/forum/#!topic/sage-devel/M4NZdu-7O38
AUTHORS:
Jens Rasch (2009-03-24): initial version for Sage
Jens Rasch (2009-05-31): updated to sage-4.0
OUTPUT:
Rational number times the square root of a rational number.
EXAMPLES:
>>> from sympy import S
>>> from sympy.physics.wigner import clebsch_gordan
>>> clebsch_gordan(S(3)/2, S(1)/2, 2, S(3)/2, S(1)/2, 2)
1
>>> clebsch_gordan(S(3)/2, S(1)/2, 1, S(3)/2, -S(1)/2, 1)
sqrt(3)/2
>>> clebsch_gordan(S(3)/2, S(1)/2, 1, -S(1)/2, S(1)/2, 0)
-sqrt(2)/2
NOTES:
The Clebsch-Gordan coecient will be evaluated via its relation to Wigner 3j symbols:
sympy.physics.wigner.gaunt(l 1, l 2, l 3, m 1, m 2, m 3, prec=None)
Calculate the Gaunt coecient.
The Gaunt coecient is dened as the integral over three spherical harmonics:
Y (j1 , j2 , j3 , m1 , m2 , m3 ) = Yl1 ,m1 ()Yl2 ,m2 ()Yl3 ,m3 ()d = (2l1 + 1)(2l2 + 1)(2l3 + 1)/(4) Y (j1 , j2 , j3 , 0, 0, 0) Y (
1624
INPUT:
l 1, l 2, l 3, m 1, m 2, m 3 - integer
prec - precision, default: None. Providing a precision can drastically speed up the
calculation.
OUTPUT:
Rational number times the square root of a rational number (if prec=None), or real number if a precision is given.
Examples
>>> from sympy.physics.wigner import gaunt
>>> gaunt(1,0,1,1,0,-1)
-1/(2*sqrt(pi))
>>> gaunt(1000,1000,1200,9,3,-12).n(64)
0.00689500421922113448...
NOTES:
The Gaunt coecient obeys the following symmetry rules:
invariant under any permutation of the columns
Y (j1 , j2 , j3 , m1 , m2 , m3 ) = Y (j1 , j2 , j3 , m1 , m2 , m3 )
symmetric with respect to the 72 Regge symmetries as inherited for the 3j symbols
[Regge58] (page 1916)
zero for l1 , l2 , l3 not fullling triangle relation
zero for violating any one of the conditions: l1 |m1 |, l2 |m2 |, l3 |m3 |
non-zero only for an even sum of the li , i.e. J = l1 + l2 + l3 = 2n for n in N
ALGORITHM:
This function uses the algorithm of [Liberatodebrito82] (page 1916) to calculate the value
of the Gaunt coecient exactly. Note that the formula contains alternating sums over
large factorials and is therefore unsuitable for nite precision arithmetic and only useful
for a computer algebra system [Rasch03] (page 1915).
1625
REFERENCES:
AUTHORS:
Jens Rasch (2009-03-24): initial version for Sage
OUTPUT:
Rational number times the square root of a rational number (if prec=None), or real number if a precision is given.
Examples
>>> from sympy.physics.wigner import racah
>>> racah(3,3,3,3,3,3)
-1/14
NOTES:
The Racah symbol is related to the Wigner 6j symbol:
W igner6j(j1 , j2 , j3 , j4 , j5 , j6 ) = (1)j1 +j2 +j4 +j5 W (j1 , j2 , j5 , j4 , j3 , j6 )
Please see the 6j symbol for its much richer symmetries and for additional properties.
ALGORITHM:
This function uses the algorithm of [Edmonds74] (page 1916) to calculate the value of the
6j symbol exactly. Note that the formula contains alternating sums over large factorials
and is therefore unsuitable for nite precision arithmetic and only useful for a computer
algebra system [Rasch03] (page 1915).
AUTHORS:
Jens Rasch (2009-03-24): initial version
sympy.physics.wigner.wigner 3j(j 1, j 2, j 3, m 1, m 2, m 3)
Calculate the Wigner 3j symbol W igner3j(j1 , j2 , j3 , m1 , m2 , m3 ).
INPUT:
j 1, j 2, j 3, m 1, m 2, m 3 - integer or half integer
OUTPUT:
Rational number times the square root of a rational number.
Examples
>>> from sympy.physics.wigner import wigner_3j
>>> wigner_3j(2, 6, 4, 0, 0, 0)
sqrt(715)/143
>>> wigner_3j(2, 6, 4, 0, 0, 1)
0
1626
It is an error to have arguments that are not integer or half integer values:
sage: wigner 3j(2.1, 6, 4, 0, 0, 0)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer
sage: wigner 3j(2, 6, 4, 1, 0, -1.1)
Traceback (most recent call last):
...
ValueError: m values must be integer or half integer
NOTES:
The Wigner 3j symbol obeys the following symmetry rules:
invariant under any permutation of the columns (with the exception of a sign change
where J := j1 + j2 + j3 ):
ALGORITHM:
This function uses the algorithm of [Edmonds74] (page 1916) to calculate the value of the
3j symbol exactly. Note that the formula contains alternating sums over large factorials
and is therefore unsuitable for nite precision arithmetic and only useful for a computer
algebra system [Rasch03] (page 1915).
REFERENCES:
AUTHORS:
Jens Rasch (2009-03-24): initial version
OUTPUT:
Rational number times the square root of a rational number (if prec=None), or real number if a precision is given.
1627
Examples
>>> from sympy.physics.wigner import wigner_6j
>>> wigner_6j(3,3,3,3,3,3)
-1/14
>>> wigner_6j(5,5,5,5,5,5)
1/52
It is an error to have arguments that are not integer or half integer values or do not fulll
the triangle relation:
sage: wigner 6j(2.5,2.5,2.5,2.5,2.5,2.5)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer and fulfill the triangle relation
sage: wigner 6j(0.5,0.5,1.1,0.5,0.5,1.1)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer and fulfill the triangle relation
NOTES:
The Wigner 6j symbol is related to the Racah symbol but exhibits more symmetries as
detailed below.
W igner6j(j1 , j2 , j3 , j4 , j5 , j6 ) = (1)j1 +j2 +j4 +j5 W (j1 , j2 , j5 , j4 , j3 , j6 )
The Wigner 6j symbol obeys the following symmetry rules:
Wigner 6j symbols are left invariant under any permutation of the columns:
ALGORITHM:
This function uses the algorithm of [Edmonds74] (page 1916) to calculate the value of the
6j symbol exactly. Note that the formula contains alternating sums over large factorials
and is therefore unsuitable for nite precision arithmetic and only useful for a computer
algebra system [Rasch03] (page 1915).
REFERENCES:
sympy.physics.wigner.wigner 9j(j 1, j 2, j 3, j 4, j 5, j 6, j 7, j 8, j 9, prec=None)
Calculate the Wigner 9j symbol W igner9j(j1 , j2 , j3 , j4 , j5 , j6 , j7 , j8 , j9 ).
INPUT:
j 1, ..., j 9 - integer or half integer
prec - precision, default: None. Providing a precision can drastically speed up the
calculation.
1628
OUTPUT:
Rational number times the square root of a rational number (if prec=None), or real number if a precision is given.
Examples
>>> from sympy.physics.wigner import wigner_9j
>>> wigner_9j(1,1,1, 1,1,1, 1,1,0 ,prec=64) # ==1/18
0.05555555...
It is an error to have arguments that are not integer or half integer values or do not fulll
the triangle relation:
sage: wigner 9j(0.5,0.5,0.5, 0.5,0.5,0.5, 0.5,0.5,0.5,prec=64)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer and fulfill the triangle relation
sage: wigner 9j(1,1,1, 0.5,1,1.5, 0.5,1,2.5,prec=64)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer and fulfill the triangle relation
ALGORITHM:
This function uses the algorithm of [Edmonds74] (page 1916) to calculate the value of the
3j symbol exactly. Note that the formula contains alternating sums over large factorials
and is therefore unsuitable for nite precision arithmetic and only useful for a computer
algebra system [Rasch03] (page 1915).
Units
Introduction
This module provides around 200 predened units that are commonly used in the sciences.
Additionally, it provides the Unit class which allows you to dene your own units.
Examples
All examples in this tutorial are computable, so one can just copy and paste them into a Python
shell and do something useful with them. All computations were done using the following
setup:
>>> from sympy.physics.units import *
Dimensionless quantities
less) quantities.
>>> 2*ten
20
>>> 20*percent
1/5
>>> 300*kilo*20*percent
1629
60000
>>> nano*deg
pi/180000000000
Base units The SI base units are dened variable name that are commonly used in written
and verbal communication. The singular abbreviated versions are what is used for display
purposes, but the plural non-abbreviated versions are dened in case it helps readability.
>>> 5*meters
5*m
>>> milli*kilogram
kg/1000
>>> gram
kg/1000
Note that British Imperial and U.S. customary units are not included. We strongly urge the
use of SI units; only Myanmar (Burma), Liberia, and the United States have not ocially
accepted the SI system.
Derived units
>>> joule
kg*m**2/s**2
Docstring
Units are always given in terms of base units that have a name and an abbreviation:
>>> u.A.name
ampere
>>> u.ampere.abbrev
A
The generic name for a unit (like length, mass, etc...) can help you nd units:
>>> u.find_unit(magnet)
[magnetic_flux, magnetic_constant, magnetic_flux_density]
>>> u.find_unit(u.magnetic_flux)
[Wb, wb, weber, webers, magnetic_flux]
If, for a given session, you wish to add a unit you may do so:
1630
>>> u.find_unit(gal)
[]
>>> u.gal = 4*u.quart
>>> u.gal/u.inch**3
231
To see a given quantity in terms of some other unit, divide by the desired unit:
>>> mph = u.miles/u.hours
>>> (u.m/u.s/mph).n(2)
2.2
The units are dened in terms of base units, so when you divide similar units you will obtain
a pure number. This means, for example, that if you divide a real-world mass (like grams) by
the atomic mass unit (amu) you will obtain Avogadros number. To obtain the answer in moles
you should divide by the unit avogadro:
>>> u.grams/u.amu
602214179000000000000000
>>> _/u.avogadro
mol
For chemical calculations the unit mmu (molar mass unit) has been dened so this conversion is
handled automatically. For example, the number of moles in 1 kg of water might be calculated
as:
>>> u.kg/(18*u.mmu).n(3)
55.5*mol
If you need the number of atoms in a mol as a pure number you can use avogadro number but
if you need it as a dimensional quantity you should use avogadro constant. (avogadro is a
shorthand for the dimensional quantity.)
>>> u.avogadro_number
602214179000000000000000
>>> u.avogadro_constant
602214179000000000000000/mol
class sympy.physics.units.Unit
Base class for base unit of physical units.
>>> from sympy.physics.units import Unit
>>> Unit(meter, m)
m
sympy.physics.units.find unit(quantity)
Return a list of matching units names. if quantity is a string units containing the string
quantity if quantity is a unit units having matching base units
1631
Examples
>>> from sympy.physics import units as u
>>> u.find_unit(charge)
[charge]
>>> u.find_unit(u.charge)
[C, charge, coulomb, coulombs]
>>> u.find_unit(volt)
[volt, volts, voltage]
>>> u.find_unit(u.inch**3)[:5]
[l, cl, dl, ml, liter]
Abstract
Contains docstrings for methods in high energy physics.
Gamma matrices
Note that there is already an instance of GammaMatrixHead in four dimensions: GammaMatrix, which is simply declare as
GammaMatrix = GammaMatrixHead()
>>> from sympy.physics.hep.gamma_matrices import GammaMatrix
>>> from sympy.tensor.tensor import tensor_indices
>>> i = tensor_indices(i, GammaMatrix.LorentzIndex)
>>> GammaMatrix(i)
gamma(i, auto_left, -auto_right)
1632
gamma trace(t)
trace of a single line of gamma matrices
Examples
>>> from sympy.physics.hep.gamma_matrices import GammaMatrix as G
>>> from sympy.tensor.tensor import tensor_indices, tensorhead
>>> p, q = tensorhead(p, q, [G.LorentzIndex], [[1]])
>>> i0,i1,i2,i3,i4,i5 = tensor_indices(i0:6, G.LorentzIndex)
>>> ps = p(i0)*G(-i0)
>>> qs = q(i0)*G(-i0)
>>> G.gamma_trace(G(i0)*G(i1))
4*metric(i0, i1)
>>> G.gamma_trace(ps*ps) - 4*p(i0)*p(-i0)
0
>>> G.gamma_trace(ps*qs + ps*ps) - 4*p(i0)*p(-i0) - 4*p(i0)*q(-i0)
0
1633
>>> G = GammaMatrix
>>> t = G(i1,s1,-s2)*G(i4,s7,-s6)*G(i2,s2,-s3)*G(i3,s4,-s5)*G(i5,s6,-s7)
>>> G.simplify_lines(t)
4*gamma(i3, s4, -s5)*gamma(i1, s1, -S_0)*gamma(i2, S_0, -s3)*metric(i4, i5)
Abstract
In this documentation the components of the sympy.physics.vector module have been discussed. vector has been written to facilitate the operations pertaining to 3-dimensional
vectors, as functions of time or otherwise, in sympy.physics.
Vector & ReferenceFrame In vector, vectors and reference frames are the building
blocks of dynamic systems. This document will describe these mathematically and describe
how to use them with this modules code.
Vector A vector is a geometric object that has a magnitude (or length) and a direction.
Vectors in 3-space are often represented on paper as:
Vector on page
Vector Algebra
Vector out
of page
Vector
into page
Two vectors are said to be equal if and only if (i) they have the same same magnitude and
orientation.
Vector Operations Multiple algebraic operations can be done with vectors: addition between vectors, scalar multiplication, and vector multiplication.
Vector addition as based on the parallelogram law.
a+b
1634
Scalar multiplication is the product of a vector and a scalar; the result is a vector with the
same orientation but whose magnitude is scaled by the scalar. Note that multiplication by
-1 is equivalent to rotating the vector by 180 degrees about an arbitrary axis in the plane
perpendicular to the vector.
2a
-a
A unit vector is simply a vector whose magnitude is equal to 1. Given any vector v we can
dene a unit vector as:
v
^
nv =
kvk
Note that every vector can be written as the product of a scalar and unit vector.
Three vector products are implemented in vector: the dot product, the cross product, and
the outer product.
The dot product operation maps two vectors to a scalar. It is dened as:
a b = kakkbk cos()
where is the angle between a and b.
The dot product of two unit vectors represent the magnitude of the common direction; for
other vectors, it is the product of the magnitude of the common direction and the two vectors
magnitudes. The dot product of two perpendicular is zero. The gure below shows some
examples:
a
a
ab=0
a
aa=1
c
45
a c = 1/sqrt(2)
1635
The cross product vector multiplication operation of two vectors returns a vector:
ab=c
The vector c has the following properties: its orientation is perpendicular to both a and b,
its magnitude is dened as kck = kakkbk sin() (where is the angle between a and b), and
has a sense dened by using the right hand rule between kakkbk. The gure below shows
this:
c / sqrt(2)
45
axa=0
1636
^
nx ^
ny ^
nz
a b = det ax ay az
bx by bz
ax ay az
(a b) c = det bx by bz
cx cy cz
Examples
Vector Calculus To deal with the calculus of vectors with moving object, we have to introduce the concept of a reference frame. A classic example is a train moving along its tracks,
1637
with you and a friend inside. If both you and your friend are sitting, the relative velocity between the two of you is zero. From an observer outside the train, you will both have velocity
though.
We will now apply more rigor to this denition. A reference frame is a virtual platform
which we choose to observe vector quantities from. If we have a reference frame N, vector
a is said to be xed in the frame N if none of its properties ever change when observed from
N. We will typically assign a xed orthonormal basis vector set with each reference frame; N
will have ^
nx , ^
ny , ^
nz as its basis vectors.
Derivatives of Vectors A vector which is not xed in a reference frame therefore has changing properties when observed from that frame. Calculus is the study of change, and in order
to deal with the peculiarities of vectors xed and not xed in dierent reference frames, we
need to be more explicit in our denitions.
Fixed in:
d
c
A B
cx
dx
x
e
x
f
In the above gure, we have vectors c, d, e, f. If one were to take the derivative of e with
respect to :
de
d
it is not clear what the derivative is. If you are observing from frame A, it is clearly non-zero.
If you are observing from frame B, the derivative is zero. We will therefore introduce the
frame as part of the derivative notation:
A
de
d
B
de
d
A
dc
d
B
dc
d
1638
d
(a + b) =
dt
A
d
a =
dt
A
d
(a b) =
dt
da A db
+
dt
dt
A
d
da
a+
dt
dt
A
A
da
db
b+a
dt
dt
Relating Sets of Basis Vectors We need to now dene the relationship between two different reference frames; or how to relate the basis vectors of one frame to another. We can
do this using a direction cosine matrix (DCM). The direction cosine matrix relates the basis
vectors of one frame to another, in the following fashion:
bx
^
ax
[
] ^
^
ay = A CB ^
by
^
^
az
bz
When two frames (say, A & B) are initially aligned, then one frame has all of its basis vectors
rotated around an axis which is aligned with a basis vector, we say the frames are related by
a simple rotation. The gure below shows this:
az
bz
A
ax
by
ay
bx
The above rotation is a simple rotation about the Z axis by an angle . Note that after the
rotation, the basis vectors ^
az and ^
bz are still aligned.
This rotation can be characterized by the following direction cosine matrix:
cos() sin() 0
A B
C = sin() cos() 0
0
0
1
Simple rotations about the X and Y axes are dened by:
1
0
0
DCM for x-axis rotation: 0 cos() sin()
0 sin() cos()
cos() 0 sin()
0
1
0
DCM for y-axis rotation:
sin() 0 cos()
5.36. Physics Module
1639
Rotation in the positive direction here will be dened by using the right-hand rule.
The direction cosine matrix is also involved with the denition of the dot product between
sets of basis vectors. If we have two reference frames with associated basis vectors, their
direction cosine matrix can be dened as:
^
ax ^
bx ^
ax ^
by ^
ax ^
bz
Cxx Cxy Cxz
Cyx Cyy Cyz = ^
ay ^
bx ^
ay ^
by ^
ay ^
bz
^
^
^
Czx Czy Czz
^
az bx ^
az by ^
az b z
Additionally, the direction cosine matrix is orthogonal, in that:
A
CB = (B CA )1
= (B CA )T
If we have reference frames A and B, which in this example have undergone a simple z-axis
rotation by an amount , we will have two sets of basis vectors. We can then dene two
vectors: a = ^
ax + ^
ay + ^
az and b = ^
bx + ^
by + ^
bz . If we wish to express b in the A frame, we do
the following:
b =^
bx + ^
by + ^
bz
[
]
[
]
[
]
b= ^
ax + ^
ay + ^
az
ax (^
bx + ^
by + ^
bz ) ^
ay (^
bx + ^
by + ^
bz ) ^
az (^
bx + ^
by + ^
bz ) ^
b = (cos() sin())^
ax + (sin() + cos())^
ay + ^
az
Derivatives with Multiple Frames If we have reference frames A and B we will have
two sets of basis vectors. We can then dene two vectors: a = ax^
ax + ay^
ay + az^
az and b =
^
^
^
bx bx + by by + bz bz . If we want to take the derivative of b in the reference frame A, we must
rst express it in A, and the take the derivatives of the measure numbers:
d(b ^
ay )
db
d(b ^
ax )
d(b ^
az )
^
^
^
=
ax +
ay +
az +
dx
dx
dx
dx
Examples
1640
l
by
ay
ax
bx
In this example we have two bodies, each with an attached reference frame. We will say that
and x are functions of time. We wish to know the time derivative of vector c in both the A
and B frames.
First, we need to dene c; c = x^
bx + l^
by . This provides a denition in the B frame. We can
now do the following:
B
dc
dl
dx ^
bx + ^
by
=
dt
dt
dt
= x ^
bx
cos()
A B
0
C =
sin()
0 sin()
1
0
0 cos()
Note that this is the time derivative of c in A, and is expressed in the A frame. We can express
1641
dc
= ( sin()x + cos()x)^
ax + ( cos()x + sin()x)^
az
dt
= x ^
bx x^
bz
Note the dierence in expression complexity between the two forms. They are equivalent, but
one is much simpler. This is an extremely important concept, as dening vectors in the more
complex forms can vastly slow down formulation of the equations of motion and increase their
length, sometimes to a point where they cannot be shown on screen.
Using Vectors and Reference Frames We have waited until after all of the relevant mathematical relationships have been dened for vectors and reference frames to introduce code.
This is due to how vectors are formed. When starting any problem in vector, one of the rst
steps is dening a reference frame (remember to import sympy.physics.vector rst):
>>> from sympy.physics.vector import *
>>> N = ReferenceFrame(N)
Now we have created a reference frame, N. To have access to any basis vectors, rst a
reference frame needs to be created. Now that we have made and object representing N, we
can access its basis vectors:
>>> N.x
N.x
>>> N.y
N.y
>>> N.z
N.z
Remember, dont add a scalar quantity to a vector (N.x + 5); this will raise an error. At this
point, well use SymPys Symbol in our vectors. Remember to refer to SymPys Gotchas and
Pitfalls when dealing with symbols.:
>>> from sympy import Symbol, symbols
>>> x = Symbol(x)
>>> x * N.x
x*N.x
>>> x*(N.x + N.y)
x*N.x + x*N.y
In vector multiple interfaces to vector multiplication have been implemented, at the operator
level, method level, and function level. The vector dot product can work as follows:
1642
>>>
1
>>>
0
>>>
1
>>>
0
>>>
1
>>>
0
The ocial interface is the function interface; this is what will be used in all examples. This
is to avoid confusion with the attribute and methods being next to each other, and in the case
of the operator operation priority. The operators used in vector for vector multiplication do
not posses the correct order of operations; this can lead to errors. Care with parentheses is
needed when using operators to represent vector multiplication.
The cross product is the other vector multiplication which will be discussed here. It oers
similar interfaces to the dot product, and comes with the same warnings.
>>> N.x ^ N.x
0
>>> N.x ^ N.y
N.z
>>> N.x.cross(N.x)
0
>>> N.x.cross(N.z)
- N.y
>>> cross(N.x, N.y)
N.z
>>> N.x ^ (N.y + N.z)
- N.y + N.z
Two additional operations can be done with vectors: normalizing the vector to length 1, and
getting its magnitude. These are done as follows:
>>> (N.x + N.y).normalize()
sqrt(2)/2*N.x + sqrt(2)/2*N.y
>>> (N.x + N.y).magnitude()
sqrt(2)
Vectors are often expressed in a matrix form, especially for numerical purposes. Since the
matrix form does not contain any information about the reference frame the vector is dened
in, you must provide a reference frame to extract the measure numbers from the vector. There
is a convenience function to do this:
>>> (x * N.x + 2 * x * N.y + 3 * x * N.z).to_matrix(N)
Matrix([
[ x],
[2*x],
[3*x]])
Vector Calculus, in physics.vector We have already introduced our rst reference frame.
We can take the derivative in that frame right now, if we desire:
1643
SymPy has a diff function, but it does not currently work with vector Vectors, so please use
Vectors diff method. The reason for this is that when dierentiating a Vector, the frame
of reference must be specied in addition to what you are taking the derivative with respect
to; SymPys diff function doesnt t this mold.
The more interesting case arise with multiple reference frames. If we introduce a second
reference frame, A, we now have two frames. Note that at this point we can add components
of N and A together, but cannot perform vector multiplication, as no relationship between the
two frames has been dened.
>>> A = ReferenceFrame(A)
>>> A.x + N.x
A.x + N.x
If we want to do vector multiplication, rst we have to dene and orientation. The orient
method of ReferenceFrame provides that functionality.
>>> A.orient(N, Axis, [x, N.y])
If we desire, we can view the DCM between these two frames at any time. This can be
calculated with the dcm method. This code: N.dcm(A) gives the dcm N CA .
This orients the A frame relative to the N frame by a simple rotation around the Y axis, by an
amount x. Other, more complicated rotation types include Body rotations, Space rotations,
quaternions, and arbitrary axis rotations. Body and space rotations are equivalent to doing 3
simple rotations in a row, each about a basis vector in the new frame. An example follows:
>>> N = ReferenceFrame(N)
>>> Bp = ReferenceFrame(Bp)
>>> Bpp = ReferenceFrame(Bpp)
>>> B = ReferenceFrame(B)
>>> q1,q2,q3 = symbols(q1 q2 q3)
>>> Bpp.orient(N,Axis, [q1, N.x])
>>> Bp.orient(Bpp,Axis, [q2, Bpp.y])
>>> B.orient(Bp,Axis, [q3, Bp.z])
>>> N.dcm(B)
Matrix([
[
cos(q2)*cos(q3),
-sin(q3)*cos(q2),
sin(
[sin(q1)*sin(q2)*cos(q3) + sin(q3)*cos(q1), -sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3), -sin(q1)*cos(
[sin(q1)*sin(q3) - sin(q2)*cos(q1)*cos(q3), sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1), cos(q1)*cos(
>>> B.orient(N,Body,[q1,q2,q3],XYZ)
>>> N.dcm(B)
Matrix([
[
cos(q2)*cos(q3),
-sin(q3)*cos(q2),
sin(
[sin(q1)*sin(q2)*cos(q3) + sin(q3)*cos(q1), -sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3), -sin(q1)*cos(
[sin(q1)*sin(q3) - sin(q2)*cos(q1)*cos(q3), sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1), cos(q1)*cos(
Space orientations are similar to body orientation, but applied from the frame to body. Body
and space rotations can involve either two or three axes: XYZ works, as does YZX, ZXZ,
YXY, etc. What is key is that each simple rotation is about a dierent axis than the previous
one; ZZX does not completely orient a set of basis vectors in 3 space.
Sometimes it will be more convenient to create a new reference frame and orient relative to an
existing one in one step. The orientnew method allows for this functionality, and essentially
wraps the orient method. All of the things you can do in orient, you can do in orientnew.
1644
Quaternions (or Euler Parameters) use 4 value to characterize the orientation of the frame.
This and arbitrary axis rotations are described in the orient and orientnew method help, or
in the references [Kane1983] (page 1916).
Finally, before starting multiframe calculus operations, we will introduce another vector tool:
dynamicsymbols. dynamicsymbols is a shortcut function to create undened functions of time
within SymPy. The derivative of such a dynamicsymbol is shown below.
>>> from sympy import diff
>>> q1, q2, q3 = dynamicsymbols(q1 q2 q3)
>>> diff(q1, Symbol(t))
Derivative(q1(t), t)
The dynamicsymbol printing is not very clear above; we will also introduce a few other tools
here. We can use vprint instead of print for non-interactive sessions.
>>> q1
q1(t)
>>> q1d = diff(q1, Symbol(t))
>>> vprint(q1)
q1
>>> vprint(q1d)
q1
For interactive sessions use init vprinting. There also exist analogs for SymPys vprint,
vpprint, and latex, vlatex.
>>>
>>>
>>>
q1
>>>
q1
A dynamicsymbol should be used to represent any time varying quantity in vector, whether
it is a coordinate, varying position, or force. The primary use of a dynamicsymbol is for
speeds and coordinates (of which there will be more discussion in the Kinematics Section of
the documentation).
Now we will dene the orientation of our new frames with a dynamicsymbol, and can take
derivatives and time derivatives with ease. Some examples follow.
>>> N = ReferenceFrame(N)
>>> B = N.orientnew(B, Axis, [q1, N.x])
>>> (B.y*q2 + B.z).diff(q2, N)
B.y
>>> (B.y*q2 + B.z).dt(N)
(-q1 + q2)*B.y + q2*q1*B.z
Note that the output vectors are kept in the same frames that they were provided in. This
remains true for vectors with components made of basis vectors from multiple frames:
>>> (B.y*q2 + B.z + q2*N.x).diff(q2, N)
B.y + N.x
1645
How Vectors are Coded What follows is a short description of how vectors are dened by
the code in vector. It is provided for those who want to learn more about how this part of
sympy.physics.vector works, and does not need to be read to use this module; dont read it
unless you want to learn how this module was implemented.
Every Vectors main information is stored in the args attribute, which stores the three measure numbers for each basis vector in a frame, for every relevant frame. A vector does not
exist in code until a ReferenceFrame is created. At this point, the x, y, and z attributes of the
reference frame are immutable Vectors which have measure numbers of [1,0,0], [0,1,0], and
[0,0,1] associated with that ReferenceFrame. Once these vectors are accessible, new vectors
can be created by doing algebraic operations with the basis vectors. A vector can have components from multiple frames though. That is why args is a list; it has as many elements in
the list as there are unique ReferenceFrames in its components, i.e. if there are A and B frame
basis vectors in our new vector, args is of length 2; if it has A, B, and C frame basis vector,
args is of length three.
Each element in the args list is a 2-tuple; the rst element is a SymPy Matrix (this is where
the measure numbers for each set of basis vectors are stored) and the second element is a
ReferenceFrame to associate those measure numbers with.
ReferenceFrame stores a few things. First, it stores the name you supply it on creation (name
attribute). It also stores the direction cosine matrices, dened upon creation with the orientnew method, or calling the orient method after creation. The direction cosine matrices
are represented by SymPys Matrix, and are part of a dictionary where the keys are the ReferenceFrame and the value the Matrix; these are set bi-directionally; in that when you orient
A to N you are setting As orientation dictionary to include N and its Matrix, but also you
also are setting Ns orientation dictionary to include A and its Matrix (that DCM being the
transpose of the other).
Vector: Kinematics This document will give some mathematical background to describing
a systems kinematics as well as how to represent the kinematics in physics.vector.
Introduction to Kinematics The rst topic is rigid motion kinematics. A rigid body is an
idealized representation of a physical object which has mass and rotational inertia. Rigid
bodies are obviously not exible. We can break down rigid body motion into translational motion, and rotational motion (when dealing with particles, we only have translational motion).
Rotational motion can further be broken down into simple rotations and general rotations.
Translation of a rigid body is dened as a motion where the orientation of the body does not
change during the motion; or during the motion any line segment would be parallel to itself
at the start of the motion.
Simple rotations are rotations in which the orientation of the body may change, but there is
always one line which remains parallel to itself at the start of the motion.
General rotations are rotations which there is not always one line parallel to itself at the start
of the motion.
Angular Velocity The angular velocity of a rigid body refers to the rate of change of its
orientation. The angular velocity of a body is written down as: N B , or the angular velocity of
B in N, which is a vector. Note that here, the term rigid body was used, but reference frames
can also have angular velocities. Further discussion of the distinction between a rigid body
and a reference frame will occur later when describing the code representation.
Angular velocity is dened as being positive in the direction which causes the orientation
angles to increase (for simple rotations, or series of simple rotations).
1646
nx
nx
nz
ny
wB=q nx
The angular velocity vector represents the time derivative of the orientation. As a time derivative vector quantity, like those covered in the Vector & ReferenceFrame documentation, this
quantity (angular velocity) needs to be dened in a reference frame. That is what the N is in
the above denition of angular velocity; the frame in which the angular velocity is dened in.
The angular velocity of B in N can also be dened by:
N
B = (
N ^
N ^
d^
by ^ ^
dbz ^ ^
dbx ^ ^
bz )bx + (
bx )by + (
by )bz
dt
dt
dt
B = wx^
bx + wy^
by + wz^
bz
There are a few additional important points relating to angular velocity. The rst is the addition theorem for angular velocities, a way of relating the angular velocities of multiple bodies
and frames. The theorem follows:
N
D =N A +A B +B C +C D
1647
N
nx
nz
ax
ny
q1
q2
cy
bz
q3
A = 0
B = q1^
ax
B C
= q2^
bz
C
D = q3^
cy
D = q1^
ax q2^
bz + q3^
cy
Note the signs used in the angular velocity denitions, which are related to how the displacement angle is dened in this case.
This theorem makes dening angular velocities of multibody systems much easier, as the
angular velocity of a body in a chain needs to only be dened to the previous body in order to
be fully dened (and the rst body needs to be dened in the desired reference frame). The
following gure shows an example of when using this theorem can make things easier.
p2
w1
w2
w3
p3
p1
Here we can easily write the angular velocity of the body D in the reference frame of the rst
body A:
A
^1 + w2 p^2 + w3 p
^3
D = w1 p
It is very important to remember to only use this with angular velocities; you cannot use this
theorem with the velocities of points.
1648
There is another theorem commonly used: the derivative theorem. It provides an alternative
method (which can be easier) to calculate the time derivative of a vector in a reference frame:
N
B
dv
dv N B
=
+ v
dt
dt
The vector v can be any vector quantity: a position vector, a velocity vector, angular velocity
vector, etc. Instead of taking the time derivative of the vector in N, we take it in B, where B
can be any reference frame or body, usually one in which it is easy to take the derivative on v
in (v is usually composed only of the basis vector set belonging to B). Then we add the cross
product of the angular velocity of our newer frame, N B and our vector quantity v. Again, you
can choose any alternative frame for this. Examples follow:
Angular Acceleration Angular acceleration refers to the time rate of change of the angular
velocity vector. Just as the angular velocity vector is for a body and is specied in a frame,
the angular acceleration vector is for a body and is specied in a frame: N B , or the angular
acceleration of B in N, which is a vector.
Calculating the angular acceleration is relatively straight forward:
N B
N N
d B
dt
Note that this can be calculated with the derivative theorem, and when the angular velocity
is dened in a body xed frame, becomes quite simple:
N B
N N
d B
dt
d B N B N B
+
dt
N
if B = wx^
bx + wy^
by + wz^
bz
N B
B N
then
N B
B N
d B
+
dt
B N B
{z
}
this is 0 by denition
dwx ^
dwy ^
dwz ^
N B
=
bx +
by +
bz
dt
dt
dt
N B
= wx^
bx + wy^
by + wz^
bz
Again, this is only for the case in which the angular velocity of the body is dened in body
xed components.
Point Velocity & Acceleration Consider a point, P : we can dene some characteristics of
the point. First, we can dene a position vector from some other point to P . Second, we can
dene the velocity vector of P in a reference frame of our choice. Third, we can dene the
acceleration vector of P in a reference frame of our choice.
These three quantities are read as:
rOP , the position vector from O to P
N P
N P
1649
Note that the position vector does not have a frame associated with it; this is because there
is no time derivative involved, unlike the velocity and acceleration vectors.
We can nd these quantities for a simple example easily:
rOP
drOP
dt
N P
then we can calculate: v = qx^
nx + qy^
ny
N P
v =
N N P
d v
dt
N P
a = qx^
nx + qy^
ny
N
and : aP =
It is critical to understand in the above example that the point O is xed in the reference frame
N. There is no addition theorem for translational velocities; alternatives will be discussed
later though. Also note that the position of every point might not always need to be dened
to form the dynamic equations of motion. When you dont want to dene the position vector
of a point, you can start by just dening the velocity vector. For the above example:
Let us instead dene the velocity vector as:
N P
N P
v = ux^
nx + uy^
ny
a = u x^
nx + u y^
ny
There will often be cases when the velocity of a point is desired and a related points velocity
is known. For the cases in which we have two points xed on a rigid body, we use the 2-Point
Theorem:
1650
xed in B
xed in B
xed in N
Lets say we know the velocity of the point S and the angular velocity of the body B, both
dened in the reference frame N. We can calculate the velocity and acceleration of the point
P in N as follows:
v =N vS +N B rSP
N P
a =N aS +N B rSP +N B (N B rSP )
N P
When only one of the two points is xed on a body, the 1 point theorem is used instead.
not xed in B
xed in B
xed in N
Here, the velocity of point S is known in the frame N, the angular velocity of B is known in
N, and the velocity of the point P is known in the frame associated with body B. We can then
1651
N P
a =B aS +N aO +N B rSP +N B (N B rSP ) + 2N B B vP
N P
bz
B
nz
N
nx
by
bx
P
rOP
ny
This example has a disc translating and rotating in a plane. We can easily dene the angular
velocity of the body B and velocity of the point O:
N
B = u3^
nz = u3^
bz
N O
v = u1^
nx + u2^
ny
N B
N O
a = u1^
nx + u2^
ny
We can use the 2 point theorem to calculate the velocity and acceleration of point P now.
rOP = R^
bx
v =N vO +N B rOP
N P
v = u1^
nx + u2^
ny + u3^
bz R^
bx = u1^
nx + u2^
ny + u3 R^
by
N P
a =N aO +N B rOP +N B (N B rOP )
N P
a = u1^
nx + u2^
ny + u3^
bz R^
bx + u3^
bz (u3^
bz R^
bx )
N P
a = u1^
nx + u2^
ny + Ru3^
by Ru23^
bx
N P
N
O
nx
1652
ny
by
cy
bx
cx
In this example we have a double pendulum. We can use the two point theorem twice here in
order to nd the velocity of points Q and P ; point Os velocity is zero in N.
rOQ = l^
bx
rQP = l^
cx
N B
= u1^
bz
N
C = u2^
cz
v =N vO +N B rOQ
N Q
v = u1 l^
by
N Q
v =N vQ +N C rQP
N Q
v = u1 l^
by + u2^
cz l^
cx
N Q
v = u1 l^
by + u2 l^
cy
N P
nz
N
O
nx
ny
q1
Q
q2
P
cz
cy
cx
In this example we have a particle moving on a ring; the ring is supported by a rod which can
rotate about the ^
nx axis. First we use the two point theorem to nd the velocity of the center
point of the ring, Q, then use the 1 point theorem to nd the velocity of the particle on the
1653
ring.
N
C = u1^
nx
rOQ = l^
cz
N Q
v = u1 l^
cy
QP
= R(cos(q2 )^
cx + sin(q2 )^
cy )
C P
v = Ru2 (sin(q2 )^
cx + cos(q2 )^
cy )
v =C vP +N vQ +N C rQP
N P
v = Ru2 (sin(q2 )^
cx + cos(q2 )^
cy ) + u1 l^
cy + u1^
cx R(cos(q2 )^
cx + sin(q2 )^
cy
N P
v = Ru2 sin(q2 )^
cx + (Ru2 cos(q2 ) + u1 l)^
cy + Ru1 sin(q2 )^
cz
N P
A nal topic in the description of velocities of points is that of rolling, or rather, rolling without
slip. Two bodies are said to be rolling without slip if and only if the point of contact on each
body has the same velocity in another frame. See the following gure:
N
P
N Pa
= NvPb
This is commonly used to form the velocity of a point on one object rolling on another xed
object, such as in the following example:
Kinematics in physics.vector It should be clear by now that the topic of kinematics here
has been mostly describing the correct way to manipulate vectors into representing the velocities of points. Within vector there are convenient methods for storing these velocities
associated with frames and points. Well now revisit the above examples and show how to
represent them in sympy (page 704).
The topic of reference frame creation has already been covered. When a ReferenceFrame is
created though, it automatically calculates the angular velocity of the frame using the time
derivative of the DCM and the angular velocity denition.
>>> from sympy import Symbol, sin, cos
>>> from sympy.physics.vector import *
>>> N = ReferenceFrame(N)
>>> q1 = dynamicsymbols(q1)
>>> A = N.orientnew(A, Axis, [q1, N.x])
>>> A.ang_vel_in(N)
q1*N.x
1654
>>> B = ReferenceFrame(B)
>>> u1 = dynamicsymbols(u1)
>>> B.set_ang_vel(N, u1 * B.y)
>>> B.ang_vel_in(N)
u1*B.y
>>> N.ang_vel_in(B)
- u1*B.y
Both upon frame creation during orientnew and when calling set ang vel, the angular velocity is set in both frames involved, as seen above.
nz
nx
ax
ny
q1
q2
cy
bz
q3
Here we have multiple bodies with angular velocities dened relative to each other. This is
coded as:
>>> N = ReferenceFrame(N)
>>> A = ReferenceFrame(A)
>>> B = ReferenceFrame(B)
>>> C = ReferenceFrame(C)
>>> D = ReferenceFrame(D)
>>> u1, u2, u3 = dynamicsymbols(u1 u2 u3)
>>> A.set_ang_vel(N, 0)
>>> B.set_ang_vel(A, u1 * A.x)
>>> C.set_ang_vel(B, -u2 * B.z)
>>> D.set_ang_vel(C, u3 * C.y)
>>> D.ang_vel_in(N)
u3*C.y - u2*B.z + u1*A.x
In vector the shortest path between two frames is used when nding the angular velocity.
That would mean if we went back and set:
>>> D.set_ang_vel(N, 0)
>>> D.ang_vel_in(N)
0
The path that was just dened is what is used. This can cause problems though, as now the
angular velocity denitions are inconsistent. It is recommended that you avoid doing this.
Points are a translational analog to the rotational ReferenceFrame. Creating a Point can be
done in two ways, like ReferenceFrame:
1655
>>> O = Point(O)
>>> P = O.locatenew(P, 3 * N.x + N.y)
>>> P.pos_from(O)
3*N.x + N.y
>>> Q = Point(Q)
>>> Q.set_pos(P, N.z)
>>> Q.pos_from(P)
N.z
>>> Q.pos_from(O)
3*N.x + N.y + N.z
Similar to ReferenceFrame, the position vector between two points is found by the shortest
path (number of intermediate points) between them. Unlike rotational motion, there is no
addition theorem for the velocity of points. In order to have the velocity of a Point in a
ReferenceFrame, you have to set the value.
>>> O = Point(O)
>>> O.set_vel(N, u1*N.x)
>>> O.vel(N)
u1*N.x
For both translational and rotational accelerations, the value is computed by taking the time
derivative of the appropriate velocity, unless the user sets it otherwise.
>>> O.acc(N)
u1*N.x
>>> O.set_acc(N, u2*u1*N.y)
>>> O.acc(N)
u1*u2*N.y
bz
B
nz
N
nx
by
bx
ny
P
rOP
N = ReferenceFrame(N)
u1, u2, u3 = dynamicsymbols(u1 u2 u3)
R = Symbol(R)
B = ReferenceFrame(B)
O = Point(O)
O.set_vel(N, u1 * N.x + u2 * N.y)
P = O.locatenew(P, R * B.x)
B.set_ang_vel(N, u3 * B.z)
P.v2pt_theory(O, N, B)
1656
nz
N
O
nx
ny
q1
Q
q2
P
cz
cy
cx
1657
Inertia (Dyadics) A dyadic tensor is a second order tensor formed by the juxtaposition of a
pair of vectors. There are various operations dened with respect to dyadics, which have been
implemented in vector in the form of class Dyadic. To know more, refer to the Dyadic and
Vector class APIs. Dyadics are used to dene the inertia of bodies within mechanics. Inertia
dyadics can be dened explicitly but the inertia function is typically much more convenient
for the user:
>>> from sympy.physics.mechanics import ReferenceFrame, inertia
>>> N = ReferenceFrame(N)
Supply a reference frame and the moments of inertia if the object
is symmetrical:
>>> inertia(N, 1, 2, 3)
(N.x|N.x) + 2*(N.y|N.y) + 3*(N.z|N.z)
Supply a reference frame along with the products and moments of inertia
for a general object:
>>> inertia(N, 1, 2, 3, 4, 5, 6)
(N.x|N.x) + 4*(N.x|N.y) + 6*(N.x|N.z) + 4*(N.y|N.x) + 2*(N.y|N.y) + 5*(N.y|N.z) + 6*(N.z|N.x) + 5*(N.z|N.
Notice that the inertia function returns a dyadic with each component represented as two
unit vectors separated by a |. Refer to the Dyadic (page 1695) section for more information
about dyadics.
Inertia is often expressed in a matrix, or tensor, form, especially for numerical purposes.
Since the matrix form does not contain any information about the reference frame(s) the
inertia dyadic is dened in, you must provide one or two reference frames to extract the
measure numbers from the dyadic. There is a convenience function to do this:
>>> inertia(N, 1, 2, 3, 4, 5, 6).to_matrix(N)
Matrix([
[1, 4, 6],
[4, 2, 5],
[6, 5, 3]])
Common Issues Here issues with numerically integrating code, choice of dynamicsymbols
for coordinate and speed representation, printing, dierentiating, and substitution will occur.
Printing The default printing options are to use sorting for Vector and Dyadic measure
numbers, and have unsorted output from the vprint, vpprint, and vlatex functions. If you
are printing something large, please use one of those functions, as the sorting can increase
printing time from seconds to minutes.
Substitution Substitution into large expressions can be slow, and take a few minutes.
Acceleration of Points At a minimum, points need to have their velocities dened, as the
acceleration can be calculated by taking the time derivative of the velocity in the same frame.
If the 1 point or 2 point theorems were used to compute the velocity, the time derivative of the
velocity expression will most likely be more complex than if you were to use the acceleration
level 1 point and 2 point theorems. Using the acceleration level methods can result in shorted
expressions at this point, which will result in shorter expressions later (such as when forming
Kanes equations).
1658
Advanced Interfaces Here we will cover advanced options in: ReferenceFrame, dynamicsymbols, and some associated functionality.
ReferenceFrame ReferenceFrame is shown as having a .name attribute and .x, .y, and .z
attributes for accessing the basis vectors, as well as a fairly rigidly dened print output. If
you wish to have a dierent set of indices dened, there is an option for this. This will also
require a dierent interface for accessing the basis vectors.
>>> from sympy.physics.vector import ReferenceFrame, vprint, vpprint, vlatex
>>> N = ReferenceFrame(N, indices=[i, j, k])
>>> N[i]
N[i]
>>> N.x
N[i]
>>> vlatex(N.x)
\\mathbf{\\hat{n}_{i}}
Also, the latex output can have custom strings; rather than just indices though, the entirety
of each basis vector can be specied. The custom latex strings can occur without custom
indices, and also overwrites the latex string that would be used if there were custom indices.
>>> from sympy.physics.vector import ReferenceFrame, vlatex
>>> N = ReferenceFrame(N, latexs=[n1,\mathbf{n}_2,cat])
>>> vlatex(N.x)
n1
>>> vlatex(N.y)
\\mathbf{n}_2
>>> vlatex(N.z)
cat
dynamicsymbols The dynamicsymbols function also has hidden functionality; the variable
which is associated with time can be changed, as well as the notation for printing derivatives.
>>> from sympy import symbols
>>> from sympy.physics.vector import dynamicsymbols, vprint
>>> q1 = dynamicsymbols(q1)
>>> q1
q1(t)
>>> dynamicsymbols._t = symbols(T)
>>> q2 = dynamicsymbols(q2)
>>> q2
q2(T)
>>> q1
q1(t)
>>> q1d = dynamicsymbols(q1, 1)
>>> vprint(q1d)
q1
>>> dynamicsymbols._str = d
>>> vprint(q1d)
q1d
>>> dynamicsymbols._str = \
>>> dynamicsymbols._t = symbols(t)
Note that only dynamic symbols created after the change are dierent. The same is not true
for the .s tr attribute; this aects the printing output only, so dynamic symbols created before
or after will print the same way.
5.36. Physics Module
1659
Also note that Vectors .dt method uses the . t attribute of dynamicsymbols, along with a
number of other important functions and methods. Dont mix and match symbols representing
time.
Scalar and Vector Field Functionality
Introduction
Vectors and Scalars In physics, we deal with two kinds of quantities scalars and vectors.
A scalar is an entity which only has a magnitude no direction. Examples of scalar quantities
include mass, electric charge, temperature, distance, etc.
A vector, on the other hand, is an entity that is characterized by a magnitude and a direction.
Examples of vector quantities are displacement, velocity, magnetic eld, etc.
A scalar can be depicted just by a number, for e.g. a temperature of 300 K. On the other
hand, vectorial quantities like acceleration are usually denoted by a vector. Given a vector
V, the magnitude of the corresponding quantity can be calculated as the magnitude of the
vector itself kVk, while the direction would be specied by a unit vector in the direction of the
V
original vector, ^
V = kVk
.
For example, consider a displacement of (3^
i + 4^
j + 5^
k) m, where , as per standard convention,
^
i, ^
j and ^
k represent unit vectors in the X, Y and Z directions
respectively. Therefore, it can
be concluded that the distance traveled is k3^
i + 4^
j + 5^
kk m = 5 2 m. The direction of travel is
3 ^
4 ^
5 ^
given by the unit vector 5
i + 5
j + 5
k.
2
2
2
Fields In general, a f ield is a vector or scalar quantity that can be specied everywhere in
space as a function of position (Note that in general a eld may also be dependent on time
and other custom variables). In this module, we deal with 3-dimensional spaces only. Hence,
a eld is dened as a function of the x, y and z coordinates corresponding to a location in 3D
space.
For example, temperate in 3 dimensional space (a temperature eld) can be written as T (x, y, z)
a scalar function of the position. An example of a scalar eld in electromagnetism is the
electric potential.
In a similar manner, a vector eld can be dened as a vectorial function of the location (x, y, z)
of any point in space.
For instance, every point on the earth may be considered to be in the gravitational force eld
of the earth. We may specify the eld by the magnitude and the direction of acceleration due
to gravity (i.e. force per unit mass ) g(x, y, z) at every point in space.
To give an example from electromagnetism, consider an electric potential of form 2x2 y, a
scalar eld in 3D space. The corresponding conservative electric eld can be computed as
2^
the gradient of the electric potential function, and expressed as 4xy^
i + 2x
j. The magnitude of
this electric eld can in turn be expressed as a scalar eld of the form 4x4 + 16x2 y 2 .
Implementation of elds in sympy.physics.vector In sympy.physics.vector, every ReferenceFrame instance is assigned basis vectors corresponding to the X, Y and Z directions.
These can be accessed using the attributes named x, y and z respectively. Hence, to dene
a vector v of the form 3^
i + 4^
j + 5^
k with respect to a given frame R, you would do
1660
Vector math and basic calculus operations with respect to vectors have already been elaborated upon in other sections of this modules documentation.
On the other hand, base scalars (or coordinate variables) are implemented as special SymPy
Symbol s assigned to every frame, one for each direction from X, Y and Z. For a frame R, the
X, Y and Z base scalar Symbol s can be accessed using the R[0], R[1] and R[2] expressions
respectively.
Therefore, to generate the expression for the aforementioned electric potential eld 2x2 y, you
would have to do
>>> from sympy.physics.vector import ReferenceFrame
>>> R = ReferenceFrame(R)
>>> electric_potential = 2*R[0]**2*R[1]
>>> electric_potential
2*R_x**2*R_y
In string representation, R x denotes the X base scalar assigned to ReferenceFrame R. Essentially, R x is the string representation of R[0].
Scalar elds can be treated just as any other SymPy expression, for any math/calculus functionality. Hence, to dierentiate the above electric potential with respect to x (i.e. R[0]), you
would have to use the diff method.
>>> from sympy.physics.vector import ReferenceFrame
>>> R = ReferenceFrame(R)
>>> electric_potential = 2*R[0]**2*R[1]
>>> from sympy import diff
>>> diff(electric_potential, R[0])
4*R_x*R_y
Like vectors (and vector elds), scalar elds can also be re-expressed in other frames of
reference, apart from the one they were dened in assuming that an orientation relationship
exists between the concerned frames. This can be done using the express method, in a way
similar to vectors - but with the variables parameter set to True.
>>> from sympy.physics.vector import ReferenceFrame
>>> R = ReferenceFrame(R)
>>> electric_potential = 2*R[0]**2*R[1]
>>> from sympy.physics.vector import dynamicsymbols, express
>>> q = dynamicsymbols(q)
>>> R1 = R.orientnew(R1, rot_type = Axis, amounts = [q, R.z])
>>> express(electric_potential, R1, variables=True)
2*(R1_x*sin(q(t)) + R1_y*cos(q(t)))*(R1_x*cos(q(t)) - R1_y*sin(q(t)))**2
Moreover, considering scalars can also be functions of time just as vectors, dierentiation
with respect to time is also possible. Depending on the Symbol s present in the expression
and the frame with respect to which the time dierentiation is being done, the output will
change/remain the same.
>>>
>>>
>>>
>>>
>>>
1661
Field operators and other related functions Here we describe some basic eld-related
functionality implemented in sympy.physics.vector
Curl A curl is a mathematical operator that describes an innitesimal rotation of a vector
in 3D space. The direction is determined by the right-hand rule (along the axis of rotation),
and the magnitude is given by the magnitude of rotation.
In the 3D Cartesian system, the curl of a 3D vector F , denoted by F is given by (
)
(
)
)
Fy ^ ( Fx
Fy
Fz ^
Fx ^
z
F = F
i
+
j
+
k
y
z
z
x
x
y
where Fx denotes the X component of vector F.
To compute the curl of a vector eld in physics.vector, you would do
>>> from sympy.physics.vector import ReferenceFrame
>>> R = ReferenceFrame(R)
>>> from sympy.physics.vector import curl
>>> field = R[0]*R[1]*R[2]*R.x
>>> curl(field, R)
R_x*R_y*R.y - R_x*R_z*R.z
Divergence Divergence is a vector operator that measures the magnitude of a vector elds
source or sink at a given point, in terms of a signed scalar.
The divergence operator always returns a scalar after operating on a vector.
In the 3D Cartesian system, the divergence of a 3D vector F, denoted by F is given by F=
U
x
V
y
W
z
Gradient Consider a scalar eld f (x, y, z) in 3D space. The gradient of this eld is dened
as the vector of the 3 partial derivatives of f with respect to x, y and z in the X, Y and Z
directions respectively.
In the 3D Cartesian system, the divergence of a scalar eld f , denoted by f is given by f = f^
i + f^
j + f ^
k
x
1662
Conservative and Solenoidal elds In vector calculus, a conservative eld is a eld that is
the gradient of some scalar eld. Conservative elds have the property that their line integral
over any path depends only on the end-points, and is independent of the path between them.
A conservative vector eld is also said to be irrotational, since the curl of a conservative
eld is always zero.
In physics, conservative elds represent forces in physical systems where energy is conserved.
To check if a vector eld is conservative in physics.vector, use the is conservative function.
>>> from sympy.physics.vector import ReferenceFrame, is_conservative
>>> R = ReferenceFrame(R)
>>> field = R[1]*R[2]*R.x + R[0]*R[2]*R.y + R[0]*R[1]*R.z
>>> is_conservative(field)
True
>>> curl(field, R)
0
A solenoidal eld, on the other hand, is a vector eld whose divergence is zero at all points
in space.
To check if a vector eld is solenoidal in physics.vector, use the is solenoidal function.
>>> from sympy.physics.vector import ReferenceFrame, is_solenoidal
>>> R = ReferenceFrame(R)
>>> field = R[1]*R[2]*R.x + R[0]*R[2]*R.y + R[0]*R[1]*R.z
>>> is_solenoidal(field)
True
>>> divergence(field, R)
0
Scalar potential functions We have previously mentioned that every conservative eld
can be dened as the gradient of some scalar eld. This scalar eld is also called the scalar
potential eld corresponding to the aforementioned conservative eld.
The scalar potential function in physics.vector calculates the scalar potential eld corresponding to a given conservative vector eld in 3D space - minus the extra constant of
integration, of course.
Example of usage >>> from sympy.physics.vector import ReferenceFrame, scalar_potential
>>> R = ReferenceFrame(R)
>>> conservative_field = 4*R[0]*R[1]*R[2]*R.x + 2*R[0]**2*R[2]*R.y + 2*R[0]**2*R[1]*R.z
>>> scalar_potential(conservative_field, R)
2*R_x**2*R_y*R_z
1663
If provided with a scalar expression instead of a vector eld, scalar potential difference
returns the dierence between the values of that scalar eld at the two given points in space.
Vector API
Essential Classes
CoordinateSym
class sympy.physics.vector.frame.CoordinateSym
A coordinate symbol/base scalar associated wrt a Reference Frame.
Ideally, users should not instantiate this class. Instances of this class must only be accessed through the corresponding frame as frame[index].
CoordinateSyms having the same frame and index parameters are equal (even though
they may be instantiated separately).
Parameters name : string
The display name of the CoordinateSym
frame : ReferenceFrame
The reference frame this base scalar belongs to
index : 0, 1 or 2
The index of the dimension denoted by this coordinate variable
Examples
>>> from sympy.physics.vector import ReferenceFrame, CoordinateSym
>>> A = ReferenceFrame(A)
>>> A[1]
A_y
>>> type(A[0])
<class sympy.physics.vector.frame.CoordinateSym>
>>> a_y = CoordinateSym(a_y, A, 1)
>>> a_y == A[1]
True
1664
ReferenceFrame
class sympy.physics.vector.frame.ReferenceFrame(name,
indices=None,
latexs=None, variables=None)
A reference frame in classical mechanics.
ReferenceFrame is a class used to represent a reference frame in classical mechanics.
It has a standard basis of three unit vectors in the frames x, y, and z directions.
It also can have a rotation relative to a parent frame; this rotation is dened by a direction
cosine matrix relating this frames basis vectors to the parent frames basis vectors. It
can also have an angular velocity vector, dened in another frame.
ang acc in(otherframe)
Returns the angular acceleration Vector of the ReferenceFrame.
Eectively returns the Vector: N alpha B which represent the angular acceleration
of B in N, where B is self, and N is otherframe.
Parameters otherframe : ReferenceFrame
The ReferenceFrame which the angular acceleration is returned in.
Examples
>>> from sympy.physics.vector import ReferenceFrame, Vector
>>> N = ReferenceFrame(N)
>>> A = ReferenceFrame(A)
>>> V = 10 * N.x
>>> A.set_ang_acc(N, V)
>>> A.ang_acc_in(N)
10*N.x
dcm(otherframe)
The direction cosine matrix between frames.
This gives the DCM between this frame and the otherframe. The format is N.xyz =
N.dcm(B) * B.xyz A SymPy Matrix is returned.
Parameters otherframe : ReferenceFrame
1665
Now we have a choice of how to implement the orientation. First is Body. Body
orientation takes this reference frame through three successive simple rotations.
Acceptable rotation orders are of length 3, expressed in XYZ or 123, and cannot
have a rotation about about an axis twice in a row.
>>> B.orient(N, Body, [q1, q2, q3], 123)
>>> B.orient(N, Body, [q1, q2, 0], ZXZ)
>>> B.orient(N, Body, [0, 0, 0], XYX)
Next is Space. Space is like Body, but the rotations are applied in the opposite order.
>>> B.orient(N, Space, [q1, q2, q3], 312)
1666
Next is Quaternion. This orients the new ReferenceFrame with Quaternions, dened
as a nite rotation about lambda, a unit vector, by some amount theta. This orientation is described by four parameters: q0 = cos(theta/2) q1 = lambda x sin(theta/2)
q2 = lambda y sin(theta/2) q3 = lambda z sin(theta/2) Quaternion does not take in
a rotation order.
>>> B.orient(N, Quaternion, [q0, q1, q2, q3])
in-
Now we have a choice of how to implement the orientation. First is Body. Body
orientation takes this reference frame through three successive simple rotations.
Acceptable rotation orders are of length 3, expressed in XYZ or 123, and cannot
have a rotation about about an axis twice in a row.
>>> B.orient(N, Body, [q1, q2, q3], 123)
>>> B.orient(N, Body, [q1, q2, 0], ZXZ)
>>> B.orient(N, Body, [0, 0, 0], XYX)
Next is Space. Space is like Body, but the rotations are applied in the opposite order.
>>> B.orient(N, Space, [q1, q2, q3], 312)
1667
Next is Quaternion. This orients the new ReferenceFrame with Quaternions, dened
as a nite rotation about lambda, a unit vector, by some amount theta. This orientation is described by four parameters: q0 = cos(theta/2) q1 = lambda x sin(theta/2)
q2 = lambda y sin(theta/2) q3 = lambda z sin(theta/2) Quaternion does not take in
a rotation order.
>>> B.orient(N, Quaternion, [q0, q1, q2, q3])
1668
>>> A.set_ang_vel(N, V)
>>> A.ang_vel_in(N)
10*N.x
variable map(otherframe)
Returns a dictionary which expresses the coordinate variables of this frame in terms
of the variables of otherframe.
If Vector.simp is True, returns a simplied version of the mapped values. Else, returns them without simplication.
Simplication of the expressions may take time.
Parameters otherframe : ReferenceFrame
The other frame to map the variables to
Examples
>>> from sympy.physics.vector import ReferenceFrame, dynamicsymbols
>>> A = ReferenceFrame(A)
>>> q = dynamicsymbols(q)
>>> B = A.orientnew(B, Axis, [q, A.z])
>>> A.variable_map(B)
{A_x: B_x*cos(q(t)) - B_y*sin(q(t)), A_y: B_x*sin(q(t)) + B_y*cos(q(t)), A_z: B_z}
x
The basis Vector for the ReferenceFrame, in the x direction.
y
The basis Vector for the ReferenceFrame, in the y direction.
z
The basis Vector for the ReferenceFrame, in the z direction.
Vector
class sympy.physics.vector.vector.Vector(inlist)
The class used to dene vectors.
It along with ReferenceFrame are the building blocks of describing a classical mechanics
system in PyDy and sympy.physics.vector.
Attributes
simp
Boolean
cross(other)
The cross product operator for two Vectors.
Returns a Vector, expressed in the same ReferenceFrames as self.
Parameters other : Vector
The Vector which we are crossing with
1669
Examples
>>> from sympy.physics.vector import ReferenceFrame, Vector
>>> from sympy import symbols
>>> q1 = symbols(q1)
>>> N = ReferenceFrame(N)
>>> N.x ^ N.y
N.z
>>> A = N.orientnew(A, Axis, [q1, N.x])
>>> A.x ^ N.y
N.z
>>> N.y ^ A.x
- sin(q1)*A.y - cos(q1)*A.z
diff(wrt, otherframe)
Takes the partial derivative, with respect to a value, in a frame.
Returns a Vector.
Parameters wrt : Symbol
What the partial derivative is taken with respect to.
otherframe : ReferenceFrame
The ReferenceFrame that the partial derivative is taken in.
Examples
>>> from sympy.physics.vector import ReferenceFrame, Vector, dynamicsymbols
>>> from sympy import Symbol
>>> Vector.simp = True
>>> t = Symbol(t)
>>> q1 = dynamicsymbols(q1)
>>> N = ReferenceFrame(N)
>>> A = N.orientnew(A, Axis, [q1, N.y])
>>> A.x.diff(t, N)
- q1*A.z
doit(**hints)
Calls .doit() on each term in the Vector
dot(other)
Dot product of two vectors.
Returns a scalar, the dot product of the two Vectors
Parameters other : Vector
The Vector which we are dotting with
Examples
>>>
>>>
>>>
>>>
>>>
1670
1
>>> dot(N.x, N.y)
0
>>> A = N.orientnew(A, Axis, [q1, N.x])
>>> dot(N.y, A.y)
cos(q1)
dt(otherframe)
Returns a Vector which is the time derivative of the self Vector, taken in frame otherframe.
Calls the global time derivative method
Parameters otherframe : ReferenceFrame
The frame to calculate the time derivative in
express(otherframe, variables=False)
Returns a Vector equivalent to this one, expressed in otherframe. Uses the global
express method.
Parameters otherframe : ReferenceFrame
The frame for this Vector to be described in
variables : boolean
If True, the coordinate symbols(if present) in this Vector are reexpressed in terms otherframe
Examples
>>> from sympy.physics.vector import ReferenceFrame, Vector, dynamicsymbols
>>> q1 = dynamicsymbols(q1)
>>> N = ReferenceFrame(N)
>>> A = N.orientnew(A, Axis, [q1, N.y])
>>> A.x.express(N)
cos(q1)*N.x - sin(q1)*N.z
magnitude()
Returns the magnitude (Euclidean norm) of self.
normalize()
Returns a Vector of magnitude 1, codirectional with self.
outer(other)
Outer product between two Vectors.
A rank increasing operation, which returns a Dyadic from two Vectors
Parameters other : Vector
The Vector to take the outer product with
Examples
>>> from sympy.physics.vector import ReferenceFrame, outer
>>> N = ReferenceFrame(N)
>>> outer(N.x, N.x)
(N.x|N.x)
1671
separate()
The constituents of this vector in dierent reference frames, as per its denition.
Returns a dict mapping each ReferenceFrame to the corresponding constituent Vector.
Examples
>>> from sympy.physics.vector import ReferenceFrame
>>> R1 = ReferenceFrame(R1)
>>> R2 = ReferenceFrame(R2)
>>> v = R1.x + R2.x
>>> v.separate() == {R1: R1.x, R2: R2.x}
True
simplify()
Returns a simplied Vector.
subs(*args, **kwargs)
Substituion on the Vector.
Examples
>>> from sympy.physics.vector import ReferenceFrame
>>> from sympy import Symbol
>>> N = ReferenceFrame(N)
>>> s = Symbol(s)
>>> a = N.x * s
>>> a.subs({s: 2})
2*N.x
to matrix(reference frame)
Returns the matrix form of the vector with respect to the given frame.
Parameters reference frame : ReferenceFrame
The reference frame that the rows of the matrix correspond to.
Returns matrix : ImmutableMatrix, shape(3,1)
The matrix that gives the 1D vector.
Examples
>>> from sympy import symbols
>>> from sympy.physics.vector import ReferenceFrame
>>> from sympy.physics.mechanics.functions import inertia
>>> a, b, c = symbols(a, b, c)
>>> N = ReferenceFrame(N)
>>> vector = a * N.x + b * N.y + c * N.z
>>> vector.to_matrix(N)
Matrix([
[a],
[b],
[c]])
>>> beta = symbols(beta)
1672
Dyadic
class sympy.physics.vector.dyadic.Dyadic(inlist)
A Dyadic object.
See: http://en.wikipedia.org/wiki/Dyadic tensor Kane, T., Levinson, D. Dynamics Theory
and Applications. 1985 McGraw-Hill
A more powerful way to represent a rigid bodys inertia. While it is more complex, by
choosing Dyadic components to be in body xed basis vectors, the resulting matrix is
equivalent to the inertia tensor.
cross(other)
For a cross product in the form: Dyadic x Vector.
Parameters other : Vector
The Vector that we are crossing this Dyadic with
Examples
>>> from sympy.physics.vector import ReferenceFrame, outer, cross
>>> N = ReferenceFrame(N)
>>> d = outer(N.x, N.x)
>>> cross(d, N.y)
(N.x|N.z)
doit(**hints)
Calls .doit() on each term in the Dyadic
dot(other)
The inner product operator for a Dyadic and a Dyadic or Vector.
Parameters other : Dyadic or Vector
The other Dyadic or Vector to take the inner product with
Examples
>>> from sympy.physics.vector import ReferenceFrame, outer
>>> N = ReferenceFrame(N)
>>> D1 = outer(N.x, N.y)
>>> D2 = outer(N.y, N.y)
>>> D1.dot(D2)
(N.x|N.y)
>>> D1.dot(N.y)
N.x
dt(frame)
Take the time derivative of this Dyadic in a frame.
1673
express(frame1, frame2=None)
Expresses this Dyadic in alternate frame(s)
The rst frame is the list side expression, the second frame is the right side; if Dyadic
is in form A.x|B.y, you can express it in two dierent frames. If no second frame is
given, the Dyadic is expressed in only one frame.
Calls the global express function
Parameters frame1 : ReferenceFrame
The frame to express the left side of the Dyadic in
frame2 : ReferenceFrame
If provided, the frame to express the right side of the Dyadic in
Examples
>>> from sympy.physics.vector import ReferenceFrame, outer, dynamicsymbols
>>> N = ReferenceFrame(N)
>>> q = dynamicsymbols(q)
>>> B = N.orientnew(B, Axis, [q, N.z])
>>> d = outer(N.x, N.x)
>>> d.express(B, N)
cos(q)*(B.x|N.x) - sin(q)*(B.y|N.x)
simplify()
Returns a simplied Dyadic.
subs(*args, **kwargs)
Substituion on the Dyadic.
Examples
>>>
>>>
>>>
>>>
>>>
1674
Kinematics (Docstrings)
Point
class sympy.physics.vector.point.Point(name)
This object represents a point in a dynamic system.
It stores the: position, velocity, and acceleration of a point. The position is a vector
dened as the vector distance from a parent point to this point.
a1pt theory(otherpoint, outframe, interframe)
Sets the acceleration of this point with the 1-point theory.
The 1-point theory for point acceleration looks like this:
N aP = B aP + N aO + N alphaB x rOP + N omegaB x (N omegaB x
rOP) + 2 N omegaB x B vP
5.36. Physics Module
1675
1676
acc(frame)
The acceleration Vector of this Point in a ReferenceFrame.
Parameters frame : ReferenceFrame
The frame in which the returned acceleration vector will be dened
in
Examples
>>> from sympy.physics.vector import Point, ReferenceFrame
>>> N = ReferenceFrame(N)
>>> p1 = Point(p1)
>>> p1.set_acc(N, 10 * N.x)
>>> p1.acc(N)
10*N.x
locatenew(name, value)
Creates a new point with a position dened from this point.
Parameters name : str
The name for the new point
value : Vector
The position of the new point relative to this point
Examples
>>>
>>>
>>>
>>>
pos from(otherpoint)
Returns a Vector distance between this Point and the other Point.
Parameters otherpoint : Point
The otherpoint we are locating this one relative to
Examples
>>> from sympy.physics.vector import Point, ReferenceFrame
>>> N = ReferenceFrame(N)
>>> p1 = Point(p1)
>>> p2 = Point(p2)
>>> p1.set_pos(p2, 10 * N.x)
>>> p1.pos_from(p2)
10*N.x
1677
1678
>>> p1.vel(N)
10*N.x
1679
Examples
>>> from sympy.physics.vector import Point, ReferenceFrame, dynamicsymbols
>>> q = dynamicsymbols(q)
>>> qd = dynamicsymbols(q, 1)
>>> N = ReferenceFrame(N)
>>> B = N.orientnew(B, Axis, [q, N.z])
>>> O = Point(O)
>>> P = O.locatenew(P, 10 * B.x)
>>> O.set_vel(N, 5 * N.x)
>>> P.v2pt_theory(O, N, B)
5*N.x + 10*q*B.y
vel(frame)
The velocity Vector of this Point in the ReferenceFrame.
Parameters frame : ReferenceFrame
The frame in which the returned velocity vector will be dened in
Examples
>>> from sympy.physics.vector import Point, ReferenceFrame
>>> N = ReferenceFrame(N)
>>> p1 = Point(p1)
>>> p1.set_vel(N, 10 * N.x)
>>> p1.vel(N)
10*N.x
kinematic equations
sympy.physics.vector.functions.kinematic equations(speeds, coords,
rot order=)
Gives equations relating the qdots to us for a rotation type.
rot type,
Supply rotation type and order as in orient. Speeds are assumed to be body-xed; if we
are dening the orientation of B in A using by rot type, the angular velocity of B in A is
assumed to be in the form: speed[0]*B.x + speed[1]*B.y + speed[2]*B.z
Parameters speeds : list of length 3
The body xed angular velocity measure numbers.
coords : list of length 3 or 4
The coordinates used to dene the orientation of the two frames.
rot type : str
The type of rotation used to create the equations. Body, Space, or
Quaternion only
rot order : str
If applicable, the order of a series of rotations.
1680
Examples
1681
of time, they are converted to constants by substituting the time values in the dynamicsymbols. t time Symbol.
This function can also be used for calculating rotational motion parameters. Have a look
at the Parameters and Examples for more clarity.
Parameters frame : ReferenceFrame
The frame to express the motion parameters in
acceleration : Vector
Acceleration of the object/frame as a function of time
velocity : Vector
Velocity as function of time or as boundary condition of velocity at
time = timevalue1
position : Vector
Velocity as function of time or as boundary condition of velocity at
time = timevalue1
timevalue1 : sympyable
Value of time for position boundary condition
timevalue2 : sympyable
Value of time for velocity boundary condition
Examples
>>> from sympy.physics.vector import ReferenceFrame, get_motion_params, dynamicsymbols
>>> from sympy import symbols
>>> R = ReferenceFrame(R)
>>> v1, v2, v3 = dynamicsymbols(v1 v2 v3)
>>> v = v1*R.x + v2*R.y + v3*R.z
>>> get_motion_params(R, position = v)
(v1*R.x + v2*R.y + v3*R.z, v1*R.x + v2*R.y + v3*R.z, v1*R.x + v2*R.y + v3*R.z)
>>> a, b, c = symbols(a b c)
>>> v = a*R.x + b*R.y + c*R.z
>>> get_motion_params(R, velocity = v)
(0, a*R.x + b*R.y + c*R.z, a*t*R.x + b*t*R.y + c*t*R.z)
>>> parameters = get_motion_params(R, acceleration = v)
>>> parameters[1]
a*t*R.x + b*t*R.y + c*t*R.z
>>> parameters[2]
a*t**2/2*R.x + b*t**2/2*R.y + c*t**2/2*R.z
Printing (Docstrings)
init printing
1682
1683
Can
be
one
of:
function.
This
should
mimic
1684
vprint
sympy.physics.vector.printing.vprint(expr, **settings)
Function for printing of expressions generated in the sympy.physics vector package.
Extends SymPys StrPrinter, takes the same setting accepted by SymPys sstr(), and is
equivalent to print(sstr(f oo)).
Parameters expr : valid SymPy object
SymPy expression to print.
settings : args
Same as the settings accepted by SymPys sstr().
Examples
>>> from sympy.physics.vector import vprint, dynamicsymbols
>>> u1 = dynamicsymbols(u1)
>>> print(u1)
u1(t)
>>> vprint(u1)
u1
vpprint
sympy.physics.vector.printing.vpprint(expr, **settings)
Function for pretty printing of expressions generated in the sympy.physics vector package.
Mainly used for expressions not inside a vector; the output of running scripts and generating equations of motion. Takes the same options as SymPys pretty print(); see that
function for more information.
Parameters expr : valid SymPy object
SymPy expression to pretty print
settings : args
Same as those accepted by SymPys pretty print.
1685
vlatex
sympy.physics.vector.printing.vlatex(expr, **settings)
Function for printing latex representation of sympy.physics.vector objects.
For latex representation of Vectors, Dyadics, and dynamicsymbols. Takes the same options as SymPys latex(); see that function for more information;
Parameters expr : valid SymPy object
SymPy expression to represent in LaTeX form
settings : args
Same as latex()
Examples
>>> from sympy.physics.vector import vlatex, ReferenceFrame, dynamicsymbols
>>> N = ReferenceFrame(N)
>>> q1, q2 = dynamicsymbols(q1 q2)
>>> q1d, q2d = dynamicsymbols(q1 q2, 1)
>>> q1dd, q2dd = dynamicsymbols(q1 q2, 2)
>>> vlatex(N.x + N.y)
\\mathbf{\\hat{n}_x} + \\mathbf{\\hat{n}_y}
>>> vlatex(q1 + q2)
q_{1} + q_{2}
>>> vlatex(q1d)
\\dot{q}_{1}
>>> vlatex(q1 * q2d)
q_{1} \\dot{q}_{2}
>>> vlatex(q1dd * q1 / q1d)
\\frac{q_{1} \\ddot{q}_{1}}{\\dot{q}_{1}}
1686
dot
sympy.physics.vector.functions.dot(vec1, vec2)
Dot product convenience wrapper for Vector.dot(): Dot product of two vectors.
Returns a scalar, the dot product of the two Vectors
Parameters other : Vector
The Vector which we are dotting with
Examples
>>> from sympy.physics.vector import ReferenceFrame, dot
>>> from sympy import symbols
>>> q1 = symbols(q1)
>>> N = ReferenceFrame(N)
>>> dot(N.x, N.x)
1
>>> dot(N.x, N.y)
0
>>> A = N.orientnew(A, Axis, [q1, N.x])
>>> dot(N.y, A.y)
cos(q1)
cross
sympy.physics.vector.functions.cross(vec1, vec2)
Cross product convenience wrapper for Vector.cross(): The cross product operator for
two Vectors.
Returns a Vector, expressed in the same ReferenceFrames as self.
Parameters other : Vector
The Vector which we are crossing with
Examples
>>>
>>>
>>>
>>>
>>>
N.z
>>>
>>>
N.z
1687
outer
sympy.physics.vector.functions.outer(vec1, vec2)
Outer product convenience wrapper for Vector.outer(): Outer product between two Vectors.
A rank increasing operation, which returns a Dyadic from two Vectors
Parameters other : Vector
The Vector to take the outer product with
Examples
>>> from sympy.physics.vector import ReferenceFrame, outer
>>> N = ReferenceFrame(N)
>>> outer(N.x, N.x)
(N.x|N.x)
express
sympy.physics.vector.functions.express(expr,
frame,
ables=False)
Global function for express functionality.
frame2=None,
vari-
1688
time derivative
sympy.physics.vector.functions.time derivative(expr, frame, order=1)
Calculate the time derivative of a vector/scalar eld function or dyadic expression in
given frame.
Parameters expr : Vector/Dyadic/sympifyable
The expression whose time derivative is to be calculated
frame : ReferenceFrame
The reference frame to calculate the time derivative in
order : integer
The order of the derivative to be calculated
References
1689
curl
sympy.physics.vector.fieldfunctions.curl(vect, frame)
Returns the curl of a vector eld computed wrt the coordinate symbols of the given
frame.
Parameters vect : Vector
The vector operand
frame : ReferenceFrame
The reference frame to calculate the curl in
Examples
>>> from sympy.physics.vector import ReferenceFrame
>>> from sympy.physics.vector import curl
>>> R = ReferenceFrame(R)
>>> v1 = R[1]*R[2]*R.x + R[0]*R[2]*R.y + R[0]*R[1]*R.z
>>> curl(v1, R)
0
>>> v2 = R[0]*R[1]*R[2]*R.x
>>> curl(v2, R)
R_x*R_y*R.y - R_x*R_z*R.z
divergence
sympy.physics.vector.fieldfunctions.divergence(vect, frame)
Returns the divergence of a vector eld computed wrt the coordinate symbols of the
given frame.
Parameters vect : Vector
The vector operand
frame : ReferenceFrame
The reference frame to calculate the divergence in
Examples
>>> from sympy.physics.vector import ReferenceFrame
>>> from sympy.physics.vector import divergence
>>> R = ReferenceFrame(R)
>>> v1 = R[0]*R[1]*R[2] * (R.x+R.y+R.z)
>>> divergence(v1, R)
R_x*R_y + R_x*R_z + R_y*R_z
>>> v2 = 2*R[1]*R[2]*R.y
>>> divergence(v2, R)
2*R_z
gradient
sympy.physics.vector.fieldfunctions.gradient(scalar, frame)
Returns the vector gradient of a scalar eld computed wrt the coordinate symbols of the
given frame.
Parameters scalar : sympiable
1690
scalar potential
sympy.physics.vector.fieldfunctions.scalar potential(eld, frame)
Returns the scalar potential function of a eld in a given frame (without the added integration constant).
Parameters eld : Vector
The vector eld whose scalar potential function is to be calculated
frame : ReferenceFrame
The frame to do the calculation in
Examples
>>> from sympy.physics.vector import ReferenceFrame
>>> from sympy.physics.vector import scalar_potential, gradient
>>> R = ReferenceFrame(R)
>>> scalar_potential(R.z, R) == R[2]
True
>>> scalar_field = 2*R[0]**2*R[1]*R[2]
>>> grad_field = gradient(scalar_field, R)
>>> scalar_potential(grad_field, R)
2*R_x**2*R_y*R_z
1691
Paramaters
1692
is solenoidal
sympy.physics.vector.fieldfunctions.is solenoidal(eld)
Checks if a eld is solenoidal.
Examples
>>> from sympy.physics.vector import ReferenceFrame
>>> from sympy.physics.vector import is_solenoidal
>>> R = ReferenceFrame(R)
>>> is_solenoidal(R[1]*R[2]*R.x + R[0]*R[2]*R.y + R[0]*R[1]*R.z)
True
>>> is_solenoidal(R[1] * R.y)
False
Paramaters
Abstract
In this documentation many components of the physics/mechanics module will be discussed. mechanics has been written to allow for creation of symbolic equations of motion
for complicated multibody systems.
Vector
This module derives the vector-related abilities and related functionalities from
physics.vector. Please have a look at the documentation of physics.vector and its
necessary API to understand the vector capabilities of mechanics.
Mechanics
In physics, mechanics describes conditions of rest (statics) or motion (dynamics). There are a
few common steps to all mechanics problems. First, an idealized representation of a system is
described. Next, we use physical laws to generate equations that dene the systems behavior.
Then, we solve these equations, sometimes analytically but usually numerically. Finally, we
extract information from these equations and solutions. The current scope of the module is
multi-body dynamics: the motion of systems of multiple particles and/or rigid bodies. For
example, this module could be used to understand the motion of a double pendulum, planets,
robotic manipulators, bicycles, and any other system of rigid bodies that may fascinate us.
Often, the objective in multi-body dynamics is to obtain the trajectory of a system of rigid
bodies through time. The challenge for this task is to rst formulate the equations of motion
of the system. Once they are formulated, they must be solved, that is, integrated forward in
time. When digital computers came around, solving became the easy part of the problem.
1693
Now, we can tackle more complicated problems, which leaves the challenge of formulating
the equations.
The term equations of motion is used to describe the application of Newtons second law to
multi-body systems. The form of the equations of motion depends on the method used to generate them. This package implements two of these methods: Kanes method and Lagranges
method. This module facilitates the formulation of equations of motion, which can then be
solved (integrated) using generic ordinary dierential equation (ODE) solvers.
The approach to a particular class of dynamics problems, that of forward dynamics, has the
following steps:
1. describing the systems geometry and conguration,
2. specifying the way the system can move, including constraints on its motion
3. describing the external forces and moments on the system,
4. combining the above information according to Newtons second law (F = ma), and
5. organizing the resulting equations so that they can be integrated to obtain the systems
trajectory through time.
Together with the rest of SymPy, this module performs steps 4 and 5, provided that the user
can perform 1 through 3 for the module. That is to say, the user must provide a complete
representation of the free body diagrams that themselves represent the system, with which
this code can provide equations of motion in a form amenable to numerical integration. Step
5 above amounts to arduous algebra for even fairly simple multi-body systems. Thus, it is
desirable to use a symbolic math package, such as Sympy, to perform this step. It is for
this reason that this module is a part of Sympy. Step 4 amounts to this specic module,
sympy.physics.mechanics.
Guide to Mechanics
Masses, Inertias, Particles and Rigid Bodies in Physics/Mechanics This document will
describe how to represent masses and inertias in mechanics and use of the RigidBody and
Particle classes.
It is assumed that the reader is familiar with the basics of these topics, such as nding the
center of mass for a system of particles, how to manipulate an inertia tensor, and the denition
of a particle and rigid body. Any advanced dynamics text can provide a reference for these
details.
Mass The only requirement for a mass is that it needs to be a sympify-able expression. Keep
in mind that masses can be time varying.
Particle Particles are created with the class Particle in mechanics. A Particle object has
an associated point and an associated mass which are the only two attributes of the object.:
>>>
>>>
>>>
>>>
>>>
>>>
1694
The associated point contains the position, velocity and acceleration of the particle. mechanics allows one to perform kinematic analysis of points separate from their association with
masses.
Inertia See the Inertia (Dyadics) section in Advanced Topics part of physics/vector docs.
Rigid Body Rigid bodies are created in a similar fashion as particles. The RigidBody class
generates objects with four attributes: mass, center of mass, a reference frame, and an inertia
tuple:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
The mass is specied exactly as is in a particle. Similar to the Particles .point, the RigidBodys center of mass, .masscenter must be specied. The reference frame is stored in an
analogous fashion and holds information about the bodys orientation and angular velocity.
Finally, the inertia for a rigid body needs to be specied about a point. In mechanics, you are
allowed to specify any point for this. The most common is the center of mass, as shown in the
above code. If a point is selected which is not the center of mass, ensure that the position
between the point and the center of mass has been dened. The inertia is specied as a tuple
of length two with the rst entry being a Dyadic and the second entry being a Point of which
the inertia dyadic is dened about.
Dyadic In mechanics, dyadics are used to represent inertia ([Kane1985] (page 1916),
[WikiDyadics] (page 1916), [WikiDyadicProducts] (page 1916)). A dyadic is a linear polynomial of component unit dyadics, similar to a vector being a linear polynomial of component
unit vectors. A dyadic is the outer product between two vectors which returns a new quantity
representing the juxtaposition of these two vectors. For example:
^
ax ^
ax = ^
ax^
ax
^
ax ^
ay = ^
ax^
ay
Where ^
ax^
ax and ^
ax^
ay are the outer products obtained by multiplying the left side as a column
vector by the right side as a row vector. Note that the order is signicant.
Some additional properties of a dyadic are:
(xv) w = v (xw) = x(v w)
v (w + u) = v w + v u
(v + w) u = v u + w u
a
A vector in a reference frame can be represented as b or a^
i + b^
j + c^
k. Similarly, a dyadic can
c
5.36. Physics Module
1695
a11
a21
a31
a12
a22
a32
a13
a23
a33
or in dyadic form:
a11^
ax^
ax + a12^
ax^
ay + a13^
ax^
az + a21^
ay^
ax + a22^
ay^
ay + a23^
ay^
az + a31^
az^
ax + a32^
az^
ay + a33^
az^
az
Just as with vectors, the later representation makes it possible to keep track of which frames
the dyadic is dened with respect to. Also, the two components of each term in the dyadic
need not be in the same frame. The following is valid:
^
ax ^
by = ^
ax^
by
Dyadics can also be crossed and dotted with vectors; again, order matters:
^
ax^
ax ^
ax = ^
ax
^
ay^
ax ^
ax = ^
ay
^
ax^
ay ^
ax = 0
^
ax ^
ax^
ax = ^
ax
^
ax ^
ax^
ay = ^
ay
^
ax ^
ay^
ax = 0
^
ax ^
ay^
ax = ^
az^
ax
^
ax ^
ax^
ax = 0
^
ay^
ax ^
az = ^
ay^
ay
One can also take the time derivative of dyadics or express them in dierent frames, just like
with vectors.
Linear Momentum
where m is the mass of the particle P and v is the velocity of the particle in the inertial
frame.[Likins1973] .
Similarly the linear momentum of a rigid body is dened as:
LB = mv
where m is the mass of the rigid body, B, and v is the velocity of the mass center of B in the
inertial frame.
1696
HP /O = r mv
where r is a position vector from point O to the particle of mass m and v is the velocity of the
particle in the inertial frame.
Similarly the angular momentum of a rigid body B about a point O in an inertial frame N is
dened as:
N
HB/O =N HB/B +N HB
/O
where the angular momentum of the body about its mass center is:
N
HB/B = I
HB
/O
= r mv
where I is the central inertia dyadic of rigid body B, is the inertial angular velocity of B,
r is a position vector from point O to the mass center of B, m is the mass of B and v is the
velocity of the mass center in the inertial frame.
Using momenta functions in Mechanics
momenta functions in mechanics.
One begins by creating the requisite symbols to describe the system. Then the reference
frame is created and the kinematics are done.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
Finally, the bodies that make up the system are created. In this case the system consists of a
particle Pa and a RigidBody A.
>> Pa = Particle(Pa, P, m)
>> I = outer(N.z, N.z)
>> A = RigidBody(A, Ac, a, M, (I, Ac))
1697
Then one can either choose to evaluate the the momenta of individual components of the
system or of the entire system itself.
>> linear momentum(N,A)
M*l1*q1d*N.y
>> angular momentum(O, N, Pa)
4*l1**2*m*q1d*N.z
>> linear momentum(N, A, Pa)
(M*l1*q1d + 2*l1*m*q1d)*N.y
>> angular momentum(O, N, A, Pa)
(4*l1**2*m*q1d + q1d)*N.z
It should be noted that the user can determine either momenta in any frame in mechanics as
the user is allowed to specify the reference frame when calling the function. In other words
the user is not limited to determining just inertial linear and angular momenta. Please refer
to the docstrings on each function to learn more about how each function works precisely.
Kinetic Energy
1
mv2
2
where m is the mass of the particle P and v is the velocity of the particle in the inertial frame.
Similarly the kinetic energy of a rigid body B is dened as
TB = Tt + Tr
where the translational kinetic energy is given by:
Tt =
1
mv v
2
1
I
2
where m is the mass of the rigid body, v is the velocity of the mass center in the inertial
frame, is the inertial angular velocity of the body and I is the central inertia dyadic.
Potential Energy Potential energy is dened as the energy possessed by a body or system
by virtue of its position or arrangement.
Since there are a variety of denitions for potential energy, this is not discussed further here.
One can learn more about this in any elementary text book on dynamics.
Lagrangian
Using energy functions in Mechanics The following example shows how to use the energy functions in mechanics.
As was discussed above in the momenta functions, one rst creates the system by going
through an identical procedure.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
The user can then determine the kinetic energy of any number of entities of the system:
>> kinetic energy(N, Pa)
2*l1**2*m*q1d**2
>> kinetic energy(N, Pa, A)
M*l1**2*q1d**2/2 + 2*l1**2*m*q1d**2 + q1d**2/2
It should be noted that the user can determine either kinetic energy relative to any frame in
mechanics as the user is allowed to specify the reference frame when calling the function. In
other words the user is not limited to determining just inertial kinetic energy.
For potential energies, the user must rst specify the potential energy of every entity of the
system using the set potential energy method. The potential energy of any number of entities comprising the system can then be determined:
>> Pa.set potential energy(m * g * h)
>> A.set potential energy(M * g * H)
>> potential energy(A, Pa)
H*M*g + g*h*m
1699
Structure of Equations In mechanics we are assuming there are 5 basic sets of equations
needed to describe a system. They are: holonomic constraints, non-holonomic constraints,
kinematic dierential equations, dynamic equations, and dierentiated non-holonomic equations.
fh (q, t) = 0
knh (q, t)u + fnh (q, t) = 0
kkq_ (q, t)q + kku (q, t)u + fk (q, t) = 0
kd (q, t)u + fd (q, q,
u, t) = 0
kdnh (q, t)u + fdnh (q, q,
u, t) = 0
In mechanics holonomic constraints are only used for the linearization process; it is assumed
that they will be too complicated to solve for the dependent coordinate(s). If you are able to
easily solve a holonomic constraint, you should consider redening your problem in terms of
a smaller set of coordinates. Alternatively, the time-dierentiated holonomic constraints can
be supplied.
Kanes method forms two expressions, Fr and Fr , whose sum is zero. In this module, these
expressions are rearranged into the following form:
M(q, t)u = f(q, q,
u, t)
For a non-holonomic system with o total speeds and m motion constraints, we will get o - m
equations. The mass-matrix/forcing equations are then augmented in the following fashion:
[
]
kd (q, t)
M(q, t) =
kdnh (q, t)
[
]
fd (q, q,
u, t)
u, t) =
(forcing) (q, q,
fdnh (q, q,
u, t)
Kanes Method in Physics/Mechanics The formulation of the equations of motion in mechanics starts with creation of a KanesMethod object. Upon initialization of the KanesMethod
object, an inertial reference frame needs to be supplied. along with some basic system information, suchs as coordinates and speeds
>>>
>>>
>>>
>>>
>>>
It is also important to supply the order of coordinates and speeds properly if there are dependent coordinates and speeds. They must be supplied after independent coordinates and
speeds or as a keyword argument; this is shown later.
>>>
>>>
>>>
>>>
>>>
Additionally, if there are auxiliary speeds, they need to be identied here. See the examples
for more information on this. In this example u4 is the auxiliary speed.
1700
Kinematic dierential equations must also be supplied; there are to be provided as a list of
expressions which are each equal to zero. A trivial example follows:
>>> kd = [q1d - u1, q2d - u2]
Turning on mechanics printing() makes the expressions signicantly shorter and is recommended. Alternatively, the mprint and mpprint commands can be used.
If there are non-holonomic constraints, dependent speeds need to be specied (and so do
dependent coordinates, but they only come into play when linearizing the system). The constraints need to be supplied in a list of expressions which are equal to zero, trivial motion and
conguration constraints are shown below:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
...
...
...
...
N = ReferenceFrame(N)
q1, q2, q3, q4 = dynamicsymbols(q1 q2 q3 q4)
q1d, q2d, q3d, q4d = dynamicsymbols(q1 q2 q3 q4, 1)
u1, u2, u3, u4 = dynamicsymbols(u1 u2 u3 u4)
#Here we will assume q2 is dependent, and u2 and u3 are dependent
speed_cons = [u2 - u1, u3 - u1 - u4]
coord_cons = [q2 - q1]
q_ind = [q1, q3, q4]
q_dep = [q2]
u_ind = [u1, u4]
u_dep = [u2, u3]
kd = [q1d - u1, q2d - u2, q3d - u3, q4d - u4]
KM = KanesMethod(N, q_ind, u_ind, kd,
q_dependent=q_dep,
configuration_constraints=coord_cons,
u_dependent=u_dep,
velocity_constraints=speed_cons)
The nal step in forming the equations of motion is supplying a list of bodies and particles, and
a list of 2-tuples of the form (Point, Vector) or (ReferenceFrame, Vector) to represent
applied forces and torques.
>>> N = ReferenceFrame(N)
>>> q, u = dynamicsymbols(q u)
>>> qd, ud = dynamicsymbols(q u, 1)
>>> P = Point(P)
>>> P.set_vel(N, u * N.x)
>>> Pa = Particle(Pa, P, 5)
>>> BL = [Pa]
>>> FL = [(P, 7 * N.x)]
>>> KM = KanesMethod(N, [q], [u], [qd - u])
>>> (fr, frstar) = KM.kanes_equations(FL, BL)
>>> KM.mass_matrix
Matrix([[5]])
>>> KM.forcing
Matrix([[7]])
When there are motion constraints, the mass matrix is augmented by the kdnh (q, t) matrix, and
1701
In this module, the expressions formed by using Lagranges equations of the second kind are
rearranged into the following form:
M(q, t)x = f(q, q,
t)
where in the case of a system without constraints:
x = q
For a constrained system with n generalized speeds and m constraints, we will get n - m
equations. The mass-matrix/forcing equations are then augmented in the following fashion:
[ ]
q
x=
[
]
M(q, t) = md (q, t)
c (q, t)
[
]
t)
F(q,
q, t) = fd (q, q,
1702
>>>
>>>
>>>
>>>
If there are any holonomic or non-holonomic constraints, they must be supplied as keyword
arguments (hol coneqs and nonhol coneqs respectively) in a list of expressions which are
equal to zero. Modifying the example above, the equations of motion can then be generated:
>>> LM = LagrangesMethod(L, [q1, q2], hol_coneqs=[q1 - q2])
When the equations of motion are generated in this case, the Lagrange multipliers are introduced; they are represented by lam1 in this case. In general, there will be as many multipliers
as there are constraint equations.
>>> LM.form_lagranges_equations()
Matrix([
[ lam1 + 2*q1],
[-lam1 + 2*q2]])
Also in the case of systems with constraints, the full mass matrix is augmented by the kdc (q, t)
matrix, and the forcing vector by the fdc (q, q,
t) vector. The full mass matrix is of size (2n +
o) x (2n + o), i.e. its a square matrix.
>>> LM.mass_matrix_full
Matrix([
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 2, 0, -1],
[0, 0, 0, 2, 1],
[0, 0, 1, -1, 0]])
>>> LM.forcing_full
Matrix([
[q1],
1703
[q2],
[ 0],
[ 0],
[ 0]])
If there are any non-conservative forces or moments acting on the system, they must also be
supplied as keyword arguments in a list of 2-tuples of the form (Point, Vector) or (ReferenceFrame, Vector) where the Vector represents the non-conservative forces and torques.
Along with this 2-tuple, the inertial frame must also be specied as a keyword argument. This
is shown below by modifying the example above:
>>> N = ReferenceFrame(N)
>>> P = Point(P)
>>> P.set_vel(N, q1d * N.x)
>>> FL = [(P, 7 * N.x)]
>>> LM = LagrangesMethod(L, [q1, q2], forcelist=FL, frame=N)
>>> LM.form_lagranges_equations()
Matrix([
[2*q1 - 7],
[
2*q2]])
In mechanics we assume all systems can be represented in the following genfc (q, t) = 0l1
fv (q, u, t) = 0m1
fa (q, q,
u, u,
t) = 0m1
f0 (q, q,
t) + f1 (q, u, t) = 0n1
f2 (q, u, u,
t) + f3 (q, q,
u, r, t) + f4 (q, , t) = 0(om+k)1
where
q, q Rn
u, u Ro
r Rs
Rk
In this form,
1704
This generalized form is held inside the Linearizer class, which performs the actual linearization. Both KanesMethod and LagrangesMethod objects have methods for forming the
linearizer using the to linearizer class method.
A Note on Dependent Coordinates and Speeds
If the system being linearized contains constraint equations, this results in not all generalized coordinates being independent (i.e. q1 may depend on q2 ). With l conguration
constraints, and m velocity constraints, there are l dependent coordinates and m dependent speeds.
In general, you may pick any of the coordinates and speeds to be dependent, but in practice some choices may result in undesirable singularites. Methods for deciding which
coordinates/speeds to make dependent is behind the scope of this guide. For more information, please see [Blajer1994] (page 1916).
Once the system is coerced into the generalized form, the linearized EOM can be solved for.
The methods provided in mechanics allow for two dierent forms of the linearized EOM:
M , A, and B In this form, the forcing matrix is linearized into two separate matrices A and
B. This is the default form of the linearized EOM. The resulting equations are:
[ ]
q
[ ]
qi
M u = A
+ B r
ui
where
M R(n+o+k)(n+o+k)
A R(n+o+k)(nl+om)
B R(n+o+k)s
Note that qi and ui are just the independent coordinates and speeds, while q and u contains both the independent and dependent coordinates and speeds.
A and B In this form, the linearized EOM are brought into explicit rst order form, in terms of
just the independent coordinates and speeds. This form is often used in stability analysis
or control theory. The resulting equations are:
[ ]
[ ]
[ ]
qi
qi
=A
+ B r
ui
ui
1705
where
A R(nl+om)(nl+om)
B R(nl+om)s
To use this form set A and B=True in the linearize class method.
Linearizing Kanes Equations After initializing the KanesMethod object and forming Fr
and Fr using the kanes equations class method, linearization can be accomplished in a couple ways. The dierent methods will be demonstrated with a simple pendulum system:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
# Angle of pendulum
# Angular velocity
1. Using the Linearizer class directly: A linearizer object can be created using the
to linearizer class method. This coerces the representation found in the KanesMethod object into the generalized form described above. As the independent and dependent coordinates and speeds are specied upon creation of the KanesMethod object, there is no need to
speciy them here.
>>> linearizer = KM.to_linearizer()
The linearized EOM can then be formed with the linearize method of the Linearizer object:
>>> M, A, B = linearizer.linearize()
>>> M
1706
Matrix([
[1,
0],
[0, -L**2*m]])
>>> A
Matrix([
[
0, 1],
[L*g*m*cos(q1(t)), 0]])
>>> B
Matrix(0, 0, [])
Alternatively, the A and B form can be generated instead by specifying A and B=True:
>>> A, B = linearizer.linearize(A_and_B=True)
>>> A
Matrix([
[
0, 1],
[-g*cos(q1(t))/L, 0]])
>>> B
Matrix(0, 0, [])
Note that the same eect can be had by applying msubs to the matrices generated without
the op point kwarg:
>>> assert msubs(A, op_point) == A_op
Sometimes the returned matrices may not be in the most simplied form. Simplication can
be performed after the fact, or the Linearizer object can be made to perform simplication
internally by setting the simplify kwarg to True.
2. Using the linearize class method: The linearize method of the KanesMethod class
is provided as a nice wrapper that calls to linearizer internally, performs the linearization,
and returns the result. Note that all the kwargs available in the linearize method described
above are also available here:
>>> A, B, inp_vec = KM.linearize(A_and_B=True, op_point=op_point, new_method=True)
>>> A
Matrix([
[
0, 1],
[-g/L, 0]])
The additional output inp vec is a vector containing all found dynamicsymbols not included
in the generalized coordinate or speed vectors. These are assumed to be inputs to the system,
forming the r vector described in the background above. In this example there are no inputs,
so the vector is empty:
>>> inp_vec
Matrix(0, 0, [])
1707
>>>
>>>
>>>
>>>
1. Using the Linearizer class directly: A Linearizer object can be formed from a LagrangesMethod object using the to linearizer class method. The only dierence between
this process and that of the KanesMethod class is that the LagrangesMethod object doesnt already have its independent and dependent coordinates and speeds specied internally. These
must be specied in the call to to linearizer. In this example there are no dependent coordinates and speeds, but if there were they would be included in the q dep and qd dep kwargs:
>>> linearizer = LM.to_linearizer(q_ind=[q1], qd_ind=[q1d])
Once in this form, everything is the same as it was before with the KanesMethod example:
>>> A, B = linearizer.linearize(A_and_B=True, op_point=op_point)
>>> A
Matrix([
[
0, 1],
[-g/L, 0]])
1708
Potential Issues While the Linearizer class should be able to linearize all systems, there
are some potential issues that could occur. These are discussed below, along with some
troubleshooting tips for solving them.
1. Symbolic linearization with A and B=True is slow This could be due to a number of
things, but the most likely one is that solving a large linear system symbolically is an expensive
operation. Specifying an operating point will reduce the expression size and speed this up.
If a purely symbolic solution is desired though (for application of many operating points at
a later period, for example) a way to get around this is to evaluate with A and B=False, and
then solve manually after applying the operating point:
>>> M, A, B = linearizer.linearize()
>>> M_op = msubs(M, op_point)
>>> A_op = msubs(A, op_point)
>>> perm_mat = linearizer.perm_mat
>>> A_lin = perm_mat.T * M_op.LUsolve(A_op)
>>> A_lin
Matrix([
[
0, 1],
[-g/L, 0]])
The fewer symbols in A and M before solving, the faster this solution will be. Thus, for large
expressions, it may be to your benet to delay conversion to the A and B form until most
symbols are subbed in for their numeric values.
2. The linearized form has nan, zoo, or oo as matrix elements There are two potential
causes for this. The rst (and the one you should check rst) is that some choices of dependent
coordinates will result in singularities at certain operating points. Coordinate partitioning in a
systemic manner to avoid this is beyond the scope of this guide; see [Blajer1994] (page 1916)
for more information.
The other potential cause for this is that the matrices may not have been in the most reduced
form before the operating point was substituted in. A simple example of this behavior is:
>>>
>>>
>>>
>>>
nan
Note that if this expression was simplied before substitution, the correct value results:
>>> expr.simplify().subs(op_point)
1
A good way of avoiding this hasnt been found yet. For expressions of reasonable size, using
msubs with smart=True will apply an algorithm that tries to avoid these conditions. For large
expressions though this is extremely time consuming.
>>> msubs(expr, op_point, smart=True)
1
Further Examples The pendulum example used above was simple, but didnt include any
dependent coordinates or speeds. For a more thorough example, the same pendulum was
linearized with dependent coordinates using both Kanes and Lagranges methods:
1709
Nonminimal Coordinates Pendulum In this example we demonstrate the use of the functionality provided in mechanics for deriving the equations of motion (EOM) for a pendulum
with a nonminimal set of coordinates. As the pendulum is a one degree of freedom system, it
can be described using one coordinate and one speed (the pendulum angle, and the angular
velocity respectively). Choosing instead to describe the system using the x and y coordinates
of the mass results in a need for constraints. The system is shown below:
Ay
Ny
Ax
Nx
q1
L
q2
u1
u2
m
The system will be modeled using both Kanes and Lagranges methods, and the resulting
EOM linearized. While this is a simple problem, it should illustrate the use of the linearization
methods in the presence of constraints.
Kanes Method First we need to create the dynamicsymbols needed to describe the system
as shown in the above diagram. In this case, the generalized coordinates q1 and q2 represent
the mass x and y coordinates in the inertial N frame. Likewise, the generalized speeds u1 and
u2 represent the velocities in these directions. We also create some symbols to represent the
length and mass of the pendulum, as well as gravity and time.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1710
Next, we create a world coordinate frame N , and its origin point N . The velocity of the origin
is set to 0. A second coordinate frame A is oriented such that its x-axis is along the pendulum
(as shown in the diagram above).
>>>
>>>
>>>
>>>
Locating the pendulum mass is then as easy as specifying its location with in terms of its x
and y coordinates in the world frame. A Particle object is then created to represent the
mass at this location.
>>> # Locate the pendulum mass
>>> P = pN.locatenew(P1, q1*N.x + q2*N.y)
>>> pP = Particle(pP, P, m)
The kinematic dierential equations (KDEs) relate the derivatives of the generalized coordinates to the generalized speeds. In this case the speeds are the derivatives, so these are
simple. A dictionary is also created to map q to u:
>>> # Calculate the kinematic differential equations
>>> kde = Matrix([q1d - u1,
...
q2d - u2])
>>> dq_dict = solve(kde, [q1d, q2d])
The velocity of the mass is then the time derivative of the position from the origin N :
>>> # Set velocity of point P
>>> P.set_vel(N, P.pos_from(pN).dt(N).subs(dq_dict))
As this system has more coordinates than degrees of freedom, constraints are needed. The
conguration constraints relate the coordinates to each other. In this case the constraint is
that the distance from the origin to the mass is always the length L (the pendulum doesnt
get longer). Likewise, the velocity constraint is that the mass velocity in the A.x direction is
always 0 (no radial velocity).
>>> f_c = Matrix([P.pos_from(pN).magnitude() - L])
>>> f_v = Matrix([P.vel(N).express(A).dot(A.x)])
>>> f_v.simplify()
With the problem setup, the equations of motion can be generated using the KanesMethod
class. As there are constraints, dependent and independent coordinates need to be provided
to the class. In this case well use q2 and u2 as the independent coordinates and speeds:
1711
For linearization, operating points can be specied on the call, or be substituted in afterwards. In this case well provide them in the call, supplied in a list. The A and B=True kwarg
indicates to solve invert the M matrix and solve for just the explicit linearized A and B matrices. The simplify=True kwarg indicates to simplify inside the linearize call, and return
the presimplied matrices. The cost of doing this is small for simple systems, but for larger
systems this can be a costly operation, and should be avoided.
>>> # Set the operating point to be straight down, and non-moving
>>> q_op = {q1: L, q2: 0}
>>> u_op = {u1: 0, u2: 0}
>>> ud_op = {u1d: 0, u2d: 0}
>>> # Perform the linearization
>>> A, B, inp_vec = KM.linearize(op_point=[q_op, u_op, ud_op], A_and_B=True,
...
new_method=True, simplify=True)
>>> A
Matrix([
[
0, 1],
[-g/L, 0]])
>>> B
Matrix(0, 0, [])
The resulting A matrix has dimensions 2 x 2, while the number of total states is len(q) +
len(u) = 2 + 2 = 4. This is because for constrained systems the resulting A and B form has
a partitioned state vector only containing the independent coordinates and speeds. Written
out mathematically, the system linearized about this point would be written as:
[ ] [
][ ]
0 1 q2
q2
= g
u2
0 u2
L
Lagranges Method The derivation using Lagranges method is very similar to the approach using Kanes method described above. As before, we rst create the dynamicsymbols
needed to describe the system. In this case, the generalized coordinates q1 and q2 represent
the mass x and y coordinates in the inertial N frame. This results in the time derivatives q1 and
q2 representing the velocities in these directions. We also create some symbols to represent
the length and mass of the pendulum, as well as gravity and time.
>>>
>>>
>>>
>>>
>>>
Next, we create a world coordinate frame N , and its origin point N . The velocity of the origin
is set to 0. A second coordinate frame A is oriented such that its x-axis is along the pendulum
(as shown in the diagram above).
>>> # Compose World Frame
>>> N = ReferenceFrame(N)
>>> pN = Point(N*)
1712
>>>
>>>
>>>
>>>
pN.set_vel(N, 0)
# A.x is along the pendulum
theta1 = atan(q2/q1)
A = N.orientnew(A, axis, [theta1, N.z])
Locating the pendulum mass is then as easy as specifying its location with in terms of its x
and y coordinates in the world frame. A Particle object is then created to represent the
mass at this location.
>>>
>>>
>>>
>>>
As this system has more coordinates than degrees of freedom, constraints are needed. In this
case only a single holonomic constraints is needed: the distance from the origin to the mass
is always the length L (the pendulum doesnt get longer).
>>> # Holonomic Constraint Equations
>>> f_c = Matrix([q1**2 + q2**2 - L**2])
With the problem setup, the Lagrangian can be calculated, and the equations of motion
formed. Note that the call to LagrangesMethod includes the Lagrangian, the generalized
coordinates, the constraints (specied by hol coneqs or nonhol coneqs), the list of (body,
force) pairs, and the inertial frame. In contrast to the KanesMethod initializer, independent
and dependent coordinates are not partitioned inside the LagrangesMethod object. Such a
partition is supplied later.
>>>
>>>
>>>
>>>
Next, we compose the operating point dictionary, set in the hanging at rest position:
>>> # Compose operating point
>>> op_point = {q1: L, q2: 0, q1d: 0, q2d: 0, q1d.diff(t): 0, q2d.diff(t): 0}
As there are constraints in the formulation, there will be corresponding Lagrange Multipliers.
These may appear inside the linearized form as well, and thus should also be included inside
the operating point dictionary. Fortunately, the LagrangesMethod class provides an easy way
of solving for the multipliers at a given operating point using the solve multipliers method.
>>> # Solve for multiplier operating point
>>> lam_op = LM.solve_multipliers(op_point=op_point)
With this solution, linearization can be completed. Note that in contrast to the KanesMethod
approach, the LagrangesMethod.linearize method also requires the partitioning of the generalized coordinates and their time derivatives into independent and dependent vectors. This
is the same as what was passed into the KanesMethod constructor above:
>>> op_point.update(lam_op)
>>> # Perform the Linearization
1713
The resulting A matrix has dimensions 2 x 2, while the number of total states is 2*len(q)
= 4. This is because for constrained systems the resulting A and B form has a partitioned
state vector only containing the independent coordinates and their derivatives. Written out
mathematically, the system linearized about this point would be written as:
[ ] [
][ ]
0 1 q2
q2
= g
q2
0 q2
L
Examples for Physics/Mechanics Here are some examples that illustrate how one typically uses this module. We have ordered the examples roughly according to increasing diculty. If you have used this module to do something others might nd useful or interesting,
consider adding it here!
A rolling disc The disc is assumed to be innitely thin, in contact with the ground at only
1 point, and it is rolling without slip on the ground. See the image below.
nz
ny
rz
R
ry
rx
nx
1714
We model the rolling disc in three dierent ways, to show more of the functionality of this
module.
A rolling disc, with Kanes method Here the denition of the rolling discs kinematics is
formed from the contact point up, removing the need to introduce generalized speeds. Only
3 conguration and three speed variables are need to describe this system, along with the
discs mass and radius, and the local gravity (note that mass will drop out).
>>>
>>>
>>>
>>>
>>>
>>>
The kinematics are formed by a series of simple rotations. Each simple rotation creates a new
frame, and the next rotation is dened by the new frames basis vectors. This example uses a
3-1-2 series of rotations, or Z, X, Y series of rotations. Angular velocity for this is dened using
the second frames basis (the lean frame); it is for this reason that we dened intermediate
frames, rather than using a body-three orientation.
>>>
>>>
>>>
>>>
>>>
>>>
N = ReferenceFrame(N)
Y = N.orientnew(Y, Axis, [q1, N.z])
L = Y.orientnew(L, Axis, [q2, Y.x])
R = L.orientnew(R, Axis, [q3, L.y])
w_R_N_qd = R.ang_vel_in(N)
R.set_ang_vel(N, u1 * L.x + u2 * L.y + u3 * L.z)
This is the translational kinematics. We create a point with no velocity in N; this is the contact
point between the disc and ground. Next we form the position vector from the contact point
to the discs center of mass. Finally we form the velocity and acceleration of the disc.
>>> C = Point(C)
>>> C.set_vel(N, 0)
>>> Dmc = C.locatenew(Dmc, r * L.z)
>>> Dmc.v2pt_theory(C, N, R)
r*u2*L.x - r*u1*L.y
This is a simple way to form the inertia dyadic. The inertia of the disc does not change within
the lean frame as the disc rolls; this will make for simpler equations in the end.
>>> I = inertia(L, m / 4 * r**2, m / 2 * r**2, m / 4 * r**2)
>>> mprint(I)
m*r**2/4*(L.x|L.x) + m*r**2/2*(L.y|L.y) + m*r**2/4*(L.z|L.z)
Kinematic dierential equations; how the generalized coordinate time derivatives relate to
generalized speeds.
>>> kd = [dot(R.ang_vel_in(N) - w_R_N_qd, uv) for uv in L]
Creation of the force list; it is the gravitational force at the center of mass of the disc. Then
we create the disc by assigning a Point to the center of mass attribute, a ReferenceFrame to
the frame attribute, and mass and inertia. Then we form the body list.
>>> ForceList = [(Dmc, - m * g * Y.z)]
>>> BodyD = RigidBody(BodyD, Dmc, R, m, (I, Dmc))
>>> BodyList = [BodyD]
1715
Finally we form the equations of motion, using the same steps we did before. Specify inertial
frame, supply generalized coordinates and speeds, supply kinematic dierential equation dictionary, compute Fr from the force list and Fr* from the body list, compute the mass matrix
and forcing terms, then solve for the u dots (time derivatives of the generalized speeds).
>>> KM = KanesMethod(N, q_ind=[q1, q2, q3], u_ind=[u1, u2, u3], kd_eqs=kd)
>>> (fr, frstar) = KM.kanes_equations(ForceList, BodyList)
>>> MM = KM.mass_matrix
>>> forcing = KM.forcing
>>> rhs = MM.inv() * forcing
>>> kdd = KM.kindiffdict()
>>> rhs = rhs.subs(kdd)
>>> rhs.simplify()
>>> mprint(rhs)
Matrix([
[(4*g*sin(q2) + 6*r*u2*u3 - r*u3**2*tan(q2))/(5*r)],
[
-2*u1*u3/3],
[
(-2*u2 + u3*tan(q2))*u1]])
A rolling disc, with Kanes method and constraint forces We will now revisit the rolling
disc example, except this time we are bringing the non-contributing (constraint) forces into
evidence. See [Kane1985] (page 1916) for a more thorough explanation of this. Here, we will
turn on the automatic simplifcation done when doing vector operations. It makes the outputs
nicer for small problems, but can cause larger vector operations to hang.
>>>
>>>
>>>
>>>
>>>
>>>
These two lines introduce the extra quantities needed to nd the constraint forces.
>>> u4, u5, u6, f1, f2, f3 = dynamicsymbols(u4 u5 u6 f1 f2 f3)
N = ReferenceFrame(N)
Y = N.orientnew(Y, Axis, [q1, N.z])
L = Y.orientnew(L, Axis, [q2, Y.x])
R = L.orientnew(R, Axis, [q3, L.y])
w_R_N_qd = R.ang_vel_in(N)
R.set_ang_vel(N, u1 * L.x + u2 * L.y + u3 * L.z)
The denition of rolling without slip necessitates that the velocity of the contact point is zero;
as part of bringing the constraint forces into evidence, we have to introduce speeds at this
point, which will by denition always be zero. They are normal to the ground, along the path
which the disc is rolling, and along the ground in an perpendicular direction.
>>>
>>>
>>>
>>>
>>>
>>>
C = Point(C)
C.set_vel(N, u4 * L.x + u5 * (Y.z ^ L.x) + u6 * Y.z)
Dmc = C.locatenew(Dmc, r * L.z)
vel = Dmc.v2pt_theory(C, N, R)
I = inertia(L, m / 4 * r**2, m / 2 * r**2, m / 4 * r**2)
kd = [dot(R.ang_vel_in(N) - w_R_N_qd, uv) for uv in L]
1716
Just as we previously introduced three speeds as part of this process, we also introduce three
forces; they are in the same direction as the speeds, and represent the constraint forces in
those directions.
>>> ForceList = [(Dmc, - m * g * Y.z), (C, f1 * L.x + f2 * (Y.z ^ L.x) + f3 * Y.z)]
>>> BodyD = RigidBody(BodyD, Dmc, R, m, (I, Dmc))
>>> BodyList = [BodyD]
>>> KM = KanesMethod(N, q_ind=[q1, q2, q3], u_ind=[u1, u2, u3], kd_eqs=kd,
...
u_auxiliary=[u4, u5, u6])
>>> (fr, frstar) = KM.kanes_equations(ForceList, BodyList)
>>> MM = KM.mass_matrix
>>> forcing = KM.forcing
>>> rhs = MM.inv() * forcing
>>> kdd = KM.kindiffdict()
>>> rhs = rhs.subs(kdd)
>>> rhs.simplify()
>>> mprint(rhs)
Matrix([
[(4*g*sin(q2) + 6*r*u2*u3 - r*u3**2*tan(q2))/(5*r)],
[
-2*u1*u3/3],
[
(-2*u2 + u3*tan(q2))*u1]])
>>> from sympy import trigsimp, signsimp, collect, factor_terms
>>> def simplify_auxiliary_eqs(w):
...
return signsimp(trigsimp(collect(collect(factor_terms(w), f2), m*r)))
>>> mprint(KM.auxiliary_eqs.applyfunc(simplify_auxiliary_eqs))
Matrix([
[
-m*r*(u1*u3 + u2) + f1],
[-m*r*u1**2*sin(q2) - m*r*u2*u3/cos(q2) + m*r*cos(q2)*u1 + f2],
[
-g*m + m*r*(u1**2*cos(q2) + sin(q2)*u1) + f3]])
A rolling disc using Lagranges Method Here the rolling disc is formed from the contact
point up, removing the need to introduce generalized speeds. Only 3 conguration and 3
speed variables are needed to describe this system, along with the discs mass and radius,
and the local gravity.
>>>
>>>
>>>
>>>
>>>
>>>
The kinematics are formed by a series of simple rotations. Each simple rotation creates a new
frame, and the next rotation is dened by the new frames basis vectors. This example uses
a 3-1-2 series of rotations, or Z, X, Y series of rotations. Angular velocity for this is dened
using the second frames basis (the lean frame).
>>>
>>>
>>>
>>>
N
Y
L
R
=
=
=
=
ReferenceFrame(N)
N.orientnew(Y, Axis, [q1, N.z])
Y.orientnew(L, Axis, [q2, Y.x])
L.orientnew(R, Axis, [q3, L.y])
This is the translational kinematics. We create a point with no velocity in N; this is the contact
point between the disc and ground. Next we form the position vector from the contact point
to the discs center of mass. Finally we form the velocity and acceleration of the disc.
1717
>>> C = Point(C)
>>> C.set_vel(N, 0)
>>> Dmc = C.locatenew(Dmc, r * L.z)
>>> Dmc.v2pt_theory(C, N, R)
r*(sin(q2)*q1 + q3)*L.x - r*q2*L.y
We then set the potential energy and determine the Lagrangian of the rolling disc.
>>> BodyD.set_potential_energy(- m * g * r * cos(q2))
>>> Lag = Lagrangian(N, BodyD)
Then the equations of motion are generated by initializing the LagrangesMethod object. Finally we solve for the generalized accelerations(q double dots) with the rhs method.
A bicycle The bicycle is an interesting system in that it has multiple rigid bodies, nonholonomic constraints, and a holonomic constraint. The linearized equations of motion are
presented in [Meijaard2007] (page 1916). This example will go through construction of the
equations of motion in mechanics.
>>> from sympy import *
>>> from sympy.physics.mechanics import *
>>> print(Calculation of Linearized Bicycle \A\ Matrix,
...
with States: Roll, Steer, Roll Rate, Steer Rate)
Calculation of Linearized Bicycle A Matrix, with States: Roll, Steer, Roll Rate, Steer Rate
Note that this code has been crudely ported from Autolev, which is the reason for some of the
unusual naming conventions. It was purposefully as similar as possible in order to aid initial
porting & debugging. We set Vector.simp to False (in case it has been set True elsewhere),
since it slows down the computations:
>>> Vector.simp = False
>>> mechanics_printing(pretty_print=False)
1718
Declaration of Coordinates & Speeds: A simple denition for qdots, qd = u,is used in this
code. Speeds are: yaw frame ang. rate, roll frame ang. rate, rear wheel frame ang. rate
(spinning motion), frame ang. rate (pitching motion), steering frame ang. rate, and front
wheel ang. rate (spinning motion). Wheel positions are ignorable coordinates, so they are
not introduced.
>>>
>>>
>>>
>>>
Set up reference frames for the system: N - inertial Y - yaw R - roll WR - rear wheel, rotation
angle is ignorable coordinate so not oriented Frame - bicycle frame TempFrame - statically
rotated frame for easier reference inertia denition Fork - bicycle fork TempFork - statically
rotated frame for easier reference inertia denition WF - front wheel, again posses a ignorable
coordinate
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
N = ReferenceFrame(N)
Y = N.orientnew(Y, Axis, [q1, N.z])
R = Y.orientnew(R, Axis, [q2, Y.x])
Frame = R.orientnew(Frame, Axis, [q4 + htangle, R.y])
WR = ReferenceFrame(WR)
TempFrame = Frame.orientnew(TempFrame, Axis, [-htangle, Frame.y])
Fork = Frame.orientnew(Fork, Axis, [q5, Frame.x])
TempFork = Fork.orientnew(TempFork, Axis, [-htangle, Fork.y])
WF = ReferenceFrame(WF)
Kinematics of the Bicycle: First block of code is forming the positions of the relevant points
rear wheel contact -> rear wheels center of mass -> frames center of mass + frame/fork
connection -> forks center of mass + front wheels center of mass -> front wheel contact
point.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
...
WR_cont = Point(WR_cont)
WR_mc = WR_cont.locatenew(WR_mc, WRrad * R.z)
Steer = WR_mc.locatenew(Steer, framelength * Frame.z)
Frame_mc = WR_mc.locatenew(Frame_mc, -framecg1 * Frame.x + framecg3 * Frame.z)
Fork_mc = Steer.locatenew(Fork_mc, -forkcg1 * Fork.x + forkcg3 * Fork.z)
WF_mc = Steer.locatenew(WF_mc, forklength * Fork.x + forkoffset * Fork.z)
WF_cont = WF_mc.locatenew(WF_cont, WFrad*(dot(Fork.y, Y.z)*Fork.y - \
Y.z).normalize())
Set the angular velocity of each frame: Angular accelerations end up being calculated automatically by dierentiating the angular velocities when rst needed. :: u1 is yaw rate u2 is
roll rate u3 is rear wheel rate u4 is frame pitch rate u5 is fork steer rate u6 is front wheel
rate
1719
>>>
>>>
>>>
>>>
>>>
>>>
Y.set_ang_vel(N, u1 * Y.z)
R.set_ang_vel(Y, u2 * R.x)
WR.set_ang_vel(Frame, u3 * Frame.y)
Frame.set_ang_vel(R, u4 * Frame.y)
Fork.set_ang_vel(Frame, u5 * Fork.x)
WF.set_ang_vel(Fork, u6 * Fork.y)
Form the velocities of the points, using the 2-point theorem. Accelerations again are calculated automatically when rst needed.
>>> WR_cont.set_vel(N, 0)
>>> WR_mc.v2pt_theory(WR_cont, N, WR)
WRrad*(u1*sin(q2) + u3 + u4)*R.x - WRrad*u2*R.y
>>> Steer.v2pt_theory(WR_mc, N, Frame)
WRrad*(u1*sin(q2) + u3 + u4)*R.x - WRrad*u2*R.y
>>> Frame_mc.v2pt_theory(WR_mc, N, Frame)
WRrad*(u1*sin(q2) + u3 + u4)*R.x - WRrad*u2*R.y
>>> Fork_mc.v2pt_theory(Steer, N, Fork)
WRrad*(u1*sin(q2) + u3 + u4)*R.x - WRrad*u2*R.y
>>> WF_mc.v2pt_theory(Steer, N, Fork)
WRrad*(u1*sin(q2) + u3 + u4)*R.x - WRrad*u2*R.y
>>> WF_cont.v2pt_theory(WF_mc, N, WF)
WRrad*(u1*sin(q2) + u3 + u4)*R.x - WRrad*u2*R.y
Sets the inertias of each body. Uses the inertia frame to construct the inertia dyadics. Wheel
inertias are only dened by principal moments of inertia, and are in fact constant in the frame
and fork reference frames; it is for this reason that the orientations of the wheels does not
need to be dened. The frame and fork inertias are dened in the Temp frames which are
xed to the appropriate body frames; this is to allow easier input of the reference values of
the benchmark paper. Note that due to slightly dierent orientations, the products of inertia
need to have their signs ipped; this is done later when entering the numerical value.
>>>
...
>>>
>>>
>>>
The kinematic dierential equations; they are dened quite simply. Each entry in this list is
equal to zero.
>>> kd = [q1d - u1, q2d - u2, q4d - u4, q5d - u5]
The nonholonomic constraints are the velocity of the front wheel contact point dotted into the
X, Y, and Z directions; the yaw frame is used as it is closer to the front wheel (1 less DCM
connecting them). These constraints force the velocity of the front wheel contact point to be
0 in the inertial frame; the X and Y direction constraints enforce a no-slip condition, and the
Z direction constraint forces the front wheel contact point to not move away from the ground
1720
frame, essentially replicating the holonomic constraint which does not allow the frame pitch
to change in an invalid fashion.
>>> conlist_speed = [WF_cont.vel(N) & Y.x,
...
WF_cont.vel(N) & Y.y,
...
WF_cont.vel(N) & Y.z]
The holonomic constraint is that the position from the rear wheel contact point to the front
wheel contact point when dotted into the normal-to-ground plane direction must be zero;
eectively that the front and rear wheel contact points are always touching the ground plane.
This is actually not part of the dynamic equations, but instead is necessary for the linearization
process.
>>> conlist_coord = [WF_cont.pos_from(WR_cont) & Y.z]
The force list; each body has the appropriate gravitational force applied at its center of mass.
>>> FL = [(Frame_mc, -mframe * g * Y.z), (Fork_mc, -mfork * g * Y.z),
...
(WF_mc, -mwf * g * Y.z), (WR_mc, -mwr * g * Y.z)]
>>> BL = [BodyFrame, BodyFork, BodyWR, BodyWF]
The N frame is the inertial frame, coordinates are supplied in the order of independent, dependent coordinates. The kinematic dierential equations are also entered here. Here the
independent speeds are specied, followed by the dependent speeds, along with the nonholonomic constraints. The dependent coordinate is also provided, with the holonomic constraint. Again, this is only comes into play in the linearization process, but is necessary for
the linearization to correctly work.
>>> KM = KanesMethod(N, q_ind=[q1, q2, q5],
...
q_dependent=[q4], configuration_constraints=conlist_coord,
...
u_ind=[u2, u3, u5],
...
u_dependent=[u1, u4, u6], velocity_constraints=conlist_speed,
...
kd_eqs=kd)
>>> print(Before Forming Generalized Active and Inertia Forces, Fr and Fr*)
Before Forming Generalized Active and Inertia Forces, Fr and Fr*
>>> (fr, frstar) = KM.kanes_equations(FL, BL)
>>> print(Base Equations of Motion Computed)
Base Equations of Motion Computed
This is the start of entering in the numerical values from the benchmark paper to validate the
eigenvalues of the linearized equations from this model to the reference eigenvalues. Look
at the aforementioned paper for more information. Some of these are intermediate values,
used to transform values from the paper into the coordinate systems used in this model.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
...
>>>
...
>>>
PaperRadRear
PaperRadFront
HTA
TrailPaper
rake
PaperWb
PaperFrameCgX
PaperFrameCgZ
PaperForkCgX
PaperForkCgZ
FrameLength
=
=
=
=
=
=
=
=
=
=
=
FrameCGNorm
FrameCGPar
0.3
0.35
evalf.N(pi/2-pi/10)
0.08
evalf.N(-(TrailPaper*sin(HTA)-(PaperRadFront*cos(HTA))))
1.02
0.3
0.9
0.9
0.7
evalf.N(PaperWb*sin(HTA) - (rake - \
(PaperRadFront - PaperRadRear)*cos(HTA)))
evalf.N((PaperFrameCgZ - PaperRadRear - \
(PaperFrameCgX/sin(HTA))*cos(HTA))*sin(HTA))
evalf.N((PaperFrameCgX / sin(HTA) + \
1721
...
...
>>>
>>>
>>>
>>>
...
>>>
...
>>>
...
tempa
tempb
tempc
PaperForkL
=
=
=
=
ForkCGNorm
ForkCGPar
(PaperFrameCgZ - PaperRadRear - \
PaperFrameCgX / sin(HTA) * cos(HTA)) * cos(HTA)))
evalf.N((PaperForkCgZ - PaperRadFront))
evalf.N((PaperWb-PaperForkCgX))
evalf.N(sqrt(tempa**2 + tempb**2))
evalf.N((PaperWb*cos(HTA) - \
(PaperRadFront - PaperRadRear)*sin(HTA)))
evalf.N(rake + (tempc * sin(pi/2 - \
HTA - acos(tempa/tempc))))
evalf.N(tempc * cos((pi/2 - HTA) - \
acos(tempa/tempc)) - PaperForkL)
Here is the nal assembly of the numerical values. The symbol v is the forward speed of the
bicycle (a concept which only makes sense in the upright, static equilibrium case?). These
are in a dictionary which will later be substituted in. Again the sign on the product of inertia
values is ipped here, due to dierent orientations of coordinate systems.
>>>
>>>
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
>>>
>>>
v = Symbol(v)
val_dict = {
WFrad: PaperRadFront,
WRrad: PaperRadRear,
htangle: HTA,
forkoffset: rake,
forklength: PaperForkL,
framelength: FrameLength,
forkcg1: ForkCGPar,
forkcg3: ForkCGNorm,
framecg1: FrameCGNorm,
framecg3: FrameCGPar,
Iwr11: 0.0603,
Iwr22: 0.12,
Iwf11: 0.1405,
Iwf22: 0.28,
Ifork11: 0.05892,
Ifork22: 0.06,
Ifork33: 0.00708,
Ifork31: 0.00756,
Iframe11: 9.2,
Iframe22: 11,
Iframe33: 2.8,
Iframe31: -2.4,
mfork: 4,
mframe: 85,
mwf: 3,
mwr: 2,
g: 9.81,
q1: 0,
q2: 0,
q4: 0,
q5: 0,
u1: 0,
u2: 0,
u3: v/PaperRadRear,
u4: 0,
u5: 0,
u6: v/PaperRadFront}
kdd = KM.kindiffdict()
print(Before Linearization of the \Forcing\ Term)
1722
Linearizes the forcing vector; the equations are set up as MM udot = forcing, where MM is the
mass matrix, udot is the vector representing the time derivatives of the generalized speeds,
and forcing is a vector which contains both external forcing terms and internal forcing terms,
such as centripetal or Coriolis forces. This actually returns a matrix with as many rows as total
coordinates and speeds, but only as many columns as independent coordinates and speeds.
(Note that below this is commented out, as it takes a few minutes to run, which is not good
when performing the doctests)
>>> # forcing_lin = KM.linearize()[0].subs(sub_dict)
As mentioned above, the size of the linearized forcing terms is expanded to include both qs
and us, so the mass matrix must have this done as well. This will likely be changed to be part
of the linearized process, for future reference.
>>> MM_full = (KM._k_kqdot).row_join(zeros(4, 6)).col_join(
...
(zeros(6, 4)).row_join(KM.mass_matrix))
>>> print(Before Substitution of Numerical Values)
Before Substitution of Numerical Values
I think this is pretty self explanatory. It takes a really long time though. Ive experimented with
using evalf with substitution, this failed due to maximum recursion depth being exceeded; I
also tried lambdifying this, and it is also not successful. (again commented out due to speed)
>>> # MM_full = MM_full.subs(val_dict)
>>> # forcing_lin = forcing_lin.subs(val_dict)
>>> # print(Before .evalf() call)
>>> # MM_full = MM_full.evalf()
>>> # forcing_lin = forcing_lin.evalf()
Finally, we construct an A matrix for the form xdot = A x (x being the state vector, although
in this case, the sizes are a little o). The following line extracts only the minimum entries
required for eigenvalue analysis, which correspond to rows and columns for lean, steer, lean
rate, and steer rate. (this is all commented out due to being dependent on the above code,
which is also commented out):
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
#
#
#
#
#
#
#
#
#
#
#
#
#
Upon running the above code yourself, enabling the commented out lines, compare the computed eigenvalues to those is the referenced paper. This concludes the bicycle example.
Nonminimal Coordinates Pendulum In this example we demonstrate the use of the functionality provided in mechanics for deriving the equations of motion (EOM) for a pendulum
5.36. Physics Module
1723
with a nonminimal set of coordinates. As the pendulum is a one degree of freedom system, it
can be described using one coordinate and one speed (the pendulum angle, and the angular
velocity respectively). Choosing instead to describe the system using the x and y coordinates
of the mass results in a need for constraints. The system is shown below:
Ay
Ny
Ax
Nx
q1
L
q2
u1
u2
m
The system will be modeled using both Kanes and Lagranges methods, and the resulting
EOM linearized. While this is a simple problem, it should illustrate the use of the linearization
methods in the presence of constraints.
Kanes Method First we need to create the dynamicsymbols needed to describe the system
as shown in the above diagram. In this case, the generalized coordinates q1 and q2 represent
the mass x and y coordinates in the inertial N frame. Likewise, the generalized speeds u1 and
u2 represent the velocities in these directions. We also create some symbols to represent the
length and mass of the pendulum, as well as gravity and time.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1724
>>> L, m, g, t = symbols(L, m, g, t)
Next, we create a world coordinate frame N , and its origin point N . The velocity of the origin
is set to 0. A second coordinate frame A is oriented such that its x-axis is along the pendulum
(as shown in the diagram above).
>>>
>>>
>>>
>>>
Locating the pendulum mass is then as easy as specifying its location with in terms of its x
and y coordinates in the world frame. A Particle object is then created to represent the
mass at this location.
>>> # Locate the pendulum mass
>>> P = pN.locatenew(P1, q1*N.x + q2*N.y)
>>> pP = Particle(pP, P, m)
The kinematic dierential equations (KDEs) relate the derivatives of the generalized coordinates to the generalized speeds. In this case the speeds are the derivatives, so these are
simple. A dictionary is also created to map q to u:
>>> # Calculate the kinematic differential equations
>>> kde = Matrix([q1d - u1,
...
q2d - u2])
>>> dq_dict = solve(kde, [q1d, q2d])
The velocity of the mass is then the time derivative of the position from the origin N :
>>> # Set velocity of point P
>>> P.set_vel(N, P.pos_from(pN).dt(N).subs(dq_dict))
As this system has more coordinates than degrees of freedom, constraints are needed. The
conguration constraints relate the coordinates to each other. In this case the constraint is
that the distance from the origin to the mass is always the length L (the pendulum doesnt
get longer). Likewise, the velocity constraint is that the mass velocity in the A.x direction is
always 0 (no radial velocity).
>>> f_c = Matrix([P.pos_from(pN).magnitude() - L])
>>> f_v = Matrix([P.vel(N).express(A).dot(A.x)])
>>> f_v.simplify()
With the problem setup, the equations of motion can be generated using the KanesMethod
class. As there are constraints, dependent and independent coordinates need to be provided
to the class. In this case well use q2 and u2 as the independent coordinates and speeds:
>>> # Derive the equations of motion using the KanesMethod class.
>>> KM = KanesMethod(N, q_ind=[q2], u_ind=[u2], q_dependent=[q1],
...
u_dependent=[u1], configuration_constraints=f_c,
1725
...
velocity_constraints=f_v, kd_eqs=kde)
>>> (fr, frstar) = KM.kanes_equations([(P, R)], [pP])
For linearization, operating points can be specied on the call, or be substituted in afterwards. In this case well provide them in the call, supplied in a list. The A and B=True kwarg
indicates to solve invert the M matrix and solve for just the explicit linearized A and B matrices. The simplify=True kwarg indicates to simplify inside the linearize call, and return
the presimplied matrices. The cost of doing this is small for simple systems, but for larger
systems this can be a costly operation, and should be avoided.
>>> # Set the operating point to be straight down, and non-moving
>>> q_op = {q1: L, q2: 0}
>>> u_op = {u1: 0, u2: 0}
>>> ud_op = {u1d: 0, u2d: 0}
>>> # Perform the linearization
>>> A, B, inp_vec = KM.linearize(op_point=[q_op, u_op, ud_op], A_and_B=True,
...
new_method=True, simplify=True)
>>> A
Matrix([
[
0, 1],
[-g/L, 0]])
>>> B
Matrix(0, 0, [])
The resulting A matrix has dimensions 2 x 2, while the number of total states is len(q) +
len(u) = 2 + 2 = 4. This is because for constrained systems the resulting A and B form has
a partitioned state vector only containing the independent coordinates and speeds. Written
out mathematically, the system linearized about this point would be written as:
[ ] [
][ ]
0 1 q2
q2
= g
u2
0 u2
L
Lagranges Method The derivation using Lagranges method is very similar to the approach using Kanes method described above. As before, we rst create the dynamicsymbols
needed to describe the system. In this case, the generalized coordinates q1 and q2 represent
the mass x and y coordinates in the inertial N frame. This results in the time derivatives q1 and
q2 representing the velocities in these directions. We also create some symbols to represent
the length and mass of the pendulum, as well as gravity and time.
>>>
>>>
>>>
>>>
>>>
Next, we create a world coordinate frame N , and its origin point N . The velocity of the origin
is set to 0. A second coordinate frame A is oriented such that its x-axis is along the pendulum
(as shown in the diagram above).
>>>
>>>
>>>
>>>
>>>
1726
Locating the pendulum mass is then as easy as specifying its location with in terms of its x
and y coordinates in the world frame. A Particle object is then created to represent the
mass at this location.
>>>
>>>
>>>
>>>
As this system has more coordinates than degrees of freedom, constraints are needed. In this
case only a single holonomic constraints is needed: the distance from the origin to the mass
is always the length L (the pendulum doesnt get longer).
>>> # Holonomic Constraint Equations
>>> f_c = Matrix([q1**2 + q2**2 - L**2])
With the problem setup, the Lagrangian can be calculated, and the equations of motion
formed. Note that the call to LagrangesMethod includes the Lagrangian, the generalized
coordinates, the constraints (specied by hol coneqs or nonhol coneqs), the list of (body,
force) pairs, and the inertial frame. In contrast to the KanesMethod initializer, independent
and dependent coordinates are not partitioned inside the LagrangesMethod object. Such a
partition is supplied later.
>>>
>>>
>>>
>>>
Next, we compose the operating point dictionary, set in the hanging at rest position:
>>> # Compose operating point
>>> op_point = {q1: L, q2: 0, q1d: 0, q2d: 0, q1d.diff(t): 0, q2d.diff(t): 0}
As there are constraints in the formulation, there will be corresponding Lagrange Multipliers.
These may appear inside the linearized form as well, and thus should also be included inside
the operating point dictionary. Fortunately, the LagrangesMethod class provides an easy way
of solving for the multipliers at a given operating point using the solve multipliers method.
>>> # Solve for multiplier operating point
>>> lam_op = LM.solve_multipliers(op_point=op_point)
With this solution, linearization can be completed. Note that in contrast to the KanesMethod
approach, the LagrangesMethod.linearize method also requires the partitioning of the generalized coordinates and their time derivatives into independent and dependent vectors. This
is the same as what was passed into the KanesMethod constructor above:
>>> op_point.update(lam_op)
>>> # Perform the Linearization
>>> A, B, inp_vec = LM.linearize([q2], [q2d], [q1], [q1d],
...
op_point=op_point, A_and_B=True)
1727
>>> A
Matrix([
[
0, 1],
[-g/L, 0]])
>>> B
Matrix(0, 0, [])
The resulting A matrix has dimensions 2 x 2, while the number of total states is 2*len(q)
= 4. This is because for constrained systems the resulting A and B form has a partitioned
state vector only containing the independent coordinates and their derivatives. Written out
mathematically, the system linearized about this point would be written as:
][ ]
[ ] [
0 1 q2
q2
= g
q2
0 q2
L
Potential Issues/Advanced Topics/Future Features in Physics/Mechanics This document will describe some of the more advanced functionality that this module oers but which
is not part of the ocial interface. Here, some of the features that will be implemented in
the future will also be covered, along with unanswered questions about proper functionality.
Also, common problems will be discussed, along with some solutions.
Common Issues Here issues with numerically integrating code, choice of dynamicsymbols
for coordinate and speed representation, printing, dierentiating, and substitution will occur.
Numerically Integrating Code See Future Features: Code Output
Dierentiating Dierentiation of very large expressions can take some time in SymPy; it
is possible for large expressions to take minutes for the derivative to be evaluated. This will
most commonly come up in linearization.
Choice of Coordinates and Speeds The Kane object is set up with the assumption that
the generalized speeds are not the same symbol as the time derivatives of the generalized
coordinates. This isnt to say that they cant be the same, just that they have to have a dierent
symbol. If you did this:
>> KM.coords([q1, q2, q3])
>> KM.speeds([q1d, q2d, q3d])
Your code would not work. Currently, kinematic dierential equations are required to be
provided. It is at this point that we hope the user will discover they should not attempt the
behavior shown in the code above.
This behavior might not be true for other methods of forming the equations of motion though.
Printing The default printing options are to use sorting for Vector and Dyad measure numbers, and have unsorted output from the mprint, mpprint, and mlatex functions. If you are
printing something large, please use one of those functions, as the sorting can increase printing time from seconds to minutes.
1728
Dierentiating Dierentiation of very large expressions can take some time in SymPy; it
is possible for large expressions to take minutes for the derivative to be evaluated. This will
most commonly come up in linearization.
Substitution There are two common issues with substitution in mechanics:
When subbing in expressions for dynamicsymbols, sympys normal subs will substitute
in for derivatives of the dynamic symbol as well:
>>> from sympy.physics.mechanics import dynamicsymbols
>>> x = dynamicsymbols(x)
>>> expr = x.diff() + x
>>> sub_dict = {x: 1}
>>> expr.subs(sub_dict)
Derivative(1, t) + 1
In this case, x was replaced with 1 inside the Derivative as well, which is undesired.
Substitution into large expressions can be slow.
If your substitution is simple (direct replacement of expressions with other expressions, such
as when evaluating at an operating point) it is recommended to use the provided msubs function, as it is signicantly faster, and handles the derivative issue appropriately:
>>> from sympy.physics.mechanics import msubs
>>> msubs(expr, sub_dict)
Derivative(x(t), t) + 1
Linearization Currently, the linearization methods dont support cases where there are
non-coordinate, non-speed dynamic symbols outside of the dynamic equations. It also does
not support cases where time derivatives of these types of dynamic symbols show up. This
means if you have kinematic dierential equations which have a non-coordinate, non-speed
dynamic symbol, it will not work. It also means if you have dened a system parameter (say
a length or distance or mass) as a dynamic symbol, its time derivative is likely to show up in
the dynamic equations, and this will prevent linearization.
Acceleration of Points At a minimum, points need to have their velocities dened, as the
acceleration can be calculated by taking the time derivative of the velocity in the same frame.
If the 1 point or 2 point theorems were used to compute the velocity, the time derivative of the
velocity expression will most likely be more complex than if you were to use the acceleration
level 1 point and 2 point theorems. Using the acceleration level methods can result in shorted
expressions at this point, which will result in shorter expressions later (such as when forming
Kanes equations).
Advanced Interfaces
Advanced Functionality Remember that the Kane object supports bodies which have timevarying masses and inertias, although this functionality isnt completely compatible with the
linearization method.
Operators were discussed earlier as a potential way to do mathematical operations on Vector
and Dyad objects. The majority of the code in this module is actually coded with them, as it
can (subjectively) result in cleaner, shorter, more readable code. If using this interface in
1729
your code, remember to take care and use parentheses; the default order of operations in
Python results in addition occurring before some of the vector products, so use parentheses
liberally.
Future Features This will cover the planned features to be added to this submodule.
Code Output A function for generating code output for numerical integration is the highest
priority feature to implement next. There are a number of considerations here.
Code output for C (using the GSL libraries), Fortran 90 (using LSODA), MATLAB, and SciPy
is the goal. Things to be considered include: use of cse on large expressions for MATLAB and
SciPy, which are interpretive. It is currently unclear whether compiled languages will benet
from common subexpression elimination, especially considering that it is a common part of
compiler optimization, and there can be a signicant time penalty when calling cse.
Care needs to be taken when constructing the strings for these expressions, as well as handling of input parameters, and other dynamic symbols. How to deal with output quantities
when integrating also needs to be decided, with the potential for multiple options being considered.
References for Physics/Mechanics
Mechanics API
1730
get mass()
Mass of the particle.
get point()
Point of the particle.
kinetic energy(frame)
Kinetic energy of the particle
The kinetic energy, T, of a particle, P, is given by
T = 1/2 m v2
where m is the mass of particle P, and v is the velocity of the particle in the supplied
ReferenceFrame.
Parameters frame : ReferenceFrame
The Particles velocity is typically dened with respect to an inertial
frame but any relevant frame in which the velocity is known can be
supplied.
1731
Examples
>>> from sympy.physics.mechanics import Particle, Point, ReferenceFrame
>>> from sympy import symbols
>>> m, v, r = symbols(m v r)
>>> N = ReferenceFrame(N)
>>> O = Point(O)
>>> P = Particle(P, O, m)
>>> P.point.set_vel(N, v * N.y)
>>> P.kinetic_energy(N)
m*v**2/2
linear momentum(frame)
Linear momentum of the particle.
The linear momentum L, of a particle P, with respect to frame N is given by
L=m*v
where m is the mass of the particle, and v is the velocity of the particle in the frame
N.
Parameters frame : ReferenceFrame
The frame in which linear momentum is desired.
Examples
>>> from sympy.physics.mechanics import Particle, Point, ReferenceFrame
>>> from sympy.physics.mechanics import dynamicsymbols
>>> m, v = dynamicsymbols(m v)
>>> N = ReferenceFrame(N)
>>> P = Point(P)
>>> A = Particle(A, P, m)
>>> P.set_vel(N, v * N.x)
>>> A.linear_momentum(N)
m*v*N.x
mass
Mass of the particle.
point
Point of the particle.
potential energy
The potential energy of the Particle.
Examples
>>> from sympy.physics.mechanics import Particle, Point
>>> from sympy import symbols
>>> m, g, h = symbols(m g h)
>>> O = Point(O)
>>> P = Particle(P, O, m)
>>> P.set_potential_energy(m * g * h)
>>> P.potential_energy
g*h*m
1732
RigidBody
class sympy.physics.mechanics.rigidbody.RigidBody(name, masscenter,
mass, inertia)
An idealized rigid body.
frame,
This is essentially a container which holds the various components which describe a rigid
body: a name, mass, center of mass, reference frame, and inertia.
All of these need to be supplied on creation, but can be changed afterwards.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
Attributes
name
masscenter
frame
mass
inertia
string
Point
ReferenceFrame
Sympifyable
(Dyadic,
Point)
1733
central inertia
The bodys central inertia dyadic.
kinetic energy(frame)
Kinetic energy of the rigid body
The kinetic energy, T, of a rigid body, B, is given by
T = 1/2 (I omega2 + m v2)
where I and m are the central inertia dyadic and mass of rigid body B, respectively,
omega is the bodys angular velocity and v is the velocity of the bodys mass center
in the supplied ReferenceFrame.
Parameters frame : ReferenceFrame
The RigidBodys angular velocity and the velocity of its mass center
are typically dened with respect to an inertial frame but any relevant
frame in which the velocities are known can be supplied.
Examples
1734
linear momentum(frame)
Linear momentum of the rigid body.
The linear momentum L, of a rigid body B, with respect to frame N is given by
L = M * v*
where M is the mass of the rigid body and v* is the velocity of the mass center of B
in the frame, N.
Parameters frame : ReferenceFrame
The frame in which linear momentum is desired.
Examples
>>> from sympy.physics.mechanics import Point, ReferenceFrame, outer
>>> from sympy.physics.mechanics import RigidBody, dynamicsymbols
>>> M, v = dynamicsymbols(M v)
>>> N = ReferenceFrame(N)
>>> P = Point(P)
>>> P.set_vel(N, v * N.x)
>>> I = outer (N.x, N.x)
>>> Inertia_tuple = (I, P)
>>> B = RigidBody(B, P, N, M, Inertia_tuple)
>>> B.linear_momentum(N)
M*v*N.x
potential energy
The potential energy of the RigidBody.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1735
>>> B.potential_energy
M*g*h
inertia
sympy.physics.mechanics.functions.inertia(frame, ixx, iyy, izz, ixy=0, iyz=0,
izx=0)
Simple way to create inertia Dyadic object.
If you dont know what a Dyadic is, just treat this like the inertia tensor. Then, do the
easy thing and dene it in a body-xed frame.
Parameters frame : ReferenceFrame
The frame the inertia is dened in
ixx : Sympifyable
the xx element in the inertia dyadic
iyy : Sympifyable
the yy element in the inertia dyadic
izz : Sympifyable
the zz element in the inertia dyadic
ixy : Sympifyable
the xy element in the inertia dyadic
iyz : Sympifyable
the yz element in the inertia dyadic
izx : Sympifyable
the zx element in the inertia dyadic
1736
Examples
>>> from sympy.physics.mechanics import ReferenceFrame, inertia
>>> N = ReferenceFrame(N)
>>> inertia(N, 1, 2, 3)
(N.x|N.x) + 2*(N.y|N.y) + 3*(N.z|N.z)
linear momentum
sympy.physics.mechanics.functions.linear momentum(frame, *body)
Linear momentum of the system.
This function returns the linear momentum of a system of Particles and/or RigidBodys.
The linear momentum of a system is equal to the vector sum of the linear momentum of
its constituents. Consider a system, S, comprised of a rigid body, A, and a particle, P. The
linear momentum of the system, L, is equal to the vector sum of the linear momentum
of the particle, L1, and the linear momentum of the rigid body, L2, i.e.
L = L1 + L2
Parameters frame : ReferenceFrame
The frame in which linear momentum is desired.
body1, body2, body3... : Particle and/or RigidBody
The body (or bodies) whose linear momentum is required.
1737
Examples
>>> from sympy.physics.mechanics import Point, Particle, ReferenceFrame
>>> from sympy.physics.mechanics import RigidBody, outer, linear_momentum
>>> N = ReferenceFrame(N)
>>> P = Point(P)
>>> P.set_vel(N, 10 * N.x)
>>> Pa = Particle(Pa, P, 1)
>>> Ac = Point(Ac)
>>> Ac.set_vel(N, 25 * N.y)
>>> I = outer(N.x, N.x)
>>> A = RigidBody(A, Ac, N, 20, (I, Ac))
>>> linear_momentum(N, A, Pa)
10*N.x + 500*N.y
angular momentum
sympy.physics.mechanics.functions.angular momentum(point, frame, *body)
Angular momentum of a system
This function returns the angular momentum of a system of Particles and/or RigidBodys.
The angular momentum of such a system is equal to the vector sum of the angular momentum of its constituents. Consider a system, S, comprised of a rigid body, A, and a
particle, P. The angular momentum of the system, H, is equal to the vector sum of the
angular momentum of the particle, H1, and the angular momentum of the rigid body,
H2, i.e.
H = H1 + H2
Parameters point : Point
The point about which angular momentum of the system is desired.
frame : ReferenceFrame
The frame in which angular momentum is desired.
body1, body2, body3... : Particle and/or RigidBody
The body (or bodies) whose angular momentum is required.
Examples
>>> from sympy.physics.mechanics import Point, Particle, ReferenceFrame
>>> from sympy.physics.mechanics import RigidBody, outer, angular_momentum
>>> N = ReferenceFrame(N)
>>> O = Point(O)
>>> O.set_vel(N, 0 * N.x)
>>> P = O.locatenew(P, 1 * N.x)
>>> P.set_vel(N, 10 * N.x)
>>> Pa = Particle(Pa, P, 1)
>>> Ac = O.locatenew(Ac, 2 * N.y)
>>> Ac.set_vel(N, 5 * N.y)
>>> a = ReferenceFrame(a)
>>> a.set_ang_vel(N, 10 * N.z)
>>> I = outer(N.z, N.z)
>>> A = RigidBody(A, Ac, a, 20, (I, Ac))
>>> angular_momentum(O, N, Pa, A)
10*N.z
1738
kinetic energy
sympy.physics.mechanics.functions.kinetic energy(frame, *body)
Kinetic energy of a multibody system.
This function returns the kinetic energy of a system of Particles and/or RigidBodys.
The kinetic energy of such a system is equal to the sum of the kinetic energies of its
constituents. Consider a system, S, comprising a rigid body, A, and a particle, P. The
kinetic energy of the system, T, is equal to the vector sum of the kinetic energy of the
particle, T1, and the kinetic energy of the rigid body, T2, i.e.
T = T1 + T2
Kinetic energy is a scalar.
Parameters frame : ReferenceFrame
The frame in which the velocity or angular velocity of the body is
dened.
body1, body2, body3... : Particle and/or RigidBody
The body (or bodies) whose kinetic energy is required.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
350
potential energy
sympy.physics.mechanics.functions.potential energy(*body)
Potential energy of a multibody system.
This function returns the potential energy of a system of Particles and/or RigidBodys.
The potential energy of such a system is equal to the sum of the potential energy of its
constituents. Consider a system, S, comprising a rigid body, A, and a particle, P. The
potential energy of the system, V, is equal to the vector sum of the potential energy of
the particle, V1, and the potential energy of the rigid body, V2, i.e.
V = V1 + V2
Potential energy is a scalar.
Parameters body1, body2, body3... : Particle and/or RigidBody
The body (or bodies) whose potential energy is required.
1739
Examples
>>> from sympy.physics.mechanics import Point, Particle, ReferenceFrame
>>> from sympy.physics.mechanics import RigidBody, outer, potential_energy
>>> from sympy import symbols
>>> M, m, g, h = symbols(M m g h)
>>> N = ReferenceFrame(N)
>>> O = Point(O)
>>> O.set_vel(N, 0 * N.x)
>>> P = O.locatenew(P, 1 * N.x)
>>> Pa = Particle(Pa, P, m)
>>> Ac = O.locatenew(Ac, 2 * N.y)
>>> a = ReferenceFrame(a)
>>> I = outer(N.z, N.z)
>>> A = RigidBody(A, Ac, a, M, (I, Ac))
>>> Pa.set_potential_energy(m * g * h)
>>> A.set_potential_energy(M * g * h)
>>> potential_energy(Pa, A)
M*g*h + g*h*m
Lagrangian
sympy.physics.mechanics.functions.Lagrangian(frame, *body)
Lagrangian of a multibody system.
This function returns the Lagrangian of a system of Particles and/or RigidBodys. The
Lagrangian of such a system is equal to the dierence between the kinetic energies and
potential energies of its constituents. If T and V are the kinetic and potential energies
of a system then its Lagrangian, L, is dened as
L=T-V
The Lagrangian is a scalar.
Parameters frame : ReferenceFrame
The frame in which the velocity or angular velocity of the body is
dened to determine the kinetic energy.
body1, body2, body3... : Particle and/or RigidBody
The body (or bodies) whose Lagrangian is required.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1740
Next we need to arrange/store information in the way that KanesMethod requires. The
kinematic dierential equations need to be stored in a dict. A list of forces/torques must
be constructed, where each entry in the list is a (Point, Vector) or (ReferenceFrame,
Vector) tuple, where the Vectors represent the Force or Torque. Next a particle needs
to be created, and it needs to have a point and mass assigned to it. Finally, a list of all
bodies and particles needs to be created.
>>> kd = [qd - u]
>>> FL = [(P, (-k * q - c * u) * N.x)]
1741
>>> pa = Particle(pa, P, m)
>>> BL = [pa]
Finally we can generate the equations of motion. First we create the KanesMethod object
and supply an inertial frame, coordinates, generalized speeds, and the kinematic dierential equations. Additional quantities such as conguration and motion constraints,
dependent coordinates and speeds, and auxiliary speeds are also supplied here (see the
online documentation). Next we form FR* and FR to complete: Fr + Fr* = 0. We have
the equations of motion at this point. It makes sense to rearrnge them though, so we
calculate the mass matrix and the forcing terms, for E.o.M. in the form: [MM] udot =
forcing, where MM is the mass matrix, udot is a vector of the time derivatives of the
generalized speeds, and forcing is a vector representing forcing terms.
>>> KM = KanesMethod(N, q_ind=[q], u_ind=[u], kd_eqs=kd)
>>> (fr, frstar) = KM.kanes_equations(FL, BL)
>>> MM = KM.mass_matrix
>>> forcing = KM.forcing
>>> rhs = MM.inv() * forcing
>>> rhs
Matrix([[(-c*u(t) - k*q(t))/m]])
>>> KM.linearize(A_and_B=True, new_method=True)[0]
Matrix([
[
0,
1],
[-k/m, -c/m]])
Please look at the documentation pages for more information on how to perform linearization and how to deal with dependent coordinates & speeds, and how do deal with
bringing non-contributing forces into evidence.
Attributes
q, u
Matrix
bodylist
iterable
forcelist
iterable
auxiliary
Matrix
mass matrix Matrix
forcing
Matrix
mass matrix full
Matrix
forcMaing full
trix
auxiliary eqs
A matrix containing the auxiliary equations.
forcing
The forcing vector of the system.
forcing full
The forcing vector of the system, augmented by the kinematic dierential equations.
1742
1743
We need to then prepare the information as required by LagrangesMethod to generate equations of motion. First we create the Particle, which has a point attached to it.
Following this the lagrangian is created from the kinetic and potential energies. Then,
an iterable of nonconservative forces/torques must be constructed, where each item is
a (Point, Vector) or (ReferenceFrame, Vector) tuple, with the Vectors representing the
nonconservative forces or torques.
>>>
>>>
>>>
>>>
1744
Pa = Particle(Pa, P, m)
Pa.set_potential_energy(k * q**2 / 2.0)
L = Lagrangian(N, Pa)
fl = [(P, -b * qd * N.x)]
Finally we can generate the equations of motion. First we create the LagrangesMethod
object. To do this one must supply the Lagrangian, and the generalized coordinates.
The constraint equations, the forcelist, and the inertial frame may also be provided,
if relevant. Next we generate Lagranges equations of motion, such that: Lagranges
equations of motion = 0. We have the equations of motion at this point.
>>> l = LagrangesMethod(L, [q], forcelist = fl, frame = N)
>>> print(l.form_lagranges_equations())
Matrix([[b*Derivative(q(t), t) + 1.0*k*q(t) + m*Derivative(q(t), t, t)]])
We can also solve for the states using the rhs method.
>>> print(l.rhs())
Matrix([[Derivative(q(t), t)], [(-b*Derivative(q(t), t) - 1.0*k*q(t))/m]])
q, u
Matrix
forcelist
iterable
mass matrix Matrix
forcing
Matrix
mass matrix full
Matrix
forcMaing full
trix
forcing
Returns the forcing vector from lagranges equations method.
forcing full
Augments qdots to the forcing vector above.
form lagranges equations()
Method to form Lagranges equations of motion.
Returns a vector of equations of motion using Lagranges equations of the second
kind.
linearize(q ind=None, qd ind=None, q dep=None, qd dep=None, **kwargs)
Linearize the equations of motion about a symbolic operating point.
If kwarg A and B is False (default), returns M, A, B, r for the linearized form, M*[q,
u]T = A*[q ind, u ind]T + B*r.
If kwarg A and B is True, returns A, B, r for the linearized form dx = A*x + B*r, where
x = [q ind, u ind]T. Note that this is computationally intensive if there are many
symbolic parameters. For this reason, it may be more desirable to use the default
A and B=False, returning M, A, and B. Values may then be substituted in to these
matrices, and the state space form found as A = P.T*M.inv()*A, B = P.T*M.inv()*B,
where P = Linearizer.perm mat.
In both cases, r is found as all dynamicsymbols in the equations of motion that are
not part of q, u, q, or u. They are sorted in canonical form.
5.36. Physics Module
1745
The operating points may be also entered using the op point kwarg. This takes a
dictionary of {symbol: value}, or a an iterable of such dictionaries. The values may
be numberic or symbolic. The more values you can specify beforehand, the faster
this computation will run.
For more documentation, please see the Linearizer class.
mass matrix
Returns the mass matrix, which is augmented by the Lagrange multipliers, if necessary.
If the system is described by n generalized coordinates and there are no constraint
equations then an n X n matrix is returned.
If there are n generalized coordinates and m constraint equations have been supplied during initialization then an n X (n+m) matrix is returned. The (n + m - 1)th
and (n + m)th columns contain the coecients of the Lagrange multipliers.
mass matrix full
Augments the coecients of qdots to the mass matrix.
rhs(inv method=None, **kwargs)
Returns equations that can be solved numerically
Parameters inv method : str
The specic sympy inverse matrix calculation method to use. For a
list of valid methods, see inv()
solve multipliers(op point=None, sol type=dict)
Solves for the values of the lagrange multipliers symbolically at the specied operating point
Parameters op point : dict or iterable of dicts, optional
Point at which to solve at. The operating point is specied as a dictionary or iterable of dictionaries of {symbol: value}. The value may
be numeric or symbolic itself.
sol type : str, optional
Solution return type. Valid options are: - dict: A dict of {symbol :
value} (default) - Matrix: An ordered column matrix of the solution
to linearizer(q ind=None, qd ind=None, q dep=None, qd dep=None)
Returns an instance of the Linearizer class, initiated from the data in the LagrangesMethod class. This may be more desirable than using the linearize class method,
as the Linearizer object will allow more ecient recalculation (i.e. about varying
operating points).
Parameters q ind, qd ind : array like, optional
The independent generalized coordinates and speeds.
q dep, qd dep : array like, optional
The dependent generalized coordinates and speeds.
Linearization (Docstrings)
Linearizer
1746
class sympy.physics.mechanics.linearize.Linearizer(f 0, f 1, f 2, f 3, f 4, f c,
f v, f a, q, u, q i=None,
q d=None,
u i=None,
u d=None,
r=None,
lams=None)
This object holds the general model form for a dynamic system. This model is used for
computing the linearized form of the system, while properly dealing with constraints
leading to dependent coordinates and speeds.
Attributes
f 0, f 1, f 2, f 3, f 4,
f c, f v, f a
q, u, r
q i, u i
q d, u d
perm mat
Matrix
Matrix
Matrix
Matrix
Matrix
Note that the process of solving with A and B=True is computationally intensive if
there are many symbolic parameters. For this reason, it may be more desirable to
use the default A and B=False, returning M, A, and B. More values may then be
substituted in to these matrices later on. The state space form can then be found as
A = P.T*M.LUsolve(A), B = P.T*M.LUsolve(B), where P = Linearizer.perm mat.
Expression Manipulation (Docstrings)
1747
msubs
sympy.physics.mechanics.msubs(expr, *sub dicts, **kwargs)
A custom subs for use on expressions derived in physics.mechanics.
Traverses the expression tree once, performing the subs found in sub dicts. Terms inside
Derivative expressions are ignored:
>>> from sympy.physics.mechanics import dynamicsymbols, msubs
>>> x = dynamicsymbols(x)
>>> msubs(x.diff() + x, {x: 1})
Derivative(x(t), t) + 1
x, y, z = dynamicsymbols(x, y, z)
sub1 = {x: 1, y: 2}
sub2 = {z: 3, x.diff(): 4}
msubs(x.diff() + x + y + z, sub1, sub2)
If smart=True (default False), also checks for conditions that may result in nan, but if
simplied would yield a valid expression. For example:
>>> from sympy import sin, tan
>>> (sin(x)/tan(x)).subs(x, 0)
nan
>>> msubs(sin(x)/tan(x), {x: 0}, smart=True)
1
It does this by rst replacing all tan with sin/cos. Then each node is traversed. If
the node is a fraction, subs is rst evaluated on the denominator. If this results in 0,
simplication of the entire fraction is attempted. Using this selective simplication, only
subexpressions that result in 1/0 are targeted, resulting in faster performance.
nd dynamicsymbols
sympy.physics.mechanics.find dynamicsymbols(expression, exclude=None)
Find all dynamicsymbols in expression.
>>> from sympy.physics.mechanics import dynamicsymbols, find_dynamicsymbols
>>> x, y = dynamicsymbols(x, y)
>>> expr = x + x.diff()*y
>>> find_dynamicsymbols(expr)
set([x(t), y(t), Derivative(x(t), t)])
If the optional exclude kwarg is used, only dynamicsymbols not in the iterable exclude
are returned.
>>> find_dynamicsymbols(expr, [x, y])
set([Derivative(x(t), t)])
Printing (Docstrings)
mechanics printing This
time derivative printing.
1748
function
is
the
same
as
physics.vectors
mpprint
Abstract
Contains Docstrings of Physics-Quantum module
Quantum Functions
1749
>>> ac = AntiCommutator(A,B); ac
{A,B}
>>> ac.doit()
A*B + B*A
Adjoint operations applied to the anticommutator are properly applied to the arguments:
>>> Dagger(AntiCommutator(A,B))
{Dagger(A),Dagger(B)}
doit(**hints)
Evaluate anticommutator
Clebsch-Gordan Coecients Clebsch-Gordon Coecients.
class sympy.physics.quantum.cg.CG
Class for Clebsch-Gordan coecient
Clebsch-Gordan coecients describe the angular momentum coupling between two systems. The coecients give the expansion of a coupled total angular momentum state
and an uncoupled tensor product state. The Clebsch-Gordan coecients are dened as
[R328] (page 1916):
,m1
Cjj21,m
= hj1 , m1 ; j2 , m2 |j3 , m3 i
2 ,j3 ,m3
1750
class sympy.physics.quantum.cg.Wigner3j
Class for the Wigner-3j symbols
Wigner 3j-symbols are coecients determined by the coupling of two angular momenta.
When created, they are expressed as symbolic quantities that, for numerical parameters,
can be evaluated using the .doit() method [R329] (page 1916).
Parameters j1, m1, j2, m2, j3, m3 : Number, Symbol
Terms determining the angular momentum of coupled angular momentum systems.
See Also:
CG (page 1750) Clebsch-Gordan coecients
References
class sympy.physics.quantum.cg.Wigner6j
Class for the Wigner-6j symbols
See Also:
Wigner3j (page 1751) Wigner-3j symbols
class sympy.physics.quantum.cg.Wigner9j
Class for the Wigner-9j symbols
See Also:
Wigner3j (page 1751) Wigner-3j symbols
sympy.physics.quantum.cg.cg simp(e)
Simplify and combine CG coecients
This function uses various symmetry and properties of sums and products of ClebschGordan coecients to simplify statements involving these terms [R330] (page 1916).
1751
See Also:
CG (page 1750) Clebsh-Gordan coecients
References
1752
Adjoint operations applied to the commutator are properly applied to the arguments:
>>> Dagger(Commutator(A, B))
-[Dagger(A),Dagger(B)]
doit(**hints)
Evaluate commutator
Constants Constants (like hbar) related to quantum mechanics.
Dagger
Hermitian conjugation.
class sympy.physics.quantum.dagger.Dagger
General Hermitian conjugate operation.
Take the Hermetian conjugate of an argument [R332] (page 1916). For matrices this
operation is equivalent to transpose and complex conjugate [R333] (page 1916).
Parameters arg : Expr
The sympy expression that we want to take the dagger of.
References
1753
Examples
1754
References
In simple products of kets and bras inner products will be automatically identied and
created:
>>> b*k
<b|k>
But in more complex expressions, there is ambiguity in whether inner or outer products
should be created:
>>> k*b*k*b
|k><b|*|k>*<b|
A user can force the creation of a inner products in a complex expression by using parentheses to group the bra and ket:
>>> k*(b*k)*b
<b|k>*|k>*<b|
Notice how the inner product <b|k> moved to the left of the expression because inner
products are commutative complex numbers.
Tensor Product
class sympy.physics.quantum.tensorproduct.TensorProduct
The tensor product of two or more arguments.
For matrices, this uses matrix tensor product to compute the Kronecker or tensor product matrix. For other objects a symbolic TensorProduct instance is returned. The tensor
product is a non-commutative multiplication that is used primarily with operators and
states in quantum mechanics.
Currently, the tensor product distinguishes between commutative and non- commutative arguments. Commutative arguments are assumed to be scalars and are pulled out
in front of the TensorProduct. Non-commutative arguments remain in the resulting
TensorProduct.
Parameters args : tuple
A sequence of the objects to take the tensor product of.
5.36. Physics Module
1755
Examples
We can take the dagger of a tensor product (note the order does NOT reverse like the
dagger of a normal product):
>>> from sympy.physics.quantum import Dagger
>>> Dagger(tp)
Dagger(A)xDagger(B)
1756
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
This is the core logic of this function, and it works inside, powers, sums, commutators
and anticommutators as well:
>>> tensor_product_simp(e**2)
(A*C)x(B*D)**2
TODO:
Add 3D classes to mappings in operatorset.py
class sympy.physics.quantum.cartesian.XOp
1D cartesian position operator.
class sympy.physics.quantum.cartesian.YOp
Y cartesian coordinate operator (for 2D or 3D systems)
class sympy.physics.quantum.cartesian.ZOp
Z cartesian coordinate operator (for 3D systems)
class sympy.physics.quantum.cartesian.PxOp
1D cartesian momentum operator.
class sympy.physics.quantum.cartesian.XKet
1D cartesian position eigenket.
position
The position of the state.
class sympy.physics.quantum.cartesian.XBra
1D cartesian position eigenbra.
position
The position of the state.
class sympy.physics.quantum.cartesian.PxKet
1D cartesian momentum eigenket.
1757
momentum
The momentum of the state.
class sympy.physics.quantum.cartesian.PxBra
1D cartesian momentum eigenbra.
momentum
The momentum of the state.
class sympy.physics.quantum.cartesian.PositionState3D
Base class for 3D cartesian position eigenstates
position x
The x coordinate of the state
position y
The y coordinate of the state
position z
The z coordinate of the state
class sympy.physics.quantum.cartesian.PositionKet3D
3D cartesian position eigenket
class sympy.physics.quantum.cartesian.PositionBra3D
3D cartesian position eigenbra
Hilbert Space
dimension
Return the Hilbert dimension of the space.
class sympy.physics.quantum.hilbert.ComplexSpace
Finite dimensional Hilbert space of complex vectors.
The elements of this Hilbert space are n-dimensional complex valued vectors with the
usual inner product that takes the complex conjugate of the vector on the right.
A classic example of this type of Hilbert space is spin-1/2, which is ComplexSpace(2).
Generalizing to spin-s, the space is ComplexSpace(2*s+1). Quantum computing with N
qubits is done with the direct product space ComplexSpace(2)**N.
1758
Examples
>>> from sympy import symbols
>>> from sympy.physics.quantum.hilbert import ComplexSpace
>>> c1 = ComplexSpace(2)
>>> c1
C(2)
>>> c1.dimension
2
>>> n = symbols(n)
>>> c2 = ComplexSpace(n)
>>> c2
C(n)
>>> c2.dimension
n
class sympy.physics.quantum.hilbert.L2
The Hilbert space of square integrable functions on an interval.
An L2 object takes in a single sympy Interval argument which represents the interval its
functions (vectors) are dened on.
Examples
>>> from sympy import Interval, oo
>>> from sympy.physics.quantum.hilbert import L2
>>> hs = L2(Interval(0,oo))
>>> hs
L2([0, oo))
>>> hs.dimension
oo
>>> hs.interval
[0, oo)
class sympy.physics.quantum.hilbert.FockSpace
The Hilbert space for second quantization.
Technically, this Hilbert space is a innite direct sum of direct products of single particle
Hilbert spaces [R335] (page 1916). This is a mess, so we have a class to represent it
directly.
References
1759
Operator
TODO:
Fix early 0 in apply operators.
Debug and test apply operators.
Get cse working with classes in this le.
Doctests and documentation of special methods for InnerProduct, Commutator, AntiCommutator, represent, apply operators.
class sympy.physics.quantum.operator.Operator
Base class for non-commuting quantum operators.
An operator maps between quantum states [R337] (page 1916). In quantum mechanics,
observables (including, but not limited to, measured physical values) are represented as
Hermitian operators [R338] (page 1916).
Parameters args : tuple
The list of numbers or parameters that uniquely specify the operator.
For time-dependent operators, this will include the time.
References
1760
class sympy.physics.quantum.operator.HermitianOperator
A Hermitian operator that satises H == Dagger(H).
Parameters args : tuple
The list of numbers or parameters that uniquely specify the operator.
For time-dependent operators, this will include the time.
Examples
>>> from sympy.physics.quantum import Dagger, HermitianOperator
>>> H = HermitianOperator(H)
>>> Dagger(H)
H
class sympy.physics.quantum.operator.UnitaryOperator
A unitary operator that satises U*Dagger(U) == 1.
Parameters args : tuple
The list of numbers or parameters that uniquely specify the operator.
For time-dependent operators, this will include the time.
Examples
>>> from sympy.physics.quantum import Dagger, UnitaryOperator
>>> U = UnitaryOperator(U)
>>> U*Dagger(U)
1
1761
class sympy.physics.quantum.operator.OuterProduct
An unevaluated outer product between a ket and bra.
This constructs an outer product between any subclass of KetBase and BraBase as
|a><b|. An OuterProduct inherits from Operator as they act as operators in quantum
expressions. For reference see [R339] (page 1916).
Parameters ket : KetBase
The ket on the left side of the outer product.
bar : BraBase
The bra on the right side of the outer product.
References
In simple products of kets and bras outer products will be automatically identied and
created:
>>> k*b
|k><b|
But in more complex expressions, outer products are not automatically created:
>>> A = Operator(A)
>>> A*k*b
A*|k>*<b|
A user can force the creation of an outer product in a complex expression by using parentheses to group the ket and bra:
>>> A*(k*b)
A*|k><b|
1762
bra
Return the bra on the right side of the outer product.
ket
Return the ket on the left side of the outer product.
class sympy.physics.quantum.operator.DifferentialOperator
An operator for representing the dierential operator, i.e. d/dx
It is initialized by passing two arguments. The rst is an arbitrary expression that involves a function, such as Derivative(f(x), x). The second is the function (e.g. f(x))
which we are to replace with the Wavefunction that this DifferentialOperator is applied to.
Parameters expr : Expr
The arbitrary expression which the appropriate Wavefunction is to be
substituted into
func : Expr
A function (e.g. f(x)) which is to be replaced with the appropriate
Wavefunction when this DierentialOperator is applied
Examples
You can dene a completely arbitrary expression and specify where the Wavefunction is
to be substituted
>>> from sympy import Derivative, Function, Symbol
>>> from sympy.physics.quantum.operator import DifferentialOperator
>>> from sympy.physics.quantum.state import Wavefunction
>>> from sympy.physics.quantum.qapply import qapply
>>> f = Function(f)
>>> x = Symbol(x)
>>> d = DifferentialOperator(1/x*Derivative(f(x), x), f(x))
>>> w = Wavefunction(x**2, x)
>>> d.function
f(x)
>>> d.variables
(x,)
>>> qapply(d*w)
Wavefunction(2, x)
expr
Returns the arbitary expression which is to have the Wavefunction substituted into
it
Examples
>>> from sympy.physics.quantum.operator import DifferentialOperator
>>> from sympy import Function, Symbol, Derivative
>>> x = Symbol(x)
>>> f = Function(f)
>>> d = DifferentialOperator(Derivative(f(x), x), f(x))
>>> d.expr
Derivative(f(x), x)
>>> y = Symbol(y)
1763
free symbols
Return the free symbols of the expression.
function
Returns the function which is to be replaced with the Wavefunction
Examples
>>> from sympy.physics.quantum.operator import DifferentialOperator
>>> from sympy import Function, Symbol, Derivative
>>> x = Symbol(x)
>>> f = Function(f)
>>> d = DifferentialOperator(Derivative(f(x), x), f(x))
>>> d.function
f(x)
>>> y = Symbol(y)
>>> d = DifferentialOperator(Derivative(f(x, y), x) +
...
Derivative(f(x, y), y), f(x, y))
>>> d.function
f(x, y)
variables
Returns the variables with which the function in the specied arbitrary expression
is evaluated
Examples
>>> from sympy.physics.quantum.operator import DifferentialOperator
>>> from sympy import Symbol, Function, Derivative
>>> x = Symbol(x)
>>> f = Function(f)
>>> d = DifferentialOperator(1/x*Derivative(f(x), x), f(x))
>>> d.variables
(x,)
>>> y = Symbol(y)
>>> d = DifferentialOperator(Derivative(f(x, y), x) +
...
Derivative(f(x, y), y), f(x, y))
>>> d.variables
(x, y)
1764
TODO List: - Update the dictionary with a complete list of state-operator pairs
sympy.physics.quantum.operatorset.operators to state(operators, **options)
Returns the eigenstate of the given operator or set of operators
A global function for mapping operator classes to their associated states. It takes either
an Operator or a set of operators and returns the state associated with these.
This function can handle both instances of a given operator or just the class itself (i.e.
both XOp() and XOp)
There are multiple use cases to consider:
1) A class or set of classes is passed: First, we try to instantiate default instances for these
operators. If this fails, then the class is simply returned. If we succeed in instantiating
default instances, then we try to call state. operators to state on the operator instances.
If this fails, the class is returned. Otherwise, the instance returned by operators to state
is returned.
2) An instance or set of instances is passed: In this case, state. operators to state is
called on the instances passed. If this fails, a state class is returned. If the method
returns an instance, that instance is returned.
In both cases, if the operator class or set does not exist in the state mapping dictionary,
None is returned.
Parameters arg: Operator or set :
The class or instance of the operator or set of operators to be mapped
to a state
Examples
>>> from sympy.physics.quantum.cartesian import XOp, PxOp
>>> from sympy.physics.quantum.operatorset import operators_to_state
>>> from sympy.physics.quantum.operator import Operator
>>> operators_to_state(XOp)
|x>
>>> operators_to_state(XOp())
|x>
>>> operators_to_state(PxOp)
|px>
>>> operators_to_state(PxOp())
|px>
>>> operators_to_state(Operator)
|psi>
>>> operators_to_state(Operator())
|psi>
1765
If the creation of the default instance or if the calling of state to operators fails, then
either an operator class or set of operator classes is returned. Otherwise, the appropriate
operator instances are returned.
2) A state instance is returned: Here, state. state to operators is called for the instance.
If this fails, then a class or set of operator classes is returned. Otherwise, the instances
are returned.
In either case, if the states class does not exist in state mapping, None is returned.
Parameters arg: StateBase class or instance (or subclasses) :
The class or instance of the state to be mapped to an operator or set
of operators
Examples
>>>
>>>
>>>
>>>
X
>>>
X
>>>
Px
>>>
Px
>>>
Px
>>>
X
>>>
O
>>>
O
Qapply
Todo: * Sometimes the nal result needs to be expanded, we should do this by hand.
sympy.physics.quantum.qapply.qapply(e, **options)
Apply operators to states in a quantum expression.
Parameters e : Expr
The expression containing operators and states. This expression tree
will be walked to nd operators acting on states symbolically.
options : dict
A dict of key/value pairs that determine how the operator actions are
carried out.
The following options are valid:
dagger: try to apply Dagger operators to the left (default: False).
ip doit: call .doit() in inner products when they are encountered
(default: True).
1766
Returns e : Expr
The original expression, but with the operators applied to states.
Represent
TODO:
Get represent working with continuous hilbert spaces.
Document default basis functionality.
sympy.physics.quantum.represent.represent(expr, **options)
Represent the quantum expression in the given basis.
In quantum mechanics abstract states and operators can be represented in various basis
sets. Under this operation the follow transforms happen:
Ket -> column vector or function
Bra -> row vector of function
Operator -> matrix or dierential operator
This function will have the logic for representing instances of its class in the basis set
having a class named FooBasis.
Parameters expr : Expr
The expression to represent.
basis : Operator, basis set
An object that contains the information about the basis set. If an operator is used, the basis is assumed to be the orthonormal eigenvectors
of that operator. In general though, the basis argument can be any
object that contains the basis set information.
options : dict
Key/value pairs of options that are passed to the underlying method
that nds the representation. These options can be used to control
how the representation is done. For example, this is where the size
of the basis set would be set.
Returns e : Expr
The SymPy expression of the represented quantum expression.
Examples
Here we subclass Operator and Ket to create the z-spin operator and its spin 1/2 up
eigenstate. By denining the represent SzOp method, the ket can be represented in
the z-spin basis.
5.36. Physics Module
1767
Here we see an example of representations in a continuous basis. We see that the result
of representing various combinations of cartesian position operators and kets give us
continuous expressions involving DiracDelta functions.
>>> from sympy.physics.quantum.cartesian import XOp, XKet, XBra
>>> X = XOp()
>>> x = XKet()
>>> y = XBra(y)
>>> represent(X*x)
x*DiracDelta(x - x_2)
>>> represent(X*x*y)
x*DiracDelta(x - x_3)*DiracDelta(x_1 - y)
1768
Examples
>>> from sympy.physics.quantum.cartesian import XOp, XKet, PxOp, PxKet
>>> from sympy.physics.quantum.represent import rep_expectation
>>> rep_expectation(XOp())
x_1*DiracDelta(x_1 - x_2)
>>> rep_expectation(XOp(), basis=PxOp())
<px_2|*X*|px_1>
>>> rep_expectation(XOp(), basis=PxKet())
<px_2|*X*|px_1>
1769
3.No basis is specied. If expr is a state, then a default instance of its class is returned.
If expr is an operator, then it is mapped to the corresponding state. If it is neither,
then we cannot obtain the basis state.
If the basis cannot be mapped, then it is not changed.
This will be called from within represent, and represent will only pass QExprs.
TODO (?): Support for Muls and other types of expressions?
Parameters expr : Operator or StateBase
Expression whose basis is sought
Examples
>>>
>>>
>>>
>>>
>>>
|x>
>>>
|x>
>>>
|px>
>>>
|px>
1770
Spin
class sympy.physics.quantum.spin.Rotation
Wigner D operator in terms of Euler angles.
Denes the rotation operator in terms of the Euler angles dened by the z-y-z convention
for a passive transformation. That is the coordinate axes are rotated rst about the zaxis, giving the new x-y-z axes. Then this new coordinate system is rotated about the
new y-axis, giving new x-y-z axes. Then this new coordinate system is rotated about
the z-axis. Conventions follow those laid out in [R340] (page 1916).
Parameters alpha : Number, Symbol
First Euler Angle
beta : Number, Symbol
Second Euler angle
gamma : Number, Symbol
Third Euler angle
See Also:
WignerD (page 1773) Symbolic Wigner-D function
D (page 1771) Wigner-D function
d (page 1772) Wigner small-d function
References
With symbolic Euler angles and calculating the inverse rotation operator:
>>> from sympy import symbols
>>> a, b, c = symbols(a b c)
>>> Rotation(a, b, c)
R(a,b,c)
>>> Rotation(a, b, c).inverse()
R(-c,-b,-a)
1771
m : Number
Eigenvalue of angular momentum along axis after rotation
mp : Number
Eigenvalue of angular momentum along rotated axis
alpha : Number, Symbol
First Euler angle of rotation
beta : Number, Symbol
Second Euler angle of rotation
gamma : Number, Symbol
Third Euler angle of rotation
See Also:
WignerD (page 1773) Symbolic Wigner-D function
Examples
Return the Wigner-D matrix element for a dened rotation, both numerical and symbolic:
>>> from sympy.physics.quantum.spin import Rotation
>>> from sympy import pi, symbols
>>> alpha, beta, gamma = symbols(alpha beta gamma)
>>> Rotation.D(1, 1, 0,pi, pi/2,-pi)
WignerD(1, 1, 0, pi, pi/2, -pi)
1772
Examples
Return the Wigner-D matrix element for a dened rotation, both numerical and symbolic:
>>> from sympy.physics.quantum.spin import Rotation
>>> from sympy import pi, symbols
>>> beta = symbols(beta)
>>> Rotation.d(1, 1, 0, pi/2)
WignerD(1, 1, 0, 0, pi/2, 0)
class sympy.physics.quantum.spin.WignerD
Wigner-D function
The Wigner D-function gives the matrix elements of the rotation operator in the jmrepresentation. For the Euler angles , , , the D-function is dened such that:
< j, m|R(, , )|j 0 , m0 >= jj 0 D(j, m, m0 , , , )
Where the rotation operator is as dened by the Rotation class [R341] (page 1916).
The Wigner D-function dened in this way gives:
0
1773
References
class sympy.physics.quantum.spin.JxKet
Eigenket of Jx.
See JzKet for the usage of spin eigenstates.
See Also:
JzKet (page 1774) Usage of spin states
class sympy.physics.quantum.spin.JxBra
Eigenbra of Jx.
See JzKet for the usage of spin eigenstates.
See Also:
JzKet (page 1774) Usage of spin states
class sympy.physics.quantum.spin.JyKet
Eigenket of Jy.
See JzKet for the usage of spin eigenstates.
See Also:
JzKet (page 1774) Usage of spin states
class sympy.physics.quantum.spin.JyBra
Eigenbra of Jy.
See JzKet for the usage of spin eigenstates.
See Also:
JzKet (page 1774) Usage of spin states
1774
class sympy.physics.quantum.spin.JzKet
Eigenket of Jz.
Spin state which is an eigenstate of the Jz operator. Uncoupled states, that is states
representing the interaction of multiple separate spin states, are dened as a tensor
product of states.
Parameters j : Number, Symbol
Total spin angular momentum
m : Number, Symbol
Eigenvalue of the Jz spin operator
See Also:
JzKetCoupled (page 1777) Coupled eigenstates
TensorProduct Used to specify uncoupled states
uncouple (page 1780) Uncouples states given coupling parameters
couple (page 1779) Couples uncoupled states
Examples
Normal States:
Dening simple spin states, both numerical and symbolic:
>>> from sympy.physics.quantum.spin import JzKet, JxKet
>>> from sympy import symbols
>>> JzKet(1, 0)
|1,0>
>>> j, m = symbols(j m)
>>> JzKet(j, m)
|j,m>
Rewriting the JzKet in terms of eigenkets of the Jx operator: Note: that the resulting
eigenstates are JxKets
>>> JzKet(1,1).rewrite(Jx)
|1,-1>/2 - sqrt(2)*|1,0>/2 + |1,1>/2
Get the vector representation of a state in terms of the basis elements of the Jx operator:
>>> from sympy.physics.quantum.represent import represent
>>> from sympy.physics.quantum.spin import Jx, Jz
>>> represent(JzKet(1,-1), basis=Jx)
Matrix([
[
1/2],
[sqrt(2)/2],
[
1/2]])
1775
>>> i.doit()
1/2
Uncoupled States:
Dene an uncoupled state as a TensorProduct between two Jz eigenkets:
>>> from sympy.physics.quantum.tensorproduct import TensorProduct
>>> j1,m1,j2,m2 = symbols(j1 m1 j2 m2)
>>> TensorProduct(JzKet(1,0), JzKet(1,1))
|1,0>x|1,1>
>>> TensorProduct(JzKet(j1,m1), JzKet(j2,m2))
|j1,m1>x|j2,m2>
A TensorProduct can be rewritten, in which case the eigenstates that make up the tensor
product is rewritten to the new basis:
>>> TensorProduct(JzKet(1,1),JxKet(1,1)).rewrite(Jz)
|1,1>x|1,-1>/2 + sqrt(2)*|1,1>x|1,0>/2 + |1,1>x|1,1>/2
The represent method for TensorProducts gives the vector representation of the state.
Note that the state in the product basis is the equivalent of the tensor product of the
vector representation of the component eigenstates:
>>> represent(TensorProduct(JzKet(1,0),JzKet(1,1)))
Matrix([
[0],
[0],
[0],
[1],
[0],
[0],
[0],
[0],
[0]])
>>> represent(TensorProduct(JzKet(1,1),JxKet(1,1)), basis=Jz)
Matrix([
[
1/2],
[sqrt(2)/2],
[
1/2],
[
0],
[
0],
[
0],
[
0],
[
0],
[
0]])
class sympy.physics.quantum.spin.JzBra
Eigenbra of Jz.
See the JzKet for the usage of spin eigenstates.
See Also:
JzKet (page 1774) Usage of spin states
class sympy.physics.quantum.spin.JxKetCoupled
Coupled eigenket of Jx.
See JzKetCoupled for the usage of coupled spin eigenstates.
1776
See Also:
JzKetCoupled (page 1777) Usage of coupled spin states
class sympy.physics.quantum.spin.JxBraCoupled
Coupled eigenbra of Jx.
See JzKetCoupled for the usage of coupled spin eigenstates.
See Also:
JzKetCoupled (page 1777) Usage of coupled spin states
class sympy.physics.quantum.spin.JyKetCoupled
Coupled eigenket of Jy.
See JzKetCoupled for the usage of coupled spin eigenstates.
See Also:
JzKetCoupled (page 1777) Usage of coupled spin states
class sympy.physics.quantum.spin.JyBraCoupled
Coupled eigenbra of Jy.
See JzKetCoupled for the usage of coupled spin eigenstates.
See Also:
JzKetCoupled (page 1777) Usage of coupled spin states
class sympy.physics.quantum.spin.JzKetCoupled
Coupled eigenket of Jz
Spin state that is an eigenket of Jz which represents the coupling of separate spin spaces.
The arguments for creating instances of JzKetCoupled are j, m, jn and an optional jcoupling argument. The j and m options are the total angular momentum quantum numbers, as used for normal states (e.g. JzKet).
The other required parameter in jn, which is a tuple dening the jn angular momentum
quantum numbers of the product spaces. So for example, if a state represented the
coupling of the product basis state |j1 , m1 i|j2 , m2 i, the jn for this state would be (j1,j2).
The nal option is jcoupling, which is used to dene how the spaces specied by jn
are coupled, which includes both the order these spaces are coupled together and the
quantum numbers that arise from these couplings. The jcoupling parameter itself is
a list of lists, such that each of the sublists denes a single coupling between the spin
spaces. If there are N coupled angular momentum spaces, that is jn has N elements, then
there must be N-1 sublists. Each of these sublists making up the jcoupling parameter
have length 3. The rst two elements are the indicies of the product spaces that are
considered to be coupled together. For example, if we want to couple j1 and j4 , the
indicies would be 1 and 4. If a state has already been coupled, it is referenced by the
smallest index that is coupled, so if j2 and j4 has already been coupled to some j24 , then
this value can be coupled by referencing it with index 2. The nal element of the sublist
is the quantum number of the coupled state. So putting everything together, into a
valid sublist for jcoupling, if j1 and j2 are coupled to an angular momentum space with
quantum number j12 with the value j12, the sublist would be (1,2,j12), N-1 of these
sublists are used in the list for jcoupling.
Note the jcoupling parameter is optional, if it is not specied, the default coupling is
taken. This default value is to coupled the spaces in order and take the quantum number
5.36. Physics Module
1777
of the coupling to be the maximum value. For example, if the spin spaces are j1 , j2 , j3 ,
j4 , then the default coupling couples j1 and j2 to j12 = j1 + j2 , then, j12 and j3 are coupled
to j123 = j12 + j3 , and nally j123 and j4 to j = j123 + j4 . The jcoupling value that would
correspond to this is:
((1,2,j1+j2),(1,3,j1+j2+j3))
Parameters args : tuple
The arguments that must be passed are j, m, jn, and jcoupling. The j
value is the total angular momentum. The m value is the eigenvalue of
the Jz spin operator. The jn list are the j values of argular momentum
spaces coupled together. The jcoupling parameter is an optional
parameter dening how the spaces are coupled together. See the
above description for how these coupling parameters are dened.
See Also:
JzKet (page 1774) Normal spin eigenstates
uncouple (page 1780) Uncoupling of coupling spin states
couple (page 1779) Coupling of uncoupled spin states
Examples
Dening coupled spin states for more than 2 coupled spaces with various coupling parameters:
>>> JzKetCoupled(2, 1, (1, 1, 1))
|2,1,j1=1,j2=1,j3=1,j(1,2)=2>
>>> JzKetCoupled(2, 1, (1, 1, 1), ((1,2,2),(1,3,2)) )
|2,1,j1=1,j2=1,j3=1,j(1,2)=2>
>>> JzKetCoupled(2, 1, (1, 1, 1), ((2,3,1),(1,2,2)) )
|2,1,j1=1,j2=1,j3=1,j(2,3)=1>
Rewriting the JzKetCoupled in terms of eigenkets of the Jx operator: Note: that the
resulting eigenstates are JxKetCoupled
>>> JzKetCoupled(1,1,(1,1)).rewrite(Jx)
|1,-1,j1=1,j2=1>/2 - sqrt(2)*|1,0,j1=1,j2=1>/2 + |1,1,j1=1,j2=1>/2
The rewrite method can be used to convert a coupled state to an uncoupled state. This
is done by passing coupled=False to the rewrite function:
>>> JzKetCoupled(1, 0, (1, 1)).rewrite(Jz, coupled=False)
-sqrt(2)*|1,-1>x|1,1>/2 + sqrt(2)*|1,1>x|1,-1>/2
Get the vector representation of a state in terms of the basis elements of the Jx operator:
1778
class sympy.physics.quantum.spin.JzBraCoupled
Coupled eigenbra of Jz.
See the JzKetCoupled for the usage of coupled spin eigenstates.
See Also:
JzKetCoupled (page 1777) Usage of coupled spin states
sympy.physics.quantum.spin.couple(expr, jcoupling list=None)
Couple a tensor product of spin states
This function can be used to couple an uncoupled tensor product of spin states. All of the
eigenstates to be coupled must be of the same class. It will return a linear combination
of eigenstates that are subclasses of CoupledSpinState determined by Clebsch-Gordan
angular momentum coupling coecients.
Parameters expr : Expr
An expression involving TensorProducts of spin states to be coupled.
Each state must be a subclass of SpinState and they all must be the
same class.
jcoupling list : list or tuple
Elements of this list are sub-lists of length 2 specifying the order of
the coupling of the spin spaces. The length of this must be N-1, where
N is the number of states in the tensor product to be coupled. The
elements of this sublist are the same as the rst two elements of each
sublist in the jcoupling parameter dened for JzKetCoupled. If this
parameter is not specied, the default value is taken, which couples
the rst and second product basis spaces, then couples this new coupled space to the third product space, etc
Examples
Numerical coupling of three spaces using the default coupling method, i.e. rst and
second spaces couple, then this couples to the third space:
>>> couple(TensorProduct(JzKet(1,1), JzKet(1,1), JzKet(1,0)))
sqrt(6)*|2,2,j1=1,j2=1,j3=1,j(1,2)=2>/3 + sqrt(3)*|3,2,j1=1,j2=1,j3=1,j(1,2)=2>/3
1779
Perform this same coupling, but we dene the coupling to rst couple the rst and third
spaces:
1780
1781
class sympy.physics.quantum.state.Bra
A general time-independent Bra in quantum mechanics.
Inherits from State and BraBase. A Bra is the dual of a Ket [R343] (page 1916). This
class and its subclasses will be the main classes that users will use for expressing Bras
in Dirac notation.
Parameters args : tuple
The list of numbers or parameters that uniquely specify the ket.
This will usually be its symbol or its quantum numbers. For timedependent state, this will include the time.
1782
References
Like Kets, Bras can have compound labels and be manipulated in a similar manner:
>>> n, m = symbols(n,m)
>>> b = Bra(n,m) - I*Bra(m,n)
>>> b
-I*<mn| + <nm|
class sympy.physics.quantum.state.TimeDepState
Base class for a general time-dependent quantum state.
This class is used as a base class for any time-dependent state. The main dierence
between this class and the time-independent state is that this class takes a second argument that is the time in addition to the usual label argument.
Parameters args : tuple
The list of numbers or parameters that uniquely specify the ket.
This will usually be its symbol or its quantum numbers. For timedependent state, this will include the time as the nal argument.
label
The label of the state.
time
The time of the state.
class sympy.physics.quantum.state.TimeDepBra
General time-dependent Bra in quantum mechanics.
This inherits from TimeDepState and BraBase and is the main class that should be used
for Bras that vary with time. Its dual is a TimeDepBra.
5.36. Physics Module
1783
class sympy.physics.quantum.state.TimeDepKet
General time-dependent Ket in quantum mechanics.
This inherits from TimeDepState and KetBase and is the main class that should be used
for Kets that vary with time. Its dual is a TimeDepBra.
Parameters args : tuple
The list of numbers or parameters that uniquely specify the ket.
This will usually be its symbol or its quantum numbers. For timedependent state, this will include the time as the nal argument.
Examples
class sympy.physics.quantum.state.Wavefunction
Class for representations in continuous bases
1784
This class takes an expression and coordinates in its constructor. It can be used to easily
calculate normalizations and probabilities.
Parameters expr : Expr
The expression representing the functional form of the w.f.
coords : Symbol or tuple
The coordinates to be integrated over, and their bounds
Examples
Particle in a box, specifying bounds in the more primitive way of using Piecewise:
>>> from sympy import Symbol, Piecewise, pi, N
>>> from sympy.functions import sqrt, sin
>>> from sympy.physics.quantum.state import Wavefunction
>>> x = Symbol(x, real=True)
>>> n = 1
>>> L = 1
>>> g = Piecewise((0, x < 0), (0, x > L), (sqrt(2//L)*sin(n*pi*x/L), True))
>>> f = Wavefunction(g, x)
>>> f.norm
1
>>> f.is_normalized
True
>>> p = f.prob()
>>> p(0)
0
>>> p(L)
0
>>> p(0.5)
2
>>> p(0.85*L)
2*sin(0.85*pi)**2
>>> N(p(0.85*L))
0.412214747707527
Additionally, you can specify the bounds of the function and the indices in a more compact
way:
>>> from sympy import symbols, pi, diff
>>> from sympy.functions import sqrt, sin
>>> from sympy.physics.quantum.state import Wavefunction
>>> x, L = symbols(x,L, positive=True)
>>> n = symbols(n, integer=True, positive=True)
>>> g = sqrt(2/L)*sin(n*pi*x/L)
>>> f = Wavefunction(g, (x, 0, L))
>>> f.norm
1
>>> f(L+1)
0
>>> f(L-1)
sqrt(2)*sin(pi*n*(L - 1)/L)/sqrt(L)
>>> f(-1)
0
>>> f(0.85)
sqrt(2)*sin(0.85*pi*n/L)/sqrt(L)
1785
All arguments are automatically sympied, so you can dene the variables as strings
rather than symbols:
>>> expr = x**2
>>> f = Wavefunction(expr, x)
>>> type(f.variables[0])
<class sympy.core.symbol.Symbol>
expr
Return the expression which is the functional form of the Wavefunction
Examples
>>> from sympy.physics.quantum.state import Wavefunction
>>> from sympy import symbols
>>> x, y = symbols(x, y)
>>> f = Wavefunction(x**2, x)
>>> f.expr
x**2
is commutative
Override Functions is commutative so that order is preserved in represented expressions
is normalized
Returns true if the Wavefunction is properly normalized
Examples
>>> from sympy import symbols, pi
>>> from sympy.functions import sqrt, sin
>>> from sympy.physics.quantum.state import Wavefunction
>>> x, L = symbols(x,L, positive=True)
>>> n = symbols(n, integer=True, positive=True)
>>> g = sqrt(2/L)*sin(n*pi*x/L)
>>> f = Wavefunction(g, (x, 0, L))
>>> f.is_normalized
True
limits
Return the limits of the coordinates which the w.f. depends on If no limits are specied, defaults to (-oo, oo).
1786
Examples
>>>
>>>
>>>
>>>
>>>
{x:
>>>
>>>
{x:
>>>
>>>
{x:
norm
Return the normalization of the specied functional form.
This function integrates over the coordinates of the Wavefunction, with the bounds
specied.
Examples
>>> from sympy import symbols, pi
>>> from sympy.functions import sqrt, sin
>>> from sympy.physics.quantum.state import Wavefunction
>>> x, L = symbols(x,L, positive=True)
>>> n = symbols(n, integer=True, positive=True)
>>> g = sqrt(2/L)*sin(n*pi*x/L)
>>> f = Wavefunction(g, (x, 0, L))
>>> f.norm
1
>>> g = sin(n*pi*x/L)
>>> f = Wavefunction(g, (x, 0, L))
>>> f.norm
sqrt(2)*sqrt(L)/2
normalize()
Return a normalized version of the Wavefunction
Examples
>>> from sympy import symbols, pi
>>> from sympy.functions import sqrt, sin
>>> from sympy.physics.quantum.state import Wavefunction
>>> x = symbols(x, real=True)
>>> L = symbols(L, positive=True)
>>> n = symbols(n, integer=True, positive=True)
>>> g = sin(n*pi*x/L)
>>> f = Wavefunction(g, (x, 0, L))
>>> f.normalize()
Wavefunction(sqrt(2)*sin(pi*n*x/L)/sqrt(L), (x, 0, L))
prob()
Return the absolute magnitude of the w.f., |(x)|2
5.36. Physics Module
1787
Examples
>>> from sympy import symbols, pi
>>> from sympy.functions import sqrt, sin
>>> from sympy.physics.quantum.state import Wavefunction
>>> x, L = symbols(x,L, real=True)
>>> n = symbols(n, integer=True)
>>> g = sin(n*pi*x/L)
>>> f = Wavefunction(g, (x, 0, L))
>>> f.prob()
Wavefunction(sin(pi*n*x/L)**2, x)
variables
Return the coordinates which the wavefunction depends on
Examples
>>> from sympy.physics.quantum.state import Wavefunction
>>> from sympy import symbols
>>> x,y = symbols(x,y)
>>> f = Wavefunction(x*y, x, y)
>>> f.variables
(x, y)
>>> g = Wavefunction(x*y, x)
>>> g.variables
(x,)
Quantum Computation
sympy.physics.quantum.circuitplot.labeller(n, symbol=q)
Autogenerate labels for wires of quantum circuits.
Parameters n : int
number of qubits in the circuit
symbol : string
A character string to precede all gate labels. E.g. q 0, q 1, etc.
1788
class sympy.physics.quantum.gate.Gate
Non-controlled unitary gate operator that acts on qubits.
This is a general abstract gate that needs to be subclassed to do anything useful.
Parameters label : tuple, int
A list of the target qubits (as ints) that the gate will apply to.
get target matrix(format=sympy)
The matrix rep. of the target part of the gate.
Parameters format : str
The format string (sympy,numpy, etc.)
min qubits
The minimum number of qubits this gate needs to act on.
nqubits
The total number of qubits this gate acts on.
For controlled gate subclasses this includes both target and control qubits, so that,
for examples the CNOT gate acts on 2 qubits.
targets
A tuple of target qubits.
1789
class sympy.physics.quantum.gate.CGate
A general unitary gate with control qubits.
A general control gate applies a target gate to a set of targets if all of the control qubits
have a particular values (set by CGate.control value).
Parameters label : tuple
The label in this case has the form (controls, gate), where controls is
a tuple/list of control qubits (as ints) and gate is a Gate instance that
is the target operator.
controls
A tuple of control qubits.
decompose(**options)
Decompose the controlled gate into CNOT and single qubits gates.
eval controls(qubit)
Return True/False to indicate if the controls are satised.
gate
The non-controlled gate that will be applied to the targets.
min qubits
The minimum number of qubits this gate needs to act on.
nqubits
The total number of qubits this gate acts on.
For controlled gate subclasses this includes both target and control qubits, so that,
for examples the CNOT gate acts on 2 qubits.
plot gate(circ plot, gate idx)
Plot the controlled gate. If simplify cgate is true, simplify C-X and C-Z gates into
their more familiar forms.
targets
A tuple of target qubits.
class sympy.physics.quantum.gate.UGate
General gate specied by a set of targets and a target matrix.
Parameters label : tuple
A tuple of the form (targets, U), where targets is a tuple of the target
qubits and U is a unitary matrix with dimension of len(targets).
get target matrix(format=sympy)
The matrix rep. of the target part of the gate.
Parameters format : str
The format string (sympy,numpy, etc.)
targets
A tuple of target qubits.
class sympy.physics.quantum.gate.OneQubitGate
A single qubit unitary gate base class.
class sympy.physics.quantum.gate.TwoQubitGate
A two qubit unitary gate base class.
class sympy.physics.quantum.gate.IdentityGate
The single qubit identity gate.
1790
class sympy.physics.quantum.gate.XGate
The single qubit X, or NOT, gate.
Parameters target : int
The target qubit this gate will apply to.
class sympy.physics.quantum.gate.YGate
The single qubit Y gate.
Parameters target : int
The target qubit this gate will apply to.
class sympy.physics.quantum.gate.ZGate
The single qubit Z gate.
Parameters target : int
The target qubit this gate will apply to.
class sympy.physics.quantum.gate.TGate
The single qubit pi/8 gate.
This gate rotates the phase of the state by pi/4 if the state is |1> and does nothing if the
state is |0>.
Parameters target : int
The target qubit this gate will apply to.
class sympy.physics.quantum.gate.PhaseGate
The single qubit phase, or S, gate.
This gate rotates the phase of the state by pi/2 if the state is |1> and does nothing if the
state is |0>.
Parameters target : int
The target qubit this gate will apply to.
1791
class sympy.physics.quantum.gate.SwapGate
Two qubit SWAP gate.
This gate swap the values of the two qubits.
Parameters label : tuple
A tuple of the form (target1, target2).
decompose(**options)
Decompose the SWAP gate into CNOT gates.
class sympy.physics.quantum.gate.CNotGate
Two qubit controlled-NOT.
This gate performs the NOT or X gate on the target qubit if the control qubits all have
the value 1.
Parameters label : tuple
A tuple of the form (control, target).
Examples
>>>
>>>
>>>
>>>
>>>
|11>
controls
A tuple of control qubits.
gate
The non-controlled gate that will be applied to the targets.
min qubits
The minimum number of qubits this gate needs to act on.
targets
A tuple of target qubits.
sympy.physics.quantum.gate.CNOT
alias of CNotGate (page 1792)
sympy.physics.quantum.gate.SWAP
alias of SwapGate (page 1791)
sympy.physics.quantum.gate.H
alias of HadamardGate (page 1791)
sympy.physics.quantum.gate.X
alias of XGate (page 1791)
sympy.physics.quantum.gate.Y
alias of YGate (page 1791)
sympy.physics.quantum.gate.Z
alias of ZGate (page 1791)
sympy.physics.quantum.gate.T
alias of TGate (page 1791)
1792
sympy.physics.quantum.gate.S
alias of PhaseGate (page 1791)
sympy.physics.quantum.gate.Phase
alias of PhaseGate (page 1791)
sympy.physics.quantum.gate.normalized(normalize)
Set ag controlling normalization of Hadamard gates by 1/sqrt(2).
This is a global setting that can be used to simplify the look of various expressions, by
leaving o the leading 1/sqrt(2) of the Hadamard gate.
Parameters normalize : bool
Should the Hadamard gate include the 1/sqrt(2) normalization factor?
When True, the Hadamard gate will have the 1/sqrt(2). When False,
the Hadamard gate will not have this factor.
sympy.physics.quantum.gate.gate sort(circuit)
Sorts the gates while keeping track of commutation relations
This function uses a bubble sort to rearrange the order of gate application. Keeps track
of Quantum computations special commutation relations (e.g. things that apply to the
same Qubit do not commute with each other)
circuit is the Mul of gates that are to be sorted.
sympy.physics.quantum.gate.gate simp(circuit)
Simplies gates symbolically
It rst sorts gates using gate sort. It then applies basic simplication rules to the circuit,
e.g., XGate**2 = Identity
sympy.physics.quantum.gate.random circuit(ngates, nqubits, gate space=(<class
sympy.physics.quantum.gate.XGate>,
<class sympy.physics.quantum.gate.YGate>,
<class sympy.physics.quantum.gate.ZGate>,
<class sympy.physics.quantum.gate.PhaseGate>,
<class sympy.physics.quantum.gate.TGate>,
<class sympy.physics.quantum.gate.HadamardGate>,
<class sympy.physics.quantum.gate.CNotGate>,
<class sympy.physics.quantum.gate.SwapGate>))
Return a random circuit of ngates and nqubits.
This uses an equally weighted sample of (X, Y, Z, S, T, H, CNOT, SWAP) gates.
Parameters ngates : int
The number of gates in the circuit.
nqubits : int
The number of qubits in the circuit.
gate space : tuple
A tuple of the gate classes that will be used in the circuit. Repeating
gate classes multiple times in this tuple will increase the frequency
they appear in the random circuit.
class sympy.physics.quantum.gate.CGateS
Version of CGate that allows gate simplications. I.e. cnot looks like an oplus, cphase
has dots, etc.
1793
Grovers Algorithm
Todo:
W gate construction (or perhaps -W gate based on Mermins book)
Generalize the algorithm for an unknown function that returns 1 on multiple qubit states,
not just one.
Implement represent ZGate in OracleGate
class sympy.physics.quantum.grover.OracleGate
A black box gate.
The gate marks the desired qubits of an unknown function by ipping the sign of the
qubits. The unknown function returns true when it nds its desired qubits and false
otherwise.
Parameters qubits : int
Number of qubits.
oracle : callable
A callable function that returns a boolean on a computational basis.
Examples
Apply an Oracle gate that ips the sign of |2> on dierent qubits:
>>>
>>>
>>>
>>>
>>>
>>>
-|2>
>>>
|3>
search function
The unknown function that helps nd the sought after qubits.
targets
A tuple of target qubits.
class sympy.physics.quantum.grover.WGate
General n qubit W Gate in Grovers algorithm.
The gate performs the operation 2|phi><phi| - 1 on some qubits. |phi> = (tensor
product of n Hadamards)*(|0> with n qubits)
Parameters nqubits : int
The number of qubits to operate on
sympy.physics.quantum.grover.superposition basis(nqubits)
Creates an equal superposition of the computational basis.
Parameters nqubits : int
The number of qubits.
Returns state : Qubit
An equal superposition of the computational basis with nqubits.
1794
Examples
1795
QFT
Todo:
Update docstrings.
Update tests.
Implement apply using decompose.
Implement represent using decompose or something smarter. For this to work we rst
have to implement represent for SWAP.
Decide if we want upper index to be inclusive in the constructor.
Fix the printing of Rk gates in plotting.
class sympy.physics.quantum.qft.QFT
The forward quantum Fourier transform.
decompose()
Decomposes QFT into elementary gates.
class sympy.physics.quantum.qft.IQFT
The inverse quantum Fourier transform.
decompose()
Decomposes IQFT into elementary gates.
class sympy.physics.quantum.qft.RkGate
This is the R k gate of the QTF.
sympy.physics.quantum.qft.Rk
alias of RkGate (page 1796)
Qubit
Todo: * Finish implementing measurement logic. This should include POVM. * Update docstrings. * Update tests.
class sympy.physics.quantum.qubit.Qubit
A multi-qubit ket in the computational (z) basis.
We use the normal convention that the least signicant qubit is on the right, so |00001>
has a 1 in the least signicant qubit.
Parameters values : list, str
The qubit values as a list of ints ([0,0,0,1,1,]) or a string (011).
Examples
1796
>>>
4
>>>
4
>>>
4
>>>
(0,
q.nqubits
len(q)
q.dimension
q.qubit_values
1, 0, 1)
class sympy.physics.quantum.qubit.QubitBra
A multi-qubit bra in the computational (z) basis.
We use the normal convention that the least signicant qubit is on the right, so |00001>
has a 1 in the least signicant qubit.
Parameters values : list, str
The qubit values as a list of ints ([0,0,0,1,1,]) or a string (011).
See Also:
Qubit (page 1796) Examples using qubits
class sympy.physics.quantum.qubit.IntQubit
A qubit ket that store integers as binary numbers in qubit values.
The dierences between this class and Qubit are:
The form of the constructor.
The qubit values are printed as their corresponding integer, rather than the raw
qubit values. The internal storage format of the qubit values in the same as Qubit.
1797
Examples
q = IntQubit(Qubit(101))
q
q.as_int()
q.nqubits
q.qubit_values
0, 1)
class sympy.physics.quantum.qubit.IntQubitBra
A qubit bra that store integers as binary numbers in qubit values.
sympy.physics.quantum.qubit.qubit to matrix(qubit, format=sympy)
Coverts an Add/Mul of Qubit objects into its matrix representation
This function is the inverse of matrix to qubit and is a shorthand for represent(qubit).
sympy.physics.quantum.qubit.matrix to qubit(matrix)
Convert from the matrix repr. to a sum of Qubit objects.
Parameters matrix : Matrix, numpy.matrix, scipy.sparse
The matrix to build the Qubit representation of. This works with
sympy matrices, numpy matrices and scipy.sparse sparse matrices.
Examples
sympy.physics.quantum.qubit.matrix to density(mat)
Works by nding the eigenvectors and eigenvalues of the matrix. We know we can decompose rho by doing: sum(EigenVal*|Eigenvect><Eigenvect|)
1798
sympy.physics.quantum.qubit.measure all(qubit,
format=sympy,
ize=True)
Perform an ensemble measurement of all qubits.
normal-
1799
>>> c = H(0)*H(1)*Qubit(00)
>>> c
H(0)*H(1)*|00>
>>> q = qapply(c)
>>> measure_partial(q, (0,))
[(sqrt(2)*|00>/2 + sqrt(2)*|10>/2, 1/2), (sqrt(2)*|01>/2 + sqrt(2)*|11>/2, 1/2)]
for-
A oneshot measurement is equivalent to performing a measurement on a quantum system. This type of measurement does not return the probabilities like an ensemble measurement does, but rather returns one of the possible resulting states. The exact state
that is returned is determined by picking a state randomly according to the ensemble
probabilities.
Parameters qubits : Qubit
The qubit to measure. This can be any Qubit or a linear combination
of them.
bits : tuple
The qubits to measure.
format : str
The format of the intermediate matrices to use. Possible values
are (sympy,numpy,scipy.sparse). Currently only sympy is implemented.
Returns result : Qubit
The qubit that the system collapsed to upon measurement.
sympy.physics.quantum.qubit.measure all oneshot(qubit, format=sympy)
Perform a oneshot ensemble measurement on all qubits.
A oneshot measurement is equivalent to performing a measurement on a quantum system. This type of measurement does not return the probabilities like an ensemble measurement does, but rather returns one of the possible resulting states. The exact state
that is returned is determined by picking a state randomly according to the ensemble
probabilities.
Parameters qubits : Qubit
The qubit to measure. This can be any Qubit or a linear combination
of them.
format : str
The format of the intermediate matrices to use. Possible values
are (sympy,numpy,scipy.sparse). Currently only sympy is implemented.
Returns result : Qubit
The qubit that the system collapsed to upon measurement.
Shors Algorithm
Todo:
1800
Get the CMod gate working again using the new Gate API.
Fix everything.
Update docstrings and reformat.
Remove print statements. We may want to think about a better API for this.
class sympy.physics.quantum.shor.CMod
A controlled mod gate.
This is black box controlled Mod function for use by shors algorithm. TODO implement
a decompose property that returns how to do this in terms of elementary gates
N
N is the type of modular arithmetic we are doing.
a
Base of the controlled mod function.
t
Size of 1/2 input register. First 1/2 holds output.
sympy.physics.quantum.shor.period find(a, N)
Finds the period of a in modulo N arithmetic
This is quantum part of Shors algorithm.It takes two registers, puts rst in superposition
of states with Hadamards so: |k>|0> with k being all possible choices. It then does a
controlled mod and a QFT to determine the order of a.
sympy.physics.quantum.shor.shor(N)
This function implements Shors factoring algorithm on the Integer N
The algorithm starts by picking a random number (a) and seeing if it is coprime with N.
If it isnt, then the gcd of the two numbers is a factor and we are done. Otherwise, it
begins the period nding subroutine which nds the period of a in modulo N arithmetic.
This period, if even, can be used to calculate factors by taking a**(r/2)-1 and a**(r/2)+1.
These values are returned.
Analytic Solutions
Particle in a Box
class sympy.physics.quantum.piab.PIABHamiltonian
Particle in a box Hamiltonian operator.
class sympy.physics.quantum.piab.PIABKet
Particle in a box eigenket.
class sympy.physics.quantum.piab.PIABBra
Particle in a box eigenbra.
Optics Module
Abstract
Contains docstrings of Physics-Optics module
1801
Gaussian Optics
Gaussian optics.
The module implements:
Ray transfer matrices for geometrical and gaussian optics.
1802
>>> f = Symbol(f)
>>> lens = ThinLens(f)
>>> lens
Matrix([
[
1, 0],
[-1/f, 1]])
>>> lens.C
-1/f
A
The A parameter of the Matrix.
Examples
>>> from sympy.physics.optics import RayTransferMatrix
>>> mat = RayTransferMatrix(1, 2, 3, 4)
>>> mat.A
1
B
The B parameter of the Matrix.
Examples
>>> from sympy.physics.optics import RayTransferMatrix
>>> mat = RayTransferMatrix(1, 2, 3, 4)
>>> mat.B
2
C
The C parameter of the Matrix.
Examples
>>> from sympy.physics.optics import RayTransferMatrix
>>> mat = RayTransferMatrix(1, 2, 3, 4)
>>> mat.C
3
D
The D parameter of the Matrix.
Examples
>>> from sympy.physics.optics import RayTransferMatrix
>>> mat = RayTransferMatrix(1, 2, 3, 4)
>>> mat.D
4
class sympy.physics.optics.gaussopt.FreeSpace
Ray Transfer Matrix for free space.
5.36. Physics Module
1803
Parameters distance :
See Also:
RayTransferMatrix (page 1802)
Examples
>>> from sympy.physics.optics import FreeSpace
>>> from sympy import symbols
>>> d = symbols(d)
>>> FreeSpace(d)
Matrix([
[1, d],
[0, 1]])
class sympy.physics.optics.gaussopt.FlatRefraction
Ray Transfer Matrix for refraction.
Parameters n1 : refractive index of one medium
n2 : refractive index of other medium
See Also:
RayTransferMatrix (page 1802)
Examples
>>> from sympy.physics.optics import FlatRefraction
>>> from sympy import symbols
>>> n1, n2 = symbols(n1 n2)
>>> FlatRefraction(n1, n2)
Matrix([
[1,
0],
[0, n1/n2]])
class sympy.physics.optics.gaussopt.CurvedRefraction
Ray Transfer Matrix for refraction on curved interface.
Parameters R : radius of curvature (positive for concave)
n1 : refractive index of one medium
n2 : refractive index of other medium
See Also:
RayTransferMatrix (page 1802)
Examples
>>> from sympy.physics.optics import CurvedRefraction
>>> from sympy import symbols
>>> R, n1, n2 = symbols(R n1 n2)
>>> CurvedRefraction(R, n1, n2)
Matrix([
[
1,
0],
[(n1 - n2)/(R*n2), n1/n2]])
1804
class sympy.physics.optics.gaussopt.FlatMirror
Ray Transfer Matrix for reection.
See Also:
RayTransferMatrix (page 1802)
Examples
>>> from sympy.physics.optics import FlatMirror
>>> FlatMirror()
Matrix([
[1, 0],
[0, 1]])
class sympy.physics.optics.gaussopt.CurvedMirror
Ray Transfer Matrix for reection from curved surface.
Parameters R : radius of curvature (positive for concave)
See Also:
RayTransferMatrix (page 1802)
Examples
>>> from sympy.physics.optics import CurvedMirror
>>> from sympy import symbols
>>> R = symbols(R)
>>> CurvedMirror(R)
Matrix([
[
1, 0],
[-2/R, 1]])
class sympy.physics.optics.gaussopt.ThinLens
Ray Transfer Matrix for a thin lens.
Parameters f : the focal distance
See Also:
RayTransferMatrix (page 1802)
Examples
>>> from sympy.physics.optics import ThinLens
>>> from sympy import symbols
>>> f = symbols(f)
>>> ThinLens(f)
Matrix([
[
1, 0],
[-1/f, 1]])
class sympy.physics.optics.gaussopt.GeometricRay
Representation for a geometric ray in the Ray Transfer Matrix formalism.
1805
height
The distance from the optical axis.
Examples
>>>
>>>
>>>
>>>
1806
>>> gRay.height
h
class sympy.physics.optics.gaussopt.BeamParameter
Representation for a gaussian ray in the Ray Transfer Matrix formalism.
Parameters wavelen : the wavelength,
z : the distance to waist, and
w : the waist, or
z r : the rayleigh range
See Also:
RayTransferMatrix (page 1802)
References
>>> p.q.n()
1.0 + 5.92753330865999*I
>>> p.w_0.n()
0.00100000000000000
>>> p.z_r.n()
5.92753330865999
>>> from sympy.physics.optics import FreeSpace
>>> fs = FreeSpace(10)
>>> p1 = fs*p
>>> p.w.n()
0.00101413072159615
>>> p1.w.n()
0.00210803120913829
divergence
Half of the total angular spread.
Examples
>>> from sympy.physics.optics import BeamParameter
>>> p = BeamParameter(530e-9, 1, w=1e-3)
>>> p.divergence
0.00053/pi
gouy
The Gouy phase.
5.36. Physics Module
1807
Examples
>>> from sympy.physics.optics import BeamParameter
>>> p = BeamParameter(530e-9, 1, w=1e-3)
>>> p.gouy
atan(0.53/pi)
q
The complex parameter representing the beam.
Examples
>>>
>>>
>>>
1 +
radius
The radius of curvature of the phase front.
Examples
>>> from sympy.physics.optics import BeamParameter
>>> p = BeamParameter(530e-9, 1, w=1e-3)
>>> p.radius
0.2809/pi**2 + 1
w
The beam radius at 1/e2 intensity.
See Also:
w 0 (page 1808) the minimal radius of beam
Examples
>>> from sympy.physics.optics import BeamParameter
>>> p = BeamParameter(530e-9, 1, w=1e-3)
>>> p.w
0.001*sqrt(0.2809/pi**2 + 1)
w0
The beam waist (minimal radius).
See Also:
w (page 1808) the beam radius at 1/e2 intensity
Examples
1808
sympy.physics.optics.gaussopt.waist2rayleigh(w, wavelen)
Calculate the rayleigh range from the waist of a gaussian beam.
See Also:
rayleigh2waist (page 1809), BeamParameter (page 1807)
Examples
>>> from sympy.physics.optics import waist2rayleigh
>>> from sympy import symbols
>>> w, wavelen = symbols(w wavelen)
>>> waist2rayleigh(w, wavelen)
pi*w**2/wavelen
sympy.physics.optics.gaussopt.rayleigh2waist(z r, wavelen)
Calculate the waist from the rayleigh range of a gaussian beam.
See Also:
waist2rayleigh (page 1809), BeamParameter (page 1807)
Examples
>>> from sympy.physics.optics import rayleigh2waist
>>> from sympy import symbols
>>> z_r, wavelen = symbols(z_r wavelen)
>>> rayleigh2waist(z_r, wavelen)
sqrt(wavelen*z_r)/sqrt(pi)
1809
Examples
>>> from sympy.physics.optics import geometric_conj_ab
>>> from sympy import symbols
>>> a, b = symbols(a b)
>>> geometric_conj_ab(a, b)
a*b/(a + b)
1810
1811
Medium
Contains
Medium
class sympy.physics.optics.medium.Medium
This class represents an optical medium. The prime reason to implement this is to facilitate refraction, Fermats priciple, etc.
An optical medium is a material through which electromagnetic waves propagate. The
permittivity and permeability of the medium dene how electromagnetic waves propagate in it.
Parameters name: string :
The display name of the Medium.
permittivity: Sympifyable :
Electric permittivity of the space.
permeability: Sympifyable :
Magnetic permeability of the space.
n: Sympifyable :
Index of refraction of the medium.
References
intrinsic impedance
Returns intrinsic impedance of the medium.
The intrinsic impedance of a medium is the ratio of the transverse components of the
electric and magnetic elds of the electromagnetic wave travelling in the medium.
In a region with no electrical conductivity it simplies to the square root of ratio of
magnetic permeability to electric permittivity.
Examples
1812
permeability
Returns magnetic permeability of the medium.
Examples
>>> from sympy.physics.optics import Medium
>>> m = Medium(m)
>>> m.permeability
pi*kg*m/(2500000*A**2*s**2)
permittivity
Returns electric permittivity of the medium.
Examples
>>> from sympy.physics.optics import Medium
>>> m = Medium(m)
>>> m.permittivity
625000*A**2*s**4/(22468879468420441*pi*kg*m**3)
refractive index
Returns refractive index of the medium.
Examples
>>> from sympy.physics.optics import Medium
>>> m = Medium(m)
>>> m.refractive_index
1
speed
Returns speed of the electromagnetic wave travelling in the medium.
Examples
>>> from sympy.physics.optics import Medium
>>> m = Medium(m)
>>> m.speed
299792458*m/s
Utilities
Contains
refraction angle
1813
deviation
lens makers formula
mirror formula
lens formula
1814
[
n1/n2],
[-sqrt(3)*sqrt(-2*n1**2/(3*n2**2) + 1)]])
>>> refraction_angle(r1, n1, n2, plane=P)
Ray3D(Point3D(0, 0, 0), Point3D(n1/n2, n1/n2, -sqrt(3)*sqrt(-2*n1**2/(3*n2**2) + 1)))
sympy.physics.optics.utils.deviation(incident,
medium1,
medium2,
normal=None, plane=None)
This function calculates the angle of deviation of a ray due to refraction at planar surface.
Parameters incident : Matrix, Ray3D, tuple or list
Incident vector
medium1 : sympy.physics.optics.medium.Medium or sympiable
Medium 1 or its refractive index
medium2 : sympy.physics.optics.medium.Medium or sympiable
Medium 2 or its refractive index
normal : Matrix, Ray3D, tuple or list
Normal vector
plane : Plane
Plane of separation of the two media.
Examples
>>> from sympy.physics.optics import deviation
>>> from sympy.geometry import Point3D, Ray3D, Plane
>>> from sympy.matrices import Matrix
>>> from sympy import symbols
>>> n1, n2 = symbols(n1, n2)
>>> n = Matrix([0, 0, 1])
>>> P = Plane(Point3D(0, 0, 0), normal_vector=[0, 0, 1])
>>> r1 = Ray3D(Point3D(-1, -1, 1), Point3D(0, 0, 0))
>>> deviation(r1, 1, 1, n)
0
>>> deviation(r1, n1, n2, plane=P)
-acos(-sqrt(-2*n1**2/(3*n2**2) + 1)) + acos(-sqrt(3)/3)
1815
Examples
>>> from sympy.physics.optics import lens_makers_formula
>>> lens_makers_formula(1.33, 1, 10, -10)
15.1515151515151
1816
Waves
This module has all the classes and functions related to waves in optics.
Contains
TWave
Arguments
1817
Examples
>>>
>>>
>>>
>>>
>>>
A
angular velocity
Returns angular velocity of the wave.
Examples
>>> from sympy import symbols
>>> from sympy.physics.optics import TWave
>>> A, phi, f = symbols(A, phi, f)
>>> w = TWave(A, f, phi)
>>> w.angular_velocity
2*pi*f
frequency
Returns the frequency of the wave.
Examples
>>>
>>>
>>>
>>>
>>>
f
phase
Returns the phase angle of the wave.
Examples
>>>
>>>
>>>
>>>
>>>
phi
speed
Returns the speed of travelling wave. It is medium dependent.
1818
Examples
>>> from sympy import symbols
>>> from sympy.physics.optics import TWave
>>> A, phi, f = symbols(A, phi, f)
>>> w = TWave(A, f, phi)
>>> w.speed
299792458*m/(n*s)
time period
Returns the time period of the wave.
Examples
>>>
>>>
>>>
>>>
>>>
1/f
wavelength
Returns wavelength of the wave. It depends on the medium of the wave.
Examples
>>> from sympy import symbols
>>> from sympy.physics.optics import TWave
>>> A, phi, f = symbols(A, phi, f)
>>> w = TWave(A, f, phi)
>>> w.wavelength
299792458*m/(f*n*s)
wavenumber
Returns wavenumber of the wave.
Examples
>>> from sympy import symbols
>>> from sympy.physics.optics import TWave
>>> A, phi, f = symbols(A, phi, f)
>>> w = TWave(A, f, phi)
>>> w.wavenumber
pi*f*n*s/(149896229*m)
Unit systems
This module integrates unit systems into SymPy, allowing a user choose which system to use
when doing their computations and providing utilities to display and convert units.
1819
Unit systems are composed of units and constants, which are themselves described from
dimensions and numbers, and possibly a prex. Quantities are dened by their unit and their
numerical value, with respect to the current system.
The main advantage of this implementation over the old unit module is that it divides the
units in unit systems, so that the user can decide which units to use, instead of having all in
the name space (for example astrophysicists can only use units with ua, Earth or Sun masses,
the theoricists will use natural system, etc.). Moreover it allows a better control over the
dimensions and conversions.
Ideas about future developments can be found on the Github wiki.
Philosophy behind unit systems
Dimensions
Introduction At the root of unit systems are dimension systems, whose structure mainly
determines the one of unit systems. Our denition could seem rough but they are largely
sucient for our purposes.
A dimension will be dened as a property which is measurable and assigned to a specic
phenomenom. In this sense dimensions are dierent from pure numbers because they carry
some extra-sense, and for this reason two dierent dimensions can not be added. For example
time or length are dimensions, but also any other things which has some sense for us, like
angle, number of particles (moles...) or information (bits...).
From this point of view the only truly dimensionless quantity are pure numbers. The idea
of being dimensionless is very system-dependent, as can be seen from the (c, ~, G), in which
all units appears to be dimensionless in the usual common sense. This is unavoidable for
computability of generic unit systems (but at the end we can tell the program what is dimensionless).
Dimensions can be composed together by taking their product or their ratio (to be dened
below). For example the velocity is dened as length divided by time, or we can see the length
as velocity multiplied by time, depending of what we see as the more fundamental: in general
we can select a set of base dimensions from which we can describe all the others.
Group structure After this short introduction whose aim was to introduce the dimensions
from an intuitive perspective, we describe the mathematical structure. A dimension system
with n independent dimensions {di }i=1,...,n is described by a multiplicative group G:
there an identity element 1 corresponding to pure numbers;
the product D3 = D1 D2 of two elements D1 , D2 G is also in G;
any element D G has an inverse D1 G.
We denote
Dn = D D,
|
{z
}
n times
and by denition D0 = 1. The {di }i=1,...,n are called generators of the group since any element
D G can be expressed as the product of powers of the generators:
D=
dai i ,
ai Z.
i=1
1820
dj ij .
j=1
A = M L2 T 2 ,
2
A = 1 .
2
We can change the basis to go to the natural system (m, c, ~) with dimension (L: length, V:
velocity, A: action) 10 . In this basis the generators are
1
0
0
A = 0 ,
L = 1 ,
V = 0 ,
0
0
1
9 In general we will consider only dimensions with a maximum coecient, so we can only a truncation of the
group; but this is not useful for the algorithm.
10 We anticipate a little by considering c and ~ as units and not as physical constants.
1821
M = AV 2 ,
1
M = 0 .
2
Finally the inverse change of basis matrix P 1 is obtained by gluing the vectors expressed in
the old basis:
2 1 1
P 1 = 1 0 0 .
2 0 1
To nd the change of basis matrix we just have to
0 1
P = 1 0
0 2
0
1 .
1
Units Units are constructed upon dimensions: they give them an ordering, or equivalently
a magnitude. First one has to choose some origin, usually based on some physical measurement. Then the other units of the same dimensions follow by simple rescaling (we omit for
now the case of unit with oset, such as the temperature).
For example consider the length dimension. We start by choosing the origin to be the meter
m, and we dene the other units from it: the kilometer is 103 m, the foot is 0.3048 m, etc.
After dening several units of dierent dimensions we can form a unit system, which is basically a dimension system with a notion of scale.
Constants Physical constants are really just units. They indicate that we did not understand
that two dimensions are in fact the same. For example we see a velocity for the light dierent
from 1 because we do not think that time is the same as space (which is normal because of
our sense; but it is dierent at the fundamental level). For example, once there was the heat
constant which allowed to convert between joules and calories since people did not know
that heat was energy. As soon as they understood it they xed this constant to 1 (this is a very
schematic story).
We can interpret the fact that now we x the value of fundamental constants in the SI as
showing that they are units (and we use them to dene the other usual units).
Quantities A quantity is dened from a factor and a unit. According to this construction,
they are very similar to unit since at the very end a quantity is just a scale (made from the
quantity and unit factors) and a dimension. What distinguishes units is that they play the role
of some xed references, and we always have a denite number of them.
The need for a reference It is not possible to dene from scratch units and unit systems:
one needs to dene some references, and then build the rest over them. Said in another way,
we need an origin for the scales of our units (i.e. a unit with factor 1), and to be sure that all
units of a given dimension are dened consistently we need to use the same origin for all of
them. This can happend if we want to use a derived unit as a base units in another system: we
should not dene it as having a scale 1, because, even if it is inconsistent inside the system,
1822
we could not convert to the rst system since we have two dierent units (from our point of
view) of same scale (which means they are equal for the computer).
We will say that the dimensions and scales dened outside systems are canonical, because
we use them for all computations. On the other side the dimensions and scales obtained with
reference to a system are called physical, because they ultimately carry a sense.
Lets use a concrete (and important) example: the case of the mass units. We would like to
dene the gram as the origin. We would like to dene the gram as the canonical origin for
the mass, so we assign it a scale 1. Then we can dene a system (e.g. in chemistry) that take
it as a base unit. The MKS system prefers to use the kilogram; a naive choice would be to
attribute it a scale if 1 since it is a base, but we see that we could not convert to the chemistry
system because g and kg have both been given the same factor. So we need to dene kg as
1000 g, and only then use it as a base in MKS. But as soon as we ask the question what is
the factor of kg in MKS?, we get the answer 1, since it is a base unit.
Thus we will dene all computations without referring to a system, and it is only at the end
that we can plug the result into a system to give the context we are interested in.
Literature
Examples
In the following sections we give few examples of what can be do with this module.
Dimensional analysis We will start from the second Newtons law
ma = F
where m, a and F are the mass, the acceleration and the force respectively. Knowing the
dimensions of m (M ) and a (LT 2 ), we will determine the dimension of F ; obviously we will
nd that it is a force: M LT 2 .
From there we will use the expression of the gravitational force between the particle of mass
m and the body of mass M , at a distance r
F =
GmM
r2
1823
Note that one should rst solve the equation, and then substitute with the dimensions.
Equation with quantities
we can nd the Venus orbital period using the known values for the other variables (taken
from Wikipedia). The result should be 224.701 days.
>>> from __future__ import division
>>> from sympy import solve, Symbol, symbols, pi
>>> from sympy.physics.unitsystems import Unit, Quantity as Q
>>> from sympy.physics.unitsystems.simplifiers import qsimplify
>>> from sympy.physics.unitsystems.systems import mks
>>> m, kg, s = mks[m], mks[kg], mks[s]
>>> T, a, M, G = symbols(T a M G)
>>> venus_a = Q(108208000e3, m)
>>> solar_mass = Q(1.9891e30, kg)
>>> venus_subs = {a: venus_a, M: solar_mass, G: mks[G]}
>>> Tsol = solve(T**2 / a**3 - 4*pi**2 / G / M, T)[1]
>>> q = qsimplify(Tsol.subs(venus_subs))
>>> day = Unit(s.dim, abbrev=day, factor=86400)
>>> print(q.convert_to(qsimplify(day)))
224.667 day
We could also have the solar mass and the day as units coming from the astrophysical system,
but I wanted to show how to create a unit that one needs.
We can see in this example that intermediate dimensions can be ill-dened, such as sqrt(G),
but one should check that the nal result - when all dimensions are combined - is well dened.
Dimensions and dimension systems
example (in classical mechanics) we know that time is dierent from temperature, and
dimensions make this dierence (but they do not provide any measure of these quantites).
>>> from sympy.physics.unitsystems.dimensions import Dimension
>>> length = Dimension(length=1)
>>> length
{length: 1}
>>> time = Dimension(time=1)
Dimensions behave like a dictionary where the key is the name and the value corresponds
to the exponent.
Dimensions can be composed using multiplication, division and exponentiation (by a
number) to give new dimensions. Addition and subtraction is dened only when the two
objects are the same dimension.
>>> velocity = length.div(time)
>>> velocity
{length: 1, time: -1}
>>> length.add(length)
{length: 1}
>>> length.pow(2)
{length: 2}
add(other)
Dene the addition for Dimension.
Addition of dimension has a sense only if the second object is the same dimension
(we dont add length to time).
get(k[, d ]) D[k] if k in D, else d. d defaults to None.
has integer powers
Check if the dimension object has only integer powers.
All the dimension powers should be integers, but rational powers may appear in
intermediate steps. This method may be used to check that the nal result is welldened.
is dimensionless
Check if the dimension object really has a dimension.
A dimension should have at least one component with non-zero power.
items() list of Ds (key, value) pairs, as 2-tuples
keys() list of Ds keys
values() list of Ds values
1825
class sympy.physics.unitsystems.dimensions.DimensionSystem(base,
dims=(),
name=,
descr=)
DimensionSystem represents a coherent set of dimensions.
In a system dimensions are of three types:
base dimensions;
derived dimensions: these are dened in terms of the base dimensions (for example
velocity is dened from the division of length by time);
canonical dimensions: these are used to dene systems because one has to start
somewhere: we can not build ex nihilo a system (see the discussion in the documentation for more details).
All intermediate computations will use the canonical basis, but at the end one can choose
to print result in some other basis.
In a system dimensions can be represented as a vector, where the components represent
the powers associated to each base dimension.
can transf matrix
Compute the canonical transformation matrix from the canonical to the base dimension basis.
It is the inverse of the matrix computed with inv can transf matrix().
dim
Give the dimension of the system.
That is return the number of dimensions forming the basis.
dim can vector(dim)
Vector representation in terms of the canonical base dimensions.
dim vector(dim)
Vector representation in terms of the base dimensions.
extend(base, dims=(), name=, description=)
Extend the current system into a new one.
Take the base and normal units of the current system to merge them to the base and
normal units given in argument. If not provided, name and description are overriden
by empty strings.
get dim(dim)
Find a specic dimension which is part of the system.
dim can be a string or a dimension object. If no dimension is found, then return
None.
inv can transf matrix
Compute the inverse transformation matrix from the base to the canonical dimension
basis.
It corresponds to the matrix where columns are the vector of base dimensions in
canonical basis.
This matrix will almost never be used because dimensions are always dene with
respect to the canonical basis, so no work has to be done to get them in this basis.
Nonetheless if this matrix is not square (or not invertible) it means that we have
chosen a bad basis.
is consistent
Check if the system is well dened.
1826
exponent,
Prexes are used to create derived units from a given unit. They should always be encapsulated into units.
The factor is constructed from a base (default is 10) to some power, and it gives the total
multiple or fraction. For example the kilometer km is constructed from the meter (factor
1) and the kilo (10 to the power 3, i.e. 1000). The base can be changed to allow e.g.
binary prexes.
A prex multiplied by something will always return the product of this other object times
the factor, except if the other object:
is a prex and they can be combined into a new prex;
denes multiplication with prexes (which is the case for the Unit class).
Units and unit systems
The factor represents the position of the unit with respect to the canonical unit of this
dimension. For example if we choose the gram to be the canonical dimension for the
mass, then by denition its factor is 1; on the other hand the factor dened here for
kilogram is 1000, even when it is a base unit. The explanation is that here we do not
have dened any system that we could use as a reference: here the canonical unit is the
only scale, and thus the only available origin.
Additionnaly one can add a prex and an abbreviation. The only utility of the former is to
provide a shorthand for some units, but it is never used among computations; it appears
only when dening and printing units. The same remark applies to the abbreviation.
1827
All operations (pow, mul, etc.) are dened as the corresponding ones acting on the factor
(a number) and the dimension.
abbrev
Symbol representing the unit name.
Prepend the abbreviation with the prex symbol if it is denes.
abbrev dim
Abbreviation which use only intrinsinc properties of the unit.
as quantity
Convert the unit to a quantity.
The quantity unit is given by the unit of factor 1 and with identical dimension.
>>> from sympy.physics.unitsystems.dimensions import Dimension
>>> from sympy.physics.unitsystems.units import Unit
>>> length = Dimension(length=1)
>>> u = Unit(length, factor=10)
>>> q = u.as_quantity
>>> q.factor
10
>>> q.unit == Unit(length)
True
factor
Overall magnitude of the unit.
is compatible(other)
Test if argument is a unit and has the same dimension as self.
This function is used to verify that some operations can be done.
class sympy.physics.unitsystems.units.Constant
Physical constant.
In our framework a constant is considered as a unit, to which humans givesa special
sense, because we believe that they give us a special information on nature; but it is just
a demonstration of our ignorance.
class sympy.physics.unitsystems.units.UnitSystem(base, units=(), name=, descr=)
UnitSystem represents a coherent set of units.
A unit system is basically a dimension system with notions of scales. Many of the methods
are dened in the same way.
It is much better if all base units have a symbol.
dim
Give the dimension of the system.
That is return the number of units forming the basis.
extend(base, units=(), name=, description=)
Extend the current system into a new one.
Take the base and normal units of the current system to merge them to the base and
normal units given in argument. If not provided, name and description are overriden
by empty strings.
get unit(unit)
Find a specic unit which is part of the system.
unit can be a string or a dimension object. If no unit is found, then return None.
1828
is consistent
Check if the underlying dimension system is consistent.
print unit base(unit)
Give the string expression of a unit in term of the basis.
Units are displayed by decreasing power.
Physical quantities
Physical quantities.
class sympy.physics.unitsystems.quantities.Quantity
Physical quantity.
A quantity is dened from a factor and a unit.
add(other)
Add two quantities.
If the other object is not a quantity, raise an error. Two quantities can be added only
if they have the same unit: so we convert rst the other quantity to the same unit
and, if it succedded, then we add the factors.
as unit
Convert the quantity to a unit.
convert to(unit)
Convert the quantity to another (compatible) unit.
1829
class sympy.categories.Morphism
The base class for any morphism in an abstract category.
In abstract categories, a morphism is an arrow between two category objects. The object
where the arrow starts is called the domain, while the object where the arrow ends is
called the codomain.
Two morphisms between the same pair of objects are considered to be the same morphisms. To distinguish between morphisms between the same objects use NamedMorphism (page 1831).
It is prohibited to instantiate this class. Use one of the derived classes instead.
See Also:
IdentityMorphism (page 1833), NamedMorphism (page 1831), CompositeMorphism
(page 1831)
codomain
Returns the codomain of the morphism.
Examples
>>> from sympy.categories import Object, NamedMorphism
>>> A = Object(A)
>>> B = Object(B)
>>> f = NamedMorphism(A, B, f)
>>> f.codomain
Object(B)
compose(other)
Composes self with the supplied morphism.
The order of elements in the composition is the usual order, i.e., to construct g f
use g.compose(f).
Examples
>>> from sympy.categories import Object, NamedMorphism
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> g * f
CompositeMorphism((NamedMorphism(Object(A), Object(B), f),
NamedMorphism(Object(B), Object(C), g)))
>>> (g * f).domain
Object(A)
>>> (g * f).codomain
Object(C)
domain
Returns the domain of the morphism.
1830
Examples
>>> from sympy.categories import Object, NamedMorphism
>>> A = Object(A)
>>> B = Object(B)
>>> f = NamedMorphism(A, B, f)
>>> f.domain
Object(A)
class sympy.categories.NamedMorphism
Represents a morphism which has a name.
Names are used to distinguish between morphisms which have the same domain and
codomain: two named morphisms are equal if they have the same domains, codomains,
and names.
See Also:
Morphism (page 1829)
Examples
>>> from sympy.categories import Object, NamedMorphism
>>> A = Object(A)
>>> B = Object(B)
>>> f = NamedMorphism(A, B, f)
>>> f
NamedMorphism(Object(A), Object(B), f)
>>> f.name
f
name
Returns the name of the morphism.
Examples
>>>
>>>
>>>
>>>
>>>
f
class sympy.categories.CompositeMorphism
Represents a morphism which is a composition of other morphisms.
Two composite morphisms are equal if the morphisms they were obtained from (components) are the same and were listed in the same order.
The arguments to the constructor for this class should be listed in diagram order: to
obtain the composition g f from the instances of Morphism (page 1829) g and f use
CompositeMorphism(f, g).
1831
Examples
>>> from sympy.categories import Object, NamedMorphism, CompositeMorphism
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> g * f
CompositeMorphism((NamedMorphism(Object(A), Object(B), f),
NamedMorphism(Object(B), Object(C), g)))
>>> CompositeMorphism(f, g) == g * f
True
codomain
Returns the codomain of this composite morphism.
The codomain of the composite morphism is the codomain of its last component.
Examples
>>> from sympy.categories import Object, NamedMorphism
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> (g * f).codomain
Object(C)
components
Returns the components of this composite morphism.
Examples
>>> from sympy.categories import Object, NamedMorphism
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> (g * f).components
(NamedMorphism(Object(A), Object(B), f),
NamedMorphism(Object(B), Object(C), g))
domain
Returns the domain of this composite morphism.
The domain of the composite morphism is the domain of its rst component.
Examples
1832
flatten(new name)
Forgets the composite structure of this morphism.
If new name is not empty, returns a NamedMorphism (page 1831) with the supplied
name, otherwise returns a Morphism (page 1829). In both cases the domain of the
new morphism is the domain of this composite morphism and the codomain of the
new morphism is the codomain of this composite morphism.
Examples
>>> from sympy.categories import Object, NamedMorphism
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> (g * f).flatten(h)
NamedMorphism(Object(A), Object(C), h)
class sympy.categories.IdentityMorphism
Represents an identity morphism.
An identity morphism is a morphism with equal domain and codomain, which acts as an
identity with respect to composition.
See Also:
Morphism (page 1829)
Examples
>>> from sympy.categories import Object, NamedMorphism, IdentityMorphism
>>> A = Object(A)
>>> B = Object(B)
>>> f = NamedMorphism(A, B, f)
>>> id_A = IdentityMorphism(A)
>>> id_B = IdentityMorphism(B)
>>> f * id_A == f
True
>>> id_B * f == f
True
class sympy.categories.Category
An (abstract) category.
A category [JoyOfCats] is a quadruple K = (O, hom, id, ) consisting of
a (set-theoretical) class O, whose members are called K-objects,
1833
for each pair (A, B) of K-objects, a set hom(A, B) whose members are called Kmorphisms from A to B,
for a each K-object A, a morphism id : A A, called the K-identity of A,
a composition law associating with every K-morphisms f : A B and g : B C a
K-morphism g f : A C, called the composite of f and g.
commutative diagrams
Returns the FiniteSet of diagrams which are known to be commutative in this category.
>>> from sympy.categories import Object, NamedMorphism, Diagram, Category
>>> from sympy import FiniteSet
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> d = Diagram([f, g])
>>> K = Category(K, commutative_diagrams=[d])
>>> K.commutative_diagrams == FiniteSet(d)
True
name
Returns the name of this category.
Examples
1834
objects
Returns the class of objects of this category.
Examples
>>> from sympy.categories import Object, Category
>>> from sympy import FiniteSet
>>> A = Object(A)
>>> B = Object(B)
>>> K = Category(K, FiniteSet(A, B))
>>> K.objects
Class({Object(A), Object(B)})
class sympy.categories.Diagram
Represents a diagram in a certain category.
Informally, a diagram is a collection of objects of a category and certain morphisms
between them. A diagram is still a monoid with respect to morphism composition; i.e.,
identity morphisms, as well as all composites of morphisms included in the diagram
belong to the diagram. For a more formal approach to this notion see [Pare1970].
The components of composite morphisms are also added to the diagram. No properties
are assigned to such morphisms by default.
A commutative diagram is often accompanied by a statement of the following kind: if
such morphisms with such properties exist, then such morphisms which such properties exist and the diagram is commutative. To represent this, an instance of Diagram
(page 1835) includes a collection of morphisms which are the premises and another collection of conclusions. premises and conclusions associate morphisms belonging to
the corresponding categories with the FiniteSets of their properties.
The set of properties of a composite morphism is the intersection of the sets of properties
of its components. The domain and codomain of a conclusion morphism should be among
the domains and codomains of the morphisms listed as the premises of a diagram.
No checks are carried out of whether the supplied object and morphisms do belong to
one and the same category.
References
1835
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> d = Diagram([f, g])
>>> premises_keys = sorted(d.premises.keys(), key=default_sort_key)
>>> pprint(premises_keys, use_unicode=False)
[g*f:A-->C, id:A-->A, id:B-->B, id:C-->C, f:A-->B, g:B-->C]
>>> pprint(d.premises, use_unicode=False)
{g*f:A-->C: EmptySet(), id:A-->A: EmptySet(), id:B-->B: EmptySet(), id:C-->C:
EmptySet(), f:A-->B: EmptySet(), g:B-->C: EmptySet()}
>>> d = Diagram([f, g], {g * f: unique})
>>> pprint(d.conclusions)
{g*f:A-->C: {unique}}
conclusions
Returns the conclusions of this diagram.
Examples
>>> from sympy.categories import Object, NamedMorphism
>>> from sympy.categories import IdentityMorphism, Diagram
>>> from sympy import FiniteSet
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> d = Diagram([f, g])
>>> IdentityMorphism(A) in d.premises.keys()
True
>>> g * f in d.premises.keys()
True
>>> d = Diagram([f, g], {g * f: unique})
>>> d.conclusions[g * f] == FiniteSet(unique)
True
hom(A, B)
Returns a 2-tuple of sets of morphisms between objects A and B: one set of morphisms listed as premises, and the other set of morphisms listed as conclusions.
See Also:
Object (page 1829), Morphism (page 1829)
Examples
>>> from sympy.categories import Object, NamedMorphism, Diagram
>>> from sympy import pretty
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> d = Diagram([f, g], {g * f: unique})
>>> print(pretty(d.hom(A, C), use_unicode=False))
({g*f:A-->C}, {g*f:A-->C})
1836
is subdiagram(diagram)
Checks whether diagram is a subdiagram of self. Diagram D0 is a subdiagram of D
if all premises (conclusions) of D0 are contained in the premises (conclusions) of D.
The morphisms contained both in D0 and D should have the same properties for D0
to be a subdiagram of D.
Examples
>>> from sympy.categories import Object, NamedMorphism, Diagram
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> d = Diagram([f, g], {g * f: unique})
>>> d1 = Diagram([f])
>>> d.is_subdiagram(d1)
True
>>> d1.is_subdiagram(d)
False
objects
Returns the FiniteSet of objects that appear in this diagram.
Examples
>>> from sympy.categories import Object, NamedMorphism, Diagram
>>> A = Object(A)
>>> B = Object(B)
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> d = Diagram([f, g])
>>> d.objects
{Object(A), Object(B), Object(C)}
premises
Returns the premises of this diagram.
Examples
>>> from sympy.categories import Object, NamedMorphism
>>> from sympy.categories import IdentityMorphism, Diagram
>>> from sympy import pretty
>>> A = Object(A)
>>> B = Object(B)
>>> f = NamedMorphism(A, B, f)
>>> id_A = IdentityMorphism(A)
>>> id_B = IdentityMorphism(B)
>>> d = Diagram([f])
>>> print(pretty(d.premises, use_unicode=False))
{id:A-->A: EmptySet(), id:B-->B: EmptySet(), f:A-->B: EmptySet()}
1837
groups=None,
The mission of this class is to analyse the structure of the supplied diagram and to place
its objects on a grid such that, when the objects and the morphisms are actually drawn,
the diagram would be readable, in the sense that there will not be many intersections of
moprhisms. This class does not perform any actual drawing. It does strive nevertheless
to oer sucient metadata to draw a diagram.
Consider the following simple diagram.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
Sometimes one sees the diagram as consisting of logical groups. One can advise DiagramGrid as to such groups by employing the groups keyword argument.
1838
D = Object(D)
f = NamedMorphism(A, B, f)
g = NamedMorphism(B, C, g)
h = NamedMorphism(D, A, h)
k = NamedMorphism(D, B, k)
diagram = Diagram([f, g, h, k])
Now, we can group the objects A and D to have them near one another:
>>> grid = DiagramGrid(diagram, groups=[[A, D], B, C])
>>> pprint(grid)
B
C
A
E = Object(E)
f = NamedMorphism(A, B, f)
g = NamedMorphism(B, C, g)
h = NamedMorphism(C, D, h)
i = NamedMorphism(D, E, i)
diagram = Diagram([f, g, h, i])
When laid out with the generic layout, it does not get to look linear:
>>> grid = DiagramGrid(diagram)
>>> pprint(grid)
A B
C
D
E
One may sometimes need to transpose the resulting layout. While this can always be
done by hand, DiagramGrid (page 1838) provides a hint for that purpose:
1839
morphisms
Returns those morphisms (and their properties) which are suciently meaningful
to be drawn.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
1840
width
Returns the number of columns in this diagram layout.
Examples
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
2
1841
looping start and looping end are currently only used for loop morphisms, those which
have the same domain and codomain. These two attributes should store a valid Xy-pic
direction and specify, correspondingly, the direction the arrow gets out into and the
direction the arrow gets back from:
>>> astr = ArrowStringDescription(
... unit=mm, curving=None, curving_amount=None,
... looping_start=u, looping_end=l, horizontal_direction=,
... vertical_direction=, label_position=_, label=f)
>>> print(str(astr))
\ar@(u,l)[]_{f}
label displacement controls how far the arrow label is from the ends of the arrow. For
example, to position the arrow label near the arrow head, use >:
>>> astr = ArrowStringDescription(
... unit=mm, curving=^, curving_amount=12,
... looping_start=None, looping_end=None, horizontal_direction=d,
... vertical_direction=r, label_position=_, label=f)
>>> astr.label_displacement = >
>>> print(str(astr))
\ar@/^12mm/[dr]_>{f}
Finally, arrow style is used to specify the arrow style. To get a dashed arrow, for example, use {>} as arrow style:
>>> astr = ArrowStringDescription(
... unit=mm, curving=^, curving_amount=12,
... looping_start=None, looping_end=None, horizontal_direction=d,
... vertical_direction=r, label_position=_, label=f)
>>> astr.arrow_style = {-->}
>>> print(str(astr))
\ar@/^12mm/@{-->}[dr]_{f}
See Also:
XypicDiagramDrawer (page 1843)
Notes
Instances of ArrowStringDescription (page 1841) will be constructed by XypicDiagramDrawer (page 1843) and provided for further use in formatters. The user is not
expected to construct instances of ArrowStringDescription (page 1841) themselves.
To be able to properly utilise this class, the reader is encouraged to checkout the Xy-pic
user guide, available at [Xypic].
1842
References
[Xypic] http://www.tug.org/applications/Xy-pic/
class sympy.categories.diagram drawing.XypicDiagramDrawer
Given a Diagram and the corresponding DiagramGrid (page 1838), produces the Xy-pic
representation of the diagram.
The most important method in this class is draw. Consider the following triangle diagram:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
To draw this diagram, its objects need to be laid out with a DiagramGrid (page 1838):
>>> grid = DiagramGrid(diagram)
To modify the appearance of all arrows in the diagram, set default arrow formatter.
For example, to place all morphism labels a little bit farther from the arrow head so that
they look more centred, do as follows:
>>> def default_formatter(astr):
...
astr.label_displacement = (0.45)
>>> drawer.default_arrow_formatter = default_formatter
>>> print(drawer.draw(diagram, grid))
1843
\xymatrix{
A \ar@{-->}[d]_(0.45){\exists !g\circ f} \ar[r]^(0.45){f} & B \ar[ld]^(0.45){g} \\
C &
}
In some diagrams some morphisms are drawn as curved arrows. Consider the following
diagram:
>>> D = Object(D)
>>> E = Object(E)
>>> h = NamedMorphism(D, A, h)
>>> k = NamedMorphism(D, B, k)
>>> diagram = Diagram([f, g, h, k])
>>> grid = DiagramGrid(diagram)
>>> drawer = XypicDiagramDrawer()
>>> print(drawer.draw(diagram, grid))
\xymatrix{
A \ar[r]_{f} & B \ar[d]^{g} & D \ar[l]^{k} \ar@/_3mm/[ll]_{h} \\
& C &
}
To control how far the morphisms are curved by default, one can use the unit and default curving amount attributes:
>>> drawer.unit = cm
>>> drawer.default_curving_amount = 1
>>> print(drawer.draw(diagram, grid))
\xymatrix{
A \ar[r]_{f} & B \ar[d]^{g} & D \ar[l]^{k} \ar@/_1cm/[ll]_{h} \\
& C &
}
In some diagrams, there are multiple curved morphisms between the same two objects.
To control by how much the curving changes between two such successive morphisms,
use default curving step:
>>> drawer.default_curving_step = 1
>>> h1 = NamedMorphism(A, D, h1)
>>> diagram = Diagram([f, g, h, k, h1])
>>> grid = DiagramGrid(diagram)
>>> print(drawer.draw(diagram, grid))
\xymatrix{
A \ar[r]_{f} \ar@/^1cm/[rr]^{h_{1}} & B \ar[d]^{g} & D \ar[l]^{k} \ar@/_2cm/[ll]_{h} \\
& C &
}
1844
>>>
>>>
>>>
>>>
C = Object(C)
f = NamedMorphism(A, B, f)
g = NamedMorphism(B, C, g)
diagram = Diagram([f, g], {g * f: unique})
To draw this diagram, its objects need to be laid out with a DiagramGrid (page 1838):
>>> grid = DiagramGrid(diagram)
The argument masked can be used to skip morphisms in the presentation of the
diagram:
>>> print(drawer.draw(diagram, grid, masked=[g * f]))
\xymatrix{
A \ar[r]^{f} & B \ar[ld]^{g} \\
C &
}
Finally, the diagram format argument can be used to specify the format string of
the diagram. For example, to increase the spacing by 1 cm, proceeding as follows:
>>> print(drawer.draw(diagram, grid, diagram_format=@+1cm))
\xymatrix@+1cm{
A \ar[d]_{g\circ f} \ar[r]^{f} & B \ar[ld]^{g} \\
C &
}
1845
>>> C = Object(C)
>>> f = NamedMorphism(A, B, f)
>>> g = NamedMorphism(B, C, g)
>>> diagram = Diagram([f, g], {g * f: unique})
>>> print(xypic_draw_diagram(diagram))
\xymatrix{
A \ar[d]_{g\circ f} \ar[r]^{f} & B \ar[ld]^{g} \\
C &
}
This object serves as a container/parent for all coordinate system charts that can be
dened on the patch it represents.
Examples:
Dene a Manifold and a Patch, and then dene two coord systems on that patch:
>>> from sympy import symbols, sin, cos, pi
>>> from sympy.diffgeom import Manifold, Patch, CoordSystem
>>> r, theta = symbols(r, theta)
>>> m = Manifold(M, 2)
>>> patch = Patch(P, m)
>>> rect = CoordSystem(rect, patch)
>>> polar = CoordSystem(polar, patch)
>>> rect in patch.coord_systems
True
1847
Dene a basis scalar eld (i.e. a coordinate function), that takes a point and returns its
coordinates. It is an instance of BaseScalarField.
>>> rect.coord_function(0)(p)
-sqrt(2)/2
>>> rect.coord_function(1)(p)
sqrt(2)/2
Dene a basis vector eld (i.e. a unit vector eld along the coordinate line). Vectors are
also dierential operators on scalar elds. It is an instance of BaseVectorField.
>>>
>>>
>>>
1
>>>
0
v_x = rect.base_vector(0)
x = rect.coord_function(0)
v_x(x)
v_x(v_x(x))
If you provide a list of names the elds will print nicely: - without provided names:
>>> x, v_x, dx
(rect_0, e_rect_0, drect_0)
1848
base vectors()
Returns a list of all base vectors.
For more details see the base vector method of this class.
connect to(to sys, from coords, to exprs, inverse=True, ll in gaps=False)
Register the transformation used to switch to another coordinate system.
Parameters to sys :
another instance of CoordSystem
from coords :
list of symbols in terms of which to exprs is given
to exprs :
list of the expressions of the new coordinate tuple
inverse :
try to deduce and register the inverse transformation
ll in gaps :
try to deduce other transformation that are made possible by composing the present transformation with other already registered transformation
coord function(coord index)
Return a BaseScalarField that takes a point and returns one of the coords.
Takes a point and returns its coordinate in this coordinate system.
See the docstring of CoordSystem for examples.
coord functions()
Returns a list of all coordinate functions.
For more details see the coord function method of this class.
coord tuple transform to(to sys, coords)
Transform coords to coord system to sys.
See the docstring of CoordSystem for examples.
jacobian(to sys, coords)
Return the jacobian matrix of a transformation.
point(coords)
Create a Point with coordinates given in this coord system.
See the docstring of CoordSystem for examples.
point to coords(point)
Calculate the coordinates of a point in this coord system.
See the docstring of CoordSystem for examples.
class sympy.diffgeom.Point(coord sys, coords)
Point in a Manifold object.
To dene a point you must supply coordinates and a coordinate system.
The usage of this object after its denition is independent of the coordinate system that
was used in order to dene it, however due to limitations in the simplication routines
you can arrive at complicated expressions if you use inappropriate coordinate systems.
1849
Examples
coords(to sys=None)
Coordinates of the point in a given coordinate system.
If to sys is None it returns the coordinates in the system in which the point was
dened.
class sympy.diffgeom.BaseScalarField(coord sys, index)
Base Scalar Field over a Manifold for a given Coordinate System.
A scalar eld takes a point as an argument and returns a scalar.
A base scalar eld of a coordinate system takes a point and returns one of the coordinates
of that point in the coordinate system in question.
To dene a scalar eld you need to choose the coordinate system and the index of the
coordinate.
The use of the scalar eld after its denition is independent of the coordinate system in
which it was dened, however due to limitations in the simplication routines you may
arrive at more complicated expression if you use unappropriate coordinate systems.
You can build complicated scalar elds by just building up SymPy expressions containing
BaseScalarField instances.
Examples
1850
Examples of elds:
>>> fx = BaseScalarField(rect, 0)
>>> fy = BaseScalarField(rect, 1)
>>> (fx**2+fy**2).rcall(point)
r0**2
>>> g = Function(g)
>>> ftheta = BaseScalarField(polar, 1)
>>> fg = g(ftheta-pi)
>>> fg.rcall(point)
g(-pi)
1851
>>> s_field.rcall(point_p)
g(r0*cos(theta0), r0*sin(theta0))
Vector eld:
>>> v = BaseVectorField(R2_r, 1)
>>> pprint(v(s_field))
/ d
\|
|-----(g(x, xi_2))||
\dxi_2
/|xi_2=y
>>> pprint(v(s_field).rcall(point_r).doit())
d
---(g(x0, y0))
dy0
>>> pprint(v(s_field).rcall(point_p).doit())
/ d
\|
|-----(g(r0*cos(theta0), xi_2))||
\dxi_2
/|xi_2=r0*sin(theta0)
from
from
from
from
sympy.diffgeom.rn import R2
sympy.diffgeom import Commutator
sympy import pprint
sympy.simplify import simplify
Vector elds:
>>>
>>>
>>>
>>>
0
>>>
>>>
>>>
>>>
from
from
from
from
Vector elds:
>>> e_x, e_y, = R2.e_x, R2.e_y
Dierentials:
>>> dg = Differential(s_field)
>>> dg
d(g(x, y))
>>> pprint(dg(e_x))
/ d
\|
|-----(g(xi_1, y))||
\dxi_1
/|xi_1=x
>>> pprint(dg(e_y))
/ d
\|
|-----(g(x, xi_2))||
\dxi_2
/|xi_2=y
class sympy.diffgeom.TensorProduct(*args)
Tensor product of forms.
The tensor product permits the creation of multilinear functionals (i.e. higher order tensors) out of lower order forms (e.g. 1-forms). However, the higher tensors thus created
lack the interesting features provided by the other type of product, the wedge product,
namely they are not antisymmetric and hence are not form elds.
Examples
from
from
from
from
1853
You can make partial contraction for instance when raising an index. Putting None in
the second argument of rcall means that the respective position in the tensor product
is left as it is.
>>> TP = TensorProduct
>>> metric = TP(R2.dx, R2.dx) + 3*TP(R2.dy, R2.dy)
>>> metric.rcall(R2.e_y, None)
3*dy
class sympy.diffgeom.WedgeProduct(*args)
Wedge product of forms.
In the context of integration only completely antisymmetric forms make sense. The
wedge product permits the creation of such forms.
Examples
from
from
from
from
1854
0
>>> LieDerivative(R2.e_x, R2.x)
1
>>> LieDerivative(R2.e_x, R2.e_x)
0
The Lie derivative of a tensor eld by another tensor eld is equal to their commutator:
>>> LieDerivative(R2.e_x, R2.e_r)
Commutator(e_x, e_r)
>>> LieDerivative(R2.e_x + R2.e_y, R2.x)
1
>>> tp = TensorProduct(R2.dx, R2.dy)
>>> LieDerivative(R2.e_x, tp)
LieDerivative(e_x, TensorProduct(dx, dy))
>>> LieDerivative(R2.e_x, tp).doit()
LieDerivative(e_rectangular_0, TensorProduct(dx, dy))
1855
n=6,
co-
1856
1857
sympy.diffgeom.twoform to matrix(expr)
Return the matrix representing the twoform.
For the twoform w return the matrix M such that M [i, j] = w(ei , ej ), where ei is the i-th
base vector eld for the coordinate system in which the expression of w is given.
1858
Examples
>>> from sympy.diffgeom.rn import R2
>>> from sympy.diffgeom import twoform_to_matrix, TensorProduct
>>> TP = TensorProduct
>>> twoform_to_matrix(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
Matrix([
[1, 0],
[0, 1]])
>>> twoform_to_matrix(R2.x*TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
Matrix([
[x, 0],
[0, 1]])
>>> twoform_to_matrix(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy) - TP(R2.dx, R2.dy)/2)
Matrix([
[
1, 0],
[-1/2, 1]])
1859
Examples
>>> from sympy import pprint, exp
>>> from sympy.diffgeom.rn import R2
>>> from sympy.diffgeom import metric_to_Riemann_components, TensorProduct
>>> TP = TensorProduct
>>> metric_to_Riemann_components(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
((((0, 0), (0, 0)), ((0, 0), (0, 0))), (((0, 0), (0, 0)), ((0, 0),
(0, 0))))
1860
R2.r**2*TP(
CHAPTER
SIX
DEVELOPMENT TIPS:
COMPARISONS IN PYTHON
6.1 Introduction
When debugging comparisons and hashes in SymPy, it is necessary to understand when exactly Python calls each method. Unfortunately, the ocial Python documentation for this is
not very detailed (see the docs for rich comparison, cmp () and hash () methods).
We wrote this guide to ll in the missing gaps. After reading it, you should be able to understand which methods do (and do not) get called and the order in which they are called.
6.2 Hashing
Every Python class has a
def __hash__(self):
return id(self)
You can reimplement it to return a dierent integer that you compute on your own. hash(x)
just calls x. hash (). Python builtin classes usually redene the hash () method. For
example, an int has something like this:
def __hash__(self):
return int(self)
The general idea about hashes is that if two objects have a dierent hash, they are not equal,
but if they have the same hash, they might be equal. (This is usually called a hash collision
and you need to use the methods described in the next section to determine if the objects
really are equal).
The only requirement from the Python side is that the hash value mustnt change after it is
returned by the hash () method.
Please be aware that hashing is platform-dependent. This means that you can get dierent
hashes for the same SymPy object on dierent platforms. This aects for instance sorting of
sympy expressions. You can also get SymPy objects printed in dierent order.
1861
When developing, you have to be careful about this, especially when writing tests. It is possible that your test runs on a 32-bit platform, but not on 64-bit. An example:
>> from sympy import *
>> x = Symbol(x)
>> r = rootfinding.roots quartic(Poly(x**4 - 6*x**3 + 17*x**2 - 26*x + 20, x))
>> [i.evalf(2) for i in r]
[1.0 + 1.7*I, 2.0 - 1.0*I, 2.0 + I, 1.0 - 1.7*I]
If you get this order of solutions, you are probably running 32-bit system. On a 64-bit system
you would get the following:
>> [i.evalf(2) for i in r]
[1.0 - 1.7*I, 1.0 + 1.7*I, 2.0 + I, 2.0 - 1.0*I
it will fail on a 64-bit platforms, even if it works for your 32-bit system. You can avoid this by
using the sorted() or set() Python built-in:
r = [i.evalf(2) for i in r]
assert set(r) == set([1.0 + 1.7*I, 2.0 - 1.0*I, 2.0 + I, 1.0 - 1.7*I])
This approach does not work for doctests since they always compare strings that would be
printed after a prompt. In that case you could make your test print results using a combination
of str() and sorted():
>> sorted([str(i.evalf(2)) for i in r])
[1.0 + 1.7*I, 1.0 - 1.7*I, 2.0 + I, 2.0 - 1.0*I]
or, if you dont want to show the values as strings, then sympify the results or the sorted list:
>> [S(s) for s in sorted([str(i.evalf(2)) for i in r])]
[1.0 + 1.7*I, 1.0 - 1.7*I, 2.0 + I, 2.0 - I]
The printing of SymPy expressions might be also aected, so be careful with doctests. If you
get the following on a 32-bit system:
>> print dsolve(f(x).diff(x, 2) + 2*f(x).diff(x) - f(x), f(x))
f(x) == C1*exp(-x + x*sqrt(2)) + C2*exp(-x - x*sqrt(2))
1862
a.__eq__(b)
b.__eq__(a)
a.__cmp__(b)
b.__cmp__(a)
id(a) == id(b)
If you write:
a < b
If you write:
a <= b
Python calls the same chain of methods as for the b < a and c < b comparisons.
If you write any of the following:
1 There is also the similar NotImplementedError exception, which one may be tempted to raise to obtain the same
eect as returning NotImplemented.
But these are not the same, and Python will completely ignore NotImplementedError with respect to choosing
appropriate comparison method, and will just propagate this exception upwards, to the caller.
So return NotImplemented is not the same as raise NotImplementedError.
1863
a in {d: 5}
a in set([d, d, d])
set([a, b]) == set([a, b])
If hash(a) != hash(d) then the result of the statement a in {d: 5} is immediately False
(remember how hashes work in general). If hash(a) == hash(d)) Python goes through the
method resolution of the == operator as shown above.
1864
return NotImplemented
def __cmp__(self, o):
print %s.__cmp__(%s) % (self.a, o.a)
#return cmp(self._hash, o._hash)
return NotImplemented
def __eq__(self, o):
print %s.__eq__(%s) % (self.a, o.a)
return NotImplemented
def __ne__(self, o):
print %s.__ne__(%s) % (self.a, o.a)
return NotImplemented
def __hash__(self):
print %s.__hash__() % (self.a)
return self._hash
def show(s):
print --- %s % s + -*40
eval(s)
a
b
c
d
=
=
=
=
A(a,
A(b,
A(c,
A(d,
1)
2)
3)
1)
show(a == b)
show(a != b)
show(a < b)
show(a <= b)
show(a > b)
show(a >= b)
show(sorted([a, b, c]))
show({d: 5})
show(a in {d: 5})
show(set([d, d, d]))
show(a in set([d, d, d]))
show(set([a, b]))
print --- x = set([a, b]); y = set([a, b]); ---
x = set([a, b])
y = set([a, b])
print
x == y :
x == y
print --- x = set([a, b]); y = set([b, d]); ---
x = set([a, b])
y = set([b, d])
print
x == y :
x == y
1865
a. cmp (b)
b. cmp (a)
--- a != b ---------------------------------------a. ne (b)
b. ne (a)
a. cmp (b)
b. cmp (a)
--- a < b ---------------------------------------a. lt (b)
b. gt (a)
a. cmp (b)
b. cmp (a)
--- a <= b ---------------------------------------a. le (b)
b. ge (a)
a. cmp (b)
b. cmp (a)
--- a > b ---------------------------------------a. gt (b)
b. lt (a)
a. cmp (b)
b. cmp (a)
--- a >= b ---------------------------------------a. ge (b)
b. le (a)
a. cmp (b)
b. cmp (a)
--- sorted([a, b, c]) ---------------------------------------b. lt (a)
a. gt (b)
b. cmp (a)
a. cmp (b)
c. lt (b)
b. gt (c)
c. cmp (b)
b. cmp (c)
--- {d: 5} ---------------------------------------d. hash ()
--- a in {d: 5} ---------------------------------------d. hash ()
a. hash ()
d. eq (a)
a. eq (d)
d. cmp (a)
a. cmp (d)
--- set([d, d, d]) ---------------------------------------d. hash ()
d. hash ()
d. hash ()
--- a in set([d, d, d]) ---------------------------------------d. hash ()
d. hash ()
d. hash ()
a. hash ()
d. eq (a)
a. eq (d)
d. cmp (a)
a. cmp (d)
1866
1867
1868
CHAPTER
SEVEN
WIKI
SymPy has a public wiki located at http://wiki.sympy.org. Users should feel free to contribute
to this wiki anything interesting/useful.
7.1 FAQ
FAQ is one of the most useful wiki pages. It has answers to frequently-asked questions.
1869
1870
Chapter 7. Wiki
CHAPTER
EIGHT
SYMPY PAPERS
A list of papers which either use or mention SymPy, as well as presentations given about
SymPy at conferences can be seen at SymPy Papers.
1871
1872
CHAPTER
NINE
PLANET SYMPY
We have a blog aggregator at http://planet.sympy.org.
1873
1874
CHAPTER
TEN
SYMPY LOGOS
SymPy has a collection of ocial logos, which can be generated from sympy.svg < https :
//github.com/sympy/sympy/tree/master/doc/src/sympy.svg > in your local copy of SymPy by:
$ cd doc
$ make logo # will be stored in the build/logo subdirectory
The license of all the logos is the same as SymPy: BSD. See the LICENSE le in the trunk for
more information.
1875
1876
CHAPTER
ELEVEN
1877
1878
CHAPTER
TWELVE
1879
1880
CHAPTER
THIRTEEN
ABOUT
13.1 SymPy Development Team
SymPy is a team project and it was developed by a lot of people.
Here is a list of contributors together with what they do, (and in some cases links to their
wiki pages), where they describe in more details what they do and what they are interested
in (some people didnt want to be mentioned here, so see our repository history for a full list).
1. Ondej ertk: started the project in 2006, on Jan 4, 2011 passed the project leadership
to Aaron Meurer
2. Fabian Pedregosa: everything, reviewing patches, releases, general advice (issues and
mailinglist), GSoC 2009
3. Jurjen N.E. Bos: pretty printing and other patches
4. Mateusz Paprocki: GSoC 2007, concrete math module, integration module, new core
integration, a lot of patches, general advice, new polynomial module, improvements to
solvers, simplications, patch review
5. Marc-Etienne M.Leveille: matrix patch
6. Brian Jorgensen: GSoC 2007, plotting module and related things, patches
7. Jason Gedge: GSoC 2007, geometry module, a lot of patches and xes, new core integration
8. Robert Schwarz: GSoC 2007, polynomials module, patches
9. Pearu Peterson: new core, sympycore project, general advice (issues and mailinglist)
10. Fredrik Johansson: mpmath project and its integration in SymPy, number theory, combinatorial functions, products & summation, statistics, units, patches, documentation,
general advice (issues and mailinglist)
11. Chris Wu: GSoC 2007, linear algebra module
12. Ulrich Hecht: pattern matching and other patches
13. Goutham Lakshminarayan: number theory functions
14. David Lawrence: GHOP, Mathematica parser, square root denesting
15. Jaroslaw Tworek: GHOP, sympify AST implementation, sqrt() refactoring, maxima parser
and other patches
16. David Marek: GHOP, derivative evaluation patch, int(NumberSymbol) x
17. Bernhard R. Link: documentation patch
1881
1882
1883
1884
1885
1886
202. Joseph Dougherty: modied whitespace cleaning to remove multiple newlines at eof
203. marshall2389: Spelling correction
204. Guru Devanla: Implemented quantum density operator
205. George Waksman: Implemented JavaScript code printer and MathML printer
206. Angus Grith: Fix bug in rsolve
207. Timothy Reluga: Rewrite trigonometric functions as rationals
208. Brian Stephanik: Test for a bug in fcode
209. Ljubia Moi: Serbian translation of the tutorial
210. Piotr Korgul: Polish translation of the tutorial
211. Rom le Clair: French translation of the tutorial
212. Alexandr Popov: Fixes to Pauli algebra
213. Saurabh Jha: Work on Kauers algorithm
214. Tarun Gaba: Implemented some trigonometric integrals
215. Takafumi Arakaki: Add info target to the doc Makele
216. Alexander Eberspcher: correct typo in aboutus.rst
217. Sachin Joglekar: Simplication of logic expressions to SOP and POS forms
218. Tyler Pirtle: Fix improperly formatted error message
219. Vasily Povalyaev: Fix latex(Min)
220. Colleen Lee: replace uses of fnan with S.NaN
221. Niklas Thrne: Fix links in the docs
222. Huijun Mai: Chinese translation of the tutorial
223. Marek uppa: Improvements to symbols, tests
224. Prasoon Shukla: Bug xes
225. Sergey B Kirpichev: Bug xes
226. Stefen Yin: Fixes to the mechanics module
227. Thomas Hisch: Improvements to the printing module
228. Matthew Ho: Addition to quantum module
229. Madeleine Ball: Bug x
230. Case Van Horsen: Fixes to gmpy support
231. Mary Clark: Improvements to the group theory module
232. Rishabh Dixit: Bug xes
233. Acebulf: Typos
234. Manoj Kumar: Bug x
235. Akshit Agarwal: improvements to range handling in symbols
236. CJ Carey: Fix for limits of factorials
237. Patrick Lacasse: Fix for Piecewise.subs
238. Ananya H: Bug x
239. Tarang Patel: added test for issue 4739
1887
1888
1889
1890
354. Leonid Blouvshtein: make integrals aware of both limits being +/-oo
355. Peleg Michaeli: implement the Rademacher distribution
356. Chai Wah Wu: Implement divisor sigma function
357. ck Lux: handle zoo, oo, nan in as int and round
358. zsc347: xed a bug in crypto.rsa private key
359. Hamish Dickson: improve qubit tests
360. Michael Gallaspy: improve handling of inequalities involving RootOf
361. Roman Inianskas: add svg support to preview
362. Duane Nykamp: improved function handling in parse expr
Up-to-date list in the order of the rst contribution is given in the AUTHORS le.
You can nd a brief history of SymPy in the README.
1891
13.3 License
Unless stated otherwise, all les in the SymPy project, SymPys webpage (and wiki), all images
and all documentation including this Users Guide are licensed using the new BSD license:
Copyright (c) 2006-2014 SymPy Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
a. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
b. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
c. Neither the name of SymPy nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
1892
CHAPTER
FOURTEEN
( dF )
1 ( d2 F )
1 ( d3 F )
2
h
+
h
+
h3 + ...
2
x
x
0
dx 0
2! dx
3! dx3 x0
1 ( dn F )
.
n! dxn x0
1893
What follows are manipulations using SymPy to formulate approximations for derivatives of
a given order and to assess its accuracy. First, we use SymPy to derive the approximations
by using a rather brute force method frequently covered in introductory treatments. Later
we shall make use of other SymPy functions which get the job done with more eciency.
x
0
dx
h
where the O(h) refers to the lowest order term in the series in h. This establishes that the
derivative approximation is of rst order accuracy. Put another way, if we decide that we can
only use the two pairs (xi , Fi ) and (xi+1 , Fi+1 ) we obtain a rst order accurate derivative.
In addition to (xi , Fi ) we next use the two points (xi+1 , Fi+1 ) and (xi+2 , Fi+2 ). Then we have two
equations:
Fi+1 = Fi + c1 h +
Fi+2 = Fi + c1 (2h) +
1
1
c2 h2 + c3 h3 + ...
2
3!
1
1
c2 (2h)2 + c3 (2h)3 + ...
2
3!
If we again want to nd the rst derivative (c1 ), we can do that by eliminating the term involving c2 from the two equations. We show how to do it using SymPy.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
...
Now we make a matrix consisting of the coecients of the c i in the nth degree polynomial P.
Coecients of ci evaluated at xi :
>>> m11 = P(x0 , x0, c, n).diff(c[0])
>>> m12 = P(x0 , x0, c, n).diff(c[1])
>>> m13 = P(x0 , x0, c, n).diff(c[2])
Coecients of ci evaluated at xi + h:
>>> m21 = P(x0+h, x0, c, n).diff(c[0])
>>> m22 = P(x0+h, x0, c, n).diff(c[1])
>>> m23 = P(x0+h, x0, c, n).diff(c[2])
1894
Coecients of ci evaluated at xi + 2 h:
>>> m31 = P(x0+2*h, x0, c, n).diff(c[0])
>>> m32 = P(x0+2*h, x0, c, n).diff(c[1])
>>> m33 = P(x0+2*h, x0, c, n).diff(c[2])
M.inv() * R
Note that all three coecients make up the solution. The desired rst derivative is coecient
c1 which is X[1].
>>> print(together(X[1]))
(4*F_{i+1} - F_{i+2} - 3*F_{i})/(2*h)
Now that we have the matrix of coecients we next form the right-hand-side and solve by
inverting M :
>>>
>>>
>>>
>>>
>>>
#
R
#
#
X
1895
These two examples serve to show how one can directly nd second order accurate rst
derivatives using SymPy. The rst example uses values of x and F at all three points xi , xi+1 ,
and xi+2 whereas the second example only uses values of x at the two points xi1 and xi+1 and
thus is a bit more ecient.
From these two simple examples a general rule is that if one wants a rst derivative to be
accurate to O(hn ) then one needs n+1 function values in the approximating polynomial (here
provided via the function P (x, x0, c, n)).
Now lets assess the question of the accuracy of the centered dierence result to see how we
determine that it is really second order. To do this we take the result for dF /dx and substitute
in the polynomial expansion for a higher order polynomial and see what we get. To this end,
we make a set of eight coecients d and use them to perform the check:
>>> d = symbols(c:8)
>>> dfdxcheck = (P(x0+h, x0, d, 8) - P(x0-h, x0, d, 8))/(2*h)
>>> print(simplify(dfdxcheck)) # so the appropriate cancellation of terms involving h happens
c1 + c3*h**2/6 + c5*h**4/120 + c7*h**6/5040
Thus we see that indeed the derivative is c1 with the next term in the series of order h2 .
However, it can quickly become rather tedious to generalize the direct method as presented
above when attempting to generate a derivative approximation to high order, such as 6 or 8
although the method certainly works and using the present method is certainly less tedious
than performing the calculations by hand.
As we have seen in the discussion above, the simple centered approximation for the rst
derivative only uses two point values of the (xi , Fi ) pairs. This works ne until one encounters
the last point in the domain, say at i = N . Since our centered derivative approximation would
use data at the point (xN +1 , FN +1 ) we see that the derivative formula will not work. So, what to
do? Well, a simple way to handle this is to devise a dierent formula for this last point which
uses points for which we do have values. This is the so-called backward dierence formula.
To obtain it, we can use the same direct approach, except now us the three points (xN , FN ),
(xN 1 , FN 1 ), and (xN 2 , FN 2 ) and center the approximation at (xN , FN ). Here is how it can be
done using SymPy:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
...
Now we make a matrix consisting of the coecients of the ci in the dth degree polynomial P
coecients of ci evaluated at xi , xi1 , and xi+1 :
>>> m11 = P(xN , xN, c, n).diff(c[0])
>>> m12 = P(xN, xN, c, n).diff(c[1])
>>> m13 = P(xN , xN, c, n).diff(c[2])
1896
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
M.inv() * R
The rst derivative is coecient c1 which is X[1]. Thus the second order accurate approximation for the rst derivative is:
>>> print(The first derivative centered at the last point on the right is:)
The first derivative centered at the last point on the right is:
>>> print(together(X[1]))
(-4*F_{N-1} + F_{N-2} + 3*F_{N})/(2*h)
Of course, we can devise a similar formula for the value of the derivative at the left end of the
set of points at (x1 , F1 ) in terms of values at (x2 , F2 ) and (x3 , F3 ).
Also, we note that output of formats appropriate to Fortran, C, etc. may be done in the
examples given above.
Next we show how to perform these and many other discritizations of derivatives, but using
a much more ecient approach originally due to Bengt Fornberg and now incorported into
SymPy.
1897
1898
BIBLIOGRAPHY
2) and (2 > 3). The and operator coerces each side into a bool, returning the object itself
when it short-circuits. The bool of the Than operators will raise TypeError on purpose,
because SymPy cannot determine the mathematical ordering of symbolic expressions.
Thus, if we were to compute x > y > z, with x, y, and z being Symbols, Python converts
the statement (roughly) into these steps:
1. x > y > z
2. (x > y) and (y > z)
3. (GreaterThanObject) and (y > z)
4. (GreaterThanObject. nonzero ()) and (y > z)
5. TypeError
Because of the and added at step 2, the statement gets turned into a weak ternary
statement, and the rst objects nonzero method will raise TypeError. Thus, creating
a chained inequality is not possible.
In Python, there is no way to override the and operator, or to control how it short
circuits, so it is impossible to make something like x > y > z work. There was
a PEP to change this, PEP 335, but it was ocially closed in March, 2012.
[R49] For more information, see these two bug reports:
Separate boolean and symbolic relationals Issue 4986
It right 0 < x < 1 ? Issue 6059
[R50] This implementation detail is that Python provides no reliable method to determine that
a chained inequality is being built. Chained comparison operators are evaluated pairwise,
using and logic (see http://docs.python.org/2/reference/expressions.html#notin). This is
done in an ecient way, so that each object being compared is only evaluated once and
the comparison can short-circuit. For example, 1 > 2 > 3 is evaluated by Python as (1 >
2) and (2 > 3). The and operator coerces each side into a bool, returning the object itself
when it short-circuits. The bool of the Than operators will raise TypeError on purpose,
because SymPy cannot determine the mathematical ordering of symbolic expressions.
Thus, if we were to compute x > y > z, with x, y, and z being Symbols, Python converts
the statement (roughly) into these steps:
1. x > y > z
2. (x > y) and (y > z)
3. (GreaterThanObject) and (y > z)
4. (GreaterThanObject. nonzero ()) and (y > z)
5. TypeError
Because of the and added at step 2, the statement gets turned into a weak ternary
statement, and the rst objects nonzero method will raise TypeError. Thus, creating
a chained inequality is not possible.
In Python, there is no way to override the and operator, or to control how it short
circuits, so it is impossible to make something like x > y > z work. There was
a PEP to change this, PEP 335, but it was ocially closed in March, 2012.
[R51] For more information, see these two bug reports:
Separate boolean and symbolic relationals Issue 4986
It right 0 < x < 1 ? Issue 6059
1900
Bibliography
[R52] This implementation detail is that Python provides no reliable method to determine that
a chained inequality is being built. Chained comparison operators are evaluated pairwise,
using and logic (see http://docs.python.org/2/reference/expressions.html#notin). This is
done in an ecient way, so that each object being compared is only evaluated once and
the comparison can short-circuit. For example, 1 > 2 > 3 is evaluated by Python as (1 >
2) and (2 > 3). The and operator coerces each side into a bool, returning the object itself
when it short-circuits. The bool of the Than operators will raise TypeError on purpose,
because SymPy cannot determine the mathematical ordering of symbolic expressions.
Thus, if we were to compute x > y > z, with x, y, and z being Symbols, Python converts
the statement (roughly) into these steps:
1. x > y > z
2. (x > y) and (y > z)
3. (GreaterThanObject) and (y > z)
4. (GreaterThanObject. nonzero ()) and (y > z)
5. TypeError
Because of the and added at step 2, the statement gets turned into a weak ternary
statement, and the rst objects nonzero method will raise TypeError. Thus, creating
a chained inequality is not possible.
In Python, there is no way to override the and operator, or to control how it short
circuits, so it is impossible to make something like x > y > z work. There was
a PEP to change this, PEP 335, but it was ocially closed in March, 2012.
[R53] For more information, see these two bug reports:
Separate boolean and symbolic relationals Issue 4986
It right 0 < x < 1 ? Issue 6059
[R54] This implementation detail is that Python provides no reliable method to determine that
a chained inequality is being built. Chained comparison operators are evaluated pairwise,
using and logic (see http://docs.python.org/2/reference/expressions.html#notin). This is
done in an ecient way, so that each object being compared is only evaluated once and
the comparison can short-circuit. For example, 1 > 2 > 3 is evaluated by Python as (1 >
2) and (2 > 3). The and operator coerces each side into a bool, returning the object itself
when it short-circuits. The bool of the Than operators will raise TypeError on purpose,
because SymPy cannot determine the mathematical ordering of symbolic expressions.
Thus, if we were to compute x > y > z, with x, y, and z being Symbols, Python converts
the statement (roughly) into these steps:
1. x > y > z
2. (x > y) and (y > z)
3. (GreaterThanObject) and (y > z)
4. (GreaterThanObject. nonzero ()) and (y > z)
5. TypeError
Because of the and added at step 2, the statement gets turned into a weak ternary
statement, and the rst objects nonzero method will raise TypeError. Thus, creating
a chained inequality is not possible.
In Python, there is no way to override the and operator, or to control how it short
circuits, so it is impossible to make something like x > y > z work. There was
a PEP to change this, PEP 335, but it was ocially closed in March, 2012.
Bibliography
1901
1902
Bibliography
[R19] Michael Karr, Summation in Finite Terms, Journal of the ACM, Volume 28 Issue 2,
April 1981, Pages 305-350 http://dl.acm.org/citation.cfm?doid=322248.322255
[R20] http://en.wikipedia.org/wiki/Multiplication#Capital Pi notation
[R21] http://en.wikipedia.org/wiki/Empty product
[R22] Michael Karr, Summation in Finite Terms, Journal of the ACM, Volume 28 Issue 2,
April 1981, Pages 305-350 http://dl.acm.org/citation.cfm?doid=322248.322255
[R23] Marko Petkovsek, Herbert S. Wilf, Doron Zeilberger, A = B, AK Peters, Ltd., Wellesley,
MA, USA, 1997, pp. 73100
[R87] http://en.wikipedia.org/wiki/Inverse trigonometric functions
[R88] http://dlmf.nist.gov/4.23
[R89] http://functions.wolfram.com/ElementaryFunctions/ArcCos
[R90] http://en.wikipedia.org/wiki/Inverse trigonometric functions
[R91] http://dlmf.nist.gov/4.23
[R92] http://functions.wolfram.com/ElementaryFunctions/ArcCot
[R93] http://en.wikipedia.org/wiki/Inverse trigonometric functions
[R94] http://dlmf.nist.gov/4.23
[R95] http://functions.wolfram.com/ElementaryFunctions/ArcSin
[R96] http://en.wikipedia.org/wiki/Inverse trigonometric functions
[R97] http://dlmf.nist.gov/4.23
[R98] http://functions.wolfram.com/ElementaryFunctions/ArcTan
[R99] http://en.wikipedia.org/wiki/Inverse trigonometric functions
[R100] http://en.wikipedia.org/wiki/Atan2
[R101] http://functions.wolfram.com/ElementaryFunctions/ArcTan2
[R102] http://en.wikipedia.org/wiki/Trigonometric functions
[R103] http://dlmf.nist.gov/4.14
[R104] http://functions.wolfram.com/ElementaryFunctions/Cos
[R105] http://en.wikipedia.org/wiki/Trigonometric functions
[R106] http://dlmf.nist.gov/4.14
[R107] http://functions.wolfram.com/ElementaryFunctions/Cot
[R108] http://en.wikipedia.org/wiki/Lambert W function
[R109] http://en.wikipedia.org/wiki/Directed complete partial order
[R110] http://en.wikipedia.org/wiki/Lattice %28order%29
[R111] http://en.wikipedia.org/wiki/Trigonometric functions
[R112] http://dlmf.nist.gov/4.14
[R113] http://functions.wolfram.com/ElementaryFunctions/Sin
[R114] http://mathworld.wolfram.com/TrigonometryAngles.html
[R115] http://en.wikipedia.org/wiki/Trigonometric functions
[R116] http://dlmf.nist.gov/4.14
[R117] http://functions.wolfram.com/ElementaryFunctions/Tan
Bibliography
1903
1904
Bibliography
1905
1906
Bibliography
[R206] http://dlmf.nist.gov/9
[R207] http://www.encyclopediaofmath.org/index.php/Airy functions
[R208] http://mathworld.wolfram.com/AiryFunctions.html
[R209] http://en.wikipedia.org/wiki/Airy function
[R210] http://dlmf.nist.gov/9
[R211] http://www.encyclopediaofmath.org/index.php/Airy functions
[R212] http://mathworld.wolfram.com/AiryFunctions.html
[R213] http://en.wikipedia.org/wiki/Airy function
[R214] http://dlmf.nist.gov/9
[R215] http://www.encyclopediaofmath.org/index.php/Airy functions
[R216] http://mathworld.wolfram.com/AiryFunctions.html
[R217] http://en.wikipedia.org/wiki/Airy function
[R218] http://dlmf.nist.gov/9
[R219] http://www.encyclopediaofmath.org/index.php/Airy functions
[R220] http://mathworld.wolfram.com/AiryFunctions.html
[R221] http://en.wikipedia.org/wiki/B-spline
[R222] http://dlmf.nist.gov/25.11
[R223] http://en.wikipedia.org/wiki/Hurwitz zeta function
[R224] http://en.wikipedia.org/wiki/Dirichlet eta function
[R225] Bateman, H.; Erdelyi, A. (1953), Higher Transcendental Functions, Vol. I, New York:
McGraw-Hill. Section 1.11.
[R226] http://dlmf.nist.gov/25.14
[R227] http://en.wikipedia.org/wiki/Lerch transcendent
[R228] Luke, Y. L. (1969), The Special Functions and Their Approximations, Volume 1
[R229] http://en.wikipedia.org/wiki/Generalized hypergeometric function
[R230] Luke, Y. L. (1969), The Special Functions and Their Approximations, Volume 1
[R231] http://en.wikipedia.org/wiki/Meijer G-function
[R232] http://en.wikipedia.org/wiki/Elliptic integrals
[R233] http://functions.wolfram.com/EllipticIntegrals/EllipticK
[R234] http://en.wikipedia.org/wiki/Elliptic integrals
[R235] http://functions.wolfram.com/EllipticIntegrals/EllipticF
[R236] http://en.wikipedia.org/wiki/Elliptic integrals
[R237] http://functions.wolfram.com/EllipticIntegrals/EllipticE2
[R238] http://functions.wolfram.com/EllipticIntegrals/EllipticE
[R239] http://en.wikipedia.org/wiki/Elliptic integrals
[R240] http://functions.wolfram.com/EllipticIntegrals/EllipticPi3
[R241] http://functions.wolfram.com/EllipticIntegrals/EllipticPi
[R242] http://en.wikipedia.org/wiki/Jacobi polynomials
Bibliography
1907
[R243] http://mathworld.wolfram.com/JacobiPolynomial.html
[R244] http://functions.wolfram.com/Polynomials/JacobiP/
[R245] http://en.wikipedia.org/wiki/Jacobi polynomials
[R246] http://mathworld.wolfram.com/JacobiPolynomial.html
[R247] http://functions.wolfram.com/Polynomials/JacobiP/
[R248] http://en.wikipedia.org/wiki/Gegenbauer polynomials
[R249] http://mathworld.wolfram.com/GegenbauerPolynomial.html
[R250] http://functions.wolfram.com/Polynomials/GegenbauerC3/
[R251] http://en.wikipedia.org/wiki/Chebyshev polynomial
[R252] http://mathworld.wolfram.com/ChebyshevPolynomialoftheFirstKind.html
[R253] http://mathworld.wolfram.com/ChebyshevPolynomialoftheSecondKind.html
[R254] http://functions.wolfram.com/Polynomials/ChebyshevT/
[R255] http://functions.wolfram.com/Polynomials/ChebyshevU/
[R256] http://en.wikipedia.org/wiki/Chebyshev polynomial
[R257] http://mathworld.wolfram.com/ChebyshevPolynomialoftheFirstKind.html
[R258] http://mathworld.wolfram.com/ChebyshevPolynomialoftheSecondKind.html
[R259] http://functions.wolfram.com/Polynomials/ChebyshevT/
[R260] http://functions.wolfram.com/Polynomials/ChebyshevU/
[R261] http://en.wikipedia.org/wiki/Legendre polynomial
[R262] http://mathworld.wolfram.com/LegendrePolynomial.html
[R263] http://functions.wolfram.com/Polynomials/LegendreP/
[R264] http://functions.wolfram.com/Polynomials/LegendreP2/
[R265] http://en.wikipedia.org/wiki/Associated Legendre polynomials
[R266] http://mathworld.wolfram.com/LegendrePolynomial.html
[R267] http://functions.wolfram.com/Polynomials/LegendreP/
[R268] http://functions.wolfram.com/Polynomials/LegendreP2/
[R269] http://en.wikipedia.org/wiki/Hermite polynomial
[R270] http://mathworld.wolfram.com/HermitePolynomial.html
[R271] http://functions.wolfram.com/Polynomials/HermiteH/
[R272] http://en.wikipedia.org/wiki/Laguerre polynomial
[R273] http://mathworld.wolfram.com/LaguerrePolynomial.html
[R274] http://functions.wolfram.com/Polynomials/LaguerreL/
[R275] http://functions.wolfram.com/Polynomials/LaguerreL3/
[R276] http://en.wikipedia.org/wiki/Laguerre polynomial#Assoc laguerre polynomials
[R277] http://mathworld.wolfram.com/AssociatedLaguerrePolynomial.html
[R278] http://functions.wolfram.com/Polynomials/LaguerreL/
[R279] http://functions.wolfram.com/Polynomials/LaguerreL3/
[R280] http://en.wikipedia.org/wiki/Spherical harmonics
1908
Bibliography
[R281] http://mathworld.wolfram.com/SphericalHarmonic.html
[R282] http://functions.wolfram.com/Polynomials/SphericalHarmonicY/
[R283] http://dlmf.nist.gov/14.30
[R284] http://en.wikipedia.org/wiki/Spherical harmonics
[R285] http://mathworld.wolfram.com/SphericalHarmonic.html
[R286] http://functions.wolfram.com/Polynomials/SphericalHarmonicY/
[R287] http://en.wikipedia.org/wiki/Spherical harmonics
[R288] http://mathworld.wolfram.com/SphericalHarmonic.html
[R289] http://functions.wolfram.com/Polynomials/SphericalHarmonicY/
[R290] http://en.wikipedia.org/wiki/Kronecker delta
[Doran] http://www.mrao.cam.ac.uk/cjld1/pages/book.htm Geometric Algebra for Physicists by C. Doran and A. Lasenby, Cambridge University Press, 2003.
[Hestenes] http://geocalc.clas.asu.edu/html/CA to GC.html Clifford Algebra to Geometric
Calculus by D.Hestenes and G. Sobczyk, Kluwer Academic Publishers, 1984.
[Macdonald] <http://faculty.luther.edu/macdonal> Linear and Geometric Algebra by
Alan Macdonald, http://www.amazon.com/Alan-Macdonald/e/B004MB2QJQ
[WikiPappus] Pappuss Hexagon Theorem Wikipedia, the Free Encyclopedia. Web. 26 Apr.
2013. <http://en.wikipedia.org/wiki/Pappuss hexagon theorem>
[BlogPost] http://nessgrh.wordpress.com/2011/07/07/tricky-branch-cuts/
[Bro05] M. Bronstein, Symbolic Integration I: Transcendental Functions, Second Edition,
Springer-Verlag, 2005, pp. 35-70
[R291] http://en.wikipedia.org/wiki/Gaussian quadrature
[R292] http://people.sc.fsu.edu/jburkardt/cpp src/legendre rule/legendre rule.html
[R293] http://en.wikipedia.org/wiki/Gauss%E2%80%93Laguerre quadrature
[R294] http://people.sc.fsu.edu/jburkardt/cpp src/laguerre rule/laguerre rule.html
[R295] http://en.wikipedia.org/wiki/Gauss-Hermite Quadrature
[R296] http://people.sc.fsu.edu/jburkardt/cpp src/hermite rule/hermite rule.html
[R297] http://people.sc.fsu.edu/jburkardt/cpp src/gen hermite rule/gen hermite rule.html
[R298] http://en.wikipedia.org/wiki/Gauss%E2%80%93Laguerre quadrature
[R299] http://people.sc.fsu.edu/jburkardt/cpp src/gen laguerre rule/gen laguerre rule.html
[R300] http://en.wikipedia.org/wiki/Chebyshev%E2%80%93Gauss quadrature
[R301] http://people.sc.fsu.edu/jburkardt/cpp src/chebyshev1 rule/chebyshev1 rule.html
[R302] http://en.wikipedia.org/wiki/Chebyshev%E2%80%93Gauss quadrature
[R303] http://people.sc.fsu.edu/jburkardt/cpp src/chebyshev2 rule/chebyshev2 rule.html
[R304] http://en.wikipedia.org/wiki/Gauss%E2%80%93Jacobi quadrature
[R305] http://people.sc.fsu.edu/jburkardt/cpp src/jacobi rule/jacobi rule.html
[R306] http://people.sc.fsu.edu/jburkardt/cpp src/gegenbauer rule/gegenbauer rule.html
[R307] en.wikipedia.org/wiki/Quine-McCluskey algorithm
[R308] en.wikipedia.org/wiki/Quine-McCluskey algorithm
[R309] https://en.wikipedia.org/wiki/Moore-Penrose pseudoinverse
Bibliography
1909
Quadrature,
http://crd-
Library:
Algorithms
and
Proofs,
between
Appells
and
hypergeometric
functions.
Inc.
The
Wolfram
Functions
Site.
1910
Bibliography
Groebner
Bases
Algorithm,
[Bose03] N.K. Bose, B. Buchberger, J.P. Guiver, Multidimensional Systems Theory and Applications, Springer, 2003
[Giovini91] A. Giovini, T. Mora, One sugar cube, please or Selection strategies in Buchberger algorithm, ISSAC 91, ACM
[Bronstein93] M. Bronstein, B. Salvy, Full partial fraction decomposition of rational functions,
Proceedings ISSAC 93, ACM Press, Kiev, Ukraine, 1993, pp. 157160
[Buchberger01] B. Buchberger, Groebner Bases: A Short Introduction for Systems Theorists,
In: R. Moreno-Diaz, B. Buchberger, J. L. Freire, Proceedings of EUROCAST01, February,
2001
[Davenport88] J.H. Davenport, Y. Siret, E. Tournier, Computer Algebra Systems and Algorithms for Algebraic Computation, Academic Press, London, 1988, pp. 124128
[Greuel2008] G.-M. Greuel, Gerhard Pster, A Singular Introduction to Commutative Algebra,
Springer, 2008
[Atiyah69] M.F. Atiyah, I.G. MacDonald, Introduction to Commutative Algebra, AddisonWesley, 1969
[Monagan00] M. Monagan and A. Wittkopf, On the Design and Implementation of Browns
Algorithm over the Integers and Number Fields, Proceedings of ISSAC 2000, pp. 225-233,
ACM, 2000.
Bibliography
1911
[Brown71] W.S. Brown, On Euclids Algorithm and the Computation of Polynomial Greatest
Common Divisors, J. ACM 18, 4, pp. 478-504, 1971.
[Hoeij04] M. van Hoeij and M. Monagan, Algorithms for polynomial GCD computation over
algebraic function elds, Proceedings of ISSAC 2004, pp. 297-304, ACM, 2004.
[Wang81] P.S. Wang, A p-adic algorithm for univariate partial fractions, Proceedings of SYMSAC 1981, pp. 212-217, ACM, 1981.
[Hoeij02] M. van Hoeij and M. Monagan, A modular GCD algorithm over number elds presented with multiple extensions, Proceedings of ISSAC 2002, pp. 109-116, ACM, 2002
[ManWright94] Yiu-Kwong Man and Francis J. Wright, Fast Polynomial Dispersion Computation and its Application to Indenite Summation, Proceedings of the International Symposium on Symbolic and Algebraic Computation, 1994, Pages 175-180
http://dl.acm.org/citation.cfm?doid=190347.190413
[Koepf98] Wolfram Koepf, Hypergeometric Summation: An Algorithmic Approach to Summation and Special Function Identities, Advanced lectures in mathematics, Vieweg, 1998
[Abramov71] S. A. Abramov, On the Summation of Rational Functions, USSR Computational
Mathematics and Mathematical Physics, Volume 11, Issue 4, 1971, Pages 324-330
[Man93] Yiu-Kwong Man, On Computing Closed Forms for Indenite Summations,
Journal of Symbolic Computation, Volume 16, Issue 4, 1993, Pages 355-376
http://www.sciencedirect.com/science/article/pii/S0747717183710539
[R345] Big O notation
[R346] http://en.wikipedia.org/wiki/Disjoint sets
[R347] http://en.wikipedia.org/wiki/Power set
[R348] http://en.wikipedia.org/wiki/Interval %28mathematics%29
[R349] http://en.wikipedia.org/wiki/Finite set
[R350] http://en.wikipedia.org/wiki/Union %28set theory%29
[R351] http://en.wikipedia.org/wiki/Intersection %28set theory%29
[R352] http://en.wikipedia.org/wiki/Cartesian product
[R353] http://en.wikipedia.org/wiki/Empty set
[R354] http://en.wikipedia.org/wiki/Universal set
[Roach1996] Kelly B. Roach. Hypergeometric Function Representations. In: Proceedings of
the 1996 International Symposium on Symbolic and Algebraic Computation, pages 301308, New York, 1996. ACM.
[Roach1997] Kelly B. Roach. Meijer G Function Representations. In: Proceedings of the 1997
International Symposium on Symbolic and Algebraic Computation, pages 205-211, New
York, 1997. ACM.
[Luke1969] Luke, Y. L. (1969), The Special Functions and Their Approximations, Volume 1.
[Prudnikov1990] A. P. Prudnikov, Yu. A. Brychkov and O. I. Marichev (1990). Integrals and
Series: More Special Functions, Vol. 3, Gordon and Breach Science Publisher.
[R382] http://en.wikipedia.org/wiki/Arcsine distribution
[R383] http://en.wikipedia.org/wiki/Benini distribution
[R384] http://reference.wolfram.com/legacy/v8/ref/BeniniDistribution.html
[R385] http://en.wikipedia.org/wiki/Beta distribution
[R386] http://mathworld.wolfram.com/BetaDistribution.html
1912
Bibliography
Bibliography
1913
[R359] Solving the diophantine equation ax**2 + by**2 = m by Cornacchias method, [online],
Available: http://www.numbertheory.org/php/cornacchia.html
[R360] Solving the generalized Pell equation x**2 - D*y**2 = N, John P. Robertson, July 31,
2004, Page 15. http://www.jpr2718.org/pell.pdf
[R361] Solving the equation ax2 + bxy + cy2 + dx + ey + f = 0, John P.Robertson, May 8,
2003, Page 7 - 11. http://www.jpr2718.org/ax2p.pdf
[R362] Solving the equation ax2 + bxy + cy2 + dx + ey + f = 0, John P.Robertson, May 8,
2003, Page 7 - 11. http://www.jpr2718.org/ax2p.pdf
1914
Bibliography
[online],
Available:
sum
sum
of
of
three
squares,
[online],
Available:
four
squares,
[online],
Available:
[R368] Solving the generalized Pell equation x2 - Dy2 = N, John P. Robertson, July 31, 2004,
Pages 4 - 8. http://www.jpr2718.org/pell.pdf
[R369] Solving the generalized Pell equation x**2 - D*y**2 = N, John P. Robertson, July 31,
2004, Page 12. http://www.jpr2718.org/pell.pdf
[R370] The algorithmic resolution of Diophantine equations, Nigel P. Smart, London Mathematical Society Student Texts 41, Cambridge University Press, Cambridge, 1998.
[R371] The algorithmic resolution of Diophantine equations, Nigel P. Smart, London Mathematical Society Student Texts 41, Cambridge University Press, Cambridge, 1998.
[R372] Ecient Solution of Rational Conices, J. E. Cremona and D. Rusin, Mathematics of
Computation, Volume 00, Number 0.
sum
of
four
squares,
[online],
Available:
[AOCP] Algorithm 7.1.2.5M in Volume 4A, Combinatoral Algorithms, Part 1, of The Art of
Computer Programming, by Donald Knuth.
[Factorisatio] On a Problem of Oppenheim concerning Factorisatio Numerorum E. R. Caneld, Paul Erdos, Carl Pomerance, JOURNAL OF NUMBER THEORY, Vol. 17, No. 1. August 1983. See section 7 for a description of an algorithm similar to Knuths.
[Yorgey] Generating Multiset Partitions, Brent Yorgey, The Monad.Reader, Issue 8, September 2007.
[R1] http://en.wikipedia.org/wiki/Euler%E2%80%93Lagrange equation
[R2] http://en.wikipedia.org/wiki/Mathematical singularity
[R3] Generation of Finite Dierence Formulas on Arbitrarily Spaced Grids, Bengt Fornberg;
Mathematics of computation; 51; 184; (1988); 699-706; doi:10.1090/S0025-5718-19880935077-0
[R320] https://en.wikipedia.org/wiki/DFT matrix
[R321] http://en.wikipedia.org/wiki/Gamma matrices
[R322] http://en.wikipedia.org/wiki/Pauli matrices
[R326] http://en.wikipedia.org/wiki/Pauli matrices
[R344] http://en.wikipedia.org/wiki/Kronecker delta
[Rasch03] J. Rasch and A. C. H. Yu, Ecient Storage Scheme for Pre-calculated Wigner 3j, 6j
and Gaunt Coecients, SIAM J. Sci. Comput. Volume 25, Issue 4, pp. 1416-1428 (2003)
Bibliography
1915
Free
Encyclopedia.
Web.
05
Aug.
2011.
1916
Bibliography
Bibliography
1917
1918
Bibliography
m
mpmath.functions.elliptic, 909
s
sympy, 704
sympy.assumptions, 1287
sympy.assumptions.ask, 1287
sympy.assumptions.assume, 1288
sympy.assumptions.handlers, 1291
sympy.assumptions.handlers.calculus,
1291
sympy.assumptions.handlers.ntheory,
1293
sympy.assumptions.handlers.order, 1293
sympy.assumptions.handlers.sets, 1293
sympy.assumptions.refine, 1289
sympy.calculus, 1592
sympy.calculus.euler, 1592
sympy.calculus.finite diff, 1593
sympy.calculus.singularities, 1593
sympy.categories, 1829
sympy.categories.diagram drawing, 1838
sympy.combinatorics.generators, 215
sympy.combinatorics.graycode, 256
sympy.combinatorics.group constructs,
269
sympy.combinatorics.named groups, 261
sympy.combinatorics.partitions, 187
sympy.combinatorics.perm groups, 216
sympy.combinatorics.permutations, 192
sympy.combinatorics.polyhedron, 243
sympy.combinatorics.prufer, 246
sympy.combinatorics.subsets, 250
sympy.combinatorics.tensor can, 270
sympy.combinatorics.testutil, 269
sympy.combinatorics.util, 263
sympy.core.add, 144
sympy.core.assumptions, 88
sympy.core.basic, 90
sympy.core.cache, 90
sympy.core.compatibility, 183
sympy.core.containers, 182
sympy.core.evalf, 181
sympy.core.expr, 103
sympy.core.exprtools, 185
sympy.core.function, 163
sympy.core.mod, 147
sympy.core.mul, 142
sympy.core.multidimensional, 162
sympy.core.numbers, 126
sympy.core.power, 139
sympy.core.relational, 147
sympy.core.singleton, 102
sympy.core.symbol, 122
sympy.core.sympify, 85
sympy.crypto.crypto, 303
sympy.diffgeom, 1846
sympy.functions, 340
sympy.functions.special.bessel, 408
sympy.functions.special.beta functions,
386
sympy.functions.special.elliptic integrals,
430
sympy.functions.special.error functions,
388
sympy.functions.special.gamma functions,
379
sympy.functions.special.polynomials,
433
sympy.functions.special.zeta functions,
421
sympy.galgebra, 450
sympy.galgebra.debug, 489
sympy.galgebra.ga, 451
sympy.galgebra.manifold, 483
sympy.galgebra.ncutil, 486
sympy.galgebra.precedence, 484
sympy.galgebra.printing, 485
sympy.galgebra.stringarrays, 488
sympy.galgebra.vector, 484
sympy.geometry.curve, 539
sympy.geometry.ellipse, 542
1919
sympy.geometry.entity, 493
sympy.geometry.line, 509
sympy.geometry.line3d, 525
sympy.geometry.plane, 577
sympy.geometry.point, 497
sympy.geometry.point3d, 503
sympy.geometry.polygon, 556
sympy.geometry.util, 495
sympy.integrals, 583
sympy.integrals.meijerint doc, 604
sympy.integrals.transforms, 584
sympy.logic, 625
sympy.matrices, 635
sympy.matrices.expressions, 706
sympy.matrices.expressions.blockmatrix,
711
sympy.matrices.immutable, 705
sympy.matrices.matrices, 636
sympy.matrices.sparse, 692
sympy.ntheory.continued fraction, 298
sympy.ntheory.egyptian fraction, 301
sympy.ntheory.factor , 281
sympy.ntheory.generate, 276
sympy.ntheory.modular, 290
sympy.ntheory.multinomial, 292
sympy.ntheory.partitions , 294
sympy.ntheory.primetest, 294
sympy.ntheory.residue ntheory, 295
sympy.physics, 1597
sympy.physics.hep.gamma matrices, 1632
sympy.physics.hydrogen, 1598
sympy.physics.matrices, 1600
sympy.physics.mechanics.kane, 1741
sympy.physics.mechanics.lagrange, 1744
sympy.physics.mechanics.linearize, 1746
sympy.physics.mechanics.particle, 1730
sympy.physics.mechanics.rigidbody, 1733
sympy.physics.optics.gaussopt, 1802
sympy.physics.optics.medium, 1812
sympy.physics.optics.utils, 1813
sympy.physics.optics.waves, 1817
sympy.physics.paulialgebra, 1601
sympy.physics.qho 1d, 1602
sympy.physics.quantum.anticommutator,
1749
sympy.physics.quantum.cartesian, 1757
sympy.physics.quantum.cg, 1750
sympy.physics.quantum.circuitplot, 1788
sympy.physics.quantum.commutator, 1752
sympy.physics.quantum.constants, 1753
sympy.physics.quantum.dagger, 1753
sympy.physics.quantum.gate, 1789
sympy.physics.quantum.grover, 1794
sympy.physics.quantum.hilbert, 1758
1920
sympy.physics.quantum.innerproduct,
1754
sympy.physics.quantum.operator, 1760
sympy.physics.quantum.operatorset, 1764
sympy.physics.quantum.piab, 1801
sympy.physics.quantum.qapply, 1766
sympy.physics.quantum.qft, 1796
sympy.physics.quantum.qubit, 1796
sympy.physics.quantum.represent, 1767
sympy.physics.quantum.shor, 1800
sympy.physics.quantum.spin, 1771
sympy.physics.quantum.state, 1781
sympy.physics.quantum.tensorproduct,
1755
sympy.physics.secondquant, 1604
sympy.physics.sho, 1603
sympy.physics.units, 1630
sympy.physics.unitsystems.dimensions,
1824
sympy.physics.unitsystems.prefixes,
1827
sympy.physics.unitsystems.quantities,
1829
sympy.physics.unitsystems.units, 1827
sympy.physics.vector.functions, 1680
sympy.physics.vector.point, 1675
sympy.physics.wigner, 1623
sympy.plotting.plot, 1270
sympy.plotting.pygletplot, 1283
sympy.printing.ccode, 1252
sympy.printing.codeprinter, 1266
sympy.printing.conventions, 1266
sympy.printing.fcode, 1254
sympy.printing.gtk, 1259
sympy.printing.lambdarepr, 1259
sympy.printing.latex, 1259
sympy.printing.mathematica, 1258
sympy.printing.mathml, 1262
sympy.printing.precedence, 1266
sympy.printing.pretty.pretty, 1251
sympy.printing.pretty.pretty symbology,
1266
sympy.printing.pretty.stringpict, 1268
sympy.printing.preview, 1264
sympy.printing.printer, 1248
sympy.printing.python, 1262
sympy.printing.repr, 1262
sympy.printing.str, 1263
sympy.printing.tree, 1263
sympy.series, 1304
sympy.sets.fancysets, 1324
sympy.sets.sets, 1312
sympy.simplify.cse main, 1345
sympy.simplify.epathtools, 1347
Python Module Index
sympy.simplify.hyperexpand, 1347
sympy.simplify.hyperexpand doc, 1358
sympy.simplify.simplify, 73
sympy.simplify.sqrtdenest, 1344
sympy.simplify.traversaltools, 1347
sympy.solvers, 1468
sympy.solvers.inequalities, 1505
sympy.solvers.ode, 1457
sympy.solvers.pde, 1468
sympy.solvers.recurr, 1479
sympy.stats, 1361
sympy.stats.crv, 1396
sympy.stats.crv types, 1396
sympy.stats.frv, 1396
sympy.stats.frv types, 1396
sympy.stats.rv, 1396
sympy.tensor, 1508
sympy.tensor.index methods, 1514
sympy.tensor.indexed, 1508
sympy.tensor.tensor, 1517
sympy.utilities, 1532
sympy.utilities.autowrap, 1533
sympy.utilities.codegen, 1538
sympy.utilities.decorator, 1547
sympy.utilities.enumerative, 1549
sympy.utilities.iterables, 1555
sympy.utilities.lambdify, 1573
sympy.utilities.memoization, 1576
sympy.utilities.misc, 1576
sympy.utilities.pkgdata, 1577
sympy.utilities.pytest, 1578
sympy.utilities.randtest, 1579
sympy.utilities.runtests, 1580
sympy.utilities.source, 1587
sympy.utilities.timeutils, 1587
1921
1922
INDEX
Symbols
LorentzContainer
(class
in
sympy.physics.hep.gamma matrices),
1632
TensorManager
(class
in
sympy.tensor.tensor), 1517
base ordering()
(in
module
sympy.combinatorics.util), 263
check cycles alt sym()
(in
module
sympy.combinatorics.util), 264
cmp perm lists()
(in
module
sympy.combinatorics.testutil), 269
distribute gens by base()
(in
module
sympy.combinatorics.util), 264
handle precomputed bsgs()
(in
module
sympy.combinatorics.util), 265
linear 2eq order1 type1()
(in
module
sympy.solvers.ode), 1433
linear 2eq order1 type2()
(in
module
sympy.solvers.ode), 1435
linear 2eq order1 type3()
(in
module
sympy.solvers.ode), 1435
linear 2eq order1 type4()
(in
module
sympy.solvers.ode), 1436
linear 2eq order1 type5()
(in
module
sympy.solvers.ode), 1436
linear 2eq order1 type6()
(in
module
sympy.solvers.ode), 1437
linear 2eq order1 type7()
(in
module
sympy.solvers.ode), 1437
linear 2eq order2 type1()
(in
module
sympy.solvers.ode), 1438
linear 2eq order2 type10()
(in
module
sympy.solvers.ode), 1446
linear 2eq order2 type11()
(in
module
sympy.solvers.ode), 1446
linear 2eq order2 type2()
(in
module
sympy.solvers.ode), 1439
linear 2eq order2 type3()
(in
module
sympy.solvers.ode), 1440
linear 2eq order2 type4()
(in
module
sympy.solvers.ode), 1441
linear 2eq order2 type5()
(in
module
sympy.solvers.ode), 1442
linear 2eq order2 type6()
(in
module
sympy.solvers.ode), 1443
linear 2eq order2 type7()
(in
module
sympy.solvers.ode), 1443
linear 2eq order2 type8()
(in
module
sympy.solvers.ode), 1444
linear 2eq order2 type9()
(in
module
sympy.solvers.ode), 1445
linear 3eq order1 type1()
(in
module
sympy.solvers.ode), 1447
linear 3eq order1 type2()
(in
module
sympy.solvers.ode), 1448
linear 3eq order1 type3()
(in
module
sympy.solvers.ode), 1448
linear 3eq order1 type4()
(in
module
sympy.solvers.ode), 1449
linear neq order1 type1()
(in
module
sympy.solvers.ode), 1450
naive list centralizer()
(in
module
sympy.combinatorics.testutil), 269
nonlinear 2eq order1 type1() (in module
sympy.solvers.ode), 1451
nonlinear 2eq order1 type2() (in module
sympy.solvers.ode), 1452
nonlinear 2eq order1 type3() (in module
sympy.solvers.ode), 1452
nonlinear 2eq order1 type4() (in module
sympy.solvers.ode), 1453
nonlinear 2eq order1 type5() (in module
sympy.solvers.ode), 1453
nonlinear 3eq order1 type1() (in module
sympy.solvers.ode), 1454
nonlinear 3eq order1 type2() (in module
sympy.solvers.ode), 1454
nonlinear 3eq order1 type3() (in module
sympy.solvers.ode), 1455
nonlinear 3eq order1 type4() (in module
sympy.solvers.ode), 1456
nonlinear 3eq order1 type5() (in module
1923
sympy.solvers.ode), 1456
orbits transversals from bsgs() (in module
sympy.combinatorics.util), 266
print()
(sympy.printing.printer.Printer
method), 1251
remove gens()
(in
module
sympy.combinatorics.util), 266
strip() (in module sympy.combinatorics.util),
267
strong gens from distr()
(in
module
sympy.combinatorics.util), 268
verify bsgs()
(in
module
sympy.combinatorics.testutil), 269
verify centralizer()
(in
module
sympy.combinatorics.testutil), 270
verify normal closure()
(in
module
sympy.combinatorics.testutil), 270
Index
add paren()
(in
module almosteq() (in module mpmath), 738
sympy.galgebra.precedence), 484
almosteq() (sympy.polys.domains.domain.Domain
adjoint() (sympy.matrices.immutable.ImmutableMatrix method), 1149
method), 705
almosteq() (sympy.polys.domains.RealField
adjoint() (sympy.matrices.matrices.MatrixBase
method), 1160
method), 648
almosteq()
(sympy.polys.rings.PolyElement
adjugate() (sympy.matrices.matrices.MatrixBase
method), 1216
alphabet of cipher()
(in
module
method), 648
agm() (in module mpmath), 765
sympy.crypto.crypto), 303
airyai (class in sympy.functions.special.bessel), alternating() (sympy.combinatorics.generators
414
static method), 215
airyai() (in module mpmath), 839
AlternatingGroup()
(in
module
sympy.combinatorics.named groups),
airyaiprime
(class
in
sympy.functions.special.bessel),
262
417
altitudes (sympy.geometry.polygon.Triangle
airyaizero() (in module mpmath), 848
attribute), 571
AiryBase
(class
in altzeta() (in module mpmath), 934
sympy.functions.special.bessel),
amplitude (sympy.physics.optics.waves.TWave
414
attribute), 1817
airybi (class in sympy.functions.special.bessel), an (sympy.functions.special.hyper.meijerg at415
tribute), 430
airybi() (in module mpmath), 844
And (class in sympy.logic.boolalg), 627
airybiprime
(class
in Anderson
(class
in
mpsympy.functions.special.bessel),
math.calculus.optimization), 978
418
ANewton
(class
in
mpmath.calculus.optimization), 978
airybizero() (in module mpmath), 849
algebraic, 89
ang acc in() (sympy.physics.vector.frame.ReferenceFrame
algebraic eld() (sympy.polys.domains.AlgebraicField method), 1665
method), 1158
ang vel in() (sympy.physics.vector.frame.ReferenceFrame
algebraic eld() (sympy.polys.domains.domain.Domain method), 1665
method), 1149
angerj() (in module mpmath), 834
algebraic eld() (sympy.polys.domains.IntegerRing
angle (sympy.physics.optics.gaussopt.GeometricRay
method), 1156
attribute), 1806
algebraic eld() (sympy.polys.domains.RationalField
angle between() (sympy.geometry.line.LinearEntity
method), 1158
method), 509
AlgebraicField
(class
in angle between() (sympy.geometry.line3d.LinearEntity3D
sympy.polys.domains), 1158
method), 527
AlgebraicNumber
(class
in angle between() (sympy.geometry.plane.Plane
sympy.polys.numberelds), 1117
method), 577
all coes()
(sympy.polys.polyclasses.DMP angles (sympy.geometry.polygon.Polygon atmethod), 1162
tribute), 558
all coes()
(sympy.polys.polytools.Poly angles (sympy.geometry.polygon.RegularPolygon
method), 1077
attribute), 564
all monoms() (sympy.polys.polyclasses.DMP angular momentum()
(in
module
method), 1162
sympy.physics.mechanics.functions),
all monoms()
(sympy.polys.polytools.Poly
1738
method), 1077
angular momentum()
all roots()
(sympy.polys.polytools.Poly
(sympy.physics.mechanics.particle.Particle
method), 1077
method), 1731
all terms()
(sympy.polys.polyclasses.DMP angular momentum()
method), 1163
(sympy.physics.mechanics.rigidbody.RigidBody
all terms()
(sympy.polys.polytools.Poly
method), 1733
angular velocity (sympy.physics.optics.waves.TWave
method), 1078
allhints (in module sympy.solvers.ode), 1405
attribute), 1818
Index
1925
AnnihilateBoson
(class
in
method), 1609
sympy.physics.secondquant), 1608
apply operator() (sympy.physics.secondquant.CreateFermion
AnnihilateFermion
(class
in
method), 1610
sympy.physics.secondquant), 1609
apply operators()
(in
module
annotated()
(in
module
sympy.physics.secondquant), 1613
sympy.printing.pretty.pretty symbology),
applyfunc() (sympy.matrices.sparse.SparseMatrix
1267
method), 693
ANP (class in sympy.polys.polyclasses), 1168 approximation() (sympy.core.numbers.NumberSymbol
AntiCommutator
(class
in
method), 131
sympy.physics.quantum.anticommutator),
arange() (in module mpmath), 742
1749
arbitrary metric()
(in
module
antihermitian, 89
sympy.galgebra.ga), 467
AntiSymmetricTensor
(class
in arbitrary metric conformal()
(in
module
sympy.physics.secondquant), 1620
sympy.galgebra.ga), 467
any() (in module sympy.parsing.sympy tokenize),arbitrary point() (sympy.geometry.curve.Curve
1590
method), 540
aother (sympy.functions.special.hyper.meijerg arbitrary point() (sympy.geometry.ellipse.Ellipse
attribute), 430
method), 544
ap (sympy.functions.special.hyper.hyper at- arbitrary point() (sympy.geometry.line.LinearEntity
tribute), 427
method), 510
ap (sympy.functions.special.hyper.meijerg at- arbitrary point() (sympy.geometry.line3d.LinearEntity3D
tribute), 430
method), 527
apart() (in module sympy.polys.partfrac), arbitrary point() (sympy.geometry.plane.Plane
1121
method), 578
apart() (sympy.core.expr.Expr method), 103
arbitrary point() (sympy.geometry.polygon.Polygon
method), 558
apart list() (in module sympy.polys.partfrac),
1122
Arcsin() (in module sympy.stats), 1365
apery (mpmath.mp attribute), 751
are collinear() (sympy.geometry.point3d.Point3D
apoapsis (sympy.geometry.ellipse.Ellipse atstatic method), 504
tribute), 544
are concurrent() (sympy.geometry.line.LinearEntity
apothem (sympy.geometry.polygon.RegularPolygon
static method), 510
attribute), 564
are concurrent() (sympy.geometry.line3d.LinearEntity3D
appellf1() (in module mpmath), 903
static method), 528
appellf2() (in module mpmath), 906
are concurrent() (sympy.geometry.plane.Plane
static method), 578
appellf3() (in module mpmath), 906
appellf4() (in module mpmath), 908
are coplanar() (sympy.geometry.point3d.Point3D
static method), 504
append() (sympy.plotting.plot.Plot method),
1272
are similar() (in module sympy.geometry.util),
AppliedPredicate
(class
in
496
sympy.assumptions.assume), 1288
area
(sympy.geometry.ellipse.Ellipse
attribute), 544
apply() (sympy.printing.pretty.stringpict.prettyForm
static method), 1269
area (sympy.geometry.polygon.Polygon atapply()
(sympy.simplify.epathtools.EPath
tribute), 559
area (sympy.geometry.polygon.RegularPolygon
method), 1348
apply nite di()
(in
module
attribute), 564
arg (class in sympy.functions.elementary.complexes),
sympy.calculus.nite di), 1594
apply grover()
(in
module
344
arg (sympy.assumptions.assume.AppliedPredicate
sympy.physics.quantum.grover),
1795
attribute), 1288
apply operator() (sympy.physics.secondquant.AnnihilateBoson
arg() (in module mpmath), 734
args (sympy.core.basic.Basic attribute), 90
method), 1608
apply operator() (sympy.physics.secondquant.AnnihilateFermion
args (sympy.geometry.polygon.RegularPolygon
method), 1609
attribute), 565
apply operator() (sympy.physics.secondquant.CreateBoson
args (sympy.polys.polytools.Poly attribute),
1926
Index
1078
as content primitive()
args (sympy.tensor.indexed.IndexedBase at(sympy.core.basic.Basic
method),
tribute), 1513
91
args cnc() (sympy.core.expr.Expr method), as content primitive() (sympy.core.expr.Expr
103
method), 106
Argument (class in sympy.utilities.codegen), as content primitive() (sympy.core.mul.Mul
1540
method), 142
argument (sympy.functions.special.bessel.BesselBase
as content primitive()
attribute), 408
(sympy.core.numbers.Rational
argument (sympy.functions.special.hyper.hyper
method), 131
attribute), 427
as content primitive()
argument (sympy.functions.special.hyper.meijerg
(sympy.core.power.Pow
method),
attribute), 430
140
array form (sympy.combinatorics.permutations.Permutation
as dict() (sympy.combinatorics.partitions.IntegerPartition
attribute), 197
method), 189
array form (sympy.combinatorics.polyhedron.Polyhedron
as dict() (sympy.polys.polytools.Poly method),
attribute), 243
1078
ArrowStringDescription
(class
in as dummy()
(sympy.core.symbol.Symbol
sympy.categories.diagram drawing),
method), 122
1841
as explicit() (sympy.matrices.expressions.MatrixExpr
as base exp() (sympy.core.function.Function
method), 707
method), 170
as expr() (sympy.core.expr.Expr method), 107
as base exp()
(sympy.core.power.Pow as expr() (sympy.polys.numberelds.AlgebraicNumber
method), 140
method), 1117
as base exp() (sympy.functions.elementary.exponential.log
as expr()
(sympy.polys.polytools.Poly
method), 353
method), 1078
as coe Add() (sympy.core.add.Add method), as ferrers() (sympy.combinatorics.partitions.IntegerPartition
144
method), 189
as coe add() (sympy.core.add.Add method), as nite di()
(in
module
sympy.calculus.nite di), 1595
144
as coe Add()
(sympy.core.expr.Expr as immutable() (sympy.matrices.sparse.SparseMatrix
method), 103
method), 693
as coe add()
(sympy.core.expr.Expr as independent()
(sympy.core.expr.Expr
method), 103
method), 107
as coe Add() (sympy.core.numbers.Number as int() (in module sympy.core.compatibility),
method), 127
184
as coe exponent()
(sympy.core.expr.Expr as leading term()
(sympy.core.expr.Expr
method), 104
method), 109
as coe Mul()
(sympy.core.expr.Expr as list() (sympy.polys.polytools.Poly method),
method), 103
1079
as coe mul()
(sympy.core.expr.Expr as mutable() (sympy.matrices.expressions.MatrixExpr
method), 104
method), 708
as coe Mul() (sympy.core.mul.Mul method), as mutable() (sympy.matrices.immutable.ImmutableMatrix
142
method), 705
as coe Mul() (sympy.core.numbers.Number as mutable() (sympy.matrices.sparse.SparseMatrix
method), 127
method), 693
as coecient()
(sympy.core.expr.Expr as numer denom()
(sympy.core.expr.Expr
method), 104
method), 109
as coecients dict()
(sympy.core.add.Add as ordered factors()
(sympy.core.expr.Expr
method), 144
method), 109
as coecients dict() (sympy.core.expr.Expr as ordered factors()
(sympy.core.mul.Mul
method), 105
method), 142
as content primitive() (sympy.core.add.Add as ordered terms()
(sympy.core.expr.Expr
method), 145
method), 109
Index
1927
Index
1929
method), 650
365
berkowitz minors() (sympy.matrices.matrices.MatrixBase
binomial() (in module mpmath), 779
method), 650
Binomial() (in module sympy.stats), 1363
bernfrac() (in module mpmath), 957
binomial coecients()
(in
module
bernoulli
(class
in
sympy.ntheory.multinomial), 292
sympy.functions.combinatorial.numbers),
binomial coecients list()
(in
module
364
sympy.ntheory.multinomial), 293
bernoulli() (in module mpmath), 956
Bisection
(class
in
mpBernoulli() (in module sympy.stats), 1362
math.calculus.optimization), 977
bernpoly() (in module mpmath), 958
bisectors() (sympy.geometry.polygon.Triangle
BesselBase
(class
in
method), 571
sympy.functions.special.bessel),
bitlist from subset()
(sympy.combinatorics.subsets.Subset
408
class method), 250
besseli (class in sympy.functions.special.bessel),
410
BKet (in module sympy.physics.secondquant),
besseli() (in module mpmath), 816
1612
besselj (class in sympy.functions.special.bessel),block collapse()
(in
module
409
sympy.matrices.expressions.blockmatrix),
besselj() (in module mpmath), 810
712
besseljzero() (in module mpmath), 822
BlockDiagMatrix
(class
in
besselk (class in sympy.functions.special.bessel),
sympy.matrices.expressions.blockmatrix),
411
712
besselk() (in module mpmath), 819
BlockMatrix
(class
in
besselsimp()
(in
module
sympy.matrices.expressions.blockmatrix),
sympy.simplify.simplify), 1336
711
bessely (class in sympy.functions.special.bessel),bm
(sympy.functions.special.hyper.meijerg
409
attribute), 430
bessely() (in module mpmath), 814
bool map() (in module sympy.logic.boolalg),
besselyzero() (in module mpmath), 824
634
beta (class in sympy.functions.special.beta functions),
BooleanFalse (class in sympy.logic.boolalg),
386
627
beta() (in module mpmath), 785
BooleanTrue (class in sympy.logic.boolalg),
Beta() (in module sympy.stats), 1366
627
betainc() (in module mpmath), 786
BosonicBasis
(class
in
sympy.physics.secondquant), 1613
BetaPrime() (in module sympy.stats), 1367
bid5 square()
(in
module bother (sympy.functions.special.hyper.meijerg
sympy.crypto.crypto), 310
attribute), 430
bid6 square()
(in
module boundary (sympy.sets.sets.Set attribute),
sympy.crypto.crypto), 312
1312
bid7 square()
(in
module bq (sympy.functions.special.hyper.hyper atsympy.crypto.crypto), 312
tribute), 427
bihyper() (in module mpmath), 901
bq (sympy.functions.special.hyper.meijerg atbilinear function()
(in
module
tribute), 430
Bra (class in sympy.physics.quantum.state),
sympy.galgebra.ncutil), 486
bilinear product()
(in
module
1782
bra (sympy.physics.quantum.operator.OuterProduct
sympy.galgebra.ncutil), 486
bin to gray() (sympy.combinatorics.graycode
attribute), 1762
bra (sympy.physics.secondquant.InnerProduct
static method), 260
binary function()
(in
module
attribute), 1613
sympy.utilities.autowrap), 1535
BraBase
(class
in
binary partitions()
(in
module
sympy.physics.quantum.state), 1781
sympy.utilities.iterables), 1555
bracelets()
(in
module
binomial
(class
in
sympy.utilities.iterables), 1555
sympy.functions.combinatorial.factorials),
bsgs direct product()
(in
module
1930
Index
sympy.combinatorics.tensor can),
275
bspline basis()
(in
module
sympy.functions.special.bsplines),
419
bspline basis set()
(in
module
sympy.functions.special.bsplines),
420
build expression tree()
(in
module
sympy.series.gruntz), 1306
cardinality (sympy.combinatorics.permutations.Permutation
attribute), 197
cardinality (sympy.combinatorics.subsets.Subset
attribute), 250
casoratian()
(in
module
sympy.matrices.dense), 682
Catalan (class in sympy.core.numbers), 138
catalan (class in sympy.functions.combinatorial.numbers),
366
catalan (mpmath.mp attribute), 751
Category (class in sympy.categories), 1833
C
Cauchy() (in module sympy.stats), 1368
cbrt() (in module mpmath), 752
C (in module sympy.core.basic), 102
C (sympy.matrices.immutable.ImmutableMatrixccode() (in module sympy.printing.ccode),
1252
attribute), 705
CCodeGen
(class in sympy.utilities.codegen),
C (sympy.matrices.matrices.MatrixBase at1541
tribute), 644
CCodePrinter (class in sympy.printing.ccode),
C (sympy.physics.optics.gaussopt.RayTransferMatrix
1252
attribute), 1803
ceil() (in module mpmath), 736
cacheit() (in module sympy.core.cache), 90
ceiling (class in sympy.functions.elementary.integers),
calc nodes() (mpmath.calculus.quadrature.GaussLegendre
348
method), 1012
center (sympy.geometry.ellipse.Ellipse atcalc nodes() (mpmath.calculus.quadrature.QuadratureRule
tribute), 545
method), 1010
center (sympy.geometry.polygon.RegularPolygon
calc nodes() (mpmath.calculus.quadrature.TanhSinh
attribute), 565
method), 1011
calculate series()
(in
module center() (sympy.combinatorics.perm groups.PermutationGro
method), 220
sympy.series.gruntz), 1306
central inertia (sympy.physics.mechanics.rigidbody.RigidBod
can transf matrix (sympy.physics.unitsystems.dimensions.DimensionSystem
attribute), 1734
attribute), 1826
cancel() (in module sympy.polys.polytools), centralizer() (sympy.combinatorics.perm groups.Permutatio
method), 221
1073
(sympy.geometry.polygon.Polygon
cancel() (sympy.core.expr.Expr method), 110 centroid
attribute), 559
cancel()
(sympy.polys.polyclasses.DMF
centroid (sympy.geometry.polygon.RegularPolygon
method), 1167
attribute), 565
cancel()
(sympy.polys.polyclasses.DMP
centroid() (in module sympy.geometry.util),
method), 1163
497
cancel() (sympy.polys.polytools.Poly method),
CG (class in sympy.physics.quantum.cg),
1079
1750
cancel()
(sympy.polys.rings.PolyElement
cg simp()
(in
module
method), 1216
sympy.physics.quantum.cg), 1751
canon bp() (in module sympy.tensor.tensor),
CGate (class in sympy.physics.quantum.gate),
1531
1789
canon bp()
(sympy.tensor.tensor.TensAdd
CGateS (class in sympy.physics.quantum.gate),
method), 1527
1793
canon bp()
(sympy.tensor.tensor.TensMul
characteristic()
(sympy.polys.domains.domain.Domain
method), 1529
1150
method),
canonical variables (sympy.core.basic.Basic
characteristic()
(sympy.polys.domains.FiniteField
attribute), 93
method), 1155
canonicalize()
(in
module
charpoly()
(sympy.matrices.matrices.MatrixBase
sympy.combinatorics.tensor can),
method),
650
270
chebyt()
(in
module
mpmath), 1016
capture()
(in
module
chebyshevt
(class
in
sympy.utilities.iterables), 1555
Index
1931
Index
coef function()
(in
module
method), 687
sympy.galgebra.ncutil), 487
col swap() (sympy.matrices.sparse.MutableSparseMatrix
coe() (sympy.core.expr.Expr method), 110
method), 701
coe()
(sympy.polys.rings.PolyElement collect() (in module sympy.simplify.simplify),
method), 1216
1329
coe monomial() (sympy.polys.polytools.Poly collect() (sympy.core.expr.Expr method), 112
method), 1079
collect const()
(in
module
coecients (sympy.geometry.line.LinearEntity
sympy.simplify.simplify), 1341
attribute), 511
collect sqrt()
(in
module
coes() (sympy.polys.numberelds.AlgebraicNumber sympy.simplify.simplify), 1340
method), 1117
combsimp()
(in
module
coes()
(sympy.polys.polyclasses.DMP
sympy.simplify.simplify), 1338
method), 1163
combsimp() (sympy.core.expr.Expr method),
coes() (sympy.polys.polytools.Poly method),
112
1080
comm i2symbol() (sympy.tensor.tensor. TensorManager
coes()
(sympy.polys.rings.PolyElement
method), 1517
method), 1217
comm symbols2i() (sympy.tensor.tensor. TensorManager
CoercionFailed
(class
in
method), 1517
sympy.polys.polyerrors), 1238
common prex()
(in
module
cofactor() (sympy.matrices.matrices.MatrixBase
sympy.utilities.iterables), 1556
method), 651
common sux()
(in
module
cofactorMatrix() (sympy.matrices.matrices.MatrixBase sympy.utilities.iterables), 1556
method), 651
commutative, 89
cofactors() (in module sympy.polys.polytools), commutative diagrams
(sympy.categories.Category
at1066
tribute), 1834
cofactors()
(sympy.core.numbers.Number
method), 127
Commutator (class in sympy.digeom), 1852
cofactors() (sympy.polys.domains.domain.Domain
Commutator
(class
in
method), 1150
sympy.physics.quantum.commutator),
cofactors()
(sympy.polys.polyclasses.DMP
1752
method), 1163
Commutator
(class
in
cofactors()
(sympy.polys.polytools.Poly
sympy.physics.secondquant), 1615
method), 1080
commutator() (sympy.combinatorics.perm groups.Permutati
cohen alt() (in module mpmath), 998
method), 221
Coin() (in module sympy.stats), 1363
commutator() (sympy.combinatorics.permutations.Permutat
col()
(sympy.matrices.sparse.SparseMatrix
method), 198
method), 694
commutes with() (sympy.combinatorics.permutations.Permu
col del() (sympy.matrices.dense.MutableDenseMatrix method), 198
method), 686
commutes with() (sympy.tensor.tensor.TensorHead
col del() (sympy.matrices.sparse.MutableSparseMatrix method), 1525
method), 699
comp() (in module sympy.utilities.randtest),
col insert() (sympy.matrices.matrices.MatrixBase
1579
method), 652
compare() (in module sympy.series.gruntz),
col join() (sympy.matrices.matrices.MatrixBase
1306
method), 652
compare() (sympy.core.basic.Basic method),
col join() (sympy.matrices.sparse.MutableSparseMatrix93
method), 700
Complement (class in sympy.sets.sets), 1322
col list() (sympy.matrices.sparse.SparseMatrix complement() (sympy.sets.sets.Set method),
method), 694
1313
col op() (sympy.matrices.dense.MutableDenseMatrix
complex, 89
method), 686
ComplexInnity
(class
in
col op() (sympy.matrices.sparse.MutableSparseMatrix sympy.core.numbers), 136
ComplexSpace
(class
in
method), 700
col swap() (sympy.matrices.dense.MutableDenseMatrixsympy.physics.quantum.hilbert),
Index
1933
1758
construct domain()
(in
module
components (sympy.categories.CompositeMorphism
sympy.polys.constructor), 1115
attribute), 1832
contains() (sympy.combinatorics.perm groups.PermutationG
compose() (in module sympy.polys.polytools),
method), 222
1068
contains()
(sympy.geometry.line.Line
compose()
(sympy.categories.Morphism
method), 518
method), 1830
contains() (sympy.geometry.line.LinearEntity
compose()
(sympy.polys.polyclasses.DMP
method), 511
method), 1163
contains() (sympy.geometry.line.Ray method),
compose()
(sympy.polys.polytools.Poly
520
method), 1080
contains()
(sympy.geometry.line.Segment
composite, 89
method), 523
CompositeDomain
(class
in contains()
(sympy.geometry.line3d.Line3D
sympy.polys.domains.compositedomain),
method), 525
1155
contains() (sympy.geometry.line3d.LinearEntity3D
CompositeMorphism
(class
in
method), 529
sympy.categories), 1831
contains()
(sympy.geometry.line3d.Ray3D
ComputationFailed
(class
in
method), 535
sympy.polys.polyerrors), 1238
contains() (sympy.geometry.line3d.Segment3D
compute known facts()
(in
module
method), 537
sympy.assumptions.ask), 1287
contains()
(sympy.polys.agca.ideals.Ideal
compute leading term()
method), 1139
(sympy.core.expr.Expr
method), contains() (sympy.polys.agca.modules.Module
112
method), 1132
conclusions (sympy.categories.Diagram at- contains() (sympy.polys.polytools.GroebnerBasis
tribute), 1836
method), 1112
cond (sympy.functions.elementary.piecewise.ExprCondPair
contains()
(sympy.series.order.Order
attribute), 351
method), 1310
condition number() (sympy.matrices.matrices.MatrixBase
contains() (sympy.sets.sets.Set method), 1313
method), 652
contains interval()
(in
module
ConditionalDomain (class in sympy.stats.rv),
sympy.galgebra.precedence), 484
1396
content() (in module sympy.polys.polytools),
conj() (in module mpmath), 735
1067
conjugate
(class
in content()
(sympy.polys.polyclasses.DMP
sympy.functions.elementary.complexes),
method), 1163
348
content()
(sympy.polys.polytools.Poly
method), 1081
conjugate (sympy.combinatorics.partitions.IntegerPartition
attribute), 189
content()
(sympy.polys.rings.PolyElement
conjugate gauss beams()
(in
module
method), 1217
sympy.physics.optics.gaussopt),
continued fraction convergents() (in module
sympy.ntheory.continued fraction),
1811
connect to() (sympy.digeom.CoordSystem
298
method), 1849
continued fraction iterator()
(in
module
conserve mpmath dps()
(in
module
sympy.ntheory.continued fraction),
sympy.utilities.decorator), 1547
299
const()
(sympy.polys.rings.PolyElement continued fraction periodic()
(in
module
method), 1217
sympy.ntheory.continued fraction),
Constant
(class
in
299
sympy.physics.unitsystems.units),
continued fraction reduce()
(in
module
sympy.ntheory.continued fraction),
1828
constant renumber()
(in
module
300
sympy.solvers.ode), 1407
ContinuousDomain (class in sympy.stats.crv),
constantsimp()
(in
module
1396
sympy.solvers.ode), 1407
ContinuousPSpace (class in sympy.stats.crv),
1934
Index
1396
copyin matrix() (sympy.matrices.dense.MutableDenseMatrix
ContinuousRV() (in module sympy.stats),
method), 688
1391
cornacchia()
(in
module
contract metric() (sympy.tensor.tensor.TensAdd
sympy.solvers.diophantine), 1492
method), 1527
corners (sympy.combinatorics.polyhedron.Polyhedron
contract metric() (sympy.tensor.tensor.TensMul
attribute), 244
method), 1530
cos (class in sympy.functions.elementary.trigonometric),
contraction()
(in
module
349
sympy.physics.secondquant), 1616
cos() (in module mpmath), 767
controls (sympy.physics.quantum.gate.CGate coset factor() (sympy.combinatorics.perm groups.Permutatio
attribute), 1790
method), 223
controls (sympy.physics.quantum.gate.CNotGate
coset rank() (sympy.combinatorics.perm groups.Permutation
attribute), 1792
method), 224
convergence statement
coset unrank() (sympy.combinatorics.perm groups.Permutat
(sympy.functions.special.hyper.hyper
method), 224
cosh (class in sympy.functions.elementary.hyperbolic),
attribute), 427
convert() (sympy.polys.agca.modules.FreeModule
349
method), 1133
cosh() (in module mpmath), 774
convert() (sympy.polys.agca.modules.Module cosine transform()
(in
module
method), 1132
sympy.integrals.transforms), 588
convert() (sympy.polys.agca.modules.QuotientModule
cosm() (in module mpmath), 1029
method), 1140
cospi() (in module mpmath), 770
convert() (sympy.polys.agca.modules.SubModule
cot (class in sympy.functions.elementary.trigonometric),
method), 1134
350
convert() (sympy.polys.domains.domain.Domaincot() (in module mpmath), 770
method), 1150
coth (class in sympy.functions.elementary.hyperbolic),
convert()
(sympy.polys.polyclasses.DMP
350
method), 1163
coth() (in module mpmath), 776
convert from() (sympy.polys.domains.domain.Domain
could extract minus sign()
method), 1150
(sympy.core.expr.Expr
method),
convert to() (sympy.physics.unitsystems.quantities.Quantity
112
method), 1829
coulombc() (in module mpmath), 862
convert to native paths()
(in
module coulombf() (in module mpmath), 856
sympy.utilities.runtests), 1581
coulombg() (in module mpmath), 860
convert xor()
(in
module count() (sympy.core.basic.Basic method), 93
sympy.parsing.sympy parser), 1592
count complex roots()
(sympy.polys.polyclasses.DMP
convex hull()
(in
module
sympy.geometry.util), 495
method), 1163
coord function() (sympy.digeom.CoordSystem count ops() (in module sympy.core.function),
method), 1849
177
coord functions() (sympy.digeom.CoordSystemcount ops() (sympy.core.basic.Basic method),
method), 1849
93
coord tuple transform to()
count ops() (sympy.core.expr.Expr method),
112
(sympy.digeom.CoordSystem
count partitions() (sympy.utilities.enumerative.MultisetParti
method), 1849
CoordinateSym
(class
in
method), 1551
sympy.physics.vector.frame), 1664
count real roots() (sympy.polys.polyclasses.DMP
coords()
(sympy.digeom.Point
method),
method), 1163
1850
count roots()
(in
module
sympy.polys.polytools), 1072
CoordSystem (class in sympy.digeom), 1847
copy()
(sympy.polys.rings.PolyElement count roots()
(sympy.polys.polytools.Poly
method), 1217
method), 1081
copyin list() (sympy.matrices.dense.MutableDenseMatrix
couple()
(in
module
method), 687
sympy.physics.quantum.spin), 1779
Index
1935
Index
1937
Index
div()
(sympy.polys.domains.ring.Ring
sympy.polys.densetools), 1189
method), 1154
dmp di eval in()
(in
module
div() (sympy.polys.polyclasses.DMP method),
sympy.polys.densetools), 1191
1163
dmp di in()
(in
module
div() (sympy.polys.polytools.Poly method),
sympy.polys.densetools), 1190
1085
dmp discriminant()
(in
module
div()
(sympy.polys.rings.PolyElement
sympy.polys.euclidtools), 1228
dmp div()
(in
module
method), 1218
divergence (sympy.physics.optics.gaussopt.BeamParameter
sympy.polys.densearith), 1187
attribute), 1807
dmp eject()
(in
module
divergence()
(in
module
sympy.polys.densebasic), 1180
sympy.physics.vector.eldfunctions), dmp euclidean prs()
(in
module
sympy.polys.euclidtools), 1226
1690
divisible()
(in
module dmp eval()
(in
module
sympy.solvers.diophantine), 1500
sympy.polys.densetools), 1190
divisor count()
(in
module dmp eval in()
(in
module
sympy.ntheory.factor ), 290
sympy.polys.densetools), 1190
divisors() (in module sympy.ntheory.factor ), dmp eval tail()
(in
module
289
sympy.polys.densetools), 1190
DMF (class in sympy.polys.polyclasses), 1167 dmp exclude()
(in
module
DMP (class in sympy.polys.polyclasses), 1162
sympy.polys.densebasic), 1179
dmp abs()
(in
module dmp expand()
(in
module
sympy.polys.densearith), 1183
sympy.polys.densearith), 1189
dmp add()
(in
module dmp exquo()
(in
module
sympy.polys.densearith), 1184
sympy.polys.densearith), 1188
dmp add ground()
(in
module dmp exquo ground()
(in
module
sympy.polys.densearith), 1182
sympy.polys.densearith), 1183
dmp add mul()
(in
module dmp ext factor()
(in
module
sympy.polys.densearith), 1184
sympy.polys.factortools), 1235
dmp add term()
(in
module dmp factor list()
(in
module
sympy.polys.densearith), 1181
sympy.polys.factortools), 1236
dmp apply pairs()
(in
module dmp factor list include()
(in
module
sympy.polys.densebasic), 1180
sympy.polys.factortools), 1236
dmp cancel()
(in
module dmp div()
(in
module
sympy.polys.euclidtools), 1232
sympy.polys.densearith), 1187
dmp clear denoms()
(in
module dmp prs gcd()
(in
module
sympy.polys.densetools), 1197
sympy.polys.euclidtools), 1229
dmp compose()
(in
module dmp from dict()
(in
module
sympy.polys.densetools), 1195
sympy.polys.densebasic), 1176
dmp content()
(in
module dmp from sympy()
(in
module
sympy.polys.euclidtools), 1231
sympy.polys.densebasic), 1173
dmp convert()
(in
module dmp gcd()
(in
module
sympy.polys.densebasic), 1173
sympy.polys.euclidtools), 1231
dmp copy()
(in
module dmp gcdex()
(in
module
sympy.polys.densebasic), 1172
sympy.polys.euclidtools), 1225
dmp deate()
(in
module dmp ground()
(in
module
sympy.polys.densebasic), 1178
sympy.polys.densebasic), 1175
dmp degree()
(in
module dmp ground content()
(in
module
sympy.polys.densebasic), 1170
sympy.polys.densetools), 1193
dmp degree in()
(in
module dmp ground extract()
(in
module
sympy.polys.densebasic), 1171
sympy.polys.densetools), 1194
dmp degree list()
(in
module dmp ground LC()
(in
module
sympy.polys.densebasic), 1171
sympy.polys.densebasic), 1170
dmp di()
(in
module dmp ground monic()
(in
module
Index
1939
sympy.polys.densetools), 1192
dmp ground nth()
(in
module
sympy.polys.densebasic), 1174
dmp ground p()
(in
module
sympy.polys.densebasic), 1175
dmp ground primitive()
(in
module
sympy.polys.densetools), 1193
dmp ground TC()
(in
module
sympy.polys.densebasic), 1170
dmp ground trunc()
(in
module
sympy.polys.densetools), 1191
dmp grounds()
(in
module
sympy.polys.densebasic), 1176
dmp half gcdex()
(in
module
sympy.polys.euclidtools), 1225
dmp include()
(in
module
sympy.polys.densebasic), 1179
dmp inate()
(in
module
sympy.polys.densebasic), 1178
dmp inject()
(in
module
sympy.polys.densebasic), 1179
dmp inner gcd()
(in
module
sympy.polys.euclidtools), 1230
dmp inner subresultants()
(in
module
sympy.polys.euclidtools), 1226
dmp integrate()
(in
module
sympy.polys.densetools), 1189
dmp integrate in()
(in
module
sympy.polys.densetools), 1189
dmp invert()
(in
module
sympy.polys.euclidtools), 1226
dmp irreducible p()
(in
module
sympy.polys.factortools), 1236
dmp l1 norm()
(in
module
sympy.polys.densearith), 1188
dmp LC()
(in
module
sympy.polys.densebasic), 1169
dmp lcm()
(in
module
sympy.polys.euclidtools), 1231
dmp lift()
(in
module
sympy.polys.densetools), 1196
dmp list terms()
(in
module
sympy.polys.densebasic), 1180
dmp max norm()
(in
module
sympy.polys.densearith), 1188
dmp mul()
(in
module
sympy.polys.densearith), 1185
dmp mul ground()
(in
module
sympy.polys.densearith), 1182
dmp mul term()
(in
module
sympy.polys.densearith), 1181
dmp multi deate()
(in
module
sympy.polys.densebasic), 1178
dmp neg()
(in
module
1940
sympy.polys.densearith), 1184
dmp negative p()
(in
module
sympy.polys.densebasic), 1176
dmp nest()
(in
module
sympy.polys.densebasic), 1177
dmp normal()
(in
module
sympy.polys.densebasic), 1173
dmp nth()
(in
module
sympy.polys.densebasic), 1173
dmp one()
(in
module
sympy.polys.densebasic), 1175
dmp one p()
(in
module
sympy.polys.densebasic), 1174
dmp pdiv()
(in
module
sympy.polys.densearith), 1185
dmp permute()
(in
module
sympy.polys.densebasic), 1177
dmp pexquo()
(in
module
sympy.polys.densearith), 1186
dmp positive p()
(in
module
sympy.polys.densebasic), 1176
dmp pow()
(in
module
sympy.polys.densearith), 1185
dmp pquo()
(in
module
sympy.polys.densearith), 1186
dmp prem()
(in
module
sympy.polys.densearith), 1186
dmp primitive()
(in
module
sympy.polys.euclidtools), 1231
dmp primitive prs()
(in
module
sympy.polys.euclidtools), 1226
dmp prs resultant()
(in
module
sympy.polys.euclidtools), 1227
dmp qq collins resultant()
(in
module
sympy.polys.euclidtools), 1228
dmp qq heu gcd()
(in
module
sympy.polys.euclidtools), 1230
dmp quo()
(in
module
sympy.polys.densearith), 1188
dmp quo ground()
(in
module
sympy.polys.densearith), 1182
dmp raise()
(in
module
sympy.polys.densebasic), 1178
dmp rem()
(in
module
sympy.polys.densearith), 1187
dmp resultant()
(in
module
sympy.polys.euclidtools), 1228
dmp revert()
(in
module
sympy.polys.densetools), 1197
dmp rr div()
(in
module
sympy.polys.densearith), 1187
dmp rr prs gcd()
(in
module
sympy.polys.euclidtools), 1229
dmp slice()
(in
module
Index
sympy.polys.densebasic), 1181
dmp sqr()
(in
module
sympy.polys.densearith), 1185
dmp strip()
(in
module
sympy.polys.densebasic), 1171
dmp sub()
(in
module
sympy.polys.densearith), 1184
dmp sub ground()
(in
module
sympy.polys.densearith), 1182
dmp sub mul()
(in
module
sympy.polys.densearith), 1184
dmp sub term()
(in
module
sympy.polys.densearith), 1181
dmp subresultants()
(in
module
sympy.polys.euclidtools), 1226
dmp swap()
(in
module
sympy.polys.densebasic), 1177
dmp TC()
(in
module
sympy.polys.densebasic), 1169
dmp terms gcd()
(in
module
sympy.polys.densebasic), 1180
dmp to dict()
(in
module
sympy.polys.densebasic), 1177
dmp to tuple()
(in
module
sympy.polys.densebasic), 1172
dmp trial division()
(in
module
sympy.polys.factortools), 1232
dmp true LT()
(in
module
sympy.polys.densebasic), 1170
dmp trunc()
(in
module
sympy.polys.densetools), 1191
dmp validate()
(in
module
sympy.polys.densebasic), 1171
dmp zero()
(in
module
sympy.polys.densebasic), 1174
dmp zero p()
(in
module
sympy.polys.densebasic), 1174
dmp zeros()
(in
module
sympy.polys.densebasic), 1175
dmp zz collins resultant()
(in
module
sympy.polys.euclidtools), 1228
dmp zz diophantine()
(in
module
sympy.polys.factortools), 1234
dmp zz factor()
(in
module
sympy.polys.factortools), 1235
dmp zz heu gcd()
(in
module
sympy.polys.euclidtools), 1229
dmp zz mignotte bound()
(in
module
sympy.polys.factortools), 1232
dmp zz modular resultant()
(in
module
sympy.polys.euclidtools), 1227
dmp zz wang()
(in
module
sympy.polys.factortools), 1234
dmp zz wang hensel lifting()
(in
module
Index
sympy.polys.factortools), 1234
dmp zz wang lead coes()
(in
module
sympy.polys.factortools), 1234
dmp zz wang non divisors()
(in
module
sympy.polys.factortools), 1234
dmp zz wang test points()
(in
module
sympy.polys.factortools), 1234
doctest() (in module sympy.utilities.runtests),
1581
doctest depends on()
(in
module
sympy.utilities.decorator), 1547
doit() (sympy.core.basic.Basic method), 93
doit() (sympy.functions.elementary.piecewise.Piecewise
method), 357
doit() (sympy.integrals.Integral method), 616
doit() (sympy.physics.quantum.anticommutator.AntiCommut
method), 1750
doit() (sympy.physics.quantum.commutator.Commutator
method), 1753
doit() (sympy.physics.secondquant.AntiSymmetricTensor
method), 1621
doit() (sympy.physics.secondquant.Commutator
method), 1615
doit()
(sympy.physics.secondquant.NO
method), 1617
doit()
(sympy.physics.vector.dyadic.Dyadic
method), 1673
doit()
(sympy.physics.vector.vector.Vector
method), 1670
doit() (sympy.series.limits.Limit method),
1304
doit numerically() (sympy.core.function.Derivative
method), 167
Domain (class in sympy.polys.domains.domain),
1149
domain (sympy.categories.CompositeMorphism
attribute), 1832
domain
(sympy.categories.Morphism
attribute), 1830
domain
(sympy.polys.polytools.Poly
attribute), 1085
DomainError
(class
in
sympy.polys.polyerrors), 1238
doprint() (sympy.printing.mathematica.MCodePrinter
method), 1259
doprint() (sympy.printing.mathml.MathMLPrinter
method), 1262
doprint()
(sympy.printing.printer.Printer
method), 1251
dot() (in module sympy.physics.vector.functions),
1687
dot() (sympy.geometry.point.Point method),
499
dot()
(sympy.geometry.point3d.Point3D
1941
method), 506
dump m() (sympy.utilities.codegen.OctaveCodeGen
(sympy.matrices.matrices.MatrixBase
method), 1543
method), 654
dump pyx() (sympy.utilities.autowrap.CythonCodeWrapper
dot()
(sympy.physics.vector.dyadic.Dyadic
method), 1534
method), 1673
dup content()
(in
module
dot()
(sympy.physics.vector.vector.Vector
sympy.polys.densetools), 1192
method), 1670
dup cyclotomic p()
(in
module
dotprint() (in module sympy.printing.dot),
sympy.polys.factortools), 1233
1269
dup decompose()
(in
module
double coset can rep()
(in
module
sympy.polys.densetools), 1196
sympy.combinatorics.tensor can),
dup extract()
(in
module
272
sympy.polys.densetools), 1194
draw() (sympy.categories.diagram drawing.XypicDiagramDrawer
dup gf factor()
(in
module
method), 1844
sympy.polys.factortools), 1236
drop() (sympy.polys.rings.PolyRing method), dup lshift()
(in
module
1216
sympy.polys.densearith), 1183
drop to ground() (sympy.polys.rings.PolyRing dup mirror()
(in
module
method), 1216
sympy.polys.densetools), 1194
dsolve() (in module sympy.solvers.ode), 1397 dup monic()
(in
module
dt()
(sympy.physics.vector.dyadic.Dyadic
sympy.polys.densetools), 1192
method), 1673
dup primitive()
(in
module
dt()
(sympy.physics.vector.vector.Vector
sympy.polys.densetools), 1193
method), 1671
dup random()
(in
module
dtype (sympy.polys.agca.modules.FreeModule
sympy.polys.densebasic), 1181
attribute), 1133
dup real imag()
(in
module
sympy.polys.densetools), 1194
dtype (sympy.polys.agca.modules.QuotientModule
attribute), 1141
dup reverse()
(in
module
dtype (sympy.polys.domains.AlgebraicField
sympy.polys.densebasic), 1172
attribute), 1158
dup rshift()
(in
module
sympy.polys.densearith), 1183
dtype (sympy.polys.domains.ExpressionDomain
attribute), 1161
dup scale()
(in
module
dual (sympy.physics.quantum.state.StateBase
sympy.polys.densetools), 1195
attribute), 1781
dup shift()
(in
module
dual() (sympy.matrices.matrices.MatrixBase
sympy.polys.densetools), 1195
method), 655
dup sign variations()
(in
module
dual class() (sympy.physics.quantum.state.StateBase sympy.polys.densetools), 1196
class method), 1781
dup transform()
(in
module
Dummy (class in sympy.core.symbol), 124
sympy.polys.densetools), 1195
dummy eq()
(sympy.core.basic.Basic dup zz cyclotomic factor()
(in
module
method), 94
sympy.polys.factortools), 1233
DummyWrapper
(class
in dup zz cyclotomic poly()
(in
module
sympy.utilities.autowrap), 1534
sympy.polys.factortools), 1233
dump c() (sympy.utilities.autowrap.UfuncifyCodeWrapper
dup zz factor()
(in
module
method), 1534
sympy.polys.factortools), 1234
dump c() (sympy.utilities.codegen.CCodeGen dup zz factor sqf()
(in
module
method), 1541
sympy.polys.factortools), 1233
dump code() (sympy.utilities.codegen.CodeGen dup zz hensel lift()
(in
module
method), 1540
sympy.polys.factortools), 1232
dump f95() (sympy.utilities.codegen.FCodeGen dup zz hensel step()
(in
module
method), 1542
sympy.polys.factortools), 1232
dump h() (sympy.utilities.codegen.CCodeGen dup zz irreducible p()
(in
module
method), 1542
sympy.polys.factortools), 1233
dump h() (sympy.utilities.codegen.FCodeGen dup zz zassenhaus()
(in
module
method), 1543
sympy.polys.factortools), 1233
dot()
1942
Index
1943
Index
method), 1150
expr (sympy.core.function.Subs attribute),
evaluate deltas()
(in
module
171
sympy.physics.secondquant), 1619
expr (sympy.functions.elementary.piecewise.ExprCondPair
evaluate pauli product()
(in
module
attribute), 351
sympy.physics.paulialgebra), 1601
expr (sympy.physics.quantum.operator.DierentialOperator
EvaluationFailed
(class
in
attribute), 1763
sympy.polys.polyerrors), 1238
expr (sympy.physics.quantum.state.Wavefunction
even, 89
attribute), 1786
evolute()
(sympy.geometry.ellipse.Ellipse ExprCondPair
(class
in
method), 546
sympy.functions.elementary.piecewise),
ExactQuotientFailed
(class
in
351
sympy.polys.polyerrors), 1238
express()
(in
module
sympy.physics.vector.functions),
exclude()
(sympy.polys.polyclasses.DMP
method), 1163
1688
exclude()
(sympy.polys.polytools.Poly express() (sympy.physics.vector.dyadic.Dyadic
method), 1086
method), 1674
exp (class in sympy.functions.elementary.exponential),
express() (sympy.physics.vector.vector.Vector
350
method), 1671
exp() (in module mpmath), 756
ExpressionDomain
(class
in
exp() (sympy.matrices.matrices.MatrixBase
sympy.polys.domains), 1160
method), 655
ExpressionDomain.Expression
(class
in
Exp1 (class in sympy.core.numbers), 136
sympy.polys.domains), 1161
expand() (in module sympy.core.function), exquo() (in module sympy.polys.polytools),
171
1060
expand() (sympy.core.expr.Expr method), 113 exquo() (sympy.polys.domains.domain.Domain
method), 1150
expand() (sympy.matrices.matrices.MatrixBase
method), 655
exquo()
(sympy.polys.domains.eld.Field
expand complex()
(in
module
method), 1153
sympy.core.function), 179
exquo()
(sympy.polys.domains.ring.Ring
method), 1154
expand func()
(in
module
sympy.core.function), 178
exquo()
(sympy.polys.polyclasses.DMF
expand log() (in module sympy.core.function),
method), 1167
178
exquo()
(sympy.polys.polyclasses.DMP
expand mul()
(in
module
method), 1164
sympy.core.function), 178
exquo() (sympy.polys.polytools.Poly method),
expand multinomial()
(in
module
1086
sympy.core.function), 179
exquo ground() (sympy.polys.polyclasses.DMP
expand power base()
(in
module
method), 1164
sympy.core.function), 180
exquo ground() (sympy.polys.polytools.Poly
expand power exp()
(in
module
method), 1087
sympy.core.function), 180
extend()
(sympy.ntheory.generate.Sieve
expand trig()
(in
module
method), 276
sympy.core.function), 179
extend() (sympy.physics.unitsystems.dimensions.DimensionS
expint (class in sympy.functions.special.error functions),method), 1826
399
extend() (sympy.physics.unitsystems.units.UnitSystem
expint() (in module mpmath), 798
method), 1828
expj() (in module mpmath), 757
extend() (sympy.plotting.plot.Plot method),
expjpi() (in module mpmath), 758
1272
expm() (in module mpmath), 1028
extend to no() (sympy.ntheory.generate.Sieve
method), 276
expm1() (in module mpmath), 758
Exponential() (in module sympy.stats), 1372
extended euclid()
(in
module
Expr (class in sympy.core.expr), 103
sympy.solvers.diophantine), 1500
expr (sympy.core.function.Lambda attribute), exterior angle (sympy.geometry.polygon.RegularPolygon
163
attribute), 567
Index
1945
Index
1152
Float (class in sympy.core.numbers), 127
eld isomorphism()
(in
module oor (class in sympy.functions.elementary.integers),
sympy.polys.numberelds), 1117
351
ll() (sympy.matrices.dense.MutableDenseMatrix
oor() (in module mpmath), 735
method), 688
fmod() (in module mpmath), 732
ll() (sympy.matrices.sparse.MutableSparseMatrix
fmul() (in module mpmath), 730
method), 701
fneg() (in module mpmath), 729
lter symbols()
(in
module foci
(sympy.geometry.ellipse.Ellipse
atsympy.utilities.iterables), 1556
tribute), 547
nd() (sympy.core.basic.Basic method), 94
FockSpace
(class
in
nd DN()
(in
module
sympy.physics.quantum.hilbert),
sympy.solvers.diophantine), 1495
1759
nd dynamicsymbols()
(in
module FockState
(class
in
sympy.physics.mechanics), 1748
sympy.physics.secondquant), 1612
nd executable()
(in
module FockStateBosonBra
(class
in
sympy.galgebra.printing), 486
sympy.physics.secondquant), 1612
nd executable()
(in
module FockStateBosonKet
(class
in
sympy.utilities.misc), 1576
sympy.physics.secondquant), 1612
nd unit() (in module sympy.physics.units), FockStateBra
(class
in
1631
sympy.physics.secondquant), 1612
ndpoly() (in module mpmath), 1038
FockStateKet
(class
in
ndroot() (in module mpmath), 973
sympy.physics.secondquant), 1612
nite, 89
focus distance (sympy.geometry.ellipse.Ellipse
nite di weights()
(in
module
attribute), 547
sympy.calculus.nite di), 1596
forcing (sympy.physics.mechanics.kane.KanesMethod
attribute), 1742
FiniteDomain (class in sympy.stats.frv), 1396
FiniteField (class in sympy.polys.domains), forcing (sympy.physics.mechanics.lagrange.LagrangesMeth
1155
attribute), 1745
FinitePSpace (class in sympy.stats.frv), 1396 forcing full (sympy.physics.mechanics.kane.KanesMethod
attribute), 1742
FiniteRV() (in module sympy.stats), 1363
FiniteSet (class in sympy.sets.sets), 1319
forcing full (sympy.physics.mechanics.lagrange.LagrangesM
FisherZ() (in module sympy.stats), 1374
attribute), 1745
FixedBosonicBasis
(class
in form lagranges equations()
sympy.physics.secondquant), 1614
(sympy.physics.mechanics.lagrange.LagrangesMeth
method), 1745
FKet (in module sympy.physics.secondquant),
1613
fourier() (in module mpmath), 1017
FlagError (class in sympy.polys.polyerrors), fourier transform()
(in
module
1239
sympy.integrals.transforms), 586
FlatMirror
(class
in fourierval() (in module mpmath), 1018
sympy.physics.optics.gaussopt),
fprod() (in module mpmath), 732
1804
frac (in module sympy.printing.pretty.pretty symbology),
FlatRefraction
(class
in
1267
sympy.physics.optics.gaussopt),
frac() (in module mpmath), 737
1804
frac eld() (sympy.polys.domains.domain.Domain
atten() (in module sympy.galgebra.vector),
method), 1150
484
frac unify()
(sympy.polys.polyclasses.DMF
atten() (in module sympy.utilities.iterables),
method), 1168
1556
fraction() (in module mpmath), 741
atten() (sympy.categories.CompositeMorphismfraction() (in module sympy.simplify.simplify),
method), 1833
1335
atten() (sympy.core.add.Add class method), FractionField (class in sympy.polys.domains),
146
1159
atten() (sympy.core.mul.Mul class method), Frechet() (in module sympy.stats), 1375
142
free module() (sympy.polys.domains.ring.Ring
Index
1947
method), 1154
method), 1150
free symbols
(sympy.core.basic.Basic
at- from dict()
(sympy.polys.polyclasses.DMP
tribute), 94
class method), 1164
free symbols (sympy.functions.elementary.piecewise.ExprCondPair
from dict() (sympy.polys.polytools.Poly class
attribute), 351
method), 1088
free symbols (sympy.geometry.curve.Curve from expr() (sympy.polys.polytools.Poly class
attribute), 540
method), 1088
free symbols (sympy.integrals.Integral at- from ExpressionDomain()
tribute), 616
(sympy.polys.domains.domain.Domain
free symbols (sympy.matrices.matrices.MatrixBase
method), 1150
attribute), 656
from ExpressionDomain()
free symbols (sympy.physics.quantum.operator.DierentialOperator
(sympy.polys.domains.ExpressionDomain
attribute), 1764
method), 1161
free symbols (sympy.polys.polytools.Poly at- from FF gmpy() (sympy.polys.domains.domain.Domain
tribute), 1088
method), 1150
free symbols (sympy.polys.polytools.PurePoly from FF gmpy() (sympy.polys.domains.FiniteField
attribute), 1111
method), 1155
free symbols in domain
from FF python() (sympy.polys.domains.domain.Domain
(sympy.polys.polytools.Poly
atmethod), 1150
tribute), 1088
from FF python() (sympy.polys.domains.FiniteField
FreeModule
(class
in
method), 1156
sympy.polys.agca.modules), 1132
from FractionField()
FreeSpace
(class
in
(sympy.polys.domains.domain.Domain
sympy.physics.optics.gaussopt),
method), 1150
1803
from FractionField()
(sympy.polys.domains.ExpressionDomain
frequency (sympy.physics.optics.waves.TWave
method), 1161
attribute), 1818
fresnelc (class in sympy.functions.special.error functions),
from FractionField()
396
(sympy.polys.domains.FractionField
method), 1159
fresnelc() (in module mpmath), 809
FresnelIntegral
(class
in from FractionField()
sympy.functions.special.error functions),
(sympy.polys.domains.PolynomialRing
395
method), 1157
fresnels (class in sympy.functions.special.error functions),
from GlobalPolynomialRing()
(sympy.polys.domains.domain.Domain
395
method), 1150
fresnels() (in module mpmath), 808
frexp() (in module mpmath), 740
from inversion vector()
from AlgebraicField()
(sympy.combinatorics.permutations.Permutation
(sympy.polys.domains.domain.Domain
class method), 200
method), 1150
from list()
(sympy.polys.polyclasses.DMP
class method), 1164
from AlgebraicField()
(sympy.polys.domains.FractionField
from list() (sympy.polys.polytools.Poly class
method), 1159
method), 1088
from AlgebraicField()
from poly() (sympy.polys.polytools.Poly class
(sympy.polys.domains.IntegerRing
method), 1088
from PolynomialRing()
method), 1156
from AlgebraicField()
(sympy.polys.domains.domain.Domain
(sympy.polys.domains.PolynomialRing
method), 1150
from PolynomialRing()
method), 1157
(sympy.polys.domains.ExpressionDomain
from AlgebraicField()
method), 1161
(sympy.polys.domains.RationalField
from PolynomialRing()
method), 1158
from ComplexField()
(sympy.polys.domains.FractionField
(sympy.polys.domains.domain.Domain
method), 1159
1948
Index
from PolynomialRing()
method), 1157
(sympy.polys.domains.PolynomialRing from sympy() (sympy.polys.domains.RealField
method), 1157
method), 1160
from QQ gmpy() (sympy.polys.domains.AlgebraicField
from sympy list() (sympy.polys.polyclasses.DMP
method), 1158
class method), 1164
from QQ gmpy() (sympy.polys.domains.domain.Domain
from TIDS list() (sympy.tensor.tensor.TensAdd
method), 1150
static method), 1528
from QQ gmpy() (sympy.polys.domains.ExpressionDomain
from ZZ gmpy() (sympy.polys.domains.AlgebraicField
method), 1161
method), 1158
from QQ gmpy() (sympy.polys.domains.FiniteField
from ZZ gmpy() (sympy.polys.domains.domain.Domain
method), 1156
method), 1150
from QQ gmpy() (sympy.polys.domains.FractionField
from ZZ gmpy() (sympy.polys.domains.ExpressionDomain
method), 1159
method), 1161
from QQ gmpy() (sympy.polys.domains.PolynomialRing
from ZZ gmpy() (sympy.polys.domains.FiniteField
method), 1157
method), 1156
from QQ python() (sympy.polys.domains.AlgebraicField
from ZZ gmpy() (sympy.polys.domains.FractionField
method), 1158
method), 1159
from QQ python() (sympy.polys.domains.domain.Domain
from ZZ gmpy() (sympy.polys.domains.PolynomialRing
method), 1150
method), 1157
from QQ python() (sympy.polys.domains.ExpressionDomain
from ZZ python() (sympy.polys.domains.AlgebraicField
method), 1161
method), 1158
from QQ python() (sympy.polys.domains.FiniteField
from ZZ python() (sympy.polys.domains.domain.Domain
method), 1156
method), 1150
from QQ python() (sympy.polys.domains.FractionField
from ZZ python() (sympy.polys.domains.ExpressionDomain
method), 1159
method), 1161
from QQ python() (sympy.polys.domains.PolynomialRing
from ZZ python() (sympy.polys.domains.FiniteField
method), 1157
method), 1156
from RealField() (sympy.polys.domains.AlgebraicField
from ZZ python() (sympy.polys.domains.FractionField
method), 1158
method), 1159
from RealField() (sympy.polys.domains.domain.Domain
from ZZ python() (sympy.polys.domains.PolynomialRing
method), 1150
method), 1157
from RealField() (sympy.polys.domains.ExpressionDomain
fromiter()
(sympy.core.basic.Basic
class
method), 1161
method), 94
from RealField() (sympy.polys.domains.FiniteField
fsub() (in module mpmath), 729
method), 1156
fsum() (in module mpmath), 732
from RealField() (sympy.polys.domains.FractionField
full cyclic form (sympy.combinatorics.permutations.Permuta
method), 1159
attribute), 200
from RealField() (sympy.polys.domains.PolynomialRing
fun eval()
(sympy.tensor.tensor.TensAdd
method), 1157
method), 1528
from rgs() (sympy.combinatorics.partitions.Partition
fun eval()
(sympy.tensor.tensor.TensMul
class method), 188
method), 1530
from sequence() (sympy.combinatorics.permutations.Permutation
func (sympy.core.basic.Basic attribute), 94
class method), 200
func eld modgcd
(class
in
from sympy() (sympy.polys.domains.AlgebraicField
sympy.polys.modulargcd), 1242
method), 1158
Function (class in sympy.core.function), 169
from sympy() (sympy.polys.domains.domain.Domain
function (sympy.physics.quantum.operator.DierentialOpera
method), 1151
attribute), 1764
from sympy() (sympy.polys.domains.ExpressionDomain
function exponentiation()
(in
module
method), 1161
sympy.parsing.sympy parser), 1591
from sympy() (sympy.polys.domains.FiniteField FunctionClass (class in sympy.core.function),
168
method), 1156
from sympy() (sympy.polys.domains.FractionField
FunctionMatrix
(class
in
method), 1159
sympy.matrices.expressions), 710
from sympy() (sympy.polys.domains.PolynomialRing
functions (sympy.geometry.curve.Curve atIndex
1949
tribute), 540
1810
gaussian reduce()
(in
module
G
sympy.solvers.diophantine), 1503
GaussLegendre
(class
in
mpG() (in module sympy.printing.pretty.pretty symbology),
math.calculus.quadrature), 1012
1267
gcd() (in module sympy.polys.polytools), 1066
g() (in module sympy.printing.pretty.pretty symbology),
gcd() (sympy.core.numbers.Number method),
1267
127
GA LatexPrinter
(class
in
gcd() (sympy.polys.domains.domain.Domain
sympy.galgebra.printing), 485
method), 1151
GA Printer
(class
in
gcd()
(sympy.polys.domains.eld.Field
sympy.galgebra.printing), 485
method), 1153
GAeval()
(in
module
gcd() (sympy.polys.domains.PolynomialRing
sympy.galgebra.precedence), 484
method), 1157
gamma (class in sympy.functions.special.gamma functions),
gcd()
(sympy.polys.domains.RealField
379
method), 1160
gamma() (in module mpmath), 780
gcd() (sympy.polys.polyclasses.DMP method),
Gamma() (in module sympy.stats), 1375
1164
gamma trace() (sympy.physics.hep.gamma matrices.GammaMatrixHead
gcd() (sympy.polys.polytools.Poly method),
method), 1633
1088
gammainc() (in module mpmath), 795
GammaInverse() (in module sympy.stats), gcd list() (in module sympy.polys.polytools),
1066
1376
(in
module
GammaMatrixHead
(class
in gcd terms()
sympy.core.exprtools), 185
sympy.physics.hep.gamma matrices),
gcdex() (in module sympy.polys.polytools),
1632
1061
gammaprod() (in module mpmath), 782
Gate (class in sympy.physics.quantum.gate), gcdex() (sympy.polys.domains.domain.Domain
method), 1151
1789
gate (sympy.physics.quantum.gate.CGate at- gcdex() (sympy.polys.domains.PolynomialRing
method), 1157
tribute), 1790
(sympy.polys.polyclasses.DMP
gate (sympy.physics.quantum.gate.CNotGate gcdex()
method), 1164
attribute), 1792
gate simp()
(in
module gcdex() (sympy.polys.polytools.Poly method),
1089
sympy.physics.quantum.gate), 1793
gate sort()
(in
module Ge (in module sympy.core.relational), 148
gegenbauer
(class
in
sympy.physics.quantum.gate), 1793
sympy.functions.special.polynomials),
gaunt() (in module sympy.physics.wigner),
435
1624
gauss chebyshev t()
(in
module gegenbauer() (in module mpmath), 877
gegenbauer poly()
(in
module
sympy.integrals.quadrature), 622
sympy.polys.orthopolys), 1120
gauss chebyshev u()
(in
module
gen (sympy.polys.polytools.Poly attribute),
sympy.integrals.quadrature), 623
1089
gauss gen laguerre()
(in
module
generate() (sympy.combinatorics.perm groups.PermutationG
sympy.integrals.quadrature), 621
method), 226
gauss hermite()
(in
module
generate
bell()
(in
module
sympy.integrals.quadrature), 620
sympy.utilities.iterables),
1557
gauss jacobi()
(in
module
generate derangements()
(in
module
sympy.integrals.quadrature), 624
sympy.utilities.iterables),
1558
gauss laguerre()
(in
module
generate dimino() (sympy.combinatorics.perm groups.Permu
sympy.integrals.quadrature), 620
method), 226
gauss legendre()
(in
module
generate
gray() (sympy.combinatorics.graycode.GrayCode
sympy.integrals.quadrature), 619
257
method),
gaussian conj()
(in
module
generate
involutions()
(in
module
sympy.physics.optics.gaussopt),
1950
Index
sympy.utilities.iterables), 1558
method), 1826
generate oriented forest()
(in
module get domain()
(sympy.polys.polytools.Poly
sympy.utilities.iterables), 1559
method), 1089
generate schreier sims()
get exact() (sympy.polys.domains.domain.Domain
(sympy.combinatorics.perm groups.PermutationGroup
method), 1151
method), 227
get exact() (sympy.polys.domains.RealField
generate tokens()
(in
module
method), 1160
get eld() (sympy.polys.domains.domain.Domain
sympy.parsing.sympy tokenize),
1589
method), 1151
generators (sympy.combinatorics.perm groups.PermutationGroup
get eld() (sympy.polys.domains.ExpressionDomain
attribute), 227
method), 1161
GeneratorsError
(class
in get eld()
(sympy.polys.domains.eld.Field
sympy.polys.polyerrors), 1238
method), 1153
GeneratorsNeeded
(class
in get eld() (sympy.polys.domains.FiniteField
sympy.polys.polyerrors), 1238
method), 1156
Geometric() (in module sympy.stats), 1364
get eld() (sympy.polys.domains.IntegerRing
geometric conj ab()
(in
module
method), 1156
sympy.physics.optics.gaussopt),
get eld() (sympy.polys.domains.PolynomialRing
1809
method), 1157
geometric conj af()
(in
module get indices()
(in
module
sympy.physics.optics.gaussopt),
sympy.tensor.index methods), 1516
1810
get indices()
(sympy.tensor.tensor.TensMul
geometric conj bf()
(in
module
method), 1530
sympy.physics.optics.gaussopt),
get interface() (sympy.utilities.codegen.FCodeGen
method), 1543
1810
GeometricRay
(class
in get mass() (sympy.physics.mechanics.particle.Particle
sympy.physics.optics.gaussopt),
method), 1731
1805
get matrix() (sympy.tensor.tensor.TensExpr
GeometryEntity
(class
in
method), 1526
sympy.geometry.entity), 493
get mod func()
(in
module
get() (sympy.core.containers.Dict method),
sympy.utilities.source), 1587
183
get modulus()
(sympy.polys.polytools.Poly
get() (sympy.physics.unitsystems.dimensions.Dimensionmethod), 1089
method), 1825
get motion params()
(in
module
sympy.physics.vector.functions),
get adjacency distance()
(sympy.combinatorics.permutations.Permutation
1681
method), 200
get nodes() (mpmath.calculus.quadrature.QuadratureRule
get adjacency matrix()
method), 1010
(sympy.combinatorics.permutations.Permutation
get period() (sympy.functions.special.hyper.meijerg
method), 201
method), 430
get basis()
(in
module get permuted() (sympy.physics.secondquant.PermutationOp
sympy.physics.quantum.represent),
method), 1623
1769
get point() (sympy.physics.mechanics.particle.Particle
get class() (in module sympy.utilities.source),
method), 1731
1587
get positional distance()
get comm() (sympy.tensor.tensor. TensorManager
(sympy.combinatorics.permutations.Permutation
method), 1517
method), 201
get contraction structure()
(in
module get precedence distance()
sympy.tensor.index methods), 1514
(sympy.combinatorics.permutations.Permutation
method), 202
get default datatype()
(in
module
get precedence matrix()
sympy.utilities.codegen), 1540
get diag blocks() (sympy.matrices.matrices.MatrixBase (sympy.combinatorics.permutations.Permutation
method), 656
method), 202
get dim() (sympy.physics.unitsystems.dimensions.DimensionSystem
Get Program()
(in
module
Index
1951
sympy.galgebra.printing), 486
sympy.polys.galoistools), 1208
get prototype() (sympy.utilities.codegen.CCodeGen
gf crt() (in module sympy.polys.galoistools),
method), 1542
1197
get resource()
(in
module gf crt1() (in module sympy.polys.galoistools),
sympy.utilities.pkgdata), 1578
1198
get ring() (sympy.polys.domains.AlgebraicField gf crt2() (in module sympy.polys.galoistools),
method), 1158
1198
get ring() (sympy.polys.domains.domain.Domaingf csolve()
(in
module
method), 1151
sympy.polys.galoistools), 1213
get ring() (sympy.polys.domains.ExpressionDomain
gf degree()
(in
module
method), 1161
sympy.polys.galoistools), 1198
get ring()
(sympy.polys.domains.eld.Field gf di() (in module sympy.polys.galoistools),
method), 1153
1207
get ring() (sympy.polys.domains.FractionField gf div() (in module sympy.polys.galoistools),
1203
method), 1160
get ring()
(sympy.polys.domains.RealField gf eval() (in module sympy.polys.galoistools),
method), 1160
1207
get ring()
(sympy.polys.domains.ring.Ring gf expand()
(in
module
method), 1154
sympy.polys.galoistools), 1203
get segments() (sympy.plotting.plot.LineOver1DRangeSeries
gf exquo()
(in
module
method), 1282
sympy.polys.galoistools), 1204
get segments() (sympy.plotting.plot.Parametric2DLineSeries
gf factor()
(in
module
method), 1283
sympy.polys.galoistools), 1212
get subNO() (sympy.physics.secondquant.NO gf factor sqf()
(in
module
method), 1618
sympy.polys.galoistools), 1212
get subset from bitstring()
gf from dict()
(in
module
(sympy.combinatorics.graycode
sympy.polys.galoistools), 1200
static method), 260
gf from int poly()
(in
module
get symmetric group sgs()
(in
module
sympy.polys.galoistools), 1200
sympy.combinatorics.tensor can),
gf gcd() (in module sympy.polys.galoistools),
275
1206
get sympy dir()
(in
module gf gcdex()
(in
module
sympy.utilities.runtests), 1582
sympy.polys.galoistools), 1206
get target matrix() (sympy.physics.quantum.gate.Gate
gf int() (in module sympy.polys.galoistools),
method), 1789
1198
get target matrix() (sympy.physics.quantum.gate.UGate
gf irreducible()
(in
module
method), 1790
sympy.polys.galoistools), 1209
get unit() (sympy.physics.unitsystems.units.UnitSystem
gf irreducible p()
(in
module
method), 1828
sympy.polys.galoistools), 1209
getn() (sympy.core.expr.Expr method), 114
gf LC() (in module sympy.polys.galoistools),
getO() (sympy.core.expr.Expr method), 114
1199
gf add() (in module sympy.polys.galoistools), gf lcm() (in module sympy.polys.galoistools),
1202
1206
gf add ground()
(in
module gf lshift() (in module sympy.polys.galoistools),
sympy.polys.galoistools), 1201
1205
gf add mul()
(in
module gf monic()
(in
module
sympy.polys.galoistools), 1203
sympy.polys.galoistools), 1207
gf berlekamp()
(in
module gf mul() (in module sympy.polys.galoistools),
sympy.polys.galoistools), 1211
1202
gf cofactors()
(in
module gf mul ground()
(in
module
sympy.polys.galoistools), 1206
sympy.polys.galoistools), 1201
gf compose()
(in
module gf multi eval()
(in
module
sympy.polys.galoistools), 1208
sympy.polys.galoistools), 1208
gf compose mod()
(in
module gf neg() (in module sympy.polys.galoistools),
1952
Index
1201
gf normal()
(in
module
sympy.polys.galoistools), 1199
gf pow() (in module sympy.polys.galoistools),
1205
gf pow mod()
(in
module
sympy.polys.galoistools), 1205
gf Qbasis()
(in
module
sympy.polys.galoistools), 1211
gf Qmatrix()
(in
module
sympy.polys.galoistools), 1211
gf quo() (in module sympy.polys.galoistools),
1204
gf quo ground()
(in
module
sympy.polys.galoistools), 1202
gf random()
(in
module
sympy.polys.galoistools), 1209
gf rem() (in module sympy.polys.galoistools),
1204
gf rshift()
(in
module
sympy.polys.galoistools), 1205
gf shoup()
(in
module
sympy.polys.galoistools), 1212
gf sqf list()
(in
module
sympy.polys.galoistools), 1210
gf sqf p() (in module sympy.polys.galoistools),
1209
gf sqf part()
(in
module
sympy.polys.galoistools), 1210
gf sqr() (in module sympy.polys.galoistools),
1202
gf strip() (in module sympy.polys.galoistools),
1199
gf sub() (in module sympy.polys.galoistools),
1202
gf sub ground()
(in
module
sympy.polys.galoistools), 1201
gf sub mul()
(in
module
sympy.polys.galoistools), 1203
gf TC() (in module sympy.polys.galoistools),
1199
gf to dict()
(in
module
sympy.polys.galoistools), 1200
gf to int poly()
(in
module
sympy.polys.galoistools), 1200
gf trace map()
(in
module
sympy.polys.galoistools), 1208
gf trunc()
(in
module
sympy.polys.galoistools), 1199
gf value()
(in
module
sympy.polys.galoistools), 1213
gf zassenhaus()
(in
module
sympy.polys.galoistools), 1211
g() (in module sympy.polys.polytools), 1069
Index
method), 1090
has dups()
(in
module
(in
module
sympy.utilities.iterables), 1559
sympy.parsing.sympy tokenize),
has integer powers (sympy.physics.unitsystems.dimensions.
1590
attribute), 1825
group() (in module sympy.utilities.iterables), has only gens() (sympy.polys.polytools.Poly
1559
method), 1090
grover iteration()
(in
module has q annihilators (sympy.physics.secondquant.NO
sympy.physics.quantum.grover),
attribute), 1618
1795
has q creators (sympy.physics.secondquant.NO
gruntz() (in module sympy.series.gruntz),
attribute), 1618
1306
has variety()
(in
module
Gt (in module sympy.core.relational), 148
sympy.utilities.iterables), 1560
guess degree()
(mp- Heaviside
(class
in
math.calculus.quadrature.QuadratureRule
sympy.functions.special.delta functions),
method), 1010
378
height (sympy.categories.diagram drawing.DiagramGrid
H
attribute), 1840
H (in module sympy.physics.quantum.gate), height (sympy.physics.optics.gaussopt.GeometricRay
attribute), 1806
1792
(sympy.polys.agca.ideals.Ideal
H (sympy.matrices.matrices.MatrixBase at- height()
method), 1139
tribute), 645
HadamardGate
(class
in height() (sympy.printing.pretty.stringpict.stringPict
method), 1268
sympy.physics.quantum.gate), 1791
hermite (class in sympy.functions.special.polynomials),
Half (class in sympy.core.numbers), 134
440
half gcdex()
(in
module
hermite() (in module mpmath), 878
sympy.polys.polytools), 1061
hermite poly()
(in
module
half gcdex() (sympy.polys.domains.domain.Domain
sympy.polys.orthopolys), 1120
method), 1151
half gcdex()
(sympy.polys.polyclasses.DMP hermitian, 89
HermitianOperator
(class
in
method), 1164
sympy.physics.quantum.operator),
half gcdex()
(sympy.polys.polytools.Poly
1761
method), 1090
half per()
(sympy.polys.polyclasses.DMF hessian() (in module sympy.matrices.dense),
681
method), 1168
Halley
(class
in
mp- heurisch() (sympy.integrals static method),
612
math.calculus.optimization), 977
heurisch wrapper() (sympy.integrals static
hankel1 (class in sympy.functions.special.bessel),
method), 613
411
HeuristicGCDFailed
(class
in
hankel1() (in module mpmath), 825
sympy.polys.polyerrors), 1238
hankel2 (class in sympy.functions.special.bessel),
HilbertSpace
(class
in
412
sympy.physics.quantum.hilbert),
hankel2() (in module mpmath), 827
1758
hankel transform()
(in
module
hobj()
(in
module
sympy.integrals.transforms), 589
sympy.printing.pretty.pretty symbology),
harmonic
(class
in
1267
sympy.functions.combinatorial.numbers),
holzer()
(in
module
371
1504
sympy.solvers.diophantine),
harmonic() (in module mpmath), 793
hom() (sympy.categories.Diagram method),
has() (sympy.core.basic.Basic method), 95
1836
has() (sympy.matrices.matrices.MatrixBase
homogeneous
order()
(in
module
method), 657
sympy.solvers.ode),
1403
has() (sympy.matrices.sparse.SparseMatrix
homogeneous order()
method), 695
(sympy.polys.polyclasses.DMP
group()
1954
Index
method), 1164
Identity (class in sympy.matrices.expressions),
homogeneous order()
711
(sympy.polys.polytools.Poly method), identity hom() (sympy.polys.agca.modules.FreeModule
1090
method), 1133
homogenize() (sympy.polys.polyclasses.DMP identity hom() (sympy.polys.agca.modules.Module
method), 1164
method), 1132
homogenize()
(sympy.polys.polytools.Poly identity hom() (sympy.polys.agca.modules.QuotientModule
method), 1091
method), 1141
homomorphism()
(in
module identity hom() (sympy.polys.agca.modules.SubModule
sympy.polys.agca.homomorphisms),
method), 1134
1143
IdentityFunction
(class
in
HomomorphismFailed
(class
in
sympy.functions.elementary.miscellaneous),
sympy.polys.polyerrors), 1238
352
horner() (in module sympy.polys.polyfuncs), IdentityGate
(class
in
1114
sympy.physics.quantum.gate), 1790
hradius (sympy.geometry.ellipse.Ellipse at- IdentityMorphism
(class
in
tribute), 547
sympy.categories), 1833
hstack() (sympy.matrices.matrices.MatrixBase IdentityOperator
(class
in
class method), 657
sympy.physics.quantum.operator),
hyp0f1() (in module mpmath), 888
1761
hyp1f1() (in module mpmath), 889
Idx (class in sympy.tensor.indexed), 1509
hyp1f2() (in module mpmath), 890
igcd() (in module sympy.core.numbers), 132
hyp2f0() (in module mpmath), 891
ilcm() (in module sympy.core.numbers), 132
hyp2f1() (in module mpmath), 892
Illinois
(class
in
mpmath.calculus.optimization), 978
hyp2f2() (in module mpmath), 893
hyp2f3() (in module mpmath), 893
im() (in module mpmath), 734
hyp3f2() (in module mpmath), 894
image() (sympy.polys.agca.homomorphisms.ModuleHomomo
hyper (class in sympy.functions.special.hyper),
method), 1145
426
ImageSet (class in sympy.sets.fancysets),
hyper() (in module mpmath), 895
1326
hyper2d() (in module mpmath), 902
imageset() (in module sympy.sets.sets), 1316
HyperbolicFunction
(class
in imaginary, 89
sympy.functions.elementary.hyperbolic),ImaginaryUnit
(class
in
352
sympy.core.numbers), 137
hypercomb() (in module mpmath), 898
ImmutableMatrix
(class
in
hyperexpand()
(in
module
sympy.matrices.immutable), 705
sympy.simplify.hyperexpand), 1347
ImmutableSparseMatrix
(class
in
hyperfac() (in module mpmath), 788
sympy.matrices.immutable), 703
Hypergeometric() (in module sympy.stats), implemented function()
(in
module
1363
sympy.utilities.lambdify), 1573
hypersimilar()
(in
module implicit application()
(in
module
sympy.simplify.simplify), 1339
sympy.parsing.sympy parser), 1591
hypersimp()
(in
module implicit multiplication()
(in
module
sympy.simplify.simplify), 1339
sympy.parsing.sympy parser), 1591
hyperu() (in module mpmath), 862
implicit multiplication application() (in modhypot() (in module mpmath), 752
ule
sympy.parsing.sympy parser),
1591
I
ImplicitSeries
(class
in
sympy.plotting.plot
implicit),
1283
ibin() (in module sympy.utilities.iterables),
Implies (class in sympy.logic.boolalg), 630
1560
Ideal (class in sympy.polys.agca.ideals), 1138 imul num() (sympy.polys.rings.PolyElement
method), 1219
ideal()
(sympy.polys.domains.ring.Ring
in
terms
of generators()
method), 1154
(sympy.polys.agca.modules.SubModule
identify() (in module mpmath), 1034
Index
1955
method), 1135
method), 1164
incenter (sympy.geometry.polygon.Triangle inject() (sympy.polys.polytools.Poly method),
attribute), 573
1091
incircle (sympy.geometry.polygon.RegularPolygon
InnerProduct
(class
in
attribute), 567
sympy.physics.quantum.innerproduct),
incircle
(sympy.geometry.polygon.Triangle
1754
attribute), 573
InnerProduct
(class
in
inclusion hom() (sympy.polys.agca.modules.SubModule sympy.physics.secondquant), 1613
method), 1135
inradius (sympy.geometry.polygon.RegularPolygon
indent code() (sympy.printing.ccode.CCodePrinter
attribute), 567
method), 1252
inradius (sympy.geometry.polygon.Triangle
indent code() (sympy.printing.fcode.FCodePrinter
attribute), 573
method), 1257
intcurve diequ()
(in
module
index() (sympy.combinatorics.permutations.Permutationsympy.digeom), 1857
intcurve series() (in module sympy.digeom),
method), 202
index()
(sympy.core.containers.Tuple
1855
method), 182
integer, 89
index() (sympy.physics.secondquant.FixedBosonicBasis
Integer (class in sympy.core.numbers), 131
method), 1614
integer nthroot()
(in
module
index() (sympy.physics.secondquant.VarBosonicBasis sympy.core.power), 141
method), 1613
IntegerPartition
(class
in
index() (sympy.polys.rings.PolyRing method),
sympy.combinatorics.partitions),
1216
189
Indexed (class in sympy.tensor.indexed), 1511 IntegerRing (class in sympy.polys.domains),
IndexedBase (class in sympy.tensor.indexed),
1156
1513
Integers (class in sympy.sets.fancysets), 1325
indices (sympy.tensor.indexed.Indexed at- Integral (class in sympy.integrals), 615
tribute), 1511
Integral.is commutative
(in
module
indices contain equal information
sympy.integrals.transforms), 615
(sympy.functions.special.tensor functions.KroneckerDelta
integral steps() (sympy.integrals.manualintegrate
attribute), 447
static method), 614
indices contain equal information
integrand() (sympy.functions.special.hyper.meijerg
(sympy.physics.secondquant.KroneckerDelta method), 430
attribute), 1605
integrate() (sympy.core.expr.Expr method),
inertia()
(in
module
114
sympy.physics.mechanics.functions), integrate() (sympy.integrals static method),
1736
608
inertia of point mass()
(in
module integrate() (sympy.matrices.matrices.MatrixBase
sympy.physics.mechanics.functions),
method), 657
1737
integrate()
(sympy.polys.polyclasses.DMP
method), 1164
inf (sympy.sets.sets.Set attribute), 1313
innite, 89
integrate()
(sympy.polys.polytools.Poly
innitesimals()
(in
module
method), 1091
integrate result()
(in
module
sympy.solvers.ode), 1404
Innity (class in sympy.core.numbers), 135
sympy.physics.quantum.represent),
init printing()
(in
module
1769
sympy.physics.vector.printing), 1682 interactive traversal()
(in
module
inject() (sympy.polys.domains.compositedomain.CompositeDomain
sympy.utilities.iterables), 1561
method), 1155
interior angle (sympy.geometry.polygon.RegularPolygon
attribute), 568
inject() (sympy.polys.domains.domain.Domain
interpolate()
(in
module
method), 1151
inject() (sympy.polys.domains.simpledomain.SimpleDomain
sympy.polys.polyfuncs), 1114
interpolating poly()
(in
module
method), 1155
inject()
(sympy.polys.polyclasses.DMP
sympy.polys.specialpolys), 1120
1956
Index
intersect()
(sympy.polys.agca.ideals.Ideal inverse() (sympy.functions.elementary.hyperbolic.acoth
method), 1139
method), 344
intersect() (sympy.polys.agca.modules.SubModule
inverse() (sympy.functions.elementary.hyperbolic.asinh
method), 1135
method), 345
intersect()
(sympy.sets.sets.Set
method), inverse() (sympy.functions.elementary.hyperbolic.atanh
1313
method), 347
Intersection (class in sympy.sets.sets), 1321
inverse() (sympy.functions.elementary.hyperbolic.coth
intersection()
(in
module
method), 350
sympy.geometry.util), 495
inverse() (sympy.functions.elementary.hyperbolic.sinh
intersection() (sympy.geometry.ellipse.Circle
method), 360
method), 555
inverse() (sympy.functions.elementary.hyperbolic.tanh
intersection() (sympy.geometry.ellipse.Ellipse
method), 363
method), 548
inverse() (sympy.functions.elementary.trigonometric.acos
intersection() (sympy.geometry.entity.GeometryEntity method), 343
inverse() (sympy.functions.elementary.trigonometric.acot
method), 493
intersection() (sympy.geometry.line.LinearEntity
method), 344
method), 511
inverse() (sympy.functions.elementary.trigonometric.asin
intersection() (sympy.geometry.line3d.LinearEntity3D method), 345
method), 529
inverse() (sympy.functions.elementary.trigonometric.atan
intersection() (sympy.geometry.plane.Plane
method), 346
method), 579
inverse() (sympy.functions.elementary.trigonometric.cot
intersection()
(sympy.geometry.point.Point
method), 350
method), 499
inverse() (sympy.functions.elementary.trigonometric.tan
intersection() (sympy.geometry.point3d.Point3D
method), 363
method), 506
inverse ADJ() (sympy.matrices.matrices.MatrixBase
method), 658
intersection() (sympy.geometry.polygon.Polygon
method), 560
inverse cosine transform()
(in
module
intersection() (sympy.sets.sets.Set method),
sympy.integrals.transforms), 588
1314
inverse fourier transform()
(in
module
sympy.integrals.transforms), 586
Interval (class in sympy.sets.sets), 1317
intervals() (in module sympy.polys.polytools), inverse GE() (sympy.matrices.matrices.MatrixBase
1071
method), 658
intervals()
(sympy.polys.polyclasses.DMP inverse hankel transform()
(in
module
method), 1164
sympy.integrals.transforms), 590
intervals()
(sympy.polys.polytools.Poly inverse laplace transform()
(in
module
method), 1092
sympy.integrals.transforms), 585
IntQubit
(class
in inverse LU() (sympy.matrices.matrices.MatrixBase
sympy.physics.quantum.qubit), 1797
method), 658
IntQubitBra
(class
in inverse mellin transform()
(in
module
sympy.physics.quantum.qubit), 1798
sympy.integrals.transforms), 584
intrinsic impedance
inverse sine transform()
(in
module
(sympy.physics.optics.medium.Medium
sympy.integrals.transforms), 587
attribute), 1812
inversion vector() (sympy.combinatorics.permutations.Perm
inv can transf matrix
method), 203
(sympy.physics.unitsystems.dimensions.DimensionSystem
inversions() (sympy.combinatorics.permutations.Permutation
attribute), 1826
method), 203
inv mod() (sympy.matrices.matrices.MatrixBaseinvert() (in module sympy.polys.polytools),
1061
method), 658
Inverse (class in sympy.matrices.expressions), invert() (sympy.core.expr.Expr method), 114
709
invert() (sympy.polys.domains.domain.Domain
inverse() (sympy.functions.elementary.exponential.log method), 1151
method), 354
invert()
(sympy.polys.domains.ring.Ring
inverse() (sympy.functions.elementary.hyperbolic.acoshmethod), 1154
method), 343
invert()
(sympy.polys.polyclasses.DMF
Index
1957
method), 1168
is cyclotomic (sympy.polys.polytools.Poly at(sympy.polys.polyclasses.DMP
tribute), 1093
method), 1164
is diagonal() (sympy.matrices.matrices.MatrixBase
invert() (sympy.polys.polytools.Poly method),
method), 659
1092
is diagonalizable() (sympy.matrices.matrices.MatrixBase
IQFT (class in sympy.physics.quantum.qft),
method), 660
1796
is dimensionless (sympy.physics.unitsystems.dimensions.Dim
irrational, 89
attribute), 1825
is abelian (sympy.combinatorics.perm groups.PermutationGroup
is disjoint() (sympy.sets.sets.Set method),
attribute), 227
1314
is above fermi (sympy.functions.special.tensor functions.KroneckerDelta
is dnf() (in module sympy.logic.boolalg), 633
attribute), 448
is Empty (sympy.combinatorics.permutations.Permutation
attribute), 204
is above fermi (sympy.physics.secondquant.KroneckerDelta
attribute), 1606
is equilateral() (sympy.geometry.polygon.Triangle
is algebraic expr()
(sympy.core.expr.Expr
method), 574
is even (sympy.combinatorics.permutations.Permutation
method), 114
is aliased (sympy.polys.numberelds.AlgebraicNumber attribute), 205
attribute), 1117
is full module() (sympy.polys.agca.modules.SubModule
is alt sym() (sympy.combinatorics.perm groups.PermutationGroup
method), 1135
method), 228
is full module() (sympy.polys.agca.modules.SubQuotientMod
is anti symmetric() (sympy.matrices.matrices.MatrixBase
method), 1142
method), 658
is groebner()
(in
module
is below fermi (sympy.functions.special.tensor functions.KroneckerDelta
sympy.polys.groebnertools), 1236
attribute), 448
is ground (sympy.polys.polyclasses.ANP attribute), 1168
is below fermi (sympy.physics.secondquant.KroneckerDelta
attribute), 1606
is ground (sympy.polys.polyclasses.DMP atis cnf() (in module sympy.logic.boolalg), 632
tribute), 1164
is collinear()
(sympy.geometry.point.Point is ground
(sympy.polys.polytools.Poly
atmethod), 499
tribute), 1093
is commutative (sympy.core.function.Function is group() (sympy.combinatorics.perm groups.PermutationG
attribute), 170
method), 228
is commutative (sympy.physics.quantum.state.Wavefunction
is hermitian (sympy.matrices.matrices.MatrixBase
attribute), 1786
attribute), 661
is comparable (sympy.core.basic.Basic at- is hermitian (sympy.matrices.sparse.SparseMatrix
tribute), 95
attribute), 695
is compatible() (sympy.physics.unitsystems.units.Unit
is homogeneous (sympy.polys.polyclasses.DMP
method), 1828
attribute), 1164
is concyclic()
(sympy.geometry.point.Point is homogeneous (sympy.polys.polytools.Poly
method), 500
attribute), 1093
is conservative()
(in
module is Identity (sympy.combinatorics.permutations.Permutation
sympy.physics.vector.eldfunctions),
attribute), 204
1692
is identity (sympy.core.function.Lambda atis consistent (sympy.physics.unitsystems.dimensions.DimensionSystem
tribute), 163
is injective() (sympy.polys.agca.homomorphisms.ModuleHom
attribute), 1826
is consistent (sympy.physics.unitsystems.units.UnitSystem
method), 1145
is irreducible (sympy.polys.polyclasses.DMP
attribute), 1828
is constant() (sympy.core.expr.Expr method),
attribute), 1165
115
is irreducible (sympy.polys.polytools.Poly atis convex() (sympy.geometry.polygon.Polygon
tribute), 1093
method), 561
is isomorphism() (sympy.polys.agca.homomorphisms.Module
is coplanar()
(sympy.geometry.plane.Plane
method), 1146
method), 579
is isosceles() (sympy.geometry.polygon.Triangle
is cyclotomic (sympy.polys.polyclasses.DMP
method), 574
attribute), 1164
is left unbounded
(sympy.sets.sets.Interval
invert()
1958
Index
attribute), 1318
is nonpositive() (sympy.polys.domains.FractionField
is linear (sympy.polys.polyclasses.DMP atmethod), 1160
tribute), 1165
is nonpositive() (sympy.polys.domains.PolynomialRing
is linear
(sympy.polys.polytools.Poly
atmethod), 1157
tribute), 1094
is normal() (sympy.combinatorics.perm groups.PermutationG
is lower (sympy.matrices.matrices.MatrixBase
method), 230
attribute), 661
is normalized (sympy.physics.quantum.state.Wavefunction
is lower hessenberg
attribute), 1786
(sympy.matrices.matrices.MatrixBase is nthpow residue()
(in
module
attribute), 662
sympy.ntheory.residue ntheory),
is maximal() (sympy.polys.agca.ideals.Ideal
297
method), 1139
is number (sympy.core.expr.Expr attribute),
is minimal()
(in
module
116
sympy.polys.groebnertools), 1236
is odd (sympy.combinatorics.permutations.Permutation
is monic (sympy.polys.polyclasses.DMP atattribute), 205
is one
(sympy.polys.polyclasses.ANP
attribute), 1165
is monic
(sympy.polys.polytools.Poly
attribute), 1168
tribute), 1094
is one
(sympy.polys.polyclasses.DMF
atis monomial (sympy.polys.polyclasses.DMP
tribute), 1168
attribute), 1165
is one
(sympy.polys.polyclasses.DMP
atis monomial (sympy.polys.polytools.Poly attribute), 1165
tribute), 1094
is one (sympy.polys.polytools.Poly attribute),
is multivariate
(sympy.polys.polytools.Poly
1095
attribute), 1094
is one() (sympy.polys.domains.domain.Domain
method), 1151
is negative() (sympy.polys.domains.AlgebraicField
method), 1158
is only above fermi (sympy.functions.special.tensor function
is negative() (sympy.polys.domains.domain.Domain
attribute), 448
method), 1151
is only above fermi (sympy.physics.secondquant.KroneckerD
is negative() (sympy.polys.domains.ExpressionDomain attribute), 1607
method), 1161
is only below fermi (sympy.functions.special.tensor function
is negative() (sympy.polys.domains.FractionField
attribute), 449
method), 1160
is only below fermi (sympy.physics.secondquant.KroneckerD
is negative() (sympy.polys.domains.PolynomialRing
attribute), 1607
method), 1157
is only q annihilator
(sympy.physics.secondquant.AnnihilateFermion
is nilpotent (sympy.combinatorics.perm groups.PermutationGroup
attribute), 1609
attribute), 229
is nilpotent() (sympy.matrices.matrices.MatrixBase
is only q annihilator
method), 662
(sympy.physics.secondquant.CreateFermion
is nonnegative() (sympy.polys.domains.AlgebraicField attribute), 1611
method), 1159
is only q creator (sympy.physics.secondquant.AnnihilateFerm
is nonnegative() (sympy.polys.domains.domain.Domain attribute), 1610
method), 1151
is only q creator (sympy.physics.secondquant.CreateFermio
is nonnegative() (sympy.polys.domains.ExpressionDomain
attribute), 1611
is parallel() (sympy.geometry.line.LinearEntity
method), 1161
is nonnegative() (sympy.polys.domains.FractionField method), 512
is parallel() (sympy.geometry.line3d.LinearEntity3D
method), 1160
is nonnegative() (sympy.polys.domains.PolynomialRing method), 530
is parallel()
(sympy.geometry.plane.Plane
method), 1157
is nonpositive() (sympy.polys.domains.AlgebraicField method), 580
method), 1159
is perpendicular() (sympy.geometry.line.LinearEntity
is nonpositive() (sympy.polys.domains.domain.Domain method), 512
method), 1151
is perpendicular() (sympy.geometry.line3d.LinearEntity3D
is nonpositive() (sympy.polys.domains.ExpressionDomain
method), 530
method), 1161
is perpendicular() (sympy.geometry.plane.Plane
Index
1959
method), 580
method), 574
is polynomial()
(sympy.core.expr.Expr is right unbounded (sympy.sets.sets.Interval
method), 117
attribute), 1318
is positive() (sympy.polys.domains.AlgebraicField
is scalene() (sympy.geometry.polygon.Triangle
method), 1159
method), 575
is positive() (sympy.polys.domains.domain.Domain
is sequence()
(in
module
method), 1151
sympy.core.compatibility), 184
is positive() (sympy.polys.domains.ExpressionDomain
is similar() (sympy.geometry.entity.GeometryEntity
method), 1161
method), 493
is positive() (sympy.polys.domains.FractionFieldis similar() (sympy.geometry.line.LinearEntity
method), 1160
method), 513
is positive() (sympy.polys.domains.PolynomialRing
is similar() (sympy.geometry.line3d.LinearEntity3D
method), 1157
method), 531
is primary()
(sympy.polys.agca.ideals.Ideal is similar() (sympy.geometry.polygon.Triangle
method), 1139
method), 575
is prime()
(sympy.polys.agca.ideals.Ideal is simple() (sympy.functions.special.delta functions.DiracDe
method), 1139
method), 377
is primitive (sympy.polys.polyclasses.DMP at- is Singleton (sympy.combinatorics.permutations.Permutatio
tribute), 1165
attribute), 204
is primitive (sympy.polys.polytools.Poly at- is solenoidal()
(in
module
tribute), 1095
sympy.physics.vector.eldfunctions),
is primitive() (sympy.combinatorics.perm groups.PermutationGroup
1693
method), 230
is solvable (sympy.combinatorics.perm groups.PermutationG
is primitive root()
(in
module
attribute), 231
sympy.ntheory.residue ntheory),
is sqf
(sympy.polys.polyclasses.DMP
attribute), 1165
295
is principal() (sympy.polys.agca.ideals.Ideal is sqf (sympy.polys.polytools.Poly attribute),
method), 1139
1096
is proper subset()
(sympy.sets.sets.Set is square (sympy.matrices.matrices.MatrixBase
method), 1314
attribute), 663
is proper superset()
(sympy.sets.sets.Set is subdiagram() (sympy.categories.Diagram
method), 1314
method), 1836
is q annihilator (sympy.physics.secondquant.AnnihilateFermion
is subgroup() (sympy.combinatorics.perm groups.Permutatio
attribute), 1610
method), 231
is q annihilator (sympy.physics.secondquant.CreateFermion
is submodule() (sympy.polys.agca.modules.FreeModule
attribute), 1611
method), 1133
is q creator (sympy.physics.secondquant.AnnihilateFermion
is submodule() (sympy.polys.agca.modules.Module
attribute), 1610
method), 1132
is q creator (sympy.physics.secondquant.CreateFermion
is submodule() (sympy.polys.agca.modules.QuotientModule
attribute), 1611
method), 1141
is quad residue()
(in
module is submodule() (sympy.polys.agca.modules.SubModule
sympy.ntheory.residue ntheory),
method), 1136
297
is subset()
(sympy.sets.sets.Set
method),
is quadratic
(sympy.polys.polyclasses.DMP
1314
attribute), 1165
is superset() (sympy.sets.sets.Set method),
is quadratic (sympy.polys.polytools.Poly at1315
tribute), 1095
is surjective() (sympy.polys.agca.homomorphisms.ModuleHo
is radical()
(sympy.polys.agca.ideals.Ideal
method), 1146
method), 1139
is symbolic() (sympy.matrices.matrices.MatrixBase
method), 663
is rational function() (sympy.core.expr.Expr
is symmetric() (sympy.matrices.matrices.MatrixBase
method), 117
is reduced()
(in
module
method), 663
is symmetric() (sympy.matrices.sparse.SparseMatrix
sympy.polys.groebnertools), 1236
is right() (sympy.geometry.polygon.Triangle
method), 696
1960
Index
1961
jn zeros()
(in
module ket (sympy.physics.secondquant.InnerProduct
sympy.functions.special.bessel),
attribute), 1613
413
KetBase
(class
in
jordan cell()
(in
module
sympy.physics.quantum.state), 1781
sympy.matrices.dense), 681
key2bounds() (sympy.matrices.matrices.MatrixBase
jordan cells() (sympy.matrices.matrices.MatrixBase
method), 667
method), 666
key2ij() (sympy.matrices.matrices.MatrixBase
jordan form() (sympy.matrices.matrices.MatrixBase
method), 667
method), 667
keys() (sympy.core.containers.Dict method),
josephus() (sympy.combinatorics.permutations.Permutation
183
class method), 205
keys() (sympy.physics.unitsystems.dimensions.Dimension
jtheta() (in module mpmath), 925
method), 1825
JxBra (class in sympy.physics.quantum.spin), kfrom() (in module mpmath), 911
1774
khinchin (mpmath.mp attribute), 751
JxBraCoupled
(class
in kid rsa private key()
(in
module
sympy.physics.quantum.spin), 1777
sympy.crypto.crypto), 314
JxKet (class in sympy.physics.quantum.spin), kid rsa public key()
(in
module
1774
sympy.crypto.crypto), 314
JxKetCoupled
(class
in killable index (sympy.functions.special.tensor functions.Kron
sympy.physics.quantum.spin), 1776
attribute), 449
JyBra (class in sympy.physics.quantum.spin), killable index (sympy.physics.secondquant.KroneckerDelta
1774
attribute), 1607
JyBraCoupled
(class
in kindidict() (sympy.physics.mechanics.kane.KanesMethod
sympy.physics.quantum.spin), 1777
method), 1743
JyKet (class in sympy.physics.quantum.spin), kinematic equations()
(in
module
sympy.physics.vector.functions),
1774
JyKetCoupled
(class
in
1680
sympy.physics.quantum.spin), 1777
kinetic energy()
(in
module
JzBra (class in sympy.physics.quantum.spin),
sympy.physics.mechanics.functions),
1776
1739
JzBraCoupled
(class
in kinetic energy() (sympy.physics.mechanics.particle.Particle
sympy.physics.quantum.spin), 1779
method), 1731
JzKet (class in sympy.physics.quantum.spin), kinetic energy() (sympy.physics.mechanics.rigidbody.RigidB
1774
method), 1734
JzKetCoupled
(class
in kleinj() (in module mpmath), 929
sympy.physics.quantum.spin), 1777
known functions
(in
module
sympy.printing.ccode), 1252
K
known functions
(in
module
sympy.printing.mathematica), 1258
kanes equations() (sympy.physics.mechanics.kane.KanesMethod
KroneckerDelta
(class
in
method), 1743
sympy.functions.special.tensor functions),
KanesMethod
(class
in
446
sympy.physics.mechanics.kane),
KroneckerDelta
(class
in
1741
sympy.physics.secondquant), 1604
kbins() (in module sympy.utilities.iterables),
ksubsets()
(sympy.combinatorics.subsets
1561
256
static
method),
kei() (in module mpmath), 832
Kumaraswamy()
(in
module
sympy.stats),
ker() (in module mpmath), 831
1377
kernel() (sympy.polys.agca.homomorphisms.ModuleHomomorphism
method), 1146
Ket (class in sympy.physics.quantum.state), L
(sympy.polys.polyclasses.DMP
l1 norm()
1781
method), 1165
ket (sympy.physics.quantum.operator.OuterProduct
l1 norm()
(sympy.polys.polytools.Poly
attribute), 1763
method), 1096
1962
Index
1963
length
Index
method), 1743
lower (sympy.physics.secondquant.AntiSymmetricTensor
linearize() (sympy.physics.mechanics.lagrange.LagrangesMethod
attribute), 1621
method), 1745
lower (sympy.tensor.indexed.Idx attribute),
linearize() (sympy.physics.mechanics.linearize.Linearizer
1510
method), 1747
lower central series()
Linearizer
(class
in
(sympy.combinatorics.perm groups.PermutationGro
sympy.physics.mechanics.linearize),
method), 232
1746
lower triangular solve()
LineOver1DRangeSeries
(class
in
(sympy.matrices.matrices.MatrixBase
sympy.plotting.plot), 1282
method), 668
linspace() (in module mpmath), 742
lowergamma
(class
in
list() (sympy.combinatorics.permutations.Cycle
sympy.functions.special.gamma functions),
method), 214
385
list() (sympy.combinatorics.permutations.Permutation
lseries() (sympy.core.expr.Expr method), 118
Lt (in module sympy.core.relational), 148
method), 206
list2numpy()
(in
module LT() (in module sympy.polys.polytools), 1058
sympy.matrices.dense), 683
LT() (sympy.polys.polytools.Poly method),
list can dims (sympy.physics.unitsystems.dimensions.DimensionSystem
1076
attribute), 1826
ltrim() (sympy.polys.polytools.Poly method),
list visitor()
(in
module
1097
sympy.utilities.enumerative), 1550
lucas (class in sympy.functions.combinatorial.numbers),
listcoes()
(sympy.polys.rings.PolyElement
373
method), 1220
LUdecomposition() (sympy.matrices.matrices.MatrixBase
listmonoms() (sympy.polys.rings.PolyElement
method), 646
method), 1220
LUdecomposition Simple()
(sympy.matrices.matrices.MatrixBase
listterms()
(sympy.polys.rings.PolyElement
method), 647
method), 1220
liupc() (sympy.matrices.sparse.SparseMatrix LUdecompositionFF()
method), 696
(sympy.matrices.matrices.MatrixBase
method), 646
LM() (in module sympy.polys.polytools), 1058
LM() (sympy.polys.polytools.Poly method), LUsolve() (sympy.matrices.matrices.MatrixBase
1075
method), 647
ln() (in module mpmath), 760
locatenew() (sympy.physics.vector.point.Point M
method), 1677
mag() (in module mpmath), 740
log (class in sympy.functions.elementary.exponential),
magnitude() (sympy.physics.vector.vector.Vector
353
method), 1671
log() (in module mpmath), 759
major (sympy.geometry.ellipse.Ellipse atlog() (sympy.polys.domains.domain.Domain
tribute), 549
method), 1151
make perm() (sympy.combinatorics.perm groups.Permutatio
log()
(sympy.polys.domains.IntegerRing
method), 233
method), 1156
make prime()
(in
module
log10() (in module mpmath), 761
sympy.solvers.diophantine), 1504
logcombine()
(in
module make routine()
(in
module
sympy.simplify.simplify), 1344
sympy.utilities.codegen), 1545
loggamma
(class
in mangoldt() (in module mpmath), 968
sympy.functions.special.gamma functions),
Manifold (class in sympy.digeom), 1846
380
Manifold (class in sympy.galgebra.manifold),
loggamma() (in module mpmath), 783
483
Logistic() (in module sympy.stats), 1378
Manifold() (in module sympy.galgebra.ga),
logm() (in module mpmath), 1032
469
LogNormal() (in module sympy.stats), 1379
manualintegrate() (sympy.integrals static
lommels1() (in module mpmath), 836
method), 614
lommels2() (in module mpmath), 837
Index
1965
map() (sympy.polys.domains.domain.Domain
method), 207
method), 1151
max div (sympy.combinatorics.perm groups.PermutationGro
mass (sympy.physics.mechanics.particle.Particle
attribute), 233
attribute), 1732
max norm()
(sympy.polys.polyclasses.DMP
mass matrix (sympy.physics.mechanics.kane.KanesMethod
method), 1165
attribute), 1743
max norm()
(sympy.polys.polytools.Poly
mass matrix (sympy.physics.mechanics.lagrange.LagrangesMethod
method), 1098
maxcalls() (in module mpmath), 745
attribute), 1746
mass matrix full (sympy.physics.mechanics.kane.KanesMethod
Maxwell() (in module sympy.stats), 1380
attribute), 1743
maybe()
(in
module
mass matrix full (sympy.physics.mechanics.lagrange.LagrangesMethod
sympy.parsing.sympy tokenize),
attribute), 1746
1590
MatAdd (class in sympy.matrices.expressions), MCodePrinter
(class
in
708
sympy.printing.mathematica), 1258
match() (sympy.core.basic.Basic method), 95 mdft() (in module sympy.physics.matrices),
matches() (sympy.core.basic.Basic method),
1600
96
MDNewton
(class
in
mpmathematica()
(in
module
math.calculus.optimization), 979
sympy.parsing.mathematica), 1590
measure (sympy.sets.sets.Set attribute), 1315
mathematica code()
(in
module measure all()
(in
module
sympy.printing.mathematica), 1259
sympy.physics.quantum.qubit), 1798
mathml() (in module sympy.printing.mathml), measure all oneshot()
(in
module
1262
sympy.physics.quantum.qubit), 1800
mathml tag() (sympy.printing.mathml.MathMLPrinter
measure partial()
(in
module
method), 1262
sympy.physics.quantum.qubit), 1799
MathMLPrinter
(class
in measure partial oneshot()
(in
module
sympy.printing.mathml), 1262
sympy.physics.quantum.qubit), 1800
MatMul (class in sympy.matrices.expressions), medial (sympy.geometry.polygon.Triangle at709
tribute), 575
MatPow
(class
in medians (sympy.geometry.polygon.Triangle
sympy.matrices.expressions), 709
attribute), 576
matrix2numpy()
(in
module Medium
(class
in
sympy.matrices.dense), 683
sympy.physics.optics.medium), 1812
matrix fglm()
(in
module meets()
(sympy.series.gruntz.SubsSet
sympy.polys.fglmtools), 1236
method), 1307
matrix multiply elementwise() (in module meijerg (class in sympy.functions.special.hyper),
sympy.matrices.dense), 679
428
matrix rep()
(in
module meijerg() (in module mpmath), 898
sympy.physics.secondquant), 1616
mellin transform()
(in
module
matrix to density()
(in
module
sympy.integrals.transforms), 584
sympy.physics.quantum.qubit), 1798 memoize() (in module mpmath), 745
matrix to qubit()
(in
module merge solution()
(in
module
sympy.physics.quantum.qubit), 1798
sympy.solvers.diophantine), 1500
MatrixBase
(class
in mertens (mpmath.mp attribute), 751
sympy.matrices.matrices), 644
metric to Christoel 1st()
(in
module
MatrixError
(class
in
sympy.digeom), 1859
sympy.matrices.matrices), 678
metric to Christoel 2nd()
(in
module
MatrixExpr
(class
in
sympy.digeom), 1859
sympy.matrices.expressions), 707
metric to Ricci components()
(in
module
sympy.digeom), 1860
MatrixSymbol
(class
in
metric to Riemann components() (in module
sympy.matrices.expressions), 708
Max (class in sympy.functions.elementary.miscellaneous),
sympy.digeom), 1859
355
mfrom() (in module mpmath), 910
max() (sympy.combinatorics.permutations.Permutation
mgamma()
(in
module
1966
Index
sympy.physics.matrices), 1600
attribute), 1758
midpoint (sympy.geometry.line.Segment at- momentum (sympy.physics.quantum.cartesian.PxKet
tribute), 524
attribute), 1757
midpoint (sympy.geometry.line3d.Segment3D monic() (in module sympy.polys.polytools),
attribute), 538
1067
midpoint()
(sympy.geometry.point.Point monic()
(sympy.polys.polyclasses.DMP
method), 501
method), 1165
midpoint() (sympy.geometry.point3d.Point3D monic() (sympy.polys.polytools.Poly method),
method), 507
1098
Min (class in sympy.functions.elementary.miscellaneous),
monic()
(sympy.polys.rings.PolyElement
354
method), 1220
min() (sympy.combinatorics.permutations.Permutation
monitor() (in module mpmath), 745
method), 207
Monomial (class in sympy.polys.monomials),
min qubits (sympy.physics.quantum.gate.CGate
1117
monomial basis() (sympy.polys.rings.PolyRing
attribute), 1790
min qubits (sympy.physics.quantum.gate.CNotGate
method), 1216
attribute), 1792
monomial count()
(in
module
min qubits (sympy.physics.quantum.gate.Gate
sympy.polys.monomials), 1118
attribute), 1789
monoms()
(sympy.polys.polyclasses.DMP
minimal block() (sympy.combinatorics.perm groups.PermutationGroup
method), 1165
method), 234
monoms()
(sympy.polys.polytools.Poly
minimal polynomial()
(in
module
method), 1098
sympy.polys.numberelds), 1115
monoms()
(sympy.polys.rings.PolyElement
minlex() (in module sympy.utilities.iterables),
method), 1220
1562
Morphism (class in sympy.categories), 1829
minor (sympy.geometry.ellipse.Ellipse at- morphisms (sympy.categories.diagram drawing.DiagramGri
tribute), 549
attribute), 1840
minorEntry() (sympy.matrices.matrices.MatrixBase
mpmath.functions.elliptic (module), 909
method), 668
mpmathify() (in module mpmath), 727
minorMatrix() (sympy.matrices.matrices.MatrixBase
mr() (in module sympy.ntheory.primetest),
method), 668
294
minpoly()
(in
module mrv() (in module sympy.series.gruntz), 1307
sympy.polys.numberelds), 1116
mrv leadterm()
(in
module
mirror formula()
(in
module
sympy.series.gruntz), 1306
sympy.physics.optics.utils), 1816
mrv max1() (in module sympy.series.gruntz),
MNewton
(class
in
mp1307
math.calculus.optimization), 977
mrv max3() (in module sympy.series.gruntz),
mnorm() (in module mpmath), 1023
1307
mobius (class in sympy.ntheory), 300
msigma()
(in
module
Mod (class in sympy.core.mod), 147
sympy.physics.matrices), 1601
modgcd bivariate
(class
in msubs()
(in
module
sympy.polys.modulargcd), 1240
sympy.physics.mechanics), 1748
modgcd multivariate
(class
in Mul (class in sympy.core.mul), 142
Mul() (sympy.assumptions.handlers.calculus.AskBoundedHa
sympy.polys.modulargcd), 1241
modgcd univariate
(class
in
static method), 1292
Mul() (sympy.assumptions.handlers.calculus.AskInnitesima
sympy.polys.modulargcd), 1239
Module (class in sympy.polys.agca.modules),
static method), 1292
1131
Mul() (sympy.assumptions.handlers.sets.AskAntiHermitianH
module quotient() (sympy.polys.agca.modules.SubModule
static method), 1293
method), 1136
Mul() (sympy.assumptions.handlers.sets.AskHermitianHand
ModuleHomomorphism
(class
in
static method), 1294
sympy.polys.agca.homomorphisms),
Mul() (sympy.assumptions.handlers.sets.AskImaginaryHand
1144
static method), 1294
momentum (sympy.physics.quantum.cartesian.PxBra
Mul() (sympy.assumptions.handlers.sets.AskIntegerHandler
Index
1967
Index
necklaces()
(in
module non scalar projection()
(in
module
sympy.utilities.iterables), 1565
sympy.galgebra.ncutil), 488
neg() (sympy.polys.domains.domain.Domain nonnegative, 89
method), 1151
nonpositive, 89
neg() (sympy.polys.polyclasses.DMF method), NonSquareMatrixError
(class
in
1168
sympy.matrices.matrices), 678
neg() (sympy.polys.polyclasses.DMP method), nonzero, 89
1165
Nor (class in sympy.logic.boolalg), 630
neg() (sympy.polys.polytools.Poly method), norm (sympy.physics.quantum.state.Wavefunction
1099
attribute), 1787
negative, 89
norm() (in module mpmath), 1022
NegativeInnity
(class
in norm() (sympy.matrices.matrices.MatrixBase
sympy.core.numbers), 135
method), 669
NegativeOne (class in sympy.core.numbers), Normal() (in module sympy.stats), 1382
133
normal closure() (sympy.combinatorics.perm groups.Permut
new()
(sympy.polys.polytools.Poly
class
method), 234
method), 1099
normal lines() (sympy.geometry.ellipse.Ellipse
Newton
(class
in
mpmethod), 550
math.calculus.optimization), 976
normal vector (sympy.geometry.plane.Plane
next() (sympy.combinatorics.graycode.GrayCode
attribute), 580
method), 258
normalize() (sympy.physics.quantum.state.Wavefunction
next()
(sympy.combinatorics.prufer.Prufer
method), 1787
method), 247
normalize() (sympy.physics.vector.vector.Vector
next() (sympy.printing.pretty.stringpict.stringPict
method), 1671
static method), 1268
normalized()
(in
module
sympy.physics.quantum.gate), 1793
next binary() (sympy.combinatorics.subsets.Subset
method), 251
normalized() (sympy.matrices.matrices.MatrixBase
next gray() (sympy.combinatorics.subsets.Subset
method), 669
method), 252
NormalPSpace
(class
in
sympy.stats.crv types), 1396
next lex() (sympy.combinatorics.partitions.IntegerPartition
method), 190
Not (class in sympy.logic.boolalg), 628
next lex() (sympy.combinatorics.permutations.Permutation
NotAlgebraic
(class
in
method), 207
sympy.polys.polyerrors), 1238
next lexicographic()
NotInvertible
(class
in
(sympy.combinatorics.subsets.Subset
sympy.polys.polyerrors), 1238
method), 252
NotReversible
(class
in
sympy.polys.polyerrors), 1238
next nonlex() (sympy.combinatorics.permutations.Permutation
method), 207
npartitions()
(in
module
next trotterjohnson()
sympy.ntheory.partitions ), 294
(sympy.combinatorics.permutations.Permutation
npdf() (in module mpmath), 807
method), 208
nprint() (in module mpmath), 727
nextprime()
(in
module nprod() (in module mpmath), 988
sympy.ntheory.generate), 278
nqubits (sympy.physics.quantum.gate.CGate
noat() (in module sympy.core.function), 181
attribute), 1790
nint() (in module mpmath), 736
nqubits
(sympy.physics.quantum.gate.Gate
nint distance() (in module mpmath), 741
attribute), 1789
nnz() (sympy.matrices.sparse.SparseMatrix nroots() (in module sympy.polys.polytools),
1072
method), 697
NO (class in sympy.physics.secondquant), nroots() (sympy.polys.polytools.Poly method),
1617
1099
no attrs in subclass
(in
module nseries() (sympy.core.expr.Expr method), 119
sympy.utilities.decorator), 1547
nsimplify()
(in
module
nodes (sympy.combinatorics.prufer.Prufer atsympy.simplify.simplify), 1340
tribute), 247
nsimplify() (sympy.core.expr.Expr method),
Index
1969
120
ode 1st homogeneous coe best() (in module
nsolve() (in module sympy.solvers.solvers),
sympy.solvers.ode), 1410
1476
ode 1st homogeneous coe subs dep div indep()
nstr() (in module mpmath), 727
(in module sympy.solvers.ode), 1411
nsum() (in module mpmath), 979
ode 1st homogeneous coe subs indep div dep()
nth() (sympy.polys.polyclasses.DMP method),
(in module sympy.solvers.ode), 1412
1165
ode 1st linear()
(in
module
nth() (sympy.polys.polytools.Poly method),
sympy.solvers.ode), 1414
1100
ode 1st power series()
(in
module
nth power roots poly()
(in
module
sympy.solvers.ode), 1426
sympy.polys.polytools), 1073
ode 2nd power series ordinary() (in module
nth power roots poly()
sympy.solvers.ode), 1427
(sympy.polys.polytools.Poly method), ode 2nd power series regular() (in module
1100
sympy.solvers.ode), 1427
nthroot() (in module sympy.simplify.simplify), ode almost linear()
(in
module
1332
sympy.solvers.ode), 1422
nthroot mod()
(in
module ode Bernoulli()
(in
module
sympy.ntheory.residue ntheory),
sympy.solvers.ode), 1414
296
ode lie group()
(in
module
nu (sympy.functions.special.hyper.meijerg atsympy.solvers.ode), 1425
tribute), 430
ode linear coecients()
(in
module
nullspace() (sympy.matrices.matrices.MatrixBase
sympy.solvers.ode), 1423
method), 670
ode Liouville() (in module sympy.solvers.ode),
Number (class in sympy.core.numbers), 126
1416
numbered symbols()
(in
module ode nth linear constant coe homogeneous()
sympy.utilities.iterables), 1565
(in module sympy.solvers.ode), 1418
NumberSymbol
(class
in ode nth linear constant coe undetermined coecients()
sympy.core.numbers), 131
(in module sympy.solvers.ode), 1419
numer() (sympy.polys.domains.AlgebraicField ode nth linear constant coe variation of parameters()
method), 1159
(in module sympy.solvers.ode), 1420
numer() (sympy.polys.domains.domain.Domain ode order() (in module sympy.solvers.deutils),
method), 1151
1478
numer() (sympy.polys.domains.ExpressionDomain
ode Riccati special minus2()
(in
module
method), 1161
sympy.solvers.ode), 1417
numer() (sympy.polys.domains.FractionField ode separable()
(in
module
method), 1160
sympy.solvers.ode), 1421
numer()
(sympy.polys.domains.ring.Ring ode separable reduced()
(in
module
method), 1154
sympy.solvers.ode), 1424
numer()
(sympy.polys.polyclasses.DMF ode sol simplicity()
(in
module
method), 1168
sympy.solvers.ode), 1408
nzeros() (in module mpmath), 939
odefun() (in module mpmath), 1012
odesimp() (in module sympy.solvers.ode),
O
1406
of type() (sympy.polys.domains.domain.Domain
Object (class in sympy.categories), 1829
method), 1152
objects
(sympy.categories.Category
atold
frac
eld() (sympy.polys.domains.domain.Domain
tribute), 1835
method),
1152
objects
(sympy.categories.Diagram
atold
poly
ring()
(sympy.polys.domains.domain.Domain
tribute), 1837
method), 1152
OctaveCodeGen
(class
in
One
(class
in sympy.core.numbers), 133
sympy.utilities.codegen), 1543
one
(sympy.polys.polytools.Poly
attribute),
odd, 89
1100
ode 1st exact()
(in
module
OneQubitGate
(class
in
sympy.solvers.ode), 1409
sympy.physics.quantum.gate), 1790
1970
Index
1971
partition()
(in
module
sympy.combinatorics.permutations),
sympy.solvers.diophantine), 1498
192
partitions()
(in
module PermutationGroup
(class
in
sympy.utilities.iterables), 1566
sympy.combinatorics.perm groups),
pat matrix()
(in
module
216
sympy.physics.matrices), 1601
PermutationOperator
(class
in
Patch (class in sympy.digeom), 1846
sympy.physics.secondquant), 1623
pcfd() (in module mpmath), 865
permute()
(sympy.polys.polyclasses.DMP
pcfu() (in module mpmath), 867
method), 1165
pcfv() (in module mpmath), 867
permuteBkwd() (sympy.matrices.matrices.MatrixBase
pcfw() (in module mpmath), 868
method), 670
pde 1st linear constant coe() (in module permuteFwd() (sympy.matrices.matrices.MatrixBase
sympy.solvers.pde), 1465
method), 670
pde 1st linear constant coe homogeneous() perpendicular bisector()
(in module sympy.solvers.pde), 1464
(sympy.geometry.line.Segment
pde 1st linear variable coe() (in module
method), 524
sympy.solvers.pde), 1467
perpendicular line()
pde separate()
(in
module
(sympy.geometry.line.LinearEntity
sympy.solvers.pde), 1460
method), 514
pde separate add()
(in
module perpendicular line()
sympy.solvers.pde), 1461
(sympy.geometry.line3d.LinearEntity3D
pde separate mul()
(in
module
method), 532
sympy.solvers.pde), 1461
perpendicular line()
pdiv() (in module sympy.polys.polytools),
(sympy.geometry.plane.Plane
method), 581
1058
pdiv()
(sympy.polys.polyclasses.DMP perpendicular plane()
method), 1165
(sympy.geometry.plane.Plane
pdiv() (sympy.polys.polytools.Poly method),
method), 581
1100
perpendicular segment()
(sympy.geometry.line.LinearEntity
pdsolve() (in module sympy.solvers.pde),
method), 514
1461
Pegasus
(class
in
mp- perpendicular segment()
math.calculus.optimization), 978
(sympy.geometry.line3d.LinearEntity3D
per() (sympy.polys.polyclasses.DMF method),
method), 532
1168
pexquo() (in module sympy.polys.polytools),
per() (sympy.polys.polyclasses.DMP method),
1059
1165
pexquo()
(sympy.polys.polyclasses.DMP
per() (sympy.polys.polytools.Poly method),
method), 1166
1101
pexquo()
(sympy.polys.polytools.Poly
perfect power()
(in
module
method), 1101
sympy.ntheory.factor ), 283
pgroup (sympy.combinatorics.polyhedron.Polyhedron
periapsis (sympy.geometry.ellipse.Ellipse atattribute), 244
tribute), 550
Phase
(in
module
perimeter (sympy.geometry.polygon.Polygon
sympy.physics.quantum.gate), 1793
attribute), 561
phase (sympy.physics.optics.waves.TWave atperiod nd()
(in
module
tribute), 1818
sympy.physics.quantum.shor), 1801
PhaseGate
(class
in
perm2tensor() (sympy.tensor.tensor.TensMul
sympy.physics.quantum.gate), 1791
method), 1531
phi (mpmath.mp attribute), 751
permeability (sympy.physics.optics.medium.Medium
Pi (class in sympy.core.numbers), 137
pi (mpmath.mp attribute), 751
attribute), 1813
permittivity (sympy.physics.optics.medium.Medium
PIABBra
(class
in
attribute), 1813
sympy.physics.quantum.piab), 1801
Permutation
(class
in PIABHamiltonian
(class
in
1972
Index
sympy.physics.quantum.piab), 1801
point()
(sympy.digeom.CoordSystem
PIABKet
(class
in
method), 1849
sympy.physics.quantum.piab), 1801
Point3D (class in sympy.geometry.point3d),
Piecewise
(class
in
503
sympy.functions.elementary.piecewise),point to coords() (sympy.digeom.CoordSystem
356
method), 1849
piecewise fold()
(in
module points (sympy.geometry.line.LinearEntity atsympy.functions.elementary.piecewise),
tribute), 515
357
points (sympy.geometry.line3d.LinearEntity3D
pinv() (sympy.matrices.matrices.MatrixBase
attribute), 533
method), 670
pointwise stabilizer()
pinv solve() (sympy.matrices.matrices.MatrixBase
(sympy.combinatorics.perm groups.PermutationGro
method), 671
method), 237
Plane (class in sympy.geometry.plane), 577
Poisson() (in module sympy.stats), 1364
Plot (class in sympy.plotting.plot), 1271
polar() (in module mpmath), 735
plot() (in module mpmath), 747
PoleError (class in sympy.core.function), 177
plot() (in module sympy.plotting.plot), 1273
PolicationFailed
(class
in
plot3d() (in module sympy.plotting.plot), 1277
sympy.polys.polyerrors), 1239
plot3d parametric line()
(in
module pollard pm1()
(in
module
sympy.plotting.plot), 1278
sympy.ntheory.factor ), 285
plot3d parametric surface()
(in
module pollard rho()
(in
module
sympy.plotting.plot), 1279
sympy.ntheory.factor ), 283
plot gate() (sympy.physics.quantum.gate.CGatePoly (class in sympy.polys.polytools), 1075
method), 1790
poly() (in module sympy.polys.polytools),
plot implicit()
(in
module
1057
sympy.plotting.plot implicit), 1280
poly from expr()
(in
module
plot interval() (sympy.geometry.curve.Curve
sympy.polys.polytools), 1057
method), 541
poly ring() (sympy.polys.domains.domain.Domain
plot interval() (sympy.geometry.ellipse.Ellipse
method), 1152
method), 551
poly unify()
(sympy.polys.polyclasses.DMF
plot interval()
(sympy.geometry.line.Line
method), 1168
method), 519
PolyElement (class in sympy.polys.rings),
plot interval()
(sympy.geometry.line.Ray
1216
method), 521
polyexp() (in module mpmath), 950
plot interval() (sympy.geometry.line.Segment polygamma
(class
in
method), 524
sympy.functions.special.gamma functions),
plot interval() (sympy.geometry.line3d.Line3D
382
method), 526
Polygon (class in sympy.geometry.polygon),
plot interval() (sympy.geometry.line3d.Ray3D
556
method), 535
Polyhedron
(class
in
sympy.combinatorics.polyhedron),
plot interval() (sympy.geometry.line3d.Segment3D
method), 538
243
plot interval() (sympy.geometry.polygon.Polygonpolylog (class in sympy.functions.special.zeta functions),
423
method), 561
plot parametric()
(in
module polylog() (in module mpmath), 944
PolynomialError
(class
in
sympy.plotting.plot), 1275
Point (class in sympy.digeom), 1849
sympy.polys.polyerrors), 1238
Point (class in sympy.geometry.point), 497
PolynomialRing
(class
in
Point (class in sympy.physics.vector.point),
sympy.polys.domains), 1156
1675
PolyRing (class in sympy.polys.rings), 1215
point (sympy.core.function.Subs attribute), polyroots() (in module mpmath), 971
171
polyval() (in module mpmath), 971
point (sympy.physics.mechanics.particle.Particle
pos() (sympy.polys.domains.domain.Domain
attribute), 1732
method), 1152
Index
1973
Index
sympy.utilities.iterables), 1568
sympy.ntheory.factor ), 289
prem() (in module sympy.polys.polytools), primepi() (in module mpmath), 964
1059
primepi()
(in
module
prem()
(sympy.polys.polyclasses.DMP
sympy.ntheory.generate), 277
method), 1166
primepi2() (in module mpmath), 964
prem() (sympy.polys.polytools.Poly method), primerange()
(in
module
1102
sympy.ntheory.generate), 278
premises
(sympy.categories.Diagram
at- primerange() (sympy.ntheory.generate.Sieve
tribute), 1837
method), 276
pretty()
(in
module primezeta() (in module mpmath), 951
sympy.printing.pretty.pretty), 1251
primitive() (in module sympy.polys.polytools),
pretty atom()
(in
module
1068
sympy.printing.pretty.pretty symbology),
primitive() (sympy.core.add.Add method),
1267
146
pretty print()
(in
module primitive() (sympy.core.expr.Expr method),
120
sympy.printing.pretty.pretty), 1251
pretty symbol()
(in
module primitive()
(sympy.polys.polyclasses.DMP
sympy.printing.pretty.pretty symbology),
method), 1166
1267
primitive()
(sympy.polys.polytools.Poly
pretty try use unicode()
(in
module
method), 1102
sympy.printing.pretty.pretty symbology),
primitive()
(sympy.polys.rings.PolyElement
1267
method), 1220
pretty use unicode()
(in
module primitive element()
(in
module
sympy.printing.pretty.pretty symbology),
sympy.polys.numberelds), 1117
1266
primitive root()
(in
module
sympy.ntheory.residue ntheory),
prettyForm
(class
in
sympy.printing.pretty.stringpict),
295
1269
primorial()
(in
module
PrettyPrinter
(class
in
sympy.ntheory.generate), 280
sympy.printing.pretty.pretty), 1251
print ccode()
(in
module
prev()
(sympy.combinatorics.prufer.Prufer
sympy.printing.ccode), 1254
method), 247
print dim base() (sympy.physics.unitsystems.dimensions.Dim
prev binary() (sympy.combinatorics.subsets.Subset
method), 1827
method), 252
print fcode()
(in
module
sympy.printing.fcode), 1256
prev gray() (sympy.combinatorics.subsets.Subset
method), 253
Print Function()
(in
module
sympy.galgebra.printing), 486
prev lex() (sympy.combinatorics.partitions.IntegerPartition
method), 190
print gtk() (in module sympy.printing.gtk),
prev lexicographic()
1259
(sympy.combinatorics.subsets.Subset print latex()
(in
module
method), 253
sympy.galgebra.printing), 486
preview()
(in
module print latex() (in module sympy.printing.latex),
sympy.printing.preview), 1264
1261
preview diagram()
(in
module print mathml()
(in
module
sympy.categories.diagram drawing),
sympy.printing.mathml), 1262
1846
print node() (in module sympy.printing.tree),
prevprime()
(in
module
1263
print nonzero() (sympy.matrices.matrices.MatrixBase
sympy.ntheory.generate), 278
prime, 89
method), 672
prime() (in module sympy.ntheory.generate), print product table()
(in
module
277
sympy.galgebra.debug), 489
prime as sum of two squares() (in module print sub table()
(in
module
sympy.solvers.diophantine), 1504
sympy.galgebra.debug), 489
primefactors()
(in
module print tree() (in module sympy.printing.tree),
Index
1975
1263
method), 582
print unit base() (sympy.physics.unitsystems.units.UnitSystem
Prufer (class in sympy.combinatorics.prufer),
method), 1829
246
Printer (class in sympy.printing.printer), 1249 prufer rank() (sympy.combinatorics.prufer.Prufer
printmethod (sympy.printing.ccode.CCodePrinter
method), 248
attribute), 1252
prufer repr (sympy.combinatorics.prufer.Prufer
printmethod (sympy.printing.codeprinter.CodePrinter attribute), 248
psi() (in module mpmath), 792
attribute), 1266
printmethod (sympy.printing.fcode.FCodePrinter
psi n() (in module sympy.physics.qho 1d),
attribute), 1257
1602
printmethod (sympy.printing.lambdarepr.LambdaPrinter
pslq() (in module mpmath), 1039
attribute), 1259
PSpace (class in sympy.stats.rv), 1396
printmethod (sympy.printing.latex.LatexPrinter pspace() (in module sympy.stats.rv), 1397
attribute), 1259
public() (in module sympy.utilities.decorator),
printmethod (sympy.printing.mathematica.MCodePrinter
1547
PurePoly (class in sympy.polys.polytools),
attribute), 1258
printmethod (sympy.printing.mathml.MathMLPrinter 1111
attribute), 1262
PxBra (class in sympy.physics.quantum.cartesian),
printmethod (sympy.printing.pretty.pretty.PrettyPrinter1758
attribute), 1251
PxKet (class in sympy.physics.quantum.cartesian),
printmethod (sympy.printing.printer.Printer
1757
attribute), 1251
PxOp (class in sympy.physics.quantum.cartesian),
printmethod (sympy.printing.repr.ReprPrinter
1757
attribute), 1262
PyTestReporter
(class
in
sympy.utilities.runtests), 1580
printmethod
(sympy.printing.str.StrPrinter
attribute), 1263
Python Enhancement Proposals
printtoken()
(in
module
PEP 335, 1900, 1901
sympy.parsing.sympy tokenize),
PythonFiniteField
(class
in
1589
sympy.polys.domains), 1162
prob() (sympy.physics.quantum.state.Wavefunction
PythonIntegerRing
(class
in
method), 1787
sympy.polys.domains), 1162
prod() (in module sympy.core.mul), 144
PythonRationalField
(class
in
Product (class in sympy.concrete.products),
sympy.polys.domains), 1162
324
product()
(in
module Q
sympy.concrete.products), 329
Q (class in sympy.assumptions.ask), 1287
product()
(sympy.polys.agca.ideals.Ideal q (sympy.physics.optics.gaussopt.BeamParameter
method), 1139
attribute), 1808
product derivation()
(in
module qapply()
(in
module
sympy.galgebra.ncutil), 488
sympy.physics.quantum.qapply),
ProductDomain (class in sympy.stats.rv),
1766
1396
qbarfrom() (in module mpmath), 910
ProductPSpace (class in sympy.stats.rv), 1396 qfac() (in module mpmath), 970
ProductSet (class in sympy.sets.sets), 1321
qfrom() (in module mpmath), 909
Proj() (in module sympy.galgebra.ga), 470
QFT (class in sympy.physics.quantum.qft),
project() (sympy.matrices.matrices.MatrixBase
1796
method), 672
qgamma() (in module mpmath), 969
projection() (sympy.geometry.line.LinearEntity qhyper() (in module mpmath), 970
method), 515
qp() (in module mpmath), 968
projection() (sympy.geometry.line3d.LinearEntity3D
QRdecomposition() (sympy.matrices.matrices.MatrixBase
method), 533
method), 647
projection()
(sympy.geometry.plane.Plane QRsolve() (sympy.matrices.matrices.MatrixBase
method), 582
method), 648
projection line() (sympy.geometry.plane.Plane quad() (in module mpmath), 1003
1976
Index
1977
method), 238
1809
random symbols() (in module sympy.stats.rv), RayTransferMatrix
(class
in
1397
sympy.physics.optics.gaussopt),
RandomDomain (class in sympy.stats.rv),
1802
1396
rcall() (sympy.core.basic.Basic method), 96
RandomSymbol (class in sympy.stats.rv), rcollect() (in module sympy.simplify.simplify),
1396
1331
randprime()
(in
module re (class in sympy.functions.elementary.complexes),
sympy.ntheory.generate), 279
357
ranges (sympy.tensor.indexed.Indexed at- re() (in module mpmath), 734
tribute), 1512
real, 89
rank (sympy.combinatorics.graycode.GrayCode real roots()
(in
module
attribute), 258
sympy.polys.polytools), 1072
rank (sympy.combinatorics.partitions.Partition real roots()
(sympy.polys.polytools.Poly
attribute), 188
method), 1103
rank (sympy.combinatorics.prufer.Prufer at- RealField (class in sympy.polys.domains),
tribute), 248
1160
rank
(sympy.tensor.indexed.Indexed
at- RealNumber
(in
module
tribute), 1512
sympy.core.numbers), 131
rank() (sympy.combinatorics.permutations.Permutation
reconstruct()
(in
module
method), 209
sympy.solvers.diophantine), 1505
rank() (sympy.matrices.matrices.MatrixBase rect() (in module mpmath), 735
method), 672
recurrence memo()
(in
module
rank binary (sympy.combinatorics.subsets.Subset
sympy.utilities.memoization), 1576
attribute), 253
red groebner()
(in
module
sympy.polys.groebnertools), 1236
rank gray (sympy.combinatorics.subsets.Subset
attribute), 253
reduce() (sympy.polys.polytools.GroebnerBasis
rank lexicographic (sympy.combinatorics.subsets.Subset
method), 1113
attribute), 254
reduce() (sympy.sets.sets.Complement static
method), 1323
rank nonlex() (sympy.combinatorics.permutations.Permutation
method), 209
reduce() (sympy.sets.sets.Intersection static
rank trotterjohnson()
method), 1321
(sympy.combinatorics.permutations.Permutation
reduce()
(sympy.sets.sets.Union
static
method), 210
method), 1320
rat clear denoms() (sympy.polys.polytools.Poly reduce abs inequalities()
(in
module
method), 1103
sympy.solvers.inequalities), 1506
ratint() (sympy.integrals static method), 611
reduce abs inequality()
(in
module
rational, 89
sympy.solvers.inequalities), 1506
Rational (class in sympy.core.numbers), 129
reduce element() (sympy.polys.agca.ideals.Ideal
RationalField (class in sympy.polys.domains),
method), 1140
1158
reduce element() (sympy.polys.agca.modules.SubModule
rationalize()
(in
module
method), 1137
sympy.parsing.sympy parser), 1592
reduce inequalities()
(in
module
ratsimp() (in module sympy.simplify.simplify),
sympy.solvers.inequalities), 1507
1334
reduce rational inequalities()
(in
module
ratsimp() (sympy.core.expr.Expr method),
sympy.solvers.inequalities), 1506
120
reduced() (in module sympy.polys.polytools),
rawlines() (in module sympy.utilities.misc),
1073
1576
ReferenceFrame
(class
in
sympy.physics.vector.frame), 1665
Ray (class in sympy.geometry.line), 519
Ray3D (class in sympy.geometry.line3d), 534 rene()
(in
module
Rayleigh() (in module sympy.stats), 1385
sympy.assumptions.rene), 1289
rayleigh2waist()
(in
module rene() (sympy.core.expr.Expr method), 120
sympy.physics.optics.gaussopt),
rene abs()
(in
module
1978
Index
sympy.assumptions.rene), 1290
1768
rene exp()
(in
module replace() (sympy.core.basic.Basic method),
sympy.assumptions.rene), 1291
97
rene Pow()
(in
module replace() (sympy.matrices.matrices.MatrixBase
sympy.assumptions.rene), 1290
method), 673
rene Relational()
(in
module replace()
(sympy.polys.polytools.Poly
sympy.assumptions.rene), 1290
method), 1104
rene root()
(in
module Reporter (class in sympy.utilities.runtests),
sympy.polys.polytools), 1071
1580
rene root() (sympy.polys.polyclasses.DMP represent()
(in
module
method), 1166
sympy.physics.quantum.represent),
rene root()
(sympy.polys.polytools.Poly
1767
method), 1103
reprify()
(sympy.printing.repr.ReprPrinter
RenementFailed
(class
in
method), 1263
ReprPrinter (class in sympy.printing.repr),
sympy.polys.polyerrors), 1238
reect()
(sympy.geometry.ellipse.Circle
1262
method), 556
reset() (sympy.combinatorics.polyhedron.Polyhedron
reect()
(sympy.geometry.ellipse.Ellipse
method), 245
method), 552
reshape()
(in
module
reect() (sympy.geometry.polygon.RegularPolygon
sympy.utilities.iterables), 1568
method), 569
reshape() (sympy.matrices.sparse.SparseMatrix
refraction angle()
(in
module
method), 697
sympy.physics.optics.utils), 1814
residue() (in module sympy.series.residues),
refractive index (sympy.physics.optics.medium.Medium1312
attribute), 1813
restrict codomain() (sympy.polys.agca.homomorphisms.Mod
method), 1147
register handler()
(in
module
sympy.assumptions.ask), 1287
restrict domain() (sympy.polys.agca.homomorphisms.Modul
RegularPolygon
(class
in
method), 1148
sympy.geometry.polygon), 563
Result (class in sympy.utilities.codegen),
Rel (in module sympy.core.relational), 147
1540
rem() (in module sympy.polys.polytools), 1060 result variables (sympy.utilities.codegen.Routine
rem() (sympy.polys.domains.domain.Domain
attribute), 1540
method), 1152
resultant() (in module sympy.polys.polytools),
rem()
(sympy.polys.domains.eld.Field
1062
method), 1153
resultant()
(sympy.polys.polyclasses.DMP
rem()
(sympy.polys.domains.ring.Ring
method), 1166
method), 1154
resultant()
(sympy.polys.polytools.Poly
rem()
(sympy.polys.polyclasses.DMP
method), 1104
method), 1166
retract()
(sympy.polys.polytools.Poly
rem() (sympy.polys.polytools.Poly method),
method), 1105
1104
reverse order() (sympy.concrete.products.Product
remove handler()
(in
module
method), 327
sympy.assumptions.ask), 1288
reverse order() (sympy.concrete.summations.Sum
removeO() (sympy.core.expr.Expr method),
method), 323
120
ReversedGradedLexOrder
(class
in
render() (sympy.printing.pretty.stringpict.stringPict
sympy.polys.orderings), 1119
method), 1268
revert() (sympy.polys.domains.domain.Domain
reorder()
(sympy.polys.polytools.Poly
method), 1152
method), 1104
revert()
(sympy.polys.domains.eld.Field
method), 1153
rep expectation()
(in
module
revert()
(sympy.polys.domains.ring.Ring
sympy.physics.quantum.represent),
1768
method), 1155
rep innerproduct()
(in
module revert()
(sympy.polys.polyclasses.DMP
sympy.physics.quantum.represent),
method), 1166
Index
1979
Index
1539
rs swap() (in module sympy.stats.rv), 1397
routine() (sympy.utilities.codegen.CodeGen rs trunc()
(in
module
method), 1541
sympy.polys.ring series), 1244
routine() (sympy.utilities.codegen.OctaveCodeGen
rsa private key()
(in
module
method), 1544
sympy.crypto.crypto), 313
row() (sympy.matrices.sparse.SparseMatrix rsa public key()
(in
module
method), 697
sympy.crypto.crypto), 313
row del() (sympy.matrices.dense.MutableDenseMatrix
rsolve() (in module sympy.solvers.recurr),
method), 688
1479
row del() (sympy.matrices.sparse.MutableSparseMatrix
rsolve hyper()
(in
module
method), 701
sympy.solvers.recurr), 1481
row insert() (sympy.matrices.matrices.MatrixBase
rsolve poly()
(in
module
method), 673
sympy.solvers.recurr), 1480
row join() (sympy.matrices.matrices.MatrixBasersolve ratio()
(in
module
method), 673
sympy.solvers.recurr), 1480
row join() (sympy.matrices.sparse.MutableSparseMatrix
run() (sympy.utilities.runtests.SymPyDocTestRunner
method), 702
method), 1581
row list() (sympy.matrices.sparse.SparseMatrix run all tests()
(in
module
method), 697
sympy.utilities.runtests), 1582
row op() (sympy.matrices.dense.MutableDenseMatrix
run in subprocess with hash randomization()
method), 689
(in module sympy.utilities.runtests),
row op() (sympy.matrices.sparse.MutableSparseMatrix 1582
method), 702
runs() (in module sympy.utilities.iterables),
row structure symbolic cholesky()
1569
(sympy.matrices.sparse.SparseMatrix runs() (sympy.combinatorics.permutations.Permutation
method), 698
method), 211
row swap() (sympy.matrices.dense.MutableDenseMatrix
S
method), 689
row swap() (sympy.matrices.sparse.MutableSparseMatrix
S (in module sympy.core.singleton), 102
method), 703
S (in module sympy.physics.quantum.gate),
rref() (sympy.matrices.matrices.MatrixBase
1792
method), 674
sample() (in module sympy.stats), 1395
rs compose add()
(in
module sample iter() (in module sympy.stats), 1395
sympy.polys.ring series), 1247
satisable()
(in
module
rs exp() (in module sympy.polys.ring series),
sympy.logic.inference), 635
1246
saturate()
(sympy.polys.agca.ideals.Ideal
rs hadamard exp()
(in
module
method), 1140
sympy.polys.ring series), 1247
scalar multiply() (sympy.matrices.sparse.SparseMatrix
rs integrate()
(in
module
method), 698
sympy.polys.ring series), 1246
scalar potential()
(in
module
rs log() (in module sympy.polys.ring series),
sympy.physics.vector.eldfunctions),
1246
1691
rs mul() (in module sympy.polys.ring series), scalar potential dierence()
(in
module
1244
sympy.physics.vector.eldfunctions),
rs newton()
(in
module
1691
sympy.polys.ring series), 1247
scale()
(sympy.geometry.curve.Curve
rs pow() (in module sympy.polys.ring series),
method), 542
1245
scale()
(sympy.geometry.ellipse.Circle
rs series from list()
(in
module
method), 556
sympy.polys.ring series), 1245
scale()
(sympy.geometry.ellipse.Ellipse
rs series inversion()
(in
module
method), 552
sympy.polys.ring series), 1245
scale() (sympy.geometry.entity.GeometryEntity
rs square()
(in
module
method), 494
sympy.polys.ring series), 1244
Index
1981
Index
method), 1106
method), 211
set global settings()
SimpleDomain
(class
in
(sympy.printing.printer.Printer class
sympy.polys.domains.simpledomain),
method), 1251
1155
set modulus()
(sympy.polys.polytools.Poly simplied()
(in
module
method), 1106
sympy.solvers.diophantine), 1502
set pos()
(sympy.physics.vector.point.Point simplify() (in module sympy.simplify.simplify),
1327
method), 1678
set potential energy()
simplify() (sympy.core.expr.Expr method),
(sympy.physics.mechanics.particle.Particle
122
method), 1732
simplify() (sympy.functions.special.delta functions.DiracDelt
set potential energy()
method), 378
(sympy.physics.mechanics.rigidbody.RigidBody
simplify() (sympy.matrices.dense.MutableDenseMatrix
method), 1736
method), 689
set vel()
(sympy.physics.vector.point.Point simplify() (sympy.matrices.matrices.MatrixBase
method), 1678
method), 674
seterr() (in module sympy.core.numbers), 132 simplify() (sympy.physics.vector.dyadic.Dyadic
setup() (sympy.galgebra.vector.Vector static
method), 1674
method), 484
simplify() (sympy.physics.vector.vector.Vector
shanks() (in module mpmath), 992
method), 1672
shanks()
(in
module simplify gpgp() (sympy.physics.hep.gamma matrices.Gamma
sympy.series.acceleration), 1311
static method), 1633
shape (sympy.matrices.matrices.MatrixBase simplify index permutations() (in module
attribute), 674
sympy.physics.secondquant), 1623
shape
(sympy.tensor.indexed.Indexed
at- simplify lines() (sympy.physics.hep.gamma matrices.Gamma
tribute), 1512
static method), 1633
shape (sympy.tensor.indexed.IndexedBase at- simplify logic()
(in
module
tribute), 1514
sympy.logic.boolalg), 633
ShapeError
(class
in sin (class in sympy.functions.elementary.trigonometric),
sympy.matrices.matrices), 678
359
Shi (class in sympy.functions.special.error functions),
sin() (in module mpmath), 768
406
sinc() (in module mpmath), 773
shi() (in module mpmath), 803
sincpi() (in module mpmath), 774
shift()
(sympy.polys.polyclasses.DMP sine transform()
(in
module
method), 1166
sympy.integrals.transforms), 587
shift() (sympy.polys.polytools.Poly method), SingleDomain (class in sympy.stats.rv), 1396
1106
SinglePSpace (class in sympy.stats.rv), 1396
shor()
(in
module singular values() (sympy.matrices.matrices.MatrixBase
sympy.physics.quantum.shor), 1801
method), 674
Si (class in sympy.functions.special.error functions),
singularities()
(in
module
sympy.calculus.singularities), 1593
404
si() (in module mpmath), 802
sinh (class in sympy.functions.elementary.hyperbolic),
sides (sympy.geometry.polygon.Polygon at360
sinh() (in module mpmath), 775
tribute), 562
siegeltheta() (in module mpmath), 941
sinm() (in module mpmath), 1030
siegelz() (in module mpmath), 939
sinpi() (in module mpmath), 770
Sieve (class in sympy.ntheory.generate), 276 size (sympy.combinatorics.permutations.Permutation
sift() (in module sympy.utilities.iterables),
attribute), 211
1569
size (sympy.combinatorics.polyhedron.Polyhedron
sign (class in sympy.functions.elementary.complexes), attribute), 246
361
size (sympy.combinatorics.prufer.Prufer atsign() (in module mpmath), 734
tribute), 248
sign() (in module sympy.series.gruntz), 1306 size (sympy.combinatorics.subsets.Subset atsignature() (sympy.combinatorics.permutations.Permutation
tribute), 254
Index
1983
SKIP()
Index
sqf part()
(sympy.polys.polytools.Poly str array()
(in
module
method), 1107
sympy.galgebra.stringarrays), 488
sqr() (sympy.polys.polyclasses.DMP method), str combinations()
(in
module
1167
sympy.galgebra.stringarrays), 489
sqr() (sympy.polys.polytools.Poly method), StrictGreaterThan
(class
in
1108
sympy.core.relational), 156
sqrt (class in sympy.functions.elementary.miscellaneous),
StrictLessThan
(class
in
360
sympy.core.relational), 159
sqrt() (in module mpmath), 752
stringify expr()
(in
module
sqrt() (sympy.polys.domains.domain.Domain
sympy.parsing.sympy parser), 1589
method), 1152
stringPict
(class
in
sqrt mod()
(in
module
sympy.printing.pretty.stringpict),
sympy.ntheory.residue ntheory),
1268
296
strip zero() (sympy.polys.rings.PolyElement
sqrtdenest()
(in
module
method), 1221
strong gens (sympy.combinatorics.perm groups.Permutation
sympy.simplify.sqrtdenest), 1344
sqrtm() (in module mpmath), 1030
attribute), 241
square()
(sympy.polys.rings.PolyElement StrPrinter (class in sympy.printing.str), 1263
method), 1220
struveh() (in module mpmath), 832
square factor()
(in
module struvel() (in module mpmath), 833
sympy.solvers.diophantine), 1496
StudentT() (in module sympy.stats), 1385
srepr() (in module sympy.printing.repr), 1263 sturm() (in module sympy.polys.polytools),
sring() (in module sympy.polys.rings), 1215
1068
sstrrepr() (in module sympy.printing.str), sturm()
(sympy.polys.polyclasses.DMP
method), 1167
1263
stabilizer() (sympy.combinatorics.perm groups.PermutationGroup
sturm() (sympy.polys.polytools.Poly method),
method), 241
1108
stack() (sympy.printing.pretty.stringpict.stringPict
sub (in module sympy.printing.pretty.pretty symbology),
static method), 1269
1267
standard transformations
(in
module sub() (sympy.polys.domains.domain.Domain
sympy.parsing.sympy parser), 1590
method), 1152
start (sympy.sets.sets.Interval attribute), sub() (sympy.polys.polyclasses.DMF method),
1319
1168
State (class in sympy.physics.quantum.state), sub() (sympy.polys.polyclasses.DMP method),
1781
1167
state() (sympy.physics.secondquant.FixedBosonicBasis
sub() (sympy.polys.polytools.Poly method),
method), 1614
1108
state() (sympy.physics.secondquant.VarBosonicBasis
sub ground() (sympy.polys.polyclasses.DMP
method), 1614
method), 1167
state to operators()
(in
module sub ground()
(sympy.polys.polytools.Poly
sympy.physics.quantum.operatorset),
method), 1108
1765
sub paren()
(in
module
StateBase
(class
in
sympy.galgebra.precedence), 485
subdiagram from objects()
sympy.physics.quantum.state), 1781
std() (in module sympy.stats), 1395
(sympy.categories.Diagram method),
stieltjes() (in module mpmath), 937
1837
stirling()
(in
module subgroup search() (sympy.combinatorics.perm groups.Perm
sympy.functions.combinatorial.numbers),
method), 241
374
SubModule
(class
in
sympy.polys.agca.modules), 1134
stirling1() (in module mpmath), 962
stirling2() (in module mpmath), 963
submodule() (sympy.polys.agca.modules.Module
StopTokenizing
(class
in
method), 1132
submodule() (sympy.polys.agca.modules.QuotientModule
sympy.parsing.sympy tokenize),
1590
method), 1142
Index
1985
submodule() (sympy.polys.agca.modules.SubModule
sumem() (in module mpmath), 986
method), 1137
summation()
(in
module
SubQuotientModule
(class
in
sympy.concrete.summations), 328
sympy.polys.agca.modules), 1142
summation() (mpmath.calculus.quadrature.QuadratureRule
subresultants()
(in
module
method), 1011
sympy.polys.polytools), 1061
sup (in module sympy.printing.pretty.pretty symbology),
subresultants() (sympy.polys.polyclasses.DMP
1267
sup (sympy.sets.sets.Set attribute), 1316
method), 1167
subresultants()
(sympy.polys.polytools.Poly superfac() (in module mpmath), 787
method), 1109
superposition basis()
(in
module
Subs (class in sympy.core.function), 171
sympy.physics.quantum.grover),
subs() (sympy.core.basic.Basic method), 99
1794
subs() (sympy.matrices.immutable.ImmutableSparseMatrix
superset (sympy.combinatorics.subsets.Subset
method), 704
attribute), 255
subs() (sympy.matrices.matrices.MatrixBase superset size (sympy.combinatorics.subsets.Subset
method), 676
attribute), 255
subs() (sympy.physics.vector.dyadic.Dyadic support() (sympy.combinatorics.permutations.Permutation
method), 1674
method), 212
subs()
(sympy.physics.vector.vector.Vector SurfaceBaseSeries
(class
in
method), 1672
sympy.plotting.plot), 1283
Subset (class in sympy.combinatorics.subsets), SurfaceOver2DRangeSeries
(class
in
250
sympy.plotting.plot), 1283
subset (sympy.combinatorics.subsets.Subset SWAP
(in
module
attribute), 254
sympy.physics.quantum.gate), 1792
subset()
(sympy.polys.agca.ideals.Ideal SwapGate
(class
in
method), 1140
sympy.physics.quantum.gate), 1791
subset() (sympy.polys.agca.modules.Module swinnerton dyer poly()
(in
module
method), 1132
sympy.polys.specialpolys), 1120
subset() (sympy.sets.sets.Set method), 1316
symarray()
(in
module
sympy.matrices.dense), 683
subset from bitlist()
(sympy.combinatorics.subsets.Subset symb 2txt
(in
module
class method), 254
sympy.printing.pretty.pretty symbology),
subset indices() (sympy.combinatorics.subsets.Subset 1267
class method), 255
Symbol (class in sympy.core.symbol), 122
subsets()
(in
module symbol (sympy.physics.secondquant.AntiSymmetricTensor
sympy.utilities.iterables), 1570
attribute), 1621
SubsSet (class in sympy.series.gruntz), 1307 Symbol() (sympy.assumptions.handlers.calculus.AskBounded
substitute dummies()
(in
module
static method), 1292
sympy.physics.secondquant), 1622
symbol array()
(in
module
substitute indices() (sympy.tensor.tensor.TensAdd
sympy.galgebra.stringarrays), 489
method), 1528
symbols() (in module sympy.core.symbol),
substitute indices() (sympy.tensor.tensor.TensMul
124
method), 1531
symmetric() (sympy.combinatorics.generators
Sum (class in sympy.concrete.summations),
static method), 215
321
symmetric poly()
(in
module
sum next() (mpmath.calculus.quadrature.QuadratureRule
sympy.polys.specialpolys), 1120
method), 1010
symmetric residue()
(in
module
sum next() (mpmath.calculus.quadrature.TanhSinh
sympy.ntheory.modular), 290
method), 1012
SymmetricGroup()
(in
module
sympy.combinatorics.named groups),
sum of four squares()
(in
module
261
sympy.solvers.diophantine), 1499
sum of three squares()
(in
module symmetrize()
(in
module
sympy.solvers.diophantine), 1499
sympy.polys.polyfuncs), 1113
sumap() (in module mpmath), 987
sympify() (in module sympy.core.sympify), 85
1986
Index
sympy.galgebra.ga.MV.dual()
(in
module sympy.galgebra.printing.Format() (in module
sympy.galgebra.ga), 466
sympy.galgebra.ga), 471
sympy.galgebra.ga.MV.even()
(in
module sympy.galgebra.printing.GA Printer()
(in
sympy.galgebra.ga), 466
module sympy.galgebra.ga), 471
sympy.galgebra.ga.MV.exp()
(in
module sympy.galgebra.printing.Get Program()
(in
sympy.galgebra.ga), 466
module sympy.galgebra.ga), 474
sympy.galgebra.ga.MV.expand() (in module sympy.galgebra.printing.Print Function() (in
sympy.galgebra.ga), 466
module sympy.galgebra.ga), 474
sympy.galgebra.ga.MV.factor() (in module sympy.galgebra.printing.xdvi() (in module
sympy.galgebra.ga), 466
sympy.galgebra.ga), 471
sympy.galgebra.ga.MV.func()
(in
module sympy.galgebra.stringarrays (module), 488
sympy.galgebra.ga), 466
sympy.galgebra.vector (module), 484
sympy.galgebra.ga.MV.grade() (in module sympy.geometry.curve (module), 539
sympy.galgebra.ga), 467
sympy.geometry.ellipse (module), 542
sympy.galgebra.ga.MV.inv()
(in
module sympy.geometry.entity (module), 493
sympy.geometry.line (module), 509
sympy.galgebra.ga), 467
sympy.galgebra.ga.MV.norm() (in module sympy.geometry.line3d (module), 525
sympy.galgebra.ga), 467
sympy.geometry.plane (module), 577
sympy.galgebra.ga.MV.rev()
(in
module sympy.geometry.point (module), 497
sympy.galgebra.ga), 467
sympy.geometry.point3d (module), 503
sympy.galgebra.ga.MV.scalar() (in module sympy.geometry.polygon (module), 556
sympy.galgebra.ga), 467
sympy.geometry.util (module), 495
sympy.galgebra.ga.MV.set coef() (in module sympy.integrals (module), 583
sympy.galgebra.ga), 467
sympy.integrals.meijerint doc (module), 604
sympy.galgebra.ga.MV.setup() (in module sympy.integrals.transforms (module), 584
sympy.galgebra.ga), 463
sympy.logic (module), 625
sympy.galgebra.ga.MV.simplify() (in module sympy.matrices (module), 635
sympy.galgebra.ga), 467
sympy.matrices.expressions (module), 706
sympy.galgebra.ga.MV.subs()
(in
module sympy.matrices.expressions.blockmatrix
sympy.galgebra.ga), 467
(module), 711
sympy.galgebra.ga.MV.trigsimp() (in module sympy.matrices.immutable (module), 705
sympy.galgebra.ga), 467
sympy.matrices.matrices (module), 636
sympy.galgebra.ga.Nga()
(in
module sympy.matrices.sparse (module), 692
sympy.galgebra.ga), 468
sympy.ntheory.continued fraction (module),
sympy.galgebra.ga.proj()
(in
module
298
sympy.galgebra.ga), 468
sympy.ntheory.egyptian fraction
(module),
sympy.galgebra.ga.ReciprocalFrame()
(in
301
module sympy.galgebra.ga), 468
sympy.ntheory.factor (module), 281
sympy.galgebra.ga.re()
(in
module sympy.ntheory.generate (module), 276
sympy.galgebra.ga), 468
sympy.ntheory.modular (module), 290
sympy.galgebra.ga.rot()
(in
module sympy.ntheory.multinomial (module), 292
sympy.galgebra.ga), 468
sympy.ntheory.partitions (module), 294
sympy.galgebra.ga.ScalarFunction() (in mod- sympy.ntheory.primetest (module), 294
sympy.ntheory.residue ntheory (module), 295
ule sympy.galgebra.ga), 468
sympy.galgebra.manifold (module), 483
sympy.physics (module), 1597
sympy.galgebra.ncutil (module), 486
sympy.physics.hep.gamma matrices
(modsympy.galgebra.precedence (module), 484
ule), 1632
sympy.galgebra.precedence.dene precedence()
sympy.physics.hydrogen (module), 1598
(in module sympy.galgebra.ga), 454, sympy.physics.matrices (module), 1600
468
sympy.physics.mechanics.kane
(module),
sympy.galgebra.precedence.GAeval()
(in
1741
module sympy.galgebra.ga),
454, sympy.physics.mechanics.lagrange (module),
468
1744
sympy.galgebra.printing (module), 485
1988
Index
sympy.physics.mechanics.linearize (module),
1746
sympy.physics.mechanics.particle (module),
1730
sympy.physics.mechanics.rigidbody
(module), 1733
sympy.physics.optics.gaussopt
(module),
1802
sympy.physics.optics.medium (module), 1812
sympy.physics.optics.utils (module), 1813
sympy.physics.optics.waves (module), 1817
sympy.physics.paulialgebra (module), 1601
sympy.physics.qho 1d (module), 1602
sympy.physics.quantum.anticommutator
(module), 1749
sympy.physics.quantum.cartesian (module),
1757
sympy.physics.quantum.cg (module), 1750
sympy.physics.quantum.circuitplot (module),
1788
sympy.physics.quantum.commutator
(module), 1752
sympy.physics.quantum.constants (module),
1753
sympy.physics.quantum.dagger
(module),
1753
sympy.physics.quantum.gate (module), 1789
sympy.physics.quantum.grover
(module),
1794
sympy.physics.quantum.hilbert
(module),
1758
sympy.physics.quantum.innerproduct (module), 1754
sympy.physics.quantum.operator (module),
1760
sympy.physics.quantum.operatorset
(module), 1764
sympy.physics.quantum.piab (module), 1801
sympy.physics.quantum.qapply
(module),
1766
sympy.physics.quantum.qft (module), 1796
sympy.physics.quantum.qubit (module), 1796
sympy.physics.quantum.represent (module),
1767
sympy.physics.quantum.shor (module), 1800
sympy.physics.quantum.spin (module), 1771
sympy.physics.quantum.state (module), 1781
sympy.physics.quantum.tensorproduct (module), 1755
sympy.physics.secondquant (module), 1604
sympy.physics.sho (module), 1603
sympy.physics.units (module), 1630
sympy.physics.unitsystems.dimensions (module), 1824
Index
sympy.physics.unitsystems.prexes (module),
1827
sympy.physics.unitsystems.quantities (module), 1829
sympy.physics.unitsystems.units
(module),
1827
sympy.physics.vector.functions
(module),
1680
sympy.physics.vector.point (module), 1675
sympy.physics.wigner (module), 1623
sympy.plotting.plot (module), 1270
sympy.plotting.pygletplot (module), 1283
sympy.printing.ccode (module), 1252
sympy.printing.codeprinter (module), 1266
sympy.printing.conventions (module), 1266
sympy.printing.fcode (module), 1254
sympy.printing.gtk (module), 1259
sympy.printing.lambdarepr (module), 1259
sympy.printing.latex (module), 1259
sympy.printing.mathematica (module), 1258
sympy.printing.mathml (module), 1262
sympy.printing.precedence (module), 1266
sympy.printing.pretty.pretty (module), 1251
sympy.printing.pretty.pretty symbology
(module), 1266
sympy.printing.pretty.stringpict
(module),
1268
sympy.printing.preview (module), 1264
sympy.printing.printer (module), 1248
sympy.printing.python (module), 1262
sympy.printing.repr (module), 1262
sympy.printing.str (module), 1263
sympy.printing.tree (module), 1263
sympy.series (module), 1304
sympy.sets.fancysets (module), 1324
sympy.sets.sets (module), 1312
sympy.simplify.cse main (module),
1303,
1345
sympy.simplify.epathtools (module), 1347
sympy.simplify.hyperexpand (module), 1347
sympy.simplify.hyperexpand doc
(module),
1358
sympy.simplify.simplify (module), 73
sympy.simplify.sqrtdenest (module), 1344
sympy.simplify.traversaltools (module), 1347
sympy.solvers (module), 1468
sympy.solvers.inequalities (module), 1505
sympy.solvers.ode (module), 1457
sympy.solvers.pde (module), 1468
sympy.solvers.recurr (module), 1479
sympy.stats (module), 1361
sympy.stats.crv (module), 1396
sympy.stats.crv types (module), 1396
1989
sympy.stats.Die()
(in
module take() (in module sympy.utilities.iterables),
sympy.stats.crv types), 1397
1570
sympy.stats.frv (module), 1396
tan (class in sympy.functions.elementary.trigonometric),
sympy.stats.frv types (module), 1396
362
sympy.stats.Normal()
(in
module tan() (in module mpmath), 768
sympy.stats.crv types), 1397
tangent lines() (sympy.geometry.ellipse.Ellipse
sympy.stats.rv (module), 1396
method), 553
sympy.tensor (module), 1508
tanh (class in sympy.functions.elementary.hyperbolic),
sympy.tensor.index methods (module), 1514
363
sympy.tensor.indexed (module), 1508
tanh() (in module mpmath), 775
sympy.tensor.tensor (module), 1517
TanhSinh
(class
in
mpsympy.utilities (module), 1532
math.calculus.quadrature), 1011
sympy.utilities.autowrap (module), 1533
targets (sympy.physics.quantum.gate.CGate
sympy.utilities.codegen (module), 1538
attribute), 1790
sympy.utilities.decorator (module), 1547
targets (sympy.physics.quantum.gate.CNotGate
sympy.utilities.enumerative (module), 1549
attribute), 1792
sympy.utilities.iterables (module), 1555
targets
(sympy.physics.quantum.gate.Gate
sympy.utilities.lambdify (module), 1573
attribute), 1789
sympy.utilities.memoization (module), 1576
targets (sympy.physics.quantum.gate.UGate
sympy.utilities.misc (module), 1576
attribute), 1790
sympy.utilities.pkgdata (module), 1577
targets (sympy.physics.quantum.grover.OracleGate
sympy.utilities.pytest (module), 1578
attribute), 1794
sympy.utilities.randtest (module), 1579
taufrom() (in module mpmath), 911
sympy.utilities.runtests (module), 1580
taylor() (in module mpmath), 1015
sympy.utilities.source (module), 1587
taylor term() (sympy.core.expr.Expr method),
sympy.utilities.timeutils (module), 1587
122
SymPyDocTestFinder
(class
in taylor term() (sympy.functions.elementary.exponential.exp
sympy.utilities.runtests), 1580
static method), 351
SymPyDocTestRunner
(class
in taylor term() (sympy.functions.elementary.exponential.log
sympy.utilities.runtests), 1581
static method), 354
SymPyOutputChecker
(class
in taylor term() (sympy.functions.elementary.hyperbolic.sinh
sympy.utilities.runtests), 1581
static method), 360
sympytestle()
(in
module TC() (sympy.polys.polyclasses.ANP method),
sympy.utilities.runtests), 1584
1168
SymPyTestResults
(in
module TC() (sympy.polys.polyclasses.DMP method),
sympy.utilities.runtests), 1581
1162
syzygy module() (sympy.polys.agca.modules.SubModule
TC() (sympy.polys.polytools.Poly method),
method), 1137
1076
TensAdd (class in sympy.tensor.tensor), 1526
T
TensExpr (class in sympy.tensor.tensor), 1525
T (in module sympy.physics.quantum.gate), TensMul (class in sympy.tensor.tensor), 1529
tensor indices()
(in
module
1792
sympy.tensor.tensor), 1521
T
(sympy.matrices.expressions.MatrixExpr
tensor mul() (in module sympy.tensor.tensor),
attribute), 707
1531
T (sympy.matrices.matrices.MatrixBase attensor
product
simp()
(in
module
tribute), 648
sympy.physics.quantum.tensorproduct),
t
(sympy.physics.quantum.shor.CMod
at1756
tribute), 1801
TensorHead
(class in sympy.tensor.tensor),
table() (sympy.matrices.matrices.MatrixBase
1523
method), 676
tail degree() (sympy.polys.rings.PolyElement TensorIndex (class in sympy.tensor.tensor),
1520
method), 1221
TensorIndexType
(class
in
tail degrees() (sympy.polys.rings.PolyElement
sympy.tensor.tensor),
1518
method), 1221
1990
Index
1991
method), 1169
method), 502
to sympy dict() (sympy.polys.polyclasses.DMP translate() (sympy.geometry.point3d.Point3D
method), 1167
method), 508
to sympy list() (sympy.polys.polyclasses.ANP Transpose
(class
in
method), 1169
sympy.matrices.expressions), 710
to tree() (sympy.combinatorics.prufer.Prufer transpose() (sympy.matrices.expressions.blockmatrix.BlockM
static method), 249
method), 712
to tuple()
(sympy.polys.polyclasses.ANP transpositions() (sympy.combinatorics.permutations.Permut
method), 1169
method), 212
to tuple()
(sympy.polys.polyclasses.DMP tree() (in module sympy.printing.tree), 1263
method), 1167
tree cse()
(in
module
together()
(in
module
sympy.simplify.cse main), 1346
sympy.polys.rationaltools), 1120
tree repr (sympy.combinatorics.prufer.Prufer
together() (sympy.core.expr.Expr method),
attribute), 249
122
Triangle (class in sympy.geometry.polygon),
TokenError
(class
in
570
sympy.parsing.sympy tokenize),
Triangular() (in module sympy.stats), 1386
1590
trigamma()
(in
module
tokenize()
(in
module
sympy.functions.special.gamma functions),
sympy.parsing.sympy tokenize),
384
1589
trigintegrate()
(sympy.integrals
static
tolist() (sympy.matrices.sparse.SparseMatrix
method), 613
method), 699
TrigSimp()
(in
module
topological sort()
(in
module
sympy.galgebra.vector), 484
sympy.utilities.iterables), 1570
trigsimp()
(in
module
sympy.simplify.simplify), 1336
total degree() (sympy.polys.polyclasses.DMP
method), 1167
trigsimp() (sympy.core.expr.Expr method),
total degree()
(sympy.polys.polytools.Poly
122
method), 1110
trunc() (in module sympy.polys.polytools),
totient() (in module sympy.ntheory.factor ),
1067
290
trunc()
(sympy.polys.polyclasses.DMP
Trace (class in sympy.matrices.expressions),
method), 1167
710
trunc() (sympy.polys.polytools.Poly method),
trailing() (in module sympy.ntheory.factor ),
1111
282
Tuple (class in sympy.core.containers), 182
transcendental, 89
tuple count()
(sympy.core.containers.Tuple
transform()
(sympy.geometry.point.Point
method), 182
method), 502
TWave (class in sympy.physics.optics.waves),
transform() (sympy.geometry.point3d.Point3D
1817
method), 508
twinprime (mpmath.mp attribute), 751
transform()
(sympy.integrals.Integral twoform to matrix()
(in
module
method), 617
sympy.digeom), 1858
transform nodes()
(mp- TwoQubitGate
(class
in
math.calculus.quadrature.QuadratureRule
sympy.physics.quantum.gate), 1790
method), 1011
transformation to DN()
(in
module U
sympy.solvers.diophantine), 1494
U() (in module sympy.printing.pretty.pretty symbology),
transitivity degree (sympy.combinatorics.perm groups.PermutationGroup
1266
attribute), 243
ufuncify()
(in
module
translate()
(sympy.geometry.curve.Curve
sympy.utilities.autowrap), 1536
method), 542
UfuncifyCodeWrapper
(class
in
translate() (sympy.geometry.entity.GeometryEntity
sympy.utilities.autowrap), 1534
method), 494
UGate (class in sympy.physics.quantum.gate),
translate()
(sympy.geometry.point.Point
1790
1992
Index
uncouple()
(in
module
class method), 212
sympy.physics.quantum.spin), 1780
unrank nonlex() (sympy.combinatorics.permutations.Permut
Unequality (class in sympy.core.relational),
class method), 213
155
unrank trotterjohnson()
unatten()
(in
module
(sympy.combinatorics.permutations.Permutation
sympy.utilities.iterables), 1571
class method), 213
UnicationFailed
(class
in unrestricted necklace()
(in
module
sympy.polys.polyerrors), 1238
sympy.utilities.iterables), 1572
Uniform() (in module sympy.stats), 1387
untokenize()
(in
module
UniformSum() (in module sympy.stats), 1388
sympy.parsing.sympy tokenize),
unify() (sympy.polys.domains.domain.Domain
1589
method), 1152
upper (sympy.physics.secondquant.AntiSymmetricTensor
attribute), 1621
unify()
(sympy.polys.polyclasses.ANP
method), 1169
upper (sympy.tensor.indexed.Idx attribute),
unify()
(sympy.polys.polyclasses.DMP
1511
upper triangular solve()
method), 1167
unify() (sympy.polys.polytools.Poly method),
(sympy.matrices.matrices.MatrixBase
1111
method), 677
Union (class in sympy.sets.sets), 1320
uppergamma
(class
in
union()
(sympy.polys.agca.ideals.Ideal
sympy.functions.special.gamma functions),
method), 1140
384
union() (sympy.polys.agca.modules.SubModule use() (in module sympy.simplify.traversaltools),
method), 1137
1347
union()
(sympy.series.gruntz.SubsSet
V
method), 1308
union() (sympy.sets.sets.Set method), 1316
v1pt theory() (sympy.physics.vector.point.Point
uniq() (in module sympy.utilities.iterables),
method), 1679
1572
v2pt theory() (sympy.physics.vector.point.Point
Unit (class in sympy.physics.units), 1631
method), 1679
Unit (class in sympy.physics.unitsystems.units), values()
(sympy.core.containers.Dict
1827
method), 183
unit (sympy.polys.polytools.Poly attribute), values() (sympy.matrices.matrices.MatrixBase
1111
method), 677
UnitaryOperator
(class
in values() (sympy.physics.unitsystems.dimensions.Dimension
sympy.physics.quantum.operator),
method), 1825
1761
var() (in module sympy.core.symbol), 126
unitroots() (in module mpmath), 754
VarBosonicBasis
(class
in
UnitSystem
(class
in
sympy.physics.secondquant), 1613
sympy.physics.unitsystems.units),
variable map() (sympy.physics.vector.frame.ReferenceFrame
1828
method), 1669
UnivariatePolynomialError
(class
in variables (sympy.core.function.Lambda atsympy.polys.polyerrors), 1238
tribute), 163
UniversalSet (class in sympy.sets.sets), 1324 variables
(sympy.core.function.Subs
atunparse paren()
(in
module
tribute), 171
sympy.galgebra.precedence), 485
variables (sympy.physics.quantum.operator.DierentialOper
unrank() (sympy.combinatorics.graycode.GrayCode
attribute), 1764
class method), 259
variables (sympy.physics.quantum.state.Wavefunction
unrank() (sympy.combinatorics.prufer.Prufer
attribute), 1788
class method), 250
variables
(sympy.utilities.codegen.Routine
unrank binary() (sympy.combinatorics.subsets.Subset attribute), 1540
class method), 255
variance() (in module sympy.stats), 1394
unrank gray() (sympy.combinatorics.subsets.Subset
variations()
(in
module
class method), 256
sympy.utilities.iterables), 1572
unrank lex() (sympy.combinatorics.permutations.Permutation
Index
1993
vec()
Index
1792
YGate (class in sympy.physics.quantum.gate),
x (sympy.geometry.point.Point attribute), 503
1791
x
(sympy.geometry.point3d.Point3D
at- yn (class in sympy.functions.special.bessel),
tribute), 508
413
x (sympy.physics.vector.frame.ReferenceFrame Ynm (class in sympy.functions.special.spherical harmonics),
attribute), 1669
443
XBra (class in sympy.physics.quantum.cartesian),
Ynm c()
(in
module
1757
sympy.functions.special.spherical harmonics),
xdirection
(sympy.geometry.line.Ray
at445
tribute), 521
YOp (class in sympy.physics.quantum.cartesian),
xdirection (sympy.geometry.line3d.Ray3D at1757
tribute), 536
xdvi() (in module sympy.galgebra.printing), Z
486
Z (in module sympy.physics.quantum.gate),
XGate (class in sympy.physics.quantum.gate),
1792
1791
z
(sympy.geometry.point3d.Point3D
atXKet (class in sympy.physics.quantum.cartesian),
tribute), 508
1757
z (sympy.physics.vector.frame.ReferenceFrame
xobj()
(in
module
attribute), 1669
sympy.printing.pretty.pretty symbology),
zdirection (sympy.geometry.line3d.Ray3D at1267
tribute), 536
XOp (class in sympy.physics.quantum.cartesian),zero, 89
1757
Zero (class in sympy.core.numbers), 132
Xor (class in sympy.logic.boolalg), 629
zero (sympy.polys.polytools.Poly attribute),
xreplace() (sympy.core.basic.Basic method),
1111
101
ZeroMatrix
(class
in
xring() (in module sympy.polys.rings), 1214
sympy.matrices.expressions), 711
xstr() (in module sympy.printing.pretty.pretty symbology),
zeros() (in module sympy.matrices.dense),
1267
679
xsym()
(in
module zeros() (sympy.matrices.sparse.SparseMatrix
sympy.printing.pretty.pretty symbology),
class method), 699
1267
zeta (class in sympy.functions.special.zeta functions),
xthreaded()
(in
module
421
sympy.utilities.decorator), 1548
zeta() (in module mpmath), 931
xypic draw diagram()
(in
module zetazero() (in module mpmath), 938
sympy.categories.diagram drawing), ZGate (class in sympy.physics.quantum.gate),
1845
1791
XypicDiagramDrawer
(class
in zip row op() (sympy.matrices.dense.MutableDenseMatrix
sympy.categories.diagram drawing),
method), 689
1843
zip row op() (sympy.matrices.sparse.MutableSparseMatrix
method), 703
Y
Znm (class in sympy.functions.special.spherical harmonics),
Y (in module sympy.physics.quantum.gate),
445
1792
ZOp (class in sympy.physics.quantum.cartesian),
y (sympy.geometry.point.Point attribute), 503
1757
y
(sympy.geometry.point3d.Point3D
attribute), 508
y (sympy.physics.vector.frame.ReferenceFrame
attribute), 1669
ydirection
(sympy.geometry.line.Ray
attribute), 522
ydirection (sympy.geometry.line3d.Ray3D attribute), 536
Index
1995