SymPy ist eine Python-Bibliothek für symbolische Mathematik. SymPy soll ein vollständiges Computer-Algebra-System (CAS) bereitstellen und dabei den Programmcode so einfach halten, dass er nachvollziehbar und einfach erweiterbar bleibt. SymPy ist vollständig in Python geschrieben und benötigt keine weiteren Bibliotheken.
Dieses Tutorial schafft einen Überblick und gibt eine Einführung in SymPy. Wenn du wissen möchtest, was SymPy tun kann (und wie), lies diese Seite, und wenn du mehr erfahren möchtest, lies den SymPy User’s Guide, die SymPy Modules Reference, oder den Quellcode selbst.
Am einfachsten kannst du SymPy mit der aktuellsten .tar-Datei aus den “Featured Downloads” von http://code.google.com/p/sympy/ installieren:
Dann musst du die Datei auspacken:
$ tar xzf sympy-0.5.12.tar.gz
und kannst sie mit einem Python-Interpreter ausprobieren.
$ cd sympy-0.5.12 $ python Python 2.4.4 (#2, Jan 3 2008, 13:36:28) [GCC 4.2.3 20071123 (prerelease) (Debian 4.2.2-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from sympy import Symbol, cos >>> x = Symbol("x") >>> (1/cos(x)).series(x, 0, 10) 1 + x**2/2 + 5*x**4/24 + 61*x**6/720 + 277*x**8/8064 + O(x**10)
SymPy kann wie im Beispiel gezeigt benutzt werden, und dies ist auch der übliche Weg, es von einem anderen Programm aus zu verwenden. Du kannst es ebenfalls wie jedes andere Modul mithilfe von ./setup.py install installieren. Auch ist es natürlich möglich, einfach ein Paket deiner Linux-Distribution zu verwenden, zum Beispiel:
Installing SymPy in Debian
$ sudo apt-get install python-sympy Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: python-sympy 0 upgraded, 1 newly installed, 0 to remove and 18 not upgraded. Need to get 991kB of archives. After this operation, 5976kB of additional disk space will be used. Get:1 http://ftp.cz.debian.org unstable/main python-sympy 0.5.12-1 [991kB] Fetched 991kB in 2s (361kB/s) Selecting previously deselected package python-sympy. (Reading database ... 232619 files and directories currently installed.) Unpacking python-sympy (from .../python-sympy_0.5.12-1_all.deb) ... Setting up python-sympy (0.5.12-1) ...
Weitere Installationsmöglichkeiten findest du unter Download and Installation (auf Englisch) auf der SymPy-Wiki.
Für Experimente mit neuen Funktionen und zum Ausprobieren kann die um IPython aufgebaute Umgebung namens isympy (im Quellverzeichnis unter bin/isympy) benutzt werden. Es handelt sich hierbei nur um eine Standard-Python-Konsole, die allerdings bereits die wichtigen sympy-Module importiert hat und unter anderem die Symbole x, y und z bereits definiert hat:
$ cd sympy $ ./bin/isympy IPython console for SymPy 0.7.2-git (Python 2.7.1) (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) Documentation can be found at http://www.sympy.org In [1]: (1/cos(x)).series(x, 0, 10) Out[1]: 2 4 6 8 x 5*x 61*x 277*x / 10\ 1 + -- + ---- + ----- + ------ + O\x / 2 24 720 8064
Bemerkung
Benutzereingaben sind fett dargestellt. Was in einem normalen Python-Interpreter drei Zeilen gebraucht hätte, kann mit isympy in nur einer Zeile ausgedrückt werden.
SymPy hat drei eingebaute Zahlentypen: Float, Rational und Integer.
Die Klasse Rational stellt eine rationale Zahl als Paar von zwei Ganzzahlen dar: dem Zähler und dem Nenner. Rational(1, 2) repräsentiert also 1/2, Rational(5, 2) repräsentiert 5/2 und so weiter.
>>> from sympy import Rational
>>> a = Rational(1, 2)
>>> a
1/2
>>> a*2
1
>>> Rational(2)**50/Rational(10)**50
1/88817841970012523233890533447265625
Beim Arbeiten mit Pythons Ganzzahlen und Fließkommazahlen ist Vorsicht geboten, besonders bei Division, da eine Python-Zahl statt einer SymPy-Zahl das Ergebnis sein kann. Eine Division von zwei Python-Ganzzahlen hat eine Fließkommazahl zum Ergebnis – die “echte Divison” von Python 3 und das Standardverhalten von isympy, welches division aus __future__ importiert:
>>> 1/2
0.5
In älteren Python-Versionen ohne den Import von division ist das Ergebnis hingegen eine abgerundete Ganzzahl:
>>> 1/2
0
In beiden Fällen handelt es sich jedoch nicht um eine SymPy-Zahl, weil Python seine eigenen Zahl zurückgegeben hat. Meistens wirst du aber mit Zahlen des Typs Rational arbeiten wollen, also achte darauf, auch solche zu erhalten. Oft wird zur besseren Lesbarkeit R mit Rational gleichgesetzt:
>>> R = Rational
>>> R(1, 2)
1/2
>>> R(1)/2 # R(1) is a SymPy Integer and Integer/int gives a Rational
1/2
Es gibt auch einige spezielle Konstanten wie e oder pi, die als Symbole behandelt werden (1 + pi wird nicht als Zahl ausgerechnet, sondern bleibt 1 + pi) und in beliebiger Präzision verfügbar sind:
>>> from sympy import pi, E
>>> pi**2
pi**2
>>> pi.evalf()
3.14159265358979
>>> (pi + E).evalf()
5.85987448204884
Wie man sieht, berechnet evalf aus dem Ausdruck eine Fließkommazahl.
Das Symnol oo wird für eine Klasse benutzt, die mathematische Unendlichkeit darstellt:
>>> from sympy import oo
>>> oo > 99999
True
>>> oo + 1
oo
Im Gegensatz zu anderen Computer-Algebra-Systemen müssen in SymPy symbolische Variablen ausdrücklich deklariert werden:
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> y = Symbol('y')
Links steht eine normale Python-Variable, der ein SymPy-Symbol-Objekt zugewiesen wird. Vordefiniert Symbole (inklusiv Symbole mit griechischen Namen) sind von Import von abc verfügbar:
>>> from sympy.abc import x, theta
Symbole können auch mit den symbols oder var Funktionen erstellt werden. Die letztere fügt automatisch die Symbole in den Namespace ein, und beide Funktionen akzeptieren eine Reihennotation:
>>> from sympy import symbols, var
>>> a, b, c = symbols('a,b,c')
>>> d, e, f = symbols('d:f')
>>> var('g:h')
(g, h)
>>> var('g:2')
(g0, g1)
Aus Symbol-Objekten kann man bequem Ausdrücke zusammensetzen:
>>> x + y + x - y
2*x
>>> (x + y)**2
(x + y)**2
>>> ((x + y)**2).expand()
x**2 + 2*x*y + y**2
Sie können mit subs(old, new) durch Zahlen, andere Symbole oder Ausdrücke ersetzt werden:
>>> ((x + y)**2).subs(x, 1)
(y + 1)**2
>>> ((x + y)**2).subs(x, y)
4*y**2
>>> ((x + y)**2).subs(x, 1 - y)
1
Für den Rest des Tutorials gehen wir davon aus, dass folgende Zeile ausgeführt wurde:
>>> from sympy import init_printing
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
Dies sorgt dafür, dass Ausdrücke bei der Ausgabe besser aussehen (siehe Ausgabe weiter unten). Wenn eine Unicode-Schrift installiert ist, erreichst du mit use_unicode=True eine noch hübschere Ausgabe.
Für die Partialbruchzerlegung kannst du apart(expr, x) benutzen:
>>> from sympy import apart
>>> from sympy.abc import x, y, z
>>> 1/( (x + 2)*(x + 1) )
1
---------------
(x + 1)*(x + 2)
>>> apart(1/( (x + 2)*(x + 1) ), x)
1 1
- ----- + -----
x + 2 x + 1
>>> (x + 1)/(x - 1)
x + 1
-----
x - 1
>>> apart((x + 1)/(x - 1), x)
2
1 + -----
x - 1
Zum Kombinieren gibt es die Funktion together(expr, x):
>>> from sympy import together
>>> together(1/x + 1/y + 1/z)
x*y + x*z + y*z
---------------
x*y*z
>>> together(apart((x + 1)/(x - 1), x), x)
x + 1
-----
x - 1
>>> together(apart(1/( (x + 2)*(x + 1) ), x), x)
1
---------------
(x + 1)*(x + 2)
Grenzwerte sind in SymPy einfach zu benutzen, sie folgen der Syntax limit(function, variable, point), um also den Grenzwert von f(x) bei x -> 0 zu berechnen, kann limit(f, x, 0) benutzt werden:
>>> from sympy import limit, Symbol, sin, oo
>>> x = Symbol("x")
>>> limit(sin(x)/x, x, 0)
1
Analog kann der Limes für x gegen unendlich berechnet werden:
>>> limit(x, x, oo)
oo
>>> limit(1/x, x, oo)
0
>>> limit(x**x, x, 0)
1
Einige nicht-triviale Beispiele zu Grenzwerten finden sich in der Datei test_demidovich.py
Mithilfe von diff(func, var) kann jeder SymPy-Ausdruck differenziert werden. Beispiele:
>>> from sympy import diff, Symbol, sin, tan
>>> x = Symbol('x')
>>> diff(sin(x), x)
cos(x)
>>> diff(sin(2*x), x)
2*cos(2*x)
>>> diff(tan(x), x)
2
tan (x) + 1
Folgendermaßen kann überprüft werden, ob dies korrekt ist:
>>> from sympy import limit
>>> from sympy.abc import delta
>>> limit((tan(x + delta) - tan(x))/delta, delta, 0)
2
tan (x) + 1
Höhere Ableitungen können mithilfe von diff(func, var, n) berechnet werden:
>>> diff(sin(2*x), x, 1)
2*cos(2*x)
>>> diff(sin(2*x), x, 2)
-4*sin(2*x)
>>> diff(sin(2*x), x, 3)
-8*cos(2*x)
Benutze .series(var, point, order):
>>> from sympy import Symbol, cos
>>> x = Symbol('x')
>>> cos(x).series(x, 0, 10)
2 4 6 8
x x x x / 10\
1 - -- + -- - --- + ----- + O\x /
2 24 720 40320
>>> (1/cos(x)).series(x, 0, 10)
2 4 6 8
x 5*x 61*x 277*x / 10\
1 + -- + ---- + ----- + ------ + O\x /
2 24 720 8064
Ein weiteres einfaches Beispiel:
>>> from sympy import Integral, pprint
>>> y = Symbol("y")
>>> e = 1/(x + y)
>>> s = e.series(x, 0, 5)
>>> print(s)
1/y - x/y**2 + x**2/y**3 - x**3/y**4 + x**4/y**5 + O(x**5)
>>> pprint(s)
2 3 4
1 x x x x / 5\
- - -- + -- - -- + -- + O\x /
y 2 3 4 5
y y y y
Compute the summation of f with respect to the given summation variable over the given limits.
summation(f, (i, a, b)) computes the sum of f with respect to i from a to b, i.e.,
b
____
\ `
summation(f, (i, a, b)) = ) f
/___,
i = a
If it cannot compute the sum, it prints the corresponding summation formula. Repeated sums can be computed by introducing additional limits:
>>> from sympy import summation, oo, symbols, log
>>> i, n, m = symbols('i n m', integer=True)
>>> summation(2*i - 1, (i, 1, n))
2
n
>>> summation(1/2**i, (i, 0, oo))
2
>>> summation(1/log(n)**n, (n, 2, oo))
oo
___
\ `
\ -n
/ log (n)
/__,
n = 2
>>> summation(i, (i, 0, n), (n, 0, m))
3 2
m m m
-- + -- + -
6 2 3
>>> from sympy.abc import x
>>> from sympy import factorial
>>> summation(x**n/factorial(n), (n, 0, oo))
x
e
SymPy unterstützt unendliche und endliche Integration transzendenter elementarer und spezieller Funktionen durch integrate(), welches den starken Risch-Norman-Algorithmus nutzt, sowie einige Heuristiken und Mustererkennungen:
>>> from sympy import integrate, erf, exp, sin, log, oo, pi, sinh, symbols
>>> x, y = symbols('x,y')
Es können elementare Funktionen integriert werden:
>>> integrate(6*x**5, x)
6
x
>>> integrate(sin(x), x)
-cos(x)
>>> integrate(log(x), x)
x*log(x) - x
>>> integrate(2*x + sinh(x), x)
2
x + cosh(x)
Aber auch mit speziellen Funktionen kann einfach umgegangen werden:
>>> integrate(exp(-x**2)*erf(x), x)
____ 2
\/ pi *erf (x)
--------------
4
Es ist möglich, ein endliches Integral zu berechnen:
>>> integrate(x**3, (x, -1, 1))
0
>>> integrate(sin(x), (x, 0, pi/2))
1
>>> integrate(cos(x), (x, -pi/2, pi/2))
2
Auch uneigentliche Integrale werden unterstützt:
>>> integrate(exp(-x), (x, 0, oo))
1
>>> integrate(log(x), (x, 0, 1))
-1
Mit Ausnahme der imaginären Einheit, I, die rein imaginär ist, können Symbole mit Attributen (z.B. reale, positive, komplex, usw.) erstellt werden, und dies hat Auswirkungen darauf, wie sie sich verhalten:
>>> from sympy import Symbol, exp, I
>>> x = Symbol("x") # a plain x with no attributes
>>> exp(I*x).expand()
I*x
e
>>> exp(I*x).expand(complex=True)
-im(x) -im(x)
I*e *sin(re(x)) + e *cos(re(x))
>>> x = Symbol("x", real=True)
>>> exp(I*x).expand(complex=True)
I*sin(x) + cos(x)
trigonometrische
>>> from sympy import asin, asinh, cos, sin, sinh, symbols, I
>>> x, y = symbols('x,y')
>>> sin(x + y).expand(trig=True)
sin(x)*cos(y) + sin(y)*cos(x)
>>> cos(x + y).expand(trig=True)
-sin(x)*sin(y) + cos(x)*cos(y)
>>> sin(I*x)
I*sinh(x)
>>> sinh(I*x)
I*sin(x)
>>> asinh(I)
I*pi
----
2
>>> asinh(I*x)
I*asin(x)
>>> sin(x).series(x, 0, 10)
3 5 7 9
x x x x / 10\
x - -- + --- - ---- + ------ + O\x /
6 120 5040 362880
>>> sinh(x).series(x, 0, 10)
3 5 7 9
x x x x / 10\
x + -- + --- + ---- + ------ + O\x /
6 120 5040 362880
>>> asin(x).series(x, 0, 10)
3 5 7 9
x 3*x 5*x 35*x / 10\
x + -- + ---- + ---- + ----- + O\x /
6 40 112 1152
>>> asinh(x).series(x, 0, 10)
3 5 7 9
x 3*x 5*x 35*x / 10\
x - -- + ---- - ---- + ----- + O\x /
6 40 112 1152
Kugelflächen
>>> from sympy import Ylm
>>> from sympy.abc import theta, phi
>>> Ylm(1, 0, theta, phi)
___
\/ 3 *cos(theta)
----------------
____
2*\/ pi
>>> Ylm(1, 1, theta, phi)
___ I*phi
-\/ 6 *e *sin(theta)
------------------------
____
4*\/ pi
>>> Ylm(2, 1, theta, phi)
____ I*phi
-\/ 30 *e *sin(theta)*cos(theta)
------------------------------------
____
4*\/ pi
Fakultät und Gamma-Funktion
>>> from sympy import factorial, gamma, Symbol
>>> x = Symbol("x")
>>> n = Symbol("n", integer=True)
>>> factorial(x)
x!
>>> factorial(n)
n!
>>> gamma(x + 1).series(x, 0, 3) # i.e. factorial(x)
/ 2 2\
2 |EulerGamma pi | / 3\
1 - EulerGamma*x + x *|----------- + ---| + O\x /
\ 2 12/
Zeta-Funktion
>>> from sympy import zeta
>>> zeta(4, x)
zeta(4, x)
>>> zeta(4, 1)
4
pi
---
90
>>> zeta(4, 2)
4
pi
-1 + ---
90
>>> zeta(4, 3)
4
17 pi
- -- + ---
16 90
Polynome
>>> from sympy import assoc_legendre, chebyshevt, legendre, hermite
>>> chebyshevt(2, x)
2
2*x - 1
>>> chebyshevt(4, x)
4 2
8*x - 8*x + 1
>>> legendre(2, x)
2
3*x 1
---- - -
2 2
>>> legendre(8, x)
8 6 4 2
6435*x 3003*x 3465*x 315*x 35
------- - ------- + ------- - ------ + ---
128 32 64 32 128
>>> assoc_legendre(2, 1, x)
__________
/ 2
-3*x*\/ - x + 1
>>> assoc_legendre(2, 2, x)
2
- 3*x + 3
>>> hermite(3, x)
3
8*x - 12*x
In isympy:
>>> from sympy import Function, Symbol, dsolve
>>> f = Function('f')
>>> x = Symbol('x')
>>> f(x).diff(x, x) + f(x)
2
d
f(x) + ---(f(x))
2
dx
>>> dsolve(f(x).diff(x, x) + f(x), f(x))
f(x) = C1*sin(x) + C2*cos(x)
In isympy:
>>> from sympy import solve, symbols
>>> x, y = symbols('x,y')
>>> solve(x**4 - 1, x)
[-1, 1, -I, I]
>>> solve([x + 5*y - 2, -3*x + 6*y - 15], [x, y])
{x: -3, y: 1}
Matrizen werden als Instanzen der Matrix-Klasse erzeugt:
>>> from sympy import Matrix, Symbol
>>> Matrix([[1, 0], [0, 1]])
[1 0]
[ ]
[0 1]
Sie können auch Symbole enthalten:
>>> x = Symbol('x')
>>> y = Symbol('y')
>>> A = Matrix([[1, x], [y, 1]])
>>> A
[1 x]
[ ]
[y 1]
>>> A**2
[x*y + 1 2*x ]
[ ]
[ 2*y x*y + 1]
Mehr Informationen und Beispiele zu Matrizen finden sich im LinearAlgebraTutorial.
Die Methode .match() kann gemeinsam mit der Klasse Wild Ausdrücke auf Muster überprüfen. Die Methode gibt ein dictionary mit den nötigen Ersetzungen zurück, wie im folgenden Beispiel ersichtlich:
>>> from sympy import Symbol, Wild
>>> x = Symbol('x')
>>> p = Wild('p')
>>> (5*x**2).match(p*x**2)
{p: 5}
>>> q = Wild('q')
>>> (x**2).match(p*x**q)
{p: 1, q: 2}
Wenn der Musterabgleich fehlschlägt, wird None zurückgegeben:
>>> print (x + 1).match(p**x)
None
Über den Parameter exclude kann man manches aus dem Ergebnis ausschließen:
>>> p = Wild('p', exclude=[1, x])
>>> print (x + 1).match(x + p) # 1 is excluded
None
>>> print (x + 1).match(p + 1) # x is excluded
None
>>> print (x + 1).match(x + 2 + p) # -1 is not excluded
{p_: -1}
Es existieren mehrere Wege, Ausdrücke auszugeben:
Standard
Dies ist die Ausgabe von str(expression) und sieht so aus:
>>> from sympy import Integral
>>> from sympy.abc import x
>>> print x**2
x**2
>>> print 1/x
1/x
>>> print Integral(x**2, x)
Integral(x**2, x)
ASCII-Art-Ausgabe
Eine pprint-Funktion erzeugt diese hübschere ASCII-Art-Ausgabe.
>>> from sympy import Integral, pprint
>>> from sympy.abc import x
>>> pprint(x**2)
2
x
>>> pprint(1/x)
1
-
x
>>> pprint(Integral(x**2, x))
/
|
| 2
| x dx
|
/
Wenn eine Unicode-Schriftart installiert ist, sollte die ASCII-Art-Ausgabe standardmäßig die Unicode-Fassung verwenden. Dies kann mit dem Parameter use_unicode erzwungen oder abgeschaltet werden.
>>> pprint(Integral(x**2, x), use_unicode=True)
⌠
⎮ 2
⎮ x dx
⌡
Siehe auch die Wiki-Seite Pretty Printing für mehr Beispiele von hübschen Unicode-Ausgaben.
Tipp: Die ASCII-Art-Ausgabe kann auch als Standard-Methode gesetzt werden:
$ python
Python 2.5.2 (r252:60911, Jun 25 2008, 17:58:32)
[GCC 4.3.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from sympy import init_printing, var, Integral
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
>>> var("x")
x
>>> x**3/3
3
x
--
3
>>> Integral(x**2, x) #doctest: +NORMALIZE_WHITESPACE
/
|
| 2
| x dx
|
/
Python-Ausgabe
>>> from sympy.printing.python import python
>>> from sympy import Integral
>>> from sympy.abc import x
>>> print python(x**2)
x = Symbol('x')
e = x**2
>>> print python(1/x)
x = Symbol('x')
e = 1/x
>>> print python(Integral(x**2, x))
x = Symbol('x')
e = Integral(x**2, x)
LaTeX-Ausgabe
>>> from sympy import Integral, latex
>>> from sympy.abc import x
>>> latex(x**2)
x^{2}
>>> latex(x**2, mode='inline')
$x^{2}$
>>> latex(x**2, mode='equation')
\begin{equation}x^{2}\end{equation}
>>> latex(x**2, mode='equation*')
\begin{equation*}x^{2}\end{equation*}
>>> latex(1/x)
\frac{1}{x}
>>> latex(Integral(x**2, x))
\int x^{2}\, dx
MathML
>>> from sympy.printing.mathml import mathml
>>> from sympy import Integral, latex
>>> from sympy.abc import x
>>> print mathml(x**2)
<apply><power/><ci>x</ci><cn>2</cn></apply>
>>> print mathml(1/x)
<apply><power/><ci>x</ci><cn>-1</cn></apply>
Pyglet
>>> from sympy import Integral, preview
>>> from sympy.abc import x
>>> preview(Integral(x**2, x))
Dies öffnet ein pyglet-Fenster mit dem in LaTeX gerenderten Ausdruck, wenn pyglet installiert ist:
isympy ruft pprint automatisch auf – deswegen sind die Ausgaben standardmäßig hübsch.
Es ist gibt auch ein Ausgabemodul sympy.printing. Andere Ausgabemethoden, die durch dieses Modul erreichbar sind:
Nun ist Zeit, mehr über SymPy zu lernen. Lies den SymPy User’s Guide und die SymPy Modules Reference.
Unser öffentliches Wiki unter wiki.sympy.org, enthält einen Haufen nützlicher Beispiele und Anleitungen von uns und unseren Nutzern. (Fühle dich frei, dazu beizutragen und Dinge zu verändern!)
This tutorial is also available in other languages: