SymPy е библиотека на Python за символна математика. Тя цели да стане пълнофункционална алгебрична система (CAS - computer algebra system), като поддържа кода възможно най-опростен с цел да бъде разбираем и лесен за разширяване.SymPy е изцяло написана на Python и не изисква външни библиотеки.
Този урок е въведение към SymPy. Прочетете го, за да научите какво и как може SymPy, и ако искате да научите повече, прочетете SymPy User’s Guide, SymPy Modules Reference, или сорс код директно.
Най-лесният начин да свалите SymPy е да отидете на http://code.google.com/p/sympy/ и да изтеглите последния архив.
Разархивирайте го:
$ tar xzf sympy-0.5.12.tar.gz
и го изпробвайте от интерпретатор на Python:
$ 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 както е показано отгоре, което всъщност е препоръчителният начин, ако го използвате във вашата програма. Също така може да го инсталирате, използвайки ./setup.py install, както който и да е модул на Python,или просто инсталирайте пакет във вашата любима Linux дистрибуция, например:
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) ...
For other means how to install SymPy, consult the wiki page Download and Installation.
За да експериментирате с нови функционалности или когато се опитвате да разберете как да направите нещата, може да използвате нашата специална обвивка около IPython, наречена isympy (намираща се в bin/isympy, ако сте компилирали през сорс директорията), която е стандартна конзола на Python и която включва съответните SymPy модули и дефинираните символи x, y, z, както и някои други неща:
$ 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
Note
Командите, въведени от вас, са удебелени. Така, това което направихме в 3 линии на обикновен Python, може да се направи с 1 линия на isympy.
SymPy има 3 вградени типове числа: Цели, с плаваща запетая и рационални.
Рационалният клас представлява рационална дроб като двойка от цели числа: числителя и знаменателя, така че Rational(1, 2) представлява 1/2, Rational(5, 2) 5/2 и така нататък.
>>> from sympy import Rational
>>> a = Rational(1, 2)
>>> a
1/2
>>> a*2
1
>>> Rational(2)**50/Rational(10)**50
1/88817841970012523233890533447265625
Бъдете предпазливи, когато работите с цели и с плаваща запетая числа в Python особено когато делите, защото може да създадете Python число, а не SymPy число. От съотношението на 2 цели числа в Python може да се получи число с плаваща запетая – “истинското деление”, което е стандарт в Python 3, и подразбиращото се поведение на isympy, което въвежда делението от __future__:
>>> 1/2
0.5
Но в по-ранните версии на Python, където “истинското делението” не бе въведено, като резултат ще бъде закръглено число:
>>> 1/2
0
Все пак и в двата случая не използваме SymPy числа, защото Python създава свои собствени. През повечето време най-вероятно ще работите с рационални числа, така че се уверете, че използвате Rational, за да получите очаквания резултат. Може да сметнете за удобно да използвате R като Rational:
>>> R = Rational
>>> R(1, 2)
1/2
>>> R(1)/2 # R(1) is a SymPy Integer and Integer/int gives a Rational
1/2
Ние също така имаме някои специални константи, като e и pi, които се третират като символи (1 + pi няма да се изчисли като някое число, а ще си остане 1 + pi) и имат арбитрарна точност:
>>> from sympy import pi, E
>>> pi**2
pi**2
>>> pi.evalf()
3.14159265358979
>>> (pi + E).evalf()
5.85987448204884
Както виждате, evalf изчислява израза до число с плаваща запетая.
Също така има и клас, представляващ математическа безкрайност, наречен oo:
>>> from sympy import oo
>>> oo > 99999
True
>>> oo + 1
oo
За разлика от други компютърни алгебрични системи (CAS), в SymPy вие трябва изрично да декларирате символните променливи:
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> y = Symbol('y')
Отляво е променливата, на която задаваме като стойност инстанция на SymPy класа Symbol. Инстанциите на този клас могат да се комбинират и да направят израз:
>>> from sympy.abc import x, theta
Symbols can also be created with the symbols or var functions, the latter automatically adding the created symbols to the namespace, and both accepting a range notation:
>>> 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)
Инстанциите на този клас могат да се комбинират и да направят израз:
>>> x + y + x - y
2*x
>>> (x + y)**2
(x + y)**2
>>> ((x + y)**2).expand()
x**2 + 2*x*y + y**2
И да ги замествате с други символи или числа като използвате subs(old, new):
>>> ((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
До края на този урок предполагаме, че сте изпълнили следния код:
>>> from sympy import init_printing
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
Това ще направи нещата да изглеждат по-добре, когато се принтират (pretty printing). Погледнете секцията за принтиране по-нататък. Ако имате инсталиран някой unicode шрифт, може да подадете use_unicode=True за доста по-красив изход.
За да разложите непълни дроби, използвайте apart(expr, x):
>>> 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
За да комбинирате нещата отново заедно, използвайте 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)
Границите са изключително лесни за използване в SymPy. Те имат следния синтаксис limit(function, variable, point), така че за да изчислите границата на f(x), където x -> 0 бихте използвали limit(f, x, 0):
>>> from sympy import limit, Symbol, sin, oo
>>> x = Symbol("x")
>>> limit(sin(x)/x, x, 0)
1
също така може да изчислите граница до безкрайност:
>>> limit(x, x, oo)
oo
>>> limit(1/x, x, oo)
0
>>> limit(x**x, x, 0)
1
За някои не толкова тривиални примери, може да прегледате тестовия файл test_demidovich.py
Може да изчислите производните на който и да е израз в SymPy, като използвате diff(func, var). Примери:
>>> 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
Можете да проверите, че е правилно, като:
>>> from sympy import limit
>>> from sympy.abc import delta
>>> limit((tan(x + delta) - tan(x))/delta, delta, 0)
2
tan (x) + 1
Производни от по-висок ред могат да бъдат пресметнати чрез използването на метода diff(func, var, n) :
>>> 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)
Използвайте метода .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
Друг прост пример:
>>> 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 поддръжа определени и неопределени интеграли на елементарни и специални трансцедентни функции с помощта на integrate(), който използва мощния разширен алгоритъм на Risch-Norman и няколко еврестики и сравнения с шаблони:
>>> from sympy import integrate, erf, exp, sin, log, oo, pi, sinh, symbols
>>> x, y = symbols('x,y')
Можете да декларирате елементарни функции:
>>> 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)
Лесно можете да се справите и със специалните функции:
>>> integrate(exp(-x**2)*erf(x), x)
____ 2
\/ pi *erf (x)
--------------
4
Възможно е да изчислите даден интеграл:
>>> integrate(x**3, (x, -1, 1))
0
>>> integrate(sin(x), (x, 0, pi/2))
1
>>> integrate(cos(x), (x, -pi/2, pi/2))
2
Също така се поддържат и неопределени интеграли:
>>> integrate(exp(-x), (x, 0, oo))
1
>>> integrate(log(x), (x, 0, 1))
-1
Besides the imaginary unit, I, which is imaginary, symbols can be created with attributes (e.g. real, positive, complex, etc...) and this will affect how they behave:
>>> 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)
тригонометрични
>>> 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
сферични хармонични
>>> 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
факториел и гама функции
>>> 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/
дзета функции
>>> 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
полиноми
>>> 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
В 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)
В 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}
Матриците се създават като инстанции на Matrix класа:
>>> from sympy import Matrix, Symbol
>>> Matrix([[1, 0], [0, 1]])
[1 0]
[ ]
[0 1]
също така може да слагате символи в тях:
>>> 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]
За повече информация и примери с матрици вижте Linear Algebra tutorial.
Използвайте .match() метода заедно с класа Wild за да сравнявате изрази с даден шаблон. Методът ще върне речник с изисканите замествания, както следва:
>>> 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}
Ако съвпадението е неуспешно, методът връща None:
>>> print (x + 1).match(p**x)
None
Можете да използвате и втория незадължителен параметър exclude, за да се уверите, че някои неща не се появяват в резултата:
>>> 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}
Има много начини, по които изразите може да се отпечатат.
Стандартен начин
Това е резултатът от str(expression) и изглежда така:
>>> 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)
Красиво отпечатване (pretty printing)
Това е хубаво отпечатване тип ascii-art, направено от pprint функция:
>>> 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
|
/
Ако имате инсталиран unicode шрифт, то той би трябвало да бъде използван по подразбиране. Може смените това поведение, като използвате опцията use_unicode.:
>>> pprint(Integral(x**2, x), use_unicode=True)
⌠
⎮ 2
⎮ x dx
⌡
Също така вижте уикито Pretty Printing за повече примери за добро unicode принтиране.
Съвет:За да направите красивото отпечатване(pretty printing) по подразбиране в интерпретатора на Python, използвайте:
$ 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 отпечатване
>>> 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 отпечатване
>>> 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))
И pyglet прозорец с LaTeX рендиран израз ще се появи:
isympy извиква pprint автоматично, поради тази причина виждате красивото отпечатване (pretty printing) по подразбиране.
Забележете, че също така има модул за принтиране, sympy.printing. Други методи за принтиране, налични чрез този модул, са:
Време е да научите повече за SymPy. Прегледайте SymPy User’s Guide и SymPy Modules Reference.
Не пропускайте и да прегледате нашето публично уики – wiki.sympy.org, което съдържа много полезни примери, уроци и наръчници, за които ние и нашите потребители допринасяме и Ви окуражаваме да редактирате и подобрите.
This tutorial is also available in other languages: