from __future__ import division, print_function  # Python 3

"""
Explanation: $$
\def\CC{\bf C}
\def\QQ{\bf Q}
\def\RR{\bf R}
\def\ZZ{\bf Z}
\def\NN{\bf N}
$$
Calcul symbolique
End of explanation
"""


from math import sqrt
sqrt(3)

"""
Explanation: En Python, la fonction sqrt retourne un résultat approximé sur les nombres flottants:
End of explanation
"""


from sympy import sqrt
sqrt(3)

"""
Explanation: La racine de 3 ne peut pas être écrite exactement avec un nombre fini de décimales, car c'est un nombre irrationel. La façon la plus exacte d'exprimer la racine (positive) du nombre trois est de l'écrire tel quel. En SymPy, la racine carrée de 3 est exprimée symboliquement:
End of explanation
"""


sqrt(4)

sqrt(8)

"""
Explanation: Quand c'est possible, SymPy procède à des simplifications:
End of explanation
"""


from sympy import Symbol
a = Symbol("a")     # le symbole a est stocké dans la variable a
a

"""
Explanation: Variable symbolique
La fonction Symbol de SymPy permet de créer une variable symbolique:
End of explanation
"""


a + a + a + a * a + 1/a - a

"""
Explanation: Cette variable peut être additionnée, soustraite, multipliée et divisée:
End of explanation
"""


from sympy.abc import a, epsilon
a + a * a + epsilon

"""
Explanation: Pour plus de commodité, on peut importer les variables les plus souvent utilisées du sous-module abc :
End of explanation
"""


from sympy import symbols
x4,x5,x6,x7,x8 = symbols("x4:9")
x4 + x5 + x6 + x7 + x8

"""
Explanation: Définir les variables symboliques x_1, x_2, ..., x_n
En SymPy, on peut créer plusieurs variables $x_i$ indicées pour $i=a,...,b-1$ à l'aide de la fonction symbols("xa:b") où a et b sont remplacés par des nombres entiers:
End of explanation
"""


from sympy import init_printing
init_printing(use_latex='mathjax')

"""
Explanation: Affichage automatique des résultats en LaTeX
Pour que les résultats soient affichés en LaTeX automatiquement, il suffit d'utiliser la commande suivante une seule fois pour le fichier:
End of explanation
"""


from sympy.abc import a, epsilon
a + a * a + epsilon

"""
Explanation: Dans le notebook Jupyter, cette commande utilise la librairie MathJax.
<img src="images/jupyter_mathjax.png" alt="image" width="566" />
Dans ces notes, on utilisera l'option init_printing(use_latex='mathjax', use_unicode=False) lorsque cela aide la lecture des formules. Pour un exemple de la section précédente, on obtient:
End of explanation
"""


from sympy.abc import a,b
(a + b)**2

"""
Explanation: Expressions symboliques
On peut faire des calculs impliquant plus d'une variable:
End of explanation
"""


from sympy import sin,cos
sin(a)**2 + cos(a)**2 + b

"""
Explanation: ou impliquant les fonctions de SymPy:
End of explanation
"""


from sympy import Rational,pi,exp,I
from sympy.abc import x,y
Rational(3,2)*pi + exp(I*x) / (x**2 + y)

"""
Explanation: Les expressions symboliques peuvent combiner des rationels, des fonctions et des constantes de toutes sortes:
End of explanation
"""


from sympy import srepr
expr = x - y
srepr(x - y)

"""
Explanation: Représentation interne
Pour voir comment une expression symbolique est représentée dans la machine, on peut utiliser la fonction srepr :
End of explanation
"""


from sympy.printing.dot import dotprint
s = dotprint(expr)

"""
Explanation: L'expression symbolique est représentée par un arbre d'opérations.
<img src="images/expression.png" alt="image" width="302" />
Pour information, l'image a été créée avec Graphviz avec le resultat de la fonction dotprint :
End of explanation
"""


from sympy.abc import a,b,c
expression = a + 2*b + 3*c
expression.subs(a,9)

"""
Explanation: Substitutions
Pour substituer certaines variables dans une expression, on utilise la méthode subs qui s'écrit après l'expressions sous la forme expressions.subs(&lt;INPUT&gt;). Par exemple:
End of explanation
"""


expression.subs({a:9, b:4})

expression.subs({a:9, b:4, c:100})

"""
Explanation: Pour faire plus d'une substitutions, on peut les indiquer dans un dictionaire ({}) comme ci-bas:
End of explanation
"""


from sympy import log
from sympy.abc import x,y,z
expression.subs({a:x**2, b:log(y), c:z})

"""
Explanation: On peut aussi substituer une variable symbolique par une expression symbolique:
End of explanation
"""


from sympy import pi
pi

"""
Explanation: Constantes symboliques
Contrairement au module math de Python où le nombre pi est représenté par une approximation décimale, dans SymPy, le nombre pi est représenté symboliquement. C'est une constante symbolique:
End of explanation
"""


from sympy import sin, pi
sin(pi/3)

"""
Explanation: Cela permet de faire des calculs exacts. Par exemple, le sinus d'un angle de $\pi/3$ est égal à la racine de trois sur deux:
End of explanation
"""


from sympy import asin, Rational
asin(1)

asin(Rational(1,2))

"""
Explanation: La fonction inverse du sinus aussi appelée arc sinus et représentée par la fonction asin dans SymPy peut retourner des expressions symboliques impliquant des constantes symboliques telles que le nombre $\pi$ :
End of explanation
"""


from sympy.abc import x
sin(asin(x))

"""
Explanation: SymPy sait que les fonctions sinus et arc sinus sont inverses une de l'autre:
End of explanation
"""


from sympy.abc import 
from math import sin
sin(x)

"""
Explanation: ATTENTION
La fonction sin du module math de Python ne peut pas être appelée sur des expressions symboliques, car elle assume que l'argument est un nombre réel (type float):
End of explanation
"""


from sympy import sin,cos
from sympy.abc import a
r = sin(a)**2 + cos(a)**2
r

"""
Explanation: Simplifier une expression
Les expressions ne sont pas toujours simplifiées:
End of explanation
"""


from sympy import simplify
simplify(r)

"""
Explanation: Pour simplifier une expression, on utilise la commande simplify :
End of explanation
"""


simplify((x**3 + x**2 - x - 1)/(x**2 + 2*x + 1))

"""
Explanation: Voici un autre exemple:
End of explanation
"""


from sympy import expand
from sympy.abc import a,b
(a + b)**2

expand((a + b)**2)

"""
Explanation: La fonction simplify performe une série de simplifications dans un ordre bien choisi. Les simplifications spécifiques incluent besselsimp, combsimp, exptrigsimp, hypersimp, nsimplify, powsimp, radsimp, ratsimp, ratsimpmodprime, signsimp, simplify, simplify_logic, trigsimp et d'autres encore. Il suffit de consulter le code simplify?? pour voir ce qui se passe et dans quel ordre.
Lorsque l'on sait exactement ce qu'on veut faire sur l'expression symbolique (factoriser, mettre sur un dominateur commun, etc.), on peut utiliser directement la bonne fonction. Cela peut retourner un résultat plus rapidement. Les plus importantes fonctions de modification d'expressions symboliques sont décrites dans les sections qui suivent. On trouvera plus d'informations sur les façons de simplifier une expression dans le tutoriel de SymPy: http://docs.sympy.org/latest/tutorial/simplification.html
Développer une expression
Pour développer une expression, on utilise la fonction expand :
End of explanation
"""


(a + b)**2 - (a - b)**2

expand(_)

"""
Explanation: Cela peut mener à des simplifications:
End of explanation
"""


expr = (x**2 + x*y) / x
expr

from sympy import cancel
cancel(expr)

"""
Explanation: Note: En IPython et Jupyter, la barre de soulignement (_) est une variable qui contient le dernier résultat calculé. Aussi, la double barre de soulignement (__) est une variable qui contient l'avant-dernier résultat calculé. Finalement, la triple barre de soulignement (___) est une variable qui contient l'avant-avant-dernier résultat calculé. La quadruple barre de soulignement ne contient rien.
Annuler les facteurs communs d'une fraction
Pour annuler les facteurs communs dans une fonction rationnelle, on utilise cancel :
End of explanation
"""


from sympy import factor
factor(x**3 - x**2 + x - 1)

"""
Explanation: Factoriser un polynôme
La fonction factor de SymPy permet de factoriser un polynôme en un produit de facteurs irréductibles sur l'anneau des nombres rationnels:
End of explanation
"""


factor(x**3 - x**2 + x - 1, gaussian=True)

"""
Explanation: Pour factoriser le polynôme sur les nombres de Gauss (nombres complexes à parties imaginaire et réelle entières), on ajoute l'option gaussian=True :
End of explanation
"""


factor(x**2 - 5)

factor(x**2 - 5, extension=sqrt(5))

"""
Explanation: Pour faire la factorisation sur une extension algébrique des nombres rationnels, il suffit de spéficifier un ou des nombres algébriques qui engendrent l'extension:
End of explanation
"""


expr = x*z + x**2 + x + x*y + x**2 * w + 5 - x**3
expr

"""
Explanation: Consulter la documentation factor? pour obtenir de l'aide sur la factorisation de polynômes sur d'autres domaines ou sur des extensions de corps.
Rassembler les termes d'une expression
La fonction collect rassemble les puissances communes d'un terme dans une expression. Par exemple:
End of explanation
"""


from sympy import collect
collect(expr, x)

"""
Explanation: On rassemble les termes selon les puissances de x :
End of explanation
"""


from sympy.abc import x,y,z
1/(x+1) + 1/y + 1/z

"""
Explanation: Réduire au même dénominateur
Une somme de fonctions rationnelles reste sous forme de somme:
End of explanation
"""


from sympy import ratsimp
ratsimp(1/(x+1) + 1/y + 1/z)

"""
Explanation: Pour la mettre au même dénominateur, on utilise ratsimp :
End of explanation
"""


from sympy import together
together(1/(x+1) + 1/y + 1/z)

"""
Explanation: Alternativement, on peut aussi utiliser la fonction together. À la différence de ratsimp la fonction together préserve le plus possible les termes sous la forme initiale:
End of explanation
"""


expr = (3*x**2  + 52*x - 265) / ((x - 7)*(x - 1)*(x + 34))
expr

"""
Explanation: Décomposition en fractions partielles
Soit un fraction rationnelle:
End of explanation
"""


from sympy import apart
apart(expr)

"""
Explanation: On peut la décomposer en somme de fractions rationnelles à l'aide de la fonction apart de SymPy:
End of explanation
"""


A = 1 / (1+sqrt(5))
A

from sympy import radsimp
radsimp(A)

"""
Explanation: Rationalisation du dénominateur d'une expression
Pour rationaliser le dénominateur d'un expression, on utilise la fonction radsimp de SymPy:
End of explanation
"""


