{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "*ENSAM-Bordeaux, Mathématiques et informatique. Date : le 12/10/19. Auteur : Éric Ducasse. Version : 1.0*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
*On pourra faire exécuter ce notebook cellule par cellule $\\left(\\mathtt{Maj+Entrée}\\right)$ ou intégralement par $\\mathtt{\\;Kernel\\rightarrow Restart\\;\\&\\;Run\\;All}$.*
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import sympy as sb\n", "sb.init_printing() # Pour avoir de jolies formules mathématiques à l'écran" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(f\"Version de sympy : {sb.__version__}\") " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# **Équations, et inéquations**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Voir aussi le tutoriel **sympy** :" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "https://docs.sympy.org/latest/tutorial/index.html#tutorial" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. *Généralités* " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "https://docs.sympy.org/latest/tutorial/gotchas.html#equals-signs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X,p,q = sb.symbols(\"X,p,q\", reals=True)\n", "b = (X + 2*p)**2\n", "a = b\n", "a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "( a == b, a is b, a.equals(b), sb.Eq(a,b) )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = b.expand()\n", "(a,b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "( a == b, a is b, a.equals(b), sb.Eq(a,b), sb.Eq(a,b).simplify() )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. *Résolution d'équations algébriques* " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "https://docs.sympy.org/latest/tutorial/solvers.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.1 Utilisation de **solve** sans équation " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "P = X**2 + 2*p*X + q ; P" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "liste_sol = sb.solve(P,[X]) ; liste_sol" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sb.solve(P,X) # équivalent" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "regles = sb.solve(P,X,dict=True) ; regles" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Vérification, qui utilise des règles de substitution" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[ P.xreplace(regle).simplify() for regle in regles ]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Remarque** : même si le **tutoriel sympy** recommande **solveset**, nous préférons **solve** car solveset ne résout que des équations à une seule inconnue" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ " sb.solveset(P,X)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "info = sb.solveset.__doc__ ; print(info[:688])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.2 Utilisation de **solve** avec équation " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "eq1 = sb.Eq(P,0) ; eq1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sb.solve(eq1,X)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "regles = sb.solve(eq1,X,dict=True) ; regles" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Vérification" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[ eq1.xreplace(rg).simplify() for rg in regles ]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.3 Plusieurs inconnues" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sb.solve(P,[p,q])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sb.solve(P,[p,q],dict=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'ordre des inconnues a une importance ici." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
***Attention*** *Cela peut dépendre de la version de $\\mathtt{sympy}$ ; en tous cas, cela est vrai pour la version 1.4.*
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sb.__version__" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sb.solve(P,[q,p])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sb.solve(P,[q,p],dict=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. *Système d'équations* " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x,y,a,b,c = sb.symbols(\"x,y,a,b,c\")\n", "sb.solve([sb.cos(a)*x+y-sb.sin(2*a),x+sb.cos(a)*y-sb.sin(a)],[x,y])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. *Inégalités* " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sympy.solvers.inequalities import reduce_inequalities" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x,y = sb.symbols(\"x,y\", real=True)\n", "reduce_inequalities(0 <= x + 3, [])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "reduce_inequalities(0 <= x + y*2 - 1, [x])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "reduce_inequalities(0 <= x + y*2 - 1, [y])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sb.solveset(0 <= x + 3,x,domain=sb.S.Reals)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sb.solveset( 0 <= x**2 - 3, x, domain=sb.S.Reals)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cond = reduce_inequalities( [0 <= x**2 - 3, x > -2], x) ; cond" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "reduce_inequalities( [0 <= x**2 - 3, x > 0], x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. *Équations differentielles* " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "https://docs.sympy.org/latest/tutorial/solvers.html#solving-differential-equations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Attention** : pour l'instant, les conditions aux limites ne peuvent pas être fournies à dsolve. Il faut chercher la solution générale et ensuite trouver les coefficients qui satisfont les conditions aux limites." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.1. On veut résoudre : $\\displaystyle f^{\\prime\\prime}(t)+2\\,a\\,f^{\\prime}(t)+3\\,f(t) = 0$ avec les conditions initiales $f(0)=1$ et $f^{\\prime}(0)=0$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t,a = sb.symbols(\"t,a\", real=True) ; f = sb.Function(\"f\")\n", "edo = sb.Eq(f(t).diff(t,2)+2*a*f(t).diff(t)+3*f(t),0) ; edo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### dsolve renvoie une égalité :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sol_edo = sb.dsolve(edo) ; sol_edo" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(sol_edo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Solution générale :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "solu_gene = sol_edo.rhs # right-hand side \n", "solu_gene" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Conditions initiales :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "CI = [solu_gene.xreplace({t:0})-1,solu_gene.diff(t).xreplace({t:0})] ; CI" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "constantes = sb.solve(CI,[\"C1\",\"C2\"]) ; constantes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Solution (pour $a^2\\geqslant 3$)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "solu1 = solu_gene.xreplace(constantes).simplify() ; solu1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f_num1 = sb.lambdify( (t,a), solu1, \"numpy\")\n", "f_num1(np.linspace(0,1,11),2.0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X = np.linspace(0,6,300)\n", "plt.plot(X,f_num1(X,2.0),\"-b\",label=\"a = 2.0\")\n", "plt.plot(X,f_num1(X,3.0),\"-r\",label=\"a = 3.0\")\n", "plt.grid() ; plt.legend() ;" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f_num1(1.0,1.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Autre forme de la solution (pour $a^2\\leqslant 3$)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remarque 1 : $\\mathtt{solu1.refine(\\,sb.Q.positive(3-a**2)\\,)}$ ne donne rien après une durée de recherche conséquente" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remarque 2 : $\\mathtt{xreplace}$ ne suffit pas ici. Il faut utiliser $\\mathtt{subs}$ (remplacements répétés)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "solu2 = solu1.subs({sb.sqrt(a**2-3): sb.I*sb.sqrt(3-a**2)}).rewrite(sb.cos).simplify() ; \n", "T = sb.Wild(\"T\")\n", "solu2 = solu2.collect([sb.sin(T),sb.cos(T)]) ; solu2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f_num2 = sb.lambdify( (t,a), solu2, \"numpy\")\n", "f_num2(np.linspace(0,1,11),1.0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X = np.linspace(0,10,300)\n", "plt.plot(X,f_num2(X,1.0),\"-b\",label=\"a = 1.0\")\n", "plt.plot(X,f_num2(X,0.5),\"-r\",label=\"a = 0.5\")\n", "plt.plot(X,f_num2(X,0.1),\"-g\",label=\"a = 0.1\")\n", "plt.grid() ; plt.legend() ;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.2. On veut résoudre : $\\displaystyle \\left\\lbrace T^{\\,\\prime}(x) = -\\frac{\\phi(x)}{k(x)}\\,, \\phi^{\\,\\prime}(x) = 100\\,(2\\,x-1)^2 \\right\\rbrace$, où $k(x)=1+x$, avec les conditions aux bords $\\phi(0)=h\\,(T_{\\mathrm{ext}}-T(0))$ et $\\phi(1)=h\\,(T(1)-T_{\\mathrm{ext}})$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
***Cet exemple est compliqué mais permet de montrer quelques limites du module $\\mathtt{sympy}$ en allant
au-delà de ce que est exigible dans le cadre de l'UEF MINI.***
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x,T_ext,h = sb.symbols(\"x,T_ext,h\", real=True)\n", "T = sb.Function(\"T\") ; phi = sb.Function(\"phi\")\n", "k_de_x = x+1\n", "edo_phi = sb.Eq( phi(x).diff(x) , 100*(2*x-1)**2)\n", "edo_T = sb.Eq( T(x).diff(x) , -phi(x)/k_de_x)\n", "[edo_phi,edo_T]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try :\n", " sb.dsolve([edo_phi,edo_T],[T(x),phi(x)])\n", "except Exception as e:\n", " print(f\"Non implémenté dans la version {sb.__version__} de sympy :\",e)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A,B = sb.symbols(\"A,B\", real=True)\n", "phi_de_x = sb.dsolve(edo_phi,phi(x)).rhs.xreplace({sb.symbols(\"C1\"):A}) ; phi_de_x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "edo_T = sb.Eq( k_de_x * T(x).diff(x) + phi_de_x, 0) ; edo_T" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "T_de_x = sb.dsolve(edo_T,T(x)).rhs.xreplace({sb.symbols(\"C1\"):B}) ; T_de_x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "CL = [sb.Eq( phi_de_x.xreplace({x:0}),h*(T_ext-T_de_x).xreplace({x:0})),\\\n", " sb.Eq( phi_de_x.xreplace({x:1}),h*(T_de_x-T_ext).xreplace({x:1}))] ; CL" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Résultat pas faux mais moche* :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sol_AB = sb.solve(CL,[A,B]) ; sol_AB" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Essai de simplification nécessitant plus de travail qu'avec un papier et un crayon* :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sol_AB = sb.solve(CL,[A,B])\n", "sol_AB[A] = sol_AB[A].factor().collect(h)\n", "sol_AB[B] = sol_AB[B].expand()\n", "fact_T_ext = sol_AB[B].coeff(T_ext).simplify()*T_ext\n", "sol_AB[B] = fact_T_ext + (sol_AB[B]-fact_T_ext).factor().collect(h)\n", "sol_AB" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### **Solution du problème :**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Ca = A.xreplace(sol_AB)\n", "A_num = sb.lambdify(h, A.xreplace(sol_AB), \"numpy\")\n", "A_num(1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "h_de_A = {h*(-28+39*sb.log(2)) : 3 + 9*(h*sb.log(2)+2)*A/100}\n", "(h_de_A,sol_AB[A].xreplace(h_de_A).simplify())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "phi_de_x_et_A = phi_de_x.xreplace(sol_AB).xreplace(h_de_A).simplify()\n", "A + (phi_de_x_et_A-A).factor()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "phi_num = sb.lambdify((x,h), phi_de_x_et_A.xreplace({A:A_num(h)}), \"numpy\")\n", "phi_num(0.2,1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dT_de_x_et_A = (T_de_x.xreplace(sol_AB)-T_ext).xreplace(h_de_A).simplify().collect([sb.log(x+1),A])\n", "dT_de_x_et_A" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "F = -A/h + (sb.Rational(1300,3)-A)*sb.log(x+1) ; F + (-F+dT_de_x_et_A).factor()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dT_num = sb.lambdify((x,h),dT_de_x_et_A.xreplace({A:A_num(h)}),\"numpy\")\n", "dT_num(0.2,1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Vx = np.linspace(0,1,300)\n", "plt.plot(Vx,dT_num(Vx,1.0),\"-r\",label=\"$h=1.0$\")\n", "plt.plot(Vx,dT_num(Vx,1.1),\"-b\",label=\"$h=1.1$\")\n", "plt.plot(Vx,dT_num(Vx,1.2),\"-g\",label=\"$h=1.2$\")\n", "plt.grid() ; plt.legend(loc=\"best\") ; plt.ylim(12.8,19.2) ;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.3. On veut résoudre : $\\displaystyle \\lbrace x^{\\prime}(t)-a^2\\,y(t) = 0,y^{\\prime}(t)+b^2\\,x(t)=0\\rbrace$ avec les conditions initiales $x(0)=1$ et $y(0)=0$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t,a,b = sb.symbols(\"t,a,b\", real=True, positive=True)\n", "X,Y = sb.Function(\"X\"),sb.Function(\"Y\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sdo = [sb.Eq(X(t).diff(t)-a**2*Y(t),0),sb.Eq(Y(t).diff(t)+b**2*X(t),0)] ; sdo" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ci = {X(0):1,Y(0):0} ; ci" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "solu_gen = sb.dsolve(sdo, [X(t),Y(t)]) ; solu_gen" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "eq_CI = [ eq.replace(t,0).xreplace(ci) for eq in solu_gen ] ; eq_CI" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dico_C1_C2 = sb.solve(eq_CI,sb.symbols(\"C1,C2\")) ; dico_C1_C2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "solution = sb.solve([ eq.xreplace(dico_C1_C2) for eq in solu_gen ], [X(t),Y(t)])\n", "solution" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" } }, "nbformat": 4, "nbformat_minor": 2 }