Урок

Въведение

SymPy е библиотека на Python за символна математика. Тя цели да стане пълнофункционална алгебрична система (CAS - computer algebra system), като поддържа кода възможно най-опростен с цел да бъде разбираем и лесен за разширяване.SymPy е изцяло написана на Python и не изисква външни библиотеки.

Този урок е въведение към SymPy. Прочетете го, за да научите какво и как може SymPy, и ако искате да научите повече, прочетете SymPy User’s Guide, SymPy Modules Reference, или сорс код директно.

Първи стъпки със SymPy

Най-лесният начин да свалите SymPy е да отидете на http://code.google.com/p/sympy/ и да изтеглите последния архив.

../_images/featured-downloads.png

Разархивирайте го:

$ 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.

isympy Конзола

За да експериментирате с нови функционалности или когато се опитвате да разберете как да направите нещата, може да използвате нашата специална обвивка около 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 като калкулатор

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

Summation

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 рендиран израз ще се появи:

../_images/pngview1.png

Бележки

isympy извиква pprint автоматично, поради тази причина виждате красивото отпечатване (pretty printing) по подразбиране.

Забележете, че също така има модул за принтиране, sympy.printing. Други методи за принтиране, налични чрез този модул, са:

  • pretty(expr), pretty_print(expr), pprint(expr): Връща или принтира, съответно, красива репрезентация на expr. Това е еквивалентно на второто ниво на репрезентация показано по-горе.
  • latex(expr), print_latex(expr): Връща или принтира, съответно, LaTeX репрезентация на expr
  • mathml(expr), print_mathml(expr): Връща или принтира, съответно, MathML репрезентация на expr.
  • print_gtk(expr): Print expr to Gtkmathview, a GTK widget that displays MathML code. The Gtkmathview program is required.

Допълнителна документация

Време е да научите повече за SymPy. Прегледайте SymPy User’s Guide и SymPy Modules Reference.

Не пропускайте и да прегледате нашето публично уики – wiki.sympy.org, което съдържа много полезни примери, уроци и наръчници, за които ние и нашите потребители допринасяме и Ви окуражаваме да редактирате и подобрите.

Translations

This tutorial is also available in other languages: