Sympy possède trois types numériques : Real, Rational et Integer.
La classe Rational représente un nombre rationnel sous forme de deux Integer (numérateur et dénominateur) : Rational(1,2) represente 1/2.
>>> from sympy import * >>> a = Rational(1,2) >>> a 1/2 >>> a*2 1 >>> Rational(2)**50/Rational(10)**50 1/88817841970012523233890533447265625
A manipuler avec les entiers de python en faisant attention (la division y est entière, jusqu'à python 3k).
Les constantes e et pi, et d'autres, existent dans sympy, sont traitées comme des symboles (1+pi ne sera pas évalué, à moins de le demander explicitement), et ont une précision arbitraire :
>>> pi**2 pi**2
evalf permet d'évaluer ces constantes.
>>> pi.evalf() 3.141592653589793238462643383 >>> (pi+exp(1)).evalf() 5.859874482049203234066343309
L'infini mathématique existe dans sympy. Il est représenté par oo :
>>> from sympy import * >>> oo > 99999 True >>> oo + 1 oo
A la différence des autres CAS (Computer Algebra Systems), les variables symboliques doivent être déclarées explicitement avec SymPy :
>>> from sympy import * >>> x = Symbol('x') >>> y = Symbol('y')
On peut alors faire du calcul algébrique avec :
>>> x+y+x-y 2*x
La méthode expand permet de développer des expressions algébriques :
>>> (x+y)**2 (x+y)**2 >>> ((x+y)**2).expand() 2*x*y+x**2+y**2
On peut remplacer des variables par leurs valeurs, ou d'autres variables, dans des expressions algébriques :
>>> ((x+y)**2).subs(x, 1) (1+y)**2 >>> ((x+y)**2).subs(x, y) 4*y**2
On peut résoudre des équations avec sympy, par exemple l'équation en x : x<sup>4</sup>-1=0.
>>> from sympy import * >>> solve(x**4 - 1, x) [I, 1, -1, -I]
Ainsi que des systèmes d'équations :
>>> solve([x + 5*y - 2, -3*x + 6*y - 15], [x, y]) {y: 1, x: -3}
On peut décomposer une fraction rationnelle, ou la factoriser :
>>> from sympy.simplify.rewrite import apart, together >>> from sympy.abc import x,y,z >>> apart(1/( (x+2)*(x+1) ), x) 1/(1 + x) - 1/(2 + x) >>> apart((x+1)/(x-1), x) 1 - 2/(1 - x) >>> together(1/x + 1/y + 1/z) 1/x/y/z*(x*y + x*z + y*z)
Pour faire une matrice avec sympy, plusieurs possibilités :
>>> from sympy import Matrix >>> Matrix([ [1,0], [0,1] ]) [1 0] [0 1] >>> Matrix(2, 3, [1, 2, 3, 4, 5, 6]) ⎡1 2 3⎤ ⎣4 5 6⎦
On peut aussi dresser la liste de ses éléments, puis redimensionner la matrice avec la méthode reshape :
>>> M = Matrix((-3,-3,18,1,2,3)).reshape(3,2) >>> M [-3, -3] [18, 1] [ 2, 3]
Enfin, pour accéder à un élément :
>>> M[0,0] 1
On peut aussi la remplir de variables symboliques
>>> x = Symbol('x') >>> y = Symbol('y') >>> A = Matrix([ [1,x], [y,1] ]) >>> A**2 [1+x*y 2*x] [2*y 1+x*y]
On peut enfin utiliser une fonction pour la remplir :
>>> def f(i,j): ... if i == j: ... return 1 ... else: ... return 0 ... >>> Matrix(4, 4, f) ⎡1 0 0 0⎤ ⎢0 1 0 0⎥ ⎢0 0 1 0⎥ ⎣0 0 0 1⎦ >>> Matrix(3, 4, lambda i,j: 1 - (i+j) % 2) ⎡1 0 1 0⎤ ⎢0 1 0 1⎥ ⎣1 0 1 0⎦
Pour la matrice identité, utilisez eye
>>> eye(4) ⎡1 0 0 0⎤ ⎢0 1 0 0⎥ ⎢0 0 1 0⎥ ⎣0 0 0 1⎦
Utilisez zeros pour la matrice nulle carrée, et zeronm pour la rectangulaire
>>> zero(2) ⎡0 0⎤ ⎣0 0⎦ >>> zeronm(2,5) ⎡0 0 0 0 0⎤ ⎣0 0 0 0 0⎦
Ones permet de créer une matrice de uns :
>>> ones(3) [1, 1, 1] [1, 1, 1] [1, 1, 1]
Enfin, on peut créer une matrice aléatoire comme suit :
>>> randMatrix(3,4,min=0, max=5) [3, 4, 4, 5] [3, 5, 0, 5] [1, 4, 5, 2]
Ici, la matrice générée est constituée d'entiers. Il faudra la diviser terme à terme pour obtenir des réels. Les arguments min et max sont optionnels, et fixés respectivement à 0 et 100 par défaut. Notons, pour finir, qu'il est possible de fournir la graine (argument seed) de génération des nombres pseudo-aléatoires.
Considérons les deux matrices suivantes :
>>> A = Matrix([[1,2,3],[4,5,6],[7,8,9]]) >>> B = Matrix([[1,2,1],[2,1,2],[1,1,1]])
On a accès aux opérations matricielles élémentaires : somme et multiplication matricielle, multiplication par un scalaire...
>>> A+B [2, 4, 4] [6, 6, 8] [8, 9, 10] >>> A*B [ 8, 7, 8] [20, 19, 20] [32, 31, 32] >>> 0.5*A [0.5, 1, 1.5] [2.0, 2.5, 3.0] [3.5, 4.0, 4.5] >>> A/2 [1/2, 1, 3/2] [ 2, 5/2, 3] [7/2, 4, 9/2]
On a encore la possibilité de transposer les matrices, ou d'en calculer leur trace :
>>> A [1, 2, 3] [4, 5, 6] [7, 8, 9] >>> A.T [1, 4, 7] [2, 5, 8] [3, 6, 9] >>> A.trace() 15
On peut directement calculer une inverse de matrice, un déterminant :
>>> A [1, 2, 3] [4, 5, 6] [7, 8, 1] >>> A.det() 24 >>> A.inv() [-43/24, 11/12, -1/8] [ 19/12, -5/6, 1/4] [ -1/8, 1/4, -1/8]
La différence entre calcul numérique et formel apparaît : on n'a pas ici une valeur approchée de $A^{-1}$, mais une valeur exacte. On peut aller un peu plus loin :
>>> A*A.inv() [1, 0, 0] [0, 1, 0] [0, 0, 1] >>> A*A.inv()==eye(3) True
Pour supprimer la ligne $i$ et la colonne $j$ d'une matrice $M$, on utilise la commande $M.minorMatrix(i,j)$ :
>>> M [2, 12, -3] [1, -6, -3] [2, 0, 18] >>> M.minorMatrix(1,2) [2, 12] [2, 0]
Pour récupérer toute une ligne, ou toute une colonne, on peut utiliser le symbole :...
>>> M [2, 12, -3] [1, -6, -3] [2, 0, 18] >>> M[:,2] [-3] [-3] [18] >>> M[1,:] [1, -6, -3]
Cela convient aussi si l'on souhaite récupérer plusieurs lignes, ou plusieurs colonnes :
>>> M[:2,:] [2, 12, -3] [1, -6, -3]
Soit le bout de code suivant :
>>> from sympy import * >>> M = Matrix([[1,4,3],[1,-2,1],[0,1,3]]) >>> M [1, 4, 3] [1, -2, 1] [0, 1, 3] >>> (L,U,row) = M.LUdecomposition() >>> L [1, 0, 0] [1, 1, 0] [0, -1/6, 1] >>> U [1, 4, 3] [0, -6, -2] [0, 0, 8/3] >>> L*U [1, 4, 3] [1, -2, 1] [0, 1, 3]
On voit que L et U ont bien la forme souhaitée, et que leur produit donne bien M.
Définissons une matrice $M$ qui possède bien une décomposition QR, c'est-à-dire qui est bien inversible (déterminant non nul) :
>>> M [2, 12, -3] [1, -6, -3] [2, 0, 18] >>> M.det() -540
Pour obtenir la décomposition QR de $M$, on utilise la méthode QRdecomposition :
>>> (Q,R) = M.QRdecomposition() >>> Q [2/3, 2/3, -1/3] [1/3, -2/3, -2/3] [2/3, -1/3, 2/3] >>> R [3, 6, 9] [0, 12, -6] [0, 0, 15]
$R$ est bien une matrice triangulaire supérieure à coefficients diagonaux strictement positifs. Vérifions que $Q$ est bien orthogonale (c'est-à-dire que $Q^{-1} est égale à la transposée de $Q$) :
>>> Q.inv() [ 2/3, 1/3, 2/3] [ 2/3, -2/3, -1/3] [-1/3, -2/3, 2/3] >>> Q.T [ 2/3, 1/3, 2/3] [ 2/3, -2/3, -1/3] [-1/3, -2/3, 2/3]
C'est le cas. Dernière chose : $Q \times R$ est bien égale à $M$ :
>>> Q*R [2, 12, -3] [1, -6, -3] [2, 0, 18] >>> Q*R == M True
Les vecteurs sont des matrices ayant une seule colonne, ils se créent donc comme les matrices.
>>> B1 = Matrix((2,1,2)).reshape(3,1) >>> B1 [2] [1] [2] >>> B2 = Matrix((12,-6,0)).reshape(3,1) >>> B2 [12] [-6] [ 0]
On peut fusionner des vecteurs pour former des matrices plus grandes :
>>> M=B1.row_join(B2) >>> M [2, 12] [1, -6] [2, 0]
Il existe aussi col_join pour joindre les colonnes, et la même chose pour la suppression de lignes/colonnes :
>>> M [2, 12] [1, -6] [2, 0] >>> M.col_del(1) >>> M [2] [1] [2]
Voici comment calculer la norme et le produit scalaire d'un vecteur : en utilisant respectivement les méthodes norm et dot...
>>> V = Matrix((-3,-3,18)).reshape(3,1) >>> V [-3] [-3] [18] >>> V.norm() 3*38**(1/2) >>> pprint(V.norm()) ⎽⎽⎽⎽ 3⋅╲╱ 38 >>> U = Matrix((1,3,8)).reshape(3,1) >>> U.dot(V) 132
Voici comment procéder pour résoudre le système $\left\{ \begin{array}{rll} x + 4 y & = & 2 \\ -2 x + y & = & 14\end{array}\right.$
On introduit les variables $x$ et $y$, après avoir importé la bibliothèque sympy :
>>> from sympy import * >>> x, y = symbols('xy')
On pose le système, puis on le résout :
>>> system = Matrix(( (1, 4, 2), (-2, 1, 14))) >>> solve_linear_system(system, x, y) {x: -6, y: 2}