<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Calcul symbolique en Python
Step1:  Introduction
Ce notebook est la traduction française du cours sur SymPy disponible entre autre sur Wakari avec quelques modifications et compléments notamment pour la résolution d'équations différentielles. Il a pour but de permettre aux étudiants de différents niveaux d'expérimenter des notions mathématiques en leur fournissant une base de code qu'ils peuvent modifier.
SymPy - est un module Python qui peut être utilisé dans un programme Python ou dans une session IPython. Il fournit de puissantes fonctionnalités de calcul symbolique.
Pour commencer à utiliser SymPy dans un programme ou un notebook Python, importer le module sympy
Step2:  Pour obtenir des sorties mathématiques formatées $\LaTeX$ 
Step3:  Variables symboliques
Dans SymPy on a besoin de créer des symboles pour les variables qu'on souhaite employer. Pour cela on utilise la class Symbol
Step4:  On peut ajouter des contraintes sur les symboles lors de leur création 
Step5:  Nombres complexes
L'unité imaginaire est notée I dans Sympy.
Step6:  Nombres rationnels
Il y a trois types numériques différents dans SymPy 
Step7:  Evaluation numérique
SymPy permet une précision arbitraire des évaluations numériques et fournit des expressions pour quelques constantes comme 
Step8:  Quand on évalue des expressions algébriques on souhaite souvent substituer un symbole par une valeur numérique. Dans SymPy cela s'effectue par la fonction subs 
Step9:  La fonction subs permet de substituer aussi des symboles et des expressions 
Step10:  On peut aussi combiner l'évolution d'expressions avec les tableaux de NumPy (pour tracer une fonction par ex) 
Step11:  Manipulations algébriques
Une des principales utilisations d'un système de calcul symbolique est d'effectuer des manipulations algébriques d'expression. Il est possible de développer un produit ou bien de factoriser une expression. Les fonctions pour réaliser ces opérations de bases figurent dans les exemples des sections suivantes.
Développer et factoriser
Les premiers pas dans la manipulation algébrique
Step12:  La fonction expand (développer) prend des mots clés en arguments pour indiquer le type de développement à réaliser. Par exemple pour développer une expression trigonomètrique on utilise l'argument trig=True 
Step13:  Lancer help(expand) pour une explication détaillée des différents types de développements disponibles.
L'opération opposée au développement est bien sur la factorisation qui s'effectue grâce à la fonction factor 
Step14:  Simplify
The simplify tries to simplify an expression into a nice looking expression, using various techniques. More specific alternatives to the simplify functions also exists
Step15:  simplify permet aussi de tester l'égalité d'expressions 
Step16:  apart and together
Pour manipuler des expressions numériques de fractions on dispose des fonctions apart and together 
Step17:  Simplify combine les fractions mais ne factorise pas 
Step18:  Calcul
En plus des manipulations algébriques, l'autre grande utilisation d'un système de calcul symbolique et d'effectuer des calculs comme des dérivées et intégrales d'expressions algébriques.
Dérivation
La dérivation est habituellement simple. On utilise la fonction  diff avec pour premier argument l'expression à dériver et comme second le symbole de la variable suivant laquelle dériver 
Step19:  Dérivée première
Step20:  Pour des dérivées d'ordre supérieur 
Step21:  Pour calculer la dérivée d'une expression à plusieurs variables 
Step22:  $\frac{d^3f}{dxdy^2}$
Step23:  Integration
L'intégration est réalisée de manière similaire 
Step24:  En fournissant des limites pour la variable d'intégration on peut évaluer des intégrales définies 
Step25:  et aussi des intégrales impropres pour lesquelles on ne connait pas de primitive
Step26:  Rappel, oo est la notation SymPy pour l'infini.
Sommes et produits
On peut évaluer les sommes et produits d'expression avec les fonctions Sum et Product 
Step27:  Les produits sont calculés de manière très semblables 
Step28:  Limites
Les limites sont évaluées par la fonction limit. Par exemple 
Step29:  On peut changer la direction d'approche du point limite par l'argument du mot clé dir 
Step30:  Séries
Le développement en série est une autre fonctionnalité très utile d'un système de calcul symbolique. Dans SymPy on réalise les développements en série grâce à la fonction series 
Step31:  Par défaut le développement de l'expression s'effectue au voisinage de $x=0$, mais on peut développer la série au voisinage de toute autre valeur de $x$ en incluant explicitement cette valeur lors de l'appel à la fonction 
Step32:  Et on peut explicitement définir jusqu'à quel ordre le développement doit être mené 
Step33:  Le développement en séries inclue l'ordre d'approximation. Ceci permet de gérer l'ordre du résultat de calculs utilisant des développements en séries d'ordres différents 
Step34:  Si on ne souhaite pas afficher l'ordre on utilise la méthode removeO 
Step35:  Mais cela conduit à des résultats incorrects pour des calculs avec plusieurs développements 
Step36:  Plus sur les séries
https
Step37:  Avec les instances de la classe Matrix on peut faire les opérations algébriques classiques 
Step38:  Et calculer les déterminants et inverses 
Step39:  Résolution d'équations
Pour résoudre des équations et des systèmes d'équations on utilise la fonction solve 
Step40:  Système d'équations 
Step41:  En termes d'autres expressions symboliques 
Step42:  Résolution d'équations différentielles
Pour résoudre des équations diférentielles et des systèmes d'équations différentielles on utilise la fonction dsolve 
Step43:  Exemple d'équation différentielle du 2e ordre
Step44:  SymPy ne sait pas résoudre cette equation différentielle non linéaire avec $h(x)^2$ 
Step45:  On peut résoudre cette équation différentielle avec une méthode numérique fournie par la fonction odeint de SciPy 
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
Explanation: Calcul symbolique en Python
End of explanation
from sympy import *
Explanation: Introduction
Ce notebook est la traduction française du cours sur SymPy disponible entre autre sur Wakari avec quelques modifications et compléments notamment pour la résolution d'équations différentielles. Il a pour but de permettre aux étudiants de différents niveaux d'expérimenter des notions mathématiques en leur fournissant une base de code qu'ils peuvent modifier.
SymPy - est un module Python qui peut être utilisé dans un programme Python ou dans une session IPython. Il fournit de puissantes fonctionnalités de calcul symbolique.
Pour commencer à utiliser SymPy dans un programme ou un notebook Python, importer le module sympy:
End of explanation
from sympy import init_printing
init_printing(use_latex=True)
Explanation: Pour obtenir des sorties mathématiques formatées $\LaTeX$ :
End of explanation
x = Symbol('x')
(pi + x)**2
# manière alternative de définir plusieurs symboles en une seule instruction
a, b, c = symbols("a, b, c")
Explanation: Variables symboliques
Dans SymPy on a besoin de créer des symboles pour les variables qu'on souhaite employer. Pour cela on utilise la class Symbol:
End of explanation
x = Symbol('x', real=True)
x.is_imaginary
x = Symbol('x', positive=True)
x > 0
Explanation: On peut ajouter des contraintes sur les symboles lors de leur création :
End of explanation
1+1*I
I**2
(1 + x * I)**2
Explanation: Nombres complexes
L'unité imaginaire est notée I dans Sympy.
End of explanation
r1 = Rational(4,5)
r2 = Rational(5,4)
r1
r1+r2
r1/r2
Explanation: Nombres rationnels
Il y a trois types numériques différents dans SymPy : Real (réel), Rational (rationnel), Integer (entier) :
End of explanation
pi.evalf(n=50)
E.evalf(n=4)
y = (x + pi)**2
N(y, 5) # raccourci pour evalf
Explanation: Evaluation numérique
SymPy permet une précision arbitraire des évaluations numériques et fournit des expressions pour quelques constantes comme : pi, E, oo pour l'infini.
Pour évaluer numériquement une expression nous utilisons la fonction evalf (ou N). Elle prend un argument n qui spécifie le nombre de chiffres significatifs.
End of explanation
y.subs(x, 1.5)
N(y.subs(x, 1.5))
Explanation: Quand on évalue des expressions algébriques on souhaite souvent substituer un symbole par une valeur numérique. Dans SymPy cela s'effectue par la fonction subs :
End of explanation
y.subs(x, a+pi)
Explanation: La fonction subs permet de substituer aussi des symboles et des expressions :
End of explanation
import numpy
x_vec = numpy.arange(0, 10, 0.1)
y_vec = numpy.array([N(((x + pi)**2).subs(x, xx)) for xx in x_vec])
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(x_vec, y_vec);
Explanation: On peut aussi combiner l'évolution d'expressions avec les tableaux de NumPy (pour tracer une fonction par ex) :
End of explanation
(x+1)*(x+2)*(x+3)
expand((x+1)*(x+2)*(x+3))
Explanation: Manipulations algébriques
Une des principales utilisations d'un système de calcul symbolique est d'effectuer des manipulations algébriques d'expression. Il est possible de développer un produit ou bien de factoriser une expression. Les fonctions pour réaliser ces opérations de bases figurent dans les exemples des sections suivantes.
Développer et factoriser
Les premiers pas dans la manipulation algébrique
End of explanation
sin(a+b)
expand(sin(a+b), trig=True)
sin(a+b)**3
expand(sin(a+b)**3, trig=True)
Explanation: La fonction expand (développer) prend des mots clés en arguments pour indiquer le type de développement à réaliser. Par exemple pour développer une expression trigonomètrique on utilise l'argument trig=True :
End of explanation
factor(x**3 + 6 * x**2 + 11*x + 6)
x1, x2 = symbols("x1, x2")
factor(x1**2*x2 + 3*x1*x2 + x1*x2**2)
Explanation: Lancer help(expand) pour une explication détaillée des différents types de développements disponibles.
L'opération opposée au développement est bien sur la factorisation qui s'effectue grâce à la fonction factor :
End of explanation
# simplify expands a product
simplify((x+1)*(x+2)*(x+3))
# simplify uses trigonometric identities
simplify(sin(a)**2 + cos(a)**2)
simplify(cos(x)/sin(x))
Explanation: Simplify
The simplify tries to simplify an expression into a nice looking expression, using various techniques. More specific alternatives to the simplify functions also exists: trigsimp, powsimp, logcombine, etc. 
The basic usages of these functions are as follows:
End of explanation
exp1 = sin(a+b)**3
exp2 = sin(a)**3*cos(b)**3 + 3*sin(a)**2*sin(b)*cos(a)*cos(b)**2 + 3*sin(a)*sin(b)**2*cos(a)**2*cos(b) + sin(b)**3*cos(a)**3
simplify(exp1 - exp2)
if simplify(exp1 - exp2) == 0:
    print "{0} = {1}".format(exp1, exp2)
else:
    print "exp1 et exp2 sont différentes"
Explanation: simplify permet aussi de tester l'égalité d'expressions :
End of explanation
f1 = 1/((a+1)*(a+2))
f1
apart(f1)
f2 = 1/(a+2) + 1/(a+3)
f2
together(f2)
Explanation: apart and together
Pour manipuler des expressions numériques de fractions on dispose des fonctions apart and together :
End of explanation
simplify(f2)
Explanation: Simplify combine les fractions mais ne factorise pas :
End of explanation
y
Explanation: Calcul
En plus des manipulations algébriques, l'autre grande utilisation d'un système de calcul symbolique et d'effectuer des calculs comme des dérivées et intégrales d'expressions algébriques.
Dérivation
La dérivation est habituellement simple. On utilise la fonction  diff avec pour premier argument l'expression à dériver et comme second le symbole de la variable suivant laquelle dériver :
End of explanation
diff(y**2, x)
Explanation: Dérivée première
End of explanation
diff(y**2, x, x) # dérivée seconde
diff(y**2, x, 2) # dérivée seconde avec une autre syntaxe
Explanation: Pour des dérivées d'ordre supérieur :
End of explanation
x, y, z = symbols("x,y,z")
f = sin(x*y) + cos(y*z)
Explanation: Pour calculer la dérivée d'une expression à plusieurs variables :
End of explanation
diff(f, x, 1, y, 2)
Explanation: $\frac{d^3f}{dxdy^2}$
End of explanation
f
integrate(f, x)
Explanation: Integration
L'intégration est réalisée de manière similaire :
End of explanation
integrate(f, (x, -1, 1))
Explanation: En fournissant des limites pour la variable d'intégration on peut évaluer des intégrales définies :
End of explanation
x_i = numpy.arange(-5, 5, 0.1)
y_i = numpy.array([N((exp(-x**2)).subs(x, xx)) for xx in x_i])
fig2, ax2 = plt.subplots()
ax2.plot(x_i, y_i)
ax2.set_title("$e^{-x^2}$")
integrate(exp(-x**2), (x, -oo, oo))
Explanation: et aussi des intégrales impropres pour lesquelles on ne connait pas de primitive
End of explanation
n = Symbol("n")
Sum(1/n**2, (n, 1, 10))
Sum(1/n**2, (n,1, 10)).evalf()
Sum(1/n**2, (n, 1, oo)).evalf()
N(pi**2/6) # fonction zeta(2) de Riemann
Explanation: Rappel, oo est la notation SymPy pour l'infini.
Sommes et produits
On peut évaluer les sommes et produits d'expression avec les fonctions Sum et Product :
End of explanation
Product(n, (n, 1, 10)) # 10!
Explanation: Les produits sont calculés de manière très semblables :
End of explanation
limit(sin(x)/x, x, 0)
Explanation: Limites
Les limites sont évaluées par la fonction limit. Par exemple :
End of explanation
limit(1/x, x, 0, dir="+")
limit(1/x, x, 0, dir="-")
Explanation: On peut changer la direction d'approche du point limite par l'argument du mot clé dir :
End of explanation
series(exp(x), x)
Explanation: Séries
Le développement en série est une autre fonctionnalité très utile d'un système de calcul symbolique. Dans SymPy on réalise les développements en série grâce à la fonction series :
End of explanation
series(exp(x), x, 1)
Explanation: Par défaut le développement de l'expression s'effectue au voisinage de $x=0$, mais on peut développer la série au voisinage de toute autre valeur de $x$ en incluant explicitement cette valeur lors de l'appel à la fonction :
End of explanation
series(exp(x), x, 1, 10)
Explanation: Et on peut explicitement définir jusqu'à quel ordre le développement doit être mené :
End of explanation
s1 = cos(x).series(x, 0, 5)
s1
s2 = sin(x).series(x, 0, 2)
s2
expand(s1 * s2)
Explanation: Le développement en séries inclue l'ordre d'approximation. Ceci permet de gérer l'ordre du résultat de calculs utilisant des développements en séries d'ordres différents :
End of explanation
expand(s1.removeO() * s2.removeO())
Explanation: Si on ne souhaite pas afficher l'ordre on utilise la méthode removeO :
End of explanation
(cos(x)*sin(x)).series(x, 0, 6)
Explanation: Mais cela conduit à des résultats incorrects pour des calculs avec plusieurs développements :
End of explanation
m11, m12, m21, m22 = symbols("m11, m12, m21, m22")
b1, b2 = symbols("b1, b2")
A = Matrix([[m11, m12],[m21, m22]])
A
b = Matrix([[b1], [b2]])
b
Explanation: Plus sur les séries
https://fr.wikipedia.org/wiki/D%C3%A9veloppement_limit%C3%A9 - Article de Wikipedia.
Algèbre linéaire
Matrices
Les matrices sont définies par la classe Matrix :
End of explanation
A**2
A * b
Explanation: Avec les instances de la classe Matrix on peut faire les opérations algébriques classiques :
End of explanation
A.det()
A.inv()
Explanation: Et calculer les déterminants et inverses :
End of explanation
solve(x**2 - 1, x)
solve(x**4 - x**2 - 1, x)
expand((x-1)*(x-2)*(x-3)*(x-4)*(x-5))
solve(x**5 - 15*x**4 + 85*x**3 - 225*x**2 + 274*x - 120, x)
Explanation: Résolution d'équations
Pour résoudre des équations et des systèmes d'équations on utilise la fonction solve :
End of explanation
solve([x + y - 1, x - y - 1], [x,y])
Explanation: Système d'équations :
End of explanation
solve([x + y - a, x - y - c], [x,y])
Explanation: En termes d'autres expressions symboliques :
End of explanation
from sympy import Function, dsolve, Eq, Derivative, sin, cos, symbols
from sympy.abc import x
Explanation: Résolution d'équations différentielles
Pour résoudre des équations diférentielles et des systèmes d'équations différentielles on utilise la fonction dsolve :
End of explanation
f = Function('f')
dsolve(Derivative(f(x), x, x) + 9*f(x), f(x))
dsolve(diff(f(x), x, 2) + 9*f(x), f(x), hint='default', ics={f(0):0, f(1):10})
# Essai de récupération de la valeur de la constante C1 quand une condition initiale est fournie
eqg = Symbol("eqg")
g = Function('g')
eqg = dsolve(Derivative(g(x), x) + g(x), g(x), ics={g(2): 50})
eqg
print "g(x) est de la forme {}".format(eqg.rhs)
# recherche manuelle de la valeur de c1 qui vérifie la condition initiale
c1 = Symbol("c1")
c1 = solve(Eq(c1*E**(-2),50), c1)
print c1
Explanation: Exemple d'équation différentielle du 2e ordre
End of explanation
h = Function('h')
try:
    dsolve(Derivative(h(x), x) + 0.001*h(x)**2 - 10, h(x))
except:
    print "une erreur s'est produite"
Explanation: SymPy ne sait pas résoudre cette equation différentielle non linéaire avec $h(x)^2$ :
End of explanation
from scipy.integrate import odeint
def dv_dt(vec, t, k, m, g):
    z, v = vec[0], vec[1]
    dz = -v
    dv = -k/m*v**2 + g
    return [dz, dv]
vec0 = [0, 0] # conditions initiales [altitude, vitesse]
t_si = numpy.linspace (0, 30 ,150) # de 0 à 30 s, 150 points
k = 0.1 # coefficient aérodynamique
m = 80 # masse (kg)
g = 9.81 # accélération pesanteur (m/s/s)
v_si = odeint(dv_dt, vec0, t_si, args=(k, m, g))
print "vitesse finale : {0:.1f} m/s soit {1:.0f} km/h".format(v_si[-1, 1], v_si[-1, 1] * 3.6)
fig_si, ax_si = plt.subplots()
ax_si.set_title("Vitesse en chute libre")
ax_si.set_xlabel("s")
ax_si.set_ylabel("m/s")
ax_si.plot(t_si, v_si[:,1], 'b')
Explanation: On peut résoudre cette équation différentielle avec une méthode numérique fournie par la fonction odeint de SciPy :
Méthode numérique pour équations différentielles (non SymPy)
End of explanation
<END_TASK>