diff --git "a/Chapitre 10 - Matrices orthogonales, matrices sym\303\251triques/10.1 Matrices et transformations orthogonales.ipynb" "b/Chapitre 10 - Matrices orthogonales, matrices sym\303\251triques/10.1 Matrices et transformations orthogonales.ipynb" new file mode 100644 index 0000000..0db067d --- /dev/null +++ "b/Chapitre 10 - Matrices orthogonales, matrices sym\303\251triques/10.1 Matrices et transformations orthogonales.ipynb" @@ -0,0 +1,149 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import sympy as sp\n", + "from IPython.display import display, Latex, Markdown\n", + "import plotly\n", + "import plotly.graph_objects as go\n", + "import sys, os\n", + "sys.path.append('../Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation')\n", + "from Ch8_lib import *\n", + "sys.path.append('../Librairie')\n", + "import AL_Fct as al\n", + "from Ch10_lib import *" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### DÉFINITION 1:\n", + "Soient $V$ un espace euclidien et $T: V \\rightarrow V$ une application linéaire. On dit que $T$ est orthogonale si $\\|T(v)\\|=\\|v\\|$ pour tout $v \\in V$\n", + "\n", + "### DÉFINITION 2:\n", + "Soient $V=\\mathbb{R}^{n}$ muni du produit scalaire usuel et $A \\in M_{n \\times n}(\\mathbb{R})$ une matrice de taille $n \\times n$ à coefficients réels. On dit que $A$ est orthogonale si $\\|A X\\|=\\|X\\|$ pour tout $X \\in M_{n \\times 1}(\\mathbb{R})$\n", + "\n", + "### CONSTAT 3:\n", + "Soit $T: V \\rightarrow V$ une transformation orthogonale d'un espace euclidien $V$. Alors $T$ est injective (et donc bijective par le théorème du rang)\n", + "\n", + "### PROPOSITION 4:\n", + "Soient $V$ un espace euclidien et $T: V \\rightarrow V$ une application linéaire orthogonale. Soient également $u, v \\in V$ et désignons par $\\theta$ (respectivement $\\gamma$) l'angle entre les deux vecteurs $u, v$ (respectivement, l'angle entre les deux vecteurs $T(u)$ et $T(v)$ ). Alors $\\theta=\\gamma$, i.e. $T$ préserve les angles." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercice 1:\n", + "En utilisant la définition 1 donnée ci-dessus, determinez si les matrices suivantes sont orthogonales.\n", + "\n", + "*La fonction `is_orthogonal(A)` donne la reponse détaillée pour la matrice `A` donnée en argument.*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "A1 = sp.Matrix([[1/2 , - sp.sqrt(3)/2], [sp.sqrt(3)/2, 1/2]])\n", + "A2 = sp.Matrix([[1, -1], [0, 1]])\n", + "A3 = sp.Matrix([[sp.sqrt(2)/2, -sp.sqrt(2)/2], [sp.sqrt(2)/2, sp.sqrt(2)/2]])\n", + "A4 = sp.Matrix([[sp.sqrt(2)/2, sp.sqrt(2)/2], [sp.sqrt(2)/2, sp.sqrt(2)/2]])\n", + "A5 = sp.Matrix([[0, 0, -1], [0, 1, 0], [-1, 0, 0]])\n", + "A6 = sp.Matrix([[1, -7, -1, 4], [0, 0, 1, -3], [0, 0, 1, -2], [0, 0, 0, -1]])\n", + "\n", + "A = A1\n", + "display(Latex(\"$ A = \" + latexp(A) + \"$\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "is_orthogonal(A)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exemple 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sp_tri, ep_tri = points_on_circle(3, [3,1])\n", + "sp_sq, ep_sq = points_on_circle(4)\n", + "sp_pent, ep_pent = points_on_circle(5)\n", + "sp_cir, ep_cir = points_on_circle(50)\n", + "\n", + "A1 = np.array([[np.sqrt(2)/2, -np.sqrt(2)/2], [np.sqrt(2)/2, np.sqrt(2)/2]])\n", + "A2= np.array([[1, 1],[-1, 2]])\n", + "A3 = np.array([[3, 0],[0, 2]])\n", + "\n", + "plot_geom_2D(sp_pent, ep_pent, A1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plot_geom_2D(sp_sq, ep_sq, A2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plot_geom_2D(sp_tri, ep_tri, A3)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plot_geom_2D(sp_cir, ep_cir, A3)" + ] + } + ], + "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.7.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git "a/Chapitre 10 - Matrices orthogonales, matrices sym\303\251triques/10.2 Matrices orthogonales, \303\251quivalences.ipynb" "b/Chapitre 10 - Matrices orthogonales, matrices sym\303\251triques/10.2 Matrices orthogonales, \303\251quivalences.ipynb" new file mode 100644 index 0000000..5cf4c15 --- /dev/null +++ "b/Chapitre 10 - Matrices orthogonales, matrices sym\303\251triques/10.2 Matrices orthogonales, \303\251quivalences.ipynb" @@ -0,0 +1,46 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PROPOSITION:\n", + "Soient $V=\\mathbb{R}^{n}$ muni du produit scalaire usuel et $A \\in M_{n \\times n}(\\mathbb{R})$ une matrice de taille $n \\times n$ à coefficients réels. Alors les conditions suivantes sont équivalentes.\n", + "1. $\\|A X\\|=\\|X\\|$ pour tout $X \\in M_{n \\times 1}(\\mathbb{R})$\n", + "2. $\\langle A X, A Y\\rangle=\\langle X, Y\\rangle$ pour tous $X, Y \\in M_{n \\times 1}(\\mathbb{R})$\n", + "3. $A A^{T}=I_{n}=A^{T} A$\n", + "4. Les lignes de $A$ forment une base orthonormée de $V$\n", + "5. Les colonnes de $A$ (vues comme vecteurs de $\\mathbb{R}^{n}$ ) forment une base orthonormée de $V$.\n", + "Aussi, si $A$ est orthogonale, alors det $A=\\pm 1$" + ] + }, + { + "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.7.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git "a/Chapitre 10 - Matrices orthogonales, matrices sym\303\251triques/Ch10_lib.py" "b/Chapitre 10 - Matrices orthogonales, matrices sym\303\251triques/Ch10_lib.py" new file mode 100644 index 0000000..4065260 --- /dev/null +++ "b/Chapitre 10 - Matrices orthogonales, matrices sym\303\251triques/Ch10_lib.py" @@ -0,0 +1,118 @@ +import sys, os +import numpy as np +import sympy as sp +from IPython.display import display, Latex, Markdown +import plotly +import plotly.graph_objects as go +sys.path.append('../Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation') +from Ch8_lib import * +sys.path.append('../Librairie') +import AL_Fct as al + + +def points_on_circle(n, center=np.array([0, 0])): + theta = 2 * np.pi / n + + s_pts = np.zeros((n, 2)) + e_pts = np.zeros((n, 2)) + + for i in range(n): + s_pts[i] = [np.cos(i * theta) + center[0], np.sin(i * theta) + center[1]] + e_pts[i] = [np.cos((i + 1) * theta) + center[0], np.sin((i + 1) * theta) + center[1]] + + return np.array(s_pts), np.array(e_pts) + + +def plot_geom_2D(s_pts, e_pts, A): + n = len(s_pts) + + if n != len(e_pts): + raise ValueError("start_points and end_points must have same length.") + + layout = go.Layout(yaxis=dict(scaleanchor="x", scaleratio=1)) + + display(Latex("On montre la transformation provoquée par la multiplication par la matrice $A = " + + al.texMatrix(A) + "$ sur une figure géométrique.")) + + fig = go.Figure(layout=layout) + + color = ['black', 'red', 'blue', 'green', 'yellow', 'brown', 'grey', 'cyan', 'orange', 'violet'] + + n_col = len(color) + + if n > n_col: + color = ['blue'] + n_col = 1 + + for i in range(n): + a = np.array(s_pts[i]) + b = np.array(e_pts[i]) + + a2 = A @ a + b2 = A @ b + + if i == 0: + show_legend = True + else: + show_legend = False + + fig.add_trace(go.Scatter(x=[a[0], b[0]], y=[a[1], b[1]], + line=dict(color=color[i % n_col], width=2), + mode='lines+markers', showlegend=show_legend, name='Original Figure')) + + fig.add_trace(go.Scatter(x=[a2[0], b2[0]], y=[a2[1], b2[1]], + line=dict(color=color[i % n_col], width=2, dash='dot'), + mode='lines+markers', showlegend=show_legend, name='Modified Figure')) + + fig.show() + + +def is_orthogonal(A): + if not isinstance(A, sp.Matrix): + raise ValueError("A should be a sympy matrix") + + n = A.shape[0] + if n != A.shape[1]: + raise ValueError("A should be a square matrix") + + display(Latex("On cherche à savoir si la matrice $A = " + latexp(A) + "$ est orthogonale en utilisant la " + + "définition 1.")) + + if A.is_lower or A.is_upper: + for i in range(n): + if A[i, i] != 1 and A[i, i] != -1: + display(Latex("Les valeurs propres de $A$ sont ses éléments diagonaux. Une des valeurs propres de " + + "$A$ est différente de 1 ou -1. Il existe donc un vecteur propres $v$ de $A$ tel " + + " que $A v = \lambda v$ avec $\lambda \\neq \pm 1$. Donc dans ce cas on a $\|A v\| " + + "\\neq \|v\| $." + )) + return + + v = sp.zeros(n, 1) + for i in range(n): + symb_name = "x_" + str(i + 1) + v[i] = sp.symbols(symb_name, real=True) + + b = A * v + b_norm = b.norm() ** 2 + v_norm = v.norm() ** 2 + + display(Latex("Il faut vérifier si $\|A v\| = \|v\|$ pour tout $v \in \mathbb{R}^" + str(n) + "$." + + " On utilise le carré des normes pour s'affranchir des racines carrées.")) + display(Latex("On calcule d'abord la norme au carré de $v$ et on obtient: $\|v\|^2 = " + sp.latex(v_norm) + + "$.")) + display(Latex("On calcule ensuite le produit $Av = " + latexp(b) + "$")) + + if sp.simplify(b_norm) != b_norm: + display(Latex("On calcule la norme au carré de $Av$ et on obtient: $\|Av\|^2 = " + sp.latex(b_norm) + + "=" + sp.latex(sp.simplify(b_norm)) + "$")) + else: + display(Latex("On calcule la norme au carré de $Av$ et on obtient: $\|Av\|^2 = " + sp.latex(b_norm) + + "$")) + + if sp.simplify(b_norm - v_norm) == 0: + display(Latex("Les normes sont toujours égales. La matrice est donc orthogonale.")) + else: + display(Latex("Les normes sont différente. La matrice n'est donc pas orthogonale.")) + + diff --git "a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.1 Valeurs propres et vecteurs propres, d\303\251finitions, exemples.ipynb" "b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.1 Valeurs propres et vecteurs propres, d\303\251finitions, exemples.ipynb" index 0e55e33..804eb45 100644 --- "a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.1 Valeurs propres et vecteurs propres, d\303\251finitions, exemples.ipynb" +++ "b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.1 Valeurs propres et vecteurs propres, d\303\251finitions, exemples.ipynb" @@ -1,202 +1,203 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Concept(s)-clé(s) et théorie\n", "\n", "#### Définition: Valeur propre et vecteur propre d'une application linéaire\n", "\n", "Soient $V$ un $\\mathbb{R}$-espace vectoriel et $T: V \\rightarrow V$ une transformation linéaire. On dit que $\\lambda \\in \\mathbb{R}$ est une valeur propre de $T$ s'il existe $v \\in V$ non-nul tel que $T(v)=\\lambda v$. Aussi, si $\\lambda \\in \\mathbb{R}$ est une valeur propre de $T$, alors tout vecteur non-nul $v \\in V$ tel que $T(v)=\\lambda v$ s'appelle un vecteur propre de $T$ correspondant à la valeur propre $\\lambda$.\n", "\n", "#### Définition: Valeur propre et vecteur propre d'une matrice\n", "Soit $A \\in M_{n \\times n} \\ (\\mathbb{R})$ . On dit que $\\lambda \\in \\mathbb{R}$ est une valeur propre de $A$ s'il existe $X \\in M_{n \\times 1} (\\mathbb{R})$ non-nul tel que $A X=\\lambda X$. Aussi, si $\\lambda \\in \\mathbb{R}$ est une valeur propre de $A$, alors toute solution non-nulle de $A X=\\lambda X$ s'appelle un vecteur propre de $A$ correspondant à la valeur propre $\\lambda$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import plotly\n", "import plotly.graph_objects as go\n", "import sympy as sp\n", "from IPython.display import display, Latex\n", "from Ch8_lib import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **Exemple 1**\n", "\n", "Pour savoir si un vecteur $v \\in M_{n \\times 1} \\ (\\mathbb{R})$ est un vecteur propre de la matrice $A\\in M_{n \\times n} \\ (\\mathbb{R})$, il suffit de vérifier que les vecteurs $v$ et $b = A \\ v$ sont colinéaires. Il est possible de visualiser cela graphiquement pour des vecteurs de dimension $n=2$ où $n=3$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Definition de la matrice A et du vecteur v (3D)\n", "# On utilise des numpy array pour les plots\n", - "v = np.array([1, 1, 1])\n", - "A = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]])\n", + "# Les vecteurs et matrices sont par défaut rempli de 1. Vous pouvez changer les valeurs. (2D et 3D)\n", + "v = np.array([1, 1])\n", + "A = np.array([[1, 1], [1, 1]])\n", "\n", "# Multiplication de v par A\n", "b = A@v\n", "\n", "# Plot\n", - "vector_plot_3D(v, b)" + "vector_plot(v, b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercice 1\n", "Etant donné une matrice carrée $A \\in M_{n \\times n} \\ (\\mathbb{R})$ et un vecteur $v \\in M_{n \\times 1} \\ (\\mathbb{R})$. Déterminez si $v$ est un vecteur propre de la matrice $A$. Si tel est le cas, trouvez la valeur propre $\\lambda \\in \\mathbb{R}$ associée. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Ici, les matrices ou/et vecteurs peuvent dépendre du paramètre x\n", "x = sp.symbols('x')\n", "\n", "# a)\n", "A_1 = sp.Matrix([[1, 1, 1], [1, 1, 1], [1, 1, 1]])\n", "v_1 = sp.Matrix([1, 1, 1])\n", "\n", "display(Latex(\" $A =\" + latexp(A_1) + \"\\hspace{20mm} v= \" + latexp(v_1) + \"$\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Affiche la solution pour A_1 et v_1\n", "CheckEigenVector(A_1, v_1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# b)\n", "A_2 = sp.Matrix([[4*x, 8*x], [1, 2]])\n", "v_2 = sp.Matrix([2, -1])\n", "\n", "display(Latex(\" $A =\" + latexp(A_2) + \"\\hspace{20mm} v= \" + latexp(v_2) + \"$\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Print the solution for A_2 and v_2\n", "CheckEigenVector(A_2, v_2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# c)\n", "A_3 = sp.Matrix([[1, 2], [1, 2]])\n", "v_3 = sp.Matrix([0, 0])\n", "\n", "display(Latex(\" $A =\" + latexp(A_3) + \"\\hspace{20mm} v= \" + latexp(v_3) + \"$\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Print the solution for A_3 and v_3\n", "CheckEigenVector(A_3, v_3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercice 2\n", "En utilisant la définition d'une valeur propre donnée plus haut, vérifiez si un nombre donné $\\lambda$ est une valeur propre de la matrice $A \\in M_{n \\times n} \\ (\\mathbb{R})$. Si oui trouvez un vecteur propre correspondant à $\\lambda$.\n", "\n", "##### Méthode: \n", "Poser $A v = \\lambda v \\Leftrightarrow (A - \\lambda I) v = 0 $ et étudier le nombre de solutions du système.\n", "\n", "- Si le système a une unique solution ($v$ = 0), alors $\\lambda$ n'est pas une valeur propre de la matrice A.\n", "- Si le système a une infinité de solutions, alors $\\lambda$ est une valeur propre de $A$.\n", "\n", "Si $\\lambda$ est bien une valeur propre de $A$, alors n'importe quelle solution non triviale $v$ du système $A v = \\lambda v$ est un vecteur propre associé à $\\lambda$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# a)\n", "A = sp.Matrix([[2, 0], [1, 2]])\n", "l = 2\n", "\n", "# A remplir pour vérifier avec la fonction ch8_1_exo_2\n", "# Mettre vp = True si c'est une valeur propre de A. False sinon.\n", "vp = True \n", "# Entrez un vecteur propre associé à lambda si c'est une valeur propre, sinon laissez les 0\n", "v = sp.Matrix([0, 0])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ch8_1_exo_2(A, l, vp, v)" ] } ], "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.7.2" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git "a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.3 Polyn\303\264me caract\303\251ristique.ipynb" "b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.3 Polyn\303\264me caract\303\251ristique.ipynb" index cfb1383..6a68ce7 100644 --- "a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.3 Polyn\303\264me caract\303\251ristique.ipynb" +++ "b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.3 Polyn\303\264me caract\303\251ristique.ipynb" @@ -1,146 +1,146 @@ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import sympy as sp\n", "from IPython.display import display, Latex\n", "from Ch8_lib import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Définition 1:\n", "Soient $A\\in M_{n \\times n}(\\mathbb{R})$ et $t$ une indéterminée. Le polynôme caractéristique de $A$, noté $c_A(t)$, est le polynme défini par $$c_A(t)=\\det (A-tI)$$\n", "\n", "### Proposition 2:\n", "Soient $A,P\\in M_{n\\times n}(\\mathbb{R})$ et supposons que soit inversible. Alors \n", "$$c_A(t)=c_{PAP^{-1}}(t).$$\n", "\n", "### Définition 3:\n", "Soit $T:V \\to V$ une transformation linéaire d'un $\\mathbb{R}$-espace vectoriel de dimension finie $V$. On définit le polynôme caractéristique de $T$ par $c_T(t)=c_A(t),$ où $A=[T]_{\\mathscr{B}}$ pour une base ordonnée quelconque $\\mathscr{B}$ de $V$.\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\lambda \\in \\mathbb{R}$ est une valeur propre de $A\\in M_{n \\times n}(\\mathbb{R})$ si et seulement si: $$ c_A(\\lambda) = \\det (A-\\lambda I) = 0$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exemple 1\n", "Méthode pour calculer les valeurs propres d'une matrice $3 \\times 3$.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Définition de la matrice (Par défaut, les coefficients sont fixés à 1)\n", "A = sp.Matrix([[1,1,1],[1,1,1],[1,1,1]])\n", "\n", "l = sp.symbols('\\lambda')\n", "I = sp.eye(3)\n", "\n", "# Calcul étape par étape du polynome caractéristique (degré 3 ici).\n", "Determinant_3x3(A-l*I, True, True, 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On a donc le polynome caractéristique de la matrice A, les valeurs propres sont les racines de ce polynôme.\n", "On résout $$\\det (A- \\lambda I) = 0$$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Résolution de l'équation avec sympy\n", "eq = sp.Eq(sp.det(A-l*I),0)\n", "sol = sp.solve(eq, l)\n", "\n", "display(Latex(\"Les racines du polynôme caractéristiques (les valeurs propres de A) sont: $\" + \n", " sp.latex(sol) + \"$.\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercice 1\n", "Trouver les valeurs propres des matrices données ci-dessous en trouvant les racines du polynôme caractéristique.\n", "\n", "*Pour trouver les racines des polynômes caractéristiques de degré 3 ou 4, factorisez à l'aide de racines évidentes $\\in [-2, -1, 0, 1, 2]$*" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Trouver les valeurs propres des matrices suivantes\n", "A_1 = sp.Matrix([[-2, 4], [5, -1]])\n", "A_2 = sp.Matrix([[1, 2], [3, 1]])\n", "A_3 = sp.Matrix([[1, 0, 4], [1, 3, 1], [2, 4, -1]])\n", "A_4 = sp.Matrix([[4, 0, 1], [-2, 1, 0], [-2, 0, 1]])\n", "A_5 = sp.Matrix([[1, 2, 0, 0], [2, 1, 0, 0], [-4, 2, 2, -1], [-8, 5, 0, 1]])\n", "A_6 = sp.Matrix([[4, 0, 0, 0], [7, -11, 0, 0], [-0.5, 2.3, sp.sqrt(2), 0], [-8, 5, 2, 11]])\n", "\n", "# Matrice à afficher\n", - "A = A_1\n", + "A = A_6\n", "display(Latex(\"Trouvez les valeurs propres de la matrice $A =\" + latexp(A) + \"$\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Affiche la solution étape par étape pour la matrice spécifiée comme argument de la fontion valeurs_propres\n", - "valeurs_propres(A_1)" + "valeurs_propres(A)" ] } ], "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.7.2" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.4 Espaces propres.ipynb b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.4 Espaces propres.ipynb index 50583a7..7a9d718 100644 --- a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.4 Espaces propres.ipynb +++ b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.4 Espaces propres.ipynb @@ -1,163 +1,156 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Définition 1\n", "Soient $\\phi:V\t\\to V$ une transformation linéaire d'un espace vectoriel $V$ et $\\lambda \\in \\mathbb{R}$ une valeur propre de $\\phi.$ Alors l'espace propre de $\\phi$ associé à $\\lambda$ est le sous-ensemble de $V$ défini par $E_{\\lambda}=\\{v\\in V: \\phi(v)=\\lambda v\\}$.\n", "\n", "De manière similaire, si $\\lambda\\in \\mathbb{R}$ est une valeur propre de la matrice $A\\in M_{n \\times n}(\\mathbb{R}),$ alors l'espace propre de $A$ associé à $\\lambda$ est le sous-ensemble de $M_{n \\times 1}(\\mathbb{R})$ défini par $E_{\\lambda}=\\{X\\in M_{n \\times 1}(\\mathbb{R}) : AX=\\lambda X\\}$.\n", "\n", "### Proposition 2\n", "Le sous-ensemble $E_\\lambda$ est un sous-espace vectoriel." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import plotly\n", "import plotly.graph_objects as go\n", "import sympy as sp\n", "import sys, os \n", "sys.path.append('../Librairie')\n", "import AL_Fct as al\n", "from IPython.utils import io\n", "from IPython.display import display, Latex\n", "from Ch8_lib import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercice 1\n", "**Trouvez les valeurs propres des matrices suivantes puis pour chacune des valeurs propres, trouvez une base de l'espace propre correspondant.**\n", "\n", "\n", "La fonction `eigen_basis` détaille étape par étape comment obtenir une base de l'espace propre associé à une valeur propre donnée d'une matrice. Elle vérifie également que la base de l'espace propre rentrée est correcte.\n", "Cette fonction prend 3 arguments: \n", "* La matrice (définie comme `A = sp.Matrix([[1, 0], [0, 2]])` par exemple)\n", "* La valeur propre pour laquelle on souhaite calculer l'espace propre (définie comme `l = 2` par exemple)\n", "* Une base de l'espace propre à vérifier. La base doit être exprimée comme une liste de vecteurs de base: \n", " * Exemples:\n", " * `base = [[v11, v12, v13], [v21, v22, v23]]` si la base contient deux vecteurs de dimension 3\n", " * `base = [[v11, v12]]` si la base n'a qu'un seul vecteur de dimension 2\n", "\n", "Pour appeler la fonction, on execute simplement:\n", "`eigen_basis(A, l, base)`\n", "\n", "Si vous ne trouvez pas de base pour l'espace propre, vous pouvez simplement afficher la solution en exécutant `eigen_basis(A, l)`. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A1 = sp.Matrix([[-1, 3], [-1, 3]])\n", "A2 = sp.Matrix([[4, 4], [3, 0]])\n", "\n", "# Simplement pour lambda = 3 (les autres valeurs propores sont complexes)\n", "A3 = sp.Matrix([[3, -4, -1], [0, -5, 8], [0, -1, -4]])\n", "\n", "# Trouver les valeurs propres en utilisant les racines évidentes du polynôme caractéristique\n", "A4 = sp.Matrix([[4, -1, 6],[2, 1, 6], [2, -1, 8]])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Matrice (A1, A2, A3 ou A4)\n", "A = A1\n", "display(A)\n", "\n", "# Rentrer une valeur propre que vous avez calculé\n", "l = 0\n", "\n", "# Base que vous avez calculé associé à la valeur propre ci-dessus\n", "base = [[1, 1], [1, 2]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Solution étape par étape et vérification de la base calculée\n", "eigen_basis(A1, l, base)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Visualisation des espaces propres\n", "Les espaces propres des matrices $2\\times2$ et $3\\times3$ peuvent être représenté graphiquement.\n", "\n", "La fonction `plot_eigspace` permet de visualiser les espaces propres associer à chaque valeurs propres d'une matrice $2\\times2$ ou $3\\times3$. Pour utiliser cette function, il suffit de donner comme argument une matrice. Les valeurs propres et leur espace propre associé sont calculés par la fonction et ensuite affichés.\n", "\n", "Utilisez les matrices de l'**Exercice 1** afin de visualiser les espaces propres dont vous avez calculé les bases." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A_sp = sp.Matrix([[1,0,0], [0,2,0], [0, 0, 2]])\n", "plot_eigspace(A_sp)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Observations (MOOC 8.5)\n", "* On voit que l'origine est toujours compris dans n'importe quel espace propre. Un espace propre étant un espace sous-vectoriel, il contient forcément le vecteur nul (l'origine).\n", "\n", - "* Deux espaces propres associé à deux valeurs propres distinctes de la même matrice n'ont en commun que le vecteur nul (l'origine).\n", + "* Deux espaces propres associés à deux valeurs propres distinctes de la même matrice n'ont en commun que le vecteur nul (l'origine).\n", "\n", "* Deux vecteurs propres associés à des valeurs propres distinctes sont linéairement indépendants." ] - }, - { - "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.7.2" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git "a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.8 Crit\303\250re de diagonalisabilit\303\251.ipynb" "b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.8 Crit\303\250re de diagonalisabilit\303\251.ipynb" index dee370c..7a05c9c 100644 --- "a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.8 Crit\303\250re de diagonalisabilit\303\251.ipynb" +++ "b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.8 Crit\303\250re de diagonalisabilit\303\251.ipynb" @@ -1,1624 +1,196 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Théorème\n", "Soit $\\phi: V \\rightarrow V$ une transformation linéaire d'un $\\mathbb{R}$-espace vectoriel $V$ de dimension finie $n \\in \\mathbb{N}$. Alors $\\phi$ est diagonalisable si et seulement si il existe $a \\in \\mathbb{R}, \\lambda_{1}, \\ldots, \\lambda_{r} \\in \\mathbb{R}$ distincts et $m_{1}, \\ldots, m_{r} \\in \\mathbb{N}$ tels que\n", "$$c_{\\phi}(t)=a\\left(t-\\lambda_{1}\\right)^{m_{1}} \\ldots\\left(t-\\lambda_{r}\\right)^{m_{r}}$$\n", "et $m_{i}=\\operatorname{dim} E_{\\lambda_{i}}$ pour tout $1 \\leq i \\leq n$\n", "\n", "### Critère equivalent de diagonalisabilité\n", "Une matrice $A$ $n \\times n$ est diagonalisable si et seulement si A possède $n$ vecteurs propres linéairement indépendant." ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - " \n", - " " - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import sys, os\n", "sys.path.append('../Librairie')\n", "import AL_Fct as al\n", "import numpy as np\n", "import sympy as sp\n", "from IPython.utils import io\n", "from IPython.display import display, Latex, Markdown\n", "import plotly\n", "import plotly.graph_objects as go\n", "from Ch8_lib import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercice 1\n", "À l'aide de la représentation graphique des espaces propres associés aux différentes valeurs propres d'une matrice, determinez si cette dernière est diagonalisable. (Aucun long calcul requis).\n", "\n", "**Si besoin, la méthode à appliquer est donnée plus bas.**" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "linkText": "Export to plot.ly", - "plotlyServerURL": "https://plot.ly", - "showLink": false - }, - "data": [ - { - "marker": { - "size": 6 - }, - "mode": "lines+markers", - "name": "$\\lambda = 3$", - "type": "scatter", - "x": [ - -10, - -9, - -8, - -7, - -6, - -5, - -4, - -3, - -2, - -1, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10 - ], - "y": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ] - } - ], - "layout": { - "autosize": true, - "showlegend": true, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "#2a3f5f" - }, - "error_y": { - "color": "#2a3f5f" - }, - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "baxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "#EBF0F8" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "#C8D4E3" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowcolor": "#2a3f5f", - "arrowhead": 0, - "arrowwidth": 1 - }, - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "colorscale": { - "diverging": [ - [ - 0, - "#8e0152" - ], - [ - 0.1, - "#c51b7d" - ], - [ - 0.2, - "#de77ae" - ], - [ - 0.3, - "#f1b6da" - ], - [ - 0.4, - "#fde0ef" - ], - [ - 0.5, - "#f7f7f7" - ], - [ - 0.6, - "#e6f5d0" - ], - [ - 0.7, - "#b8e186" - ], - [ - 0.8, - "#7fbc41" - ], - [ - 0.9, - "#4d9221" - ], - [ - 1, - "#276419" - ] - ], - "sequential": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "sequentialminus": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ] - }, - "colorway": [ - "#636efa", - "#EF553B", - "#00cc96", - "#ab63fa", - "#FFA15A", - "#19d3f3", - "#FF6692", - "#B6E880", - "#FF97FF", - "#FECB52" - ], - "font": { - "color": "#2a3f5f" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "#E5ECF6", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "mapbox": { - "style": "light" - }, - "paper_bgcolor": "white", - "plot_bgcolor": "#E5ECF6", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "line": { - "color": "#2a3f5f" - } - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "title": { - "x": 0.05 - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - } - } - } - } - }, - "text/html": [ - "
\n", - " \n", - " \n", - "
\n", - " \n", - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "A1 = sp.Matrix([[3, 4], [0, 3]])\n", "A2 = sp.Matrix([[1, 3], [4,5]])\n", "A3 = sp.Matrix([[5, 0, 0],[0, 1, 0], [1, 0, 1]])\n", "A4 = sp.Matrix([[1, 0, -2],[2 ,1, 0], [0, 0, 3]])\n", "\n", "# Choisir matrice (A = A1 ou A = A2 ...)\n", "A = A1\n", "\n", "# La fonction plot_eigspace affiche l'espace propre associé a chaque valeurs propre de la matrice A.\n", "plot_eigspace(A)\n" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "Oui la matrice $A = \\left(\\begin{matrix}5 & 0 & 0\\\\0 & 1 & 0\\\\1 & 0 & 1\\end{matrix}\\right)$ est diagonalisable." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Votre réponse est correcte !" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "# Affiche la solution pour la matrice A = A1 ou A = A2 ...\n", - "A = A3\n", "# Votre réponse a : La matrice A est-elle diagonlisable ? (True pour oui, False pour non)\n", "my_answer = True\n", "\n", "ch8_8_ex_1(A, my_answer)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Méthode exercice 1 (en utilisant le théorème donné dans le MOOC)\n", "On sait que le polynôme caractéristique d'une matrice $A (n \\times n)$ est d'ordre $n$. \n", "\n", "Avec $c_A(t)=a(t-\\lambda_{1})^{m_{1}} \\ldots (t-\\lambda_{r})^{m_{r}}$, avec $a \\in \\mathbb{R}$, $r\\leq n$ et $\\lambda_{1}, \\ldots, \\lambda_{r} \\in \\mathbb{R}$ distincts, on peut en déduire que $\\sum_{i=1}^r m_i = n$\n", "\n", "Sachant également que $\\dim E_{\\lambda_i} \\leq m_i$, on a $m_i = \\dim E_{\\lambda_i} $ pour tout $ i = 1, .., r$ si et seulement si $\\sum_{i=1}^r \\dim E_{\\lambda_i} = n$ \n", "\n", "Le théorème donné plus haut indique qu'une matrice est diagonalisable si et seulement si $m_i = \\dim E_{\\lambda_i}$ pour tout $ i = 1, .., r$. \n", "\n", "On vient de montrer que c'est équivalent à $\\sum_{i=1}^r \\dim E_{\\lambda_i} = n$.\n", "\n", "Grâce à la représentation graphique des espaces propres, on connait la dimension de chaque espace propre (droite -> $\\dim E_{\\lambda_i} = 1$, plan -> $\\dim E_{\\lambda_i}=2$). Il suffit donc de vérifier que la somme des dimensions de tous les espaces propres est bien égal à $n$.\n", "\n", "#### Méthode exercice 1 (en utilisant le critère equivalent de diagonalisabilité)\n", "Plus simplement, on peut simplement vérifier si il existe $n$ vecteur propres linéairement indépendants. En sachant que deux vecteurs propres associés à des valeurs propres différentes sont linéairement indépendants.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercice 2\n", "Determinez si les matrices suivantes sont diagonalisables. Essayez d'utiliser la méthode la plus simple pour chaque cas.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A1 = sp.Matrix([[1, 2], [3, 2]])\n", "A2 = sp.Matrix([[5, -7], [0, 5]])\n", "A3 = sp.Matrix([[3, 5, -10], [1, 7, 2], [-2, 2, 4]])\n", "A4 = sp.Matrix([[3, 5, -10], [1, 7, 2], [-2, 2, 4]])\n", "A5 = sp.Matrix([[1, 0, 0, 0],[11, -5, 0, 0],[-1, 2, 3, 0],[0, -2, 1, -3]])\n", "A6 = sp.Matrix([[-1, 0, 0, 0],[11, -5, 0, 0],[-1, 2, -1, 0],[0, -2, 1, -1]])\n", "\n", - "display(A1)" + "A = A1\n", + "display(A)" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "On cherche à déterminer si la matrice $A=\\left(\\begin{matrix}3 & 4\\\\0 & 3\\end{matrix}\\right)$ de taille $n \\times n$ avec $n = 2$ est diagonalisable." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Les valeurs propres sont simple à trouver, ce sont les éléments diagonaux." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Les valeurs propres ne sont pas toutes distinctes. On va donc vérifier la multiplicité géométrique des valeurs propres ayant une multiplicité algébrique supérieur à 1." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "L'ensemble des valeurs propres ayant une multiplicité algébrique supérieur à 1 est [3]." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**On calcule la multiplicité géométrique pour $\\lambda= 3$ ayant une multiplicité algébrique de 2.**" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On a $ A = \\left(\\begin{matrix}3 & 4\\\\0 & 3\\end{matrix}\\right)$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On cherche une base de l'espace propre associé à $\\lambda = 3$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On échelonne la matrice du système $A -\\lambda I = 0 \\Rightarrow \\left(\\begin{array}{cc| cc} 0 & 4 & 0 \\\\0 & 0 & 0 \\end{array}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On obtient: $\\left(\\begin{array}{cc| cc} 0 & 1 & 0 \\\\0 & 0 & 0 \\end{array}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Variable(s) libre(s): $x_1 \\ $" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On peut donc exprimer la base de l'espace propre comme: $x_1 \\cdot\\left(\\begin{array}{c} 1 \\\\0 \\end{array}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**La multiplicité géométrique pour $\\lambda= 3$ est de 1.**" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**La multiplicité géométrique est strictement inférieur à la multiplicitéalgébrique pour cette valeur propre. La matrice n'est donc pas diagonalisable.**" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Affiche la solution étape par étape pour la matrice donné en argument de la fonction isDiagonalizable\n", - "isDiagonalizable(A1)\n" + "isDiagonalizable(A)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Méthode de diagonalisation\n", "Une matrice diagonalisable peut s'exprimer comme: $$A = PDP^{-1}$$ avec $D$ une matrice diagonale, si et seulement si les colonnes de $P$ sont $n$ vecteurs propres de $A$ linéairement indépendants. Dans ce cas, les éléments diagonaux de $D$ sont les valeurs propres de $A$ qui correspondent, respectivement, aux vecteurs propres dans $P$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercice 3\n", "Pour les matrices $A$ diagonalisables suivantes, donnez les matrices $P$ et $D$ telles que $A = P D P^{-1}$." ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}1 & 6 & 2\\\\0 & 3 & 0\\\\2 & -6 & 1\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[1, 6, 2],\n", - "[0, 3, 0],\n", - "[2, -6, 1]])" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "A1 = sp.Matrix([[2, 3], [1, 4]])\n", "A2 = sp.Matrix([[0, 0], [-2, -4]])\n", "A3 = sp.Matrix([[1, 6, 2], [0, 3, 0], [2, -6, 1]])\n", "A4 = sp.Matrix([[-2, -7, -1], [0, 1, 0], [-1, -13, -2]])\n", "\n", - "A = A3\n", + "A = A1\n", "display(A)\n" ] }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "On cherche à déterminer les matrices $P$ et $D$ telles que $A=\\left(\\begin{matrix}1 & 6 & 2\\\\0 & 3 & 0\\\\2 & -6 & 1\\end{matrix}\\right)= P D P^{-1}$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On cherche les valeurs propres de la matrice $ A=\\left(\\begin{matrix}1 & 6 & 2\\\\0 & 3 & 0\\\\2 & -6 & 1\\end{matrix}\\right)$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Le polynome caractéristique de $A$ est: $$\\det(A- \\lambda I)= - \\lambda^{3} + 5 \\lambda^{2} - 3 \\lambda - 9=- \\left(\\lambda - 3\\right)^{2} \\left(\\lambda + 1\\right)$$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Les racines du polynôme caractéristique sont $\\left[ -1, \\ 3\\right]$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Ces racines sont les valeurs propres de la matrice $A$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Pour chaque valeur propre $\\lambda_i$, on cherche $n_i$ vecteurs propres linéairement indépendants (avec $n_i = \\dim E_{\\lambda_i}$). On trouve ces vecteurs on calculant une base pour chaque espace propre. On peut ensuite utiliser les vecteurs de base comme colonnes pour la matrice $P$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On cherche une base de l'espace propre associé à $\\lambda = -1$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On échelonne la matrice du système $A -\\lambda I = 0 \\Rightarrow \\left(\\begin{array}{ccc| cc} 2 & 6 & 2 & 0 \\\\0 & 4 & 0 & 0 \\\\2 & -6 & 2 & 0 \\end{array}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On obtient: $\\left(\\begin{array}{ccc| cc} 1 & 0 & 1 & 0 \\\\0 & 1 & 0 & 0 \\\\0 & 0 & 0 & 0 \\end{array}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Variable(s) libre(s): $x_3 \\ $" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On peut donc exprimer la base de l'espace propre comme: $x_3 \\cdot\\left(\\begin{array}{c} -1 \\\\0 \\\\1 \\end{array}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On cherche une base de l'espace propre associé à $\\lambda = 3$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On échelonne la matrice du système $A -\\lambda I = 0 \\Rightarrow \\left(\\begin{array}{ccc| cc} -2 & 6 & 2 & 0 \\\\0 & 0 & 0 & 0 \\\\2 & -6 & -2 & 0 \\end{array}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On obtient: $\\left(\\begin{array}{ccc| cc} 1 & -3 & -1 & 0 \\\\0 & 0 & 0 & 0 \\\\0 & 0 & 0 & 0 \\end{array}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Variable(s) libre(s): $x_2 \\ x_3 \\ $" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "On peut donc exprimer la base de l'espace propre comme: $x_2 \\cdot\\left(\\begin{array}{c} 3 \\\\1 \\\\0 \\end{array}\\right) + x_3 \\cdot\\left(\\begin{array}{c} 1 \\\\0 \\\\1 \\end{array}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "En utilisant les vecteurs de base trouvés ci dessus pour les colonnes de la matrice $P$ et en plaçant les valeurs propres de $A$ correspondantes sur la diagonal de $D$, on obtient les matrices $P$ et $D$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "$P = \\left(\\begin{matrix}-1 & 3 & 1\\\\0 & 1 & 0\\\\1 & 0 & 1\\end{matrix}\\right)$, $D = \\left(\\begin{matrix}-1 & 0 & 0\\\\0 & 3 & 0\\\\0 & 0 & 3\\end{matrix}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Votre réponse est incorrecte, $A \\neq PDP^{-1}$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "A = A3\n", - "P = sp.Matrix([[0,0], [0,0]])\n", - "D = sp.Matrix([[1, 0], [0, 1]])\n", - "\n", - "find_P_D(A, sp.eye(A.shape[0]), sp.eye(A.shape[0]))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "D = sp.Matrix([[0,0], [0, -4]])\n", - "P = sp.Matrix([[2, 0], [-1, 3]])\n", + "# Entrez les matrices P et D trouvée\n", + "P_user = sp.Matrix([[1,0], [0,1]])\n", + "D_user = sp.Matrix([[1, 0], [0, 1]])\n", "\n", - "P*D*P**-1" + "find_P_D(A, P_user, D_user)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "A1 = sp.Matrix([[]])\n", - "A3 = sp.Matrix([[1, 6, 2], [0, 3, 0], [2, -6, 1]])\n", - "\n", - "\n", - "P = sp.Matrix([[-1, 3, 1], [0, 1, 0], [1, 0, 1]])\n", - "D = sp.Matrix([[-1, 0, 0], [0, 3, 0], [0, 0, 3]])\n", - "\n", - "find_P_D(A3, P, D, step_by_step = True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "A = np.random" - ] - }, - { - "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.7.2" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.9 Valeurs propres complexes.ipynb b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.9 Valeurs propres complexes.ipynb index 4573cf1..6d8575a 100644 --- a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.9 Valeurs propres complexes.ipynb +++ b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/8.9 Valeurs propres complexes.ipynb @@ -1,458 +1,113 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Théorème fondamental de l'algèbre:\n", "\n", "Soit $p(x) \\in \\mathbb{P}(\\mathbb{C})$ un polynôme à coefficients dans $\\mathbb{C}$. Alors $p(x)$ se factorise en un produit de facteurs linéaires, i.e. il existe $\\lambda_{1}, \\ldots, \\lambda_{r} \\in \\mathbb{R}$ et\n", "$\\mu_{1}, \\ldots, \\mu_{2 s} \\in \\mathbb{C}$ tels que\n", "$$\n", "p(x)=\\pm\\left(x-\\lambda_{1}\\right) \\cdots\\left(x-\\lambda_{r}\\right)\\left(x-\\mu_{1}\\right) \\cdots\\left(x-\\mu_{2 s}\\right)\n", "$$\n", "\n", - "De plus, si $v=a+i b \\in \\mathbb{C}$ est une racine de $p(x),$ alors $\\bar{\\mu}=a-i b$ est également une racine de $p(x)$\n", + "De plus, si $\\mu=a+i b \\in \\mathbb{C}$ est une racine de $p(x),$ alors $\\bar{\\mu}=a-i b$ est également une racine de $p(x)$\n", "\n", "### Critère de diagonalisabilité sur $\\mathbb{C}$ \n", "\n", - "Une transformation linéaire $\\phi: V \\rightarrow V$ d'un $\\mathbb{C}$ -espace vectoriel de dimension finie est diagonalisable si et seulement si la multiplicité géométrique de chaque valeur propre de $\\phi$ est égale à sa multipicité algébrique." + "Une transformation linéaire $\\phi: V \\rightarrow V$ d'un $\\mathbb{C}$-espace vectoriel de dimension finie est diagonalisable si et seulement si la multiplicité géométrique de chaque valeur propre de $\\phi$ est égale à sa multipicité algébrique." ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - " \n", - " " - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import sys, os\n", "sys.path.append('../Librairie')\n", "import AL_Fct as al\n", "import numpy as np\n", "import sympy as sp\n", "from IPython.utils import io\n", "from IPython.display import display, Latex, Markdown\n", "import plotly\n", "import plotly.graph_objects as go\n", "from Ch8_lib import *\n", "from sympy import I" ] }, { - "cell_type": "code", - "execution_count": 290, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}0 & -1 & 0 & 0\\\\0 & -1 & -1 & -1\\\\-1 & 0 & 0 & -1\\\\-1 & 0 & -1 & 0\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[ 0, -1, 0, 0],\n", - "[ 0, -1, -1, -1],\n", - "[-1, 0, 0, -1],\n", - "[-1, 0, -1, 0]])" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], "source": [ - "A1 = sp.Matrix([[0, 1], [-1, 0]])\n", - "A2 = sp.Matrix([[0, 0, 0], [0, -2, 1], [-2, -1, -2]])\n", - "A3 = sp.Matrix([[0, -1, 0, 0], [0, -1, -1, -1], [-1, 0, 0, -1], [-1, 0, -1, 0]])\n", + "### Exerice 1\n", + "En utilisant la même méthode de diagonalisation que précedemment, diagonalisez les matrices suivantes. Donnez les matrices P et D.\n", "\n", - "display(A3)\n", - "\n" + "Certaines valeurs propres de ces matrices à coefficients réels sont complexes. Toutefois, l'échelonnage et les autres opérations sur les matrices sont applicables de manière similaire à ce que l'on a vu avec les nombres réels. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "D = sp.Matrix([[1-I, 0, 0], [0, 1+I, 0], [0, 0, 2]])\n", - "\n", - "P * D * P**-1" - ] - }, - { - "cell_type": "code", - "execution_count": 284, - "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}-3 & -1 & -2 & -3\\\\0 & -3 & 2 & -2\\\\3 & 0 & 0 & 3\\\\0 & 0 & -1 & -2\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[-3, -1, -2, -3],\n", - "[ 0, -3, 2, -2],\n", - "[ 3, 0, 0, 3],\n", - "[ 0, 0, -1, -2]])" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "{-2: 1, -3: 1, -3/2 - 3*sqrt(3)*I/2: 1, -3/2 + 3*sqrt(3)*I/2: 1}" - ] - }, - "execution_count": 284, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A = np.random.randint(-3, 4, (4,4))\n", - "A = sp.Matrix(A)\n", - "display(A)\n", - "A.eigenvals()" - ] - }, - { - "cell_type": "code", - "execution_count": 83, - "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}-1 & 0 & 1 & 1\\\\1 & 0 & 0 & -1\\\\1 & 1 & 0 & 0\\\\0 & 0 & 1 & -1\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[-1, 0, 1, 1],\n", - "[ 1, 0, 0, -1],\n", - "[ 1, 1, 0, 0],\n", - "[ 0, 0, 1, -1]])" - ] - }, - "execution_count": 83, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}1 & 0 & 0 & 1 + i\\\\0 & 1 & 0 & 1 - i\\\\0 & 0 & 1 & -1\\\\0 & 0 & 0 & 0\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[1, 0, 0, 1 + I],\n", - "[0, 1, 0, 1 - I],\n", - "[0, 0, 1, -1],\n", - "[0, 0, 0, 0]])" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "A = sp.Matrix([[0, -1, 0, 0], [0, -1, -1, -1], [-1, 0, 0, -1], [-1, 0, -1, 0]])\n", - "eig = A.eigenvects()\n", + "A1 = sp.Matrix([[0, 1], [-1, 0]])\n", + "A2 = sp.Matrix([[0, 0, 0], [0, -2, 1], [-2, -1, -2]])\n", + "A3 = sp.Matrix([[0, -1, 0, 0], [0, -1, -1, -1], [-1, 0, 0, -1], [-1, 0, -1, 0]])\n", "\n", "\n", - "A_ech = (A - sp.eye(4)*I).rref()\n", - "display(sp.simplify(A_ech[0]))" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}-1 - i\\\\-1 + i\\\\1\\\\1\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[-1 - I],\n", - "[-1 + I],\n", - "[ 1],\n", - "[ 1]])" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sp.simplify(eig[3][2][0])" + "A = A1\n", + "display(A)" ] }, { "cell_type": "code", - "execution_count": 83, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "def diagonalizeComplex(A):\n", - " if not A.is_diagonalizable():\n", - " display(Latex(\"A n'est pas diagonalisable.\"))\n", - " return\n", - " \n", - " lamda = sp.symbols('lamda')\n", - " poly = A.charpoly(lamda)\n", - " poly = sp.factor(poly, extension=[I])\n", - " eig = A.eigenvects()\n", - " \n", - " eigenval = []\n", - " mult = []\n", - " \n", - " for el in eig:\n", - " eigenval.append(sp.simplify(el[0]))\n", - " mult.append(el[1])\n", - " \n", - " display(Latex(\"Le polynome caractéristique de la matrice $A = \" + latexp(A) + \"$ est $ c_A (\\lambda) = \" + sp.latex(poly) + \"$\"))\n", - " \n", - " display(Latex(\"Les valeurs propres de A sont donc: \" + listsp_to_str(eigenval)))\n", - " \n", - " display(Latex(\"Pour chaque valeur propre $\\lambda$, on calcule une base de l'espace propre associé \"\n", - " \"($\\ker (A -\\lambda I)$). On se sert ensuite des vecteurs propres (vecteur de base de l'espaces\" +\n", - " \" propre) pour diagonaliser la matrice.\"))\n", - " \n", - " \n", - " k = 0\n", - " P = sp.zeros(A.shape[0], A.shape[0])\n", - " D = sp.zeros(A.shape[0], A.shape[0])\n", - " for i, l in enumerate(eigenval):\n", - " display(Latex(\"Pour la valeur propres $\\lambda = \" + sp.latex(l) + \"$, on trouve une base de l'espace propre associé. \"\n", - " + \"On obtient comme base: \" + listsp_to_str(eig[i][2])))\n", - " \n", - " for vec in eig[i][2]:\n", - " P[:, k] = vec\n", - " D[k, k] = l\n", - " k+=1\n", - " \n", - " P = sp.simplify(P)\n", - " D = sp.simplify(D)\n", - " \n", - " display(Latex(\"Avec la matrice $D= \" + latexp(D) + \"$ on obtient la matrice $P = \" + latexp(P) + \"$.\"))\n", - " \n", - " display(Latex(\"La matrice $A$ se diagonalise donc avec comme $A = P D P^{-1}$\"))\n", - " \n", - " display(Latex(\"$P D P^{-1} = \" + latexp(P) + latexp(D) + latexp(sp.simplify(P**-1)) + \" = \" + \n", - " latexp(sp.simplify(P*D*P**-1)) +\" = A$ \"))\n", - " \n", - "def listsp_to_str(splist):\n", - " out = \"$\" + sp.latex(sp.simplify(splist[0]), mat_delim='(') + \"$\"\n", - " \n", - " if len(splist)==1:\n", - " return out\n", - " \n", - " for i in range(1, len(splist)-1):\n", - " out += \", $\" + sp.latex(sp.simplify(splist[i]), mat_delim='(') + \"$\"\n", - " \n", - " out += \" et $\" + sp.latex(sp.simplify(splist[-1]), mat_delim='(') + \"$\"\n", - " return out" + "# Entrez vos matrices P et D\n", + "P = sp.Matrix([[1, 0], [0, 1]])\n", + "D = sp.Matrix([[1, 0], [0, 1]])\n", + "\n", + "# Vérifier votre résultat en regardant si A est égale P*A*P**-1\n", + "display(Latex(\"$A = \" + latexp(A) + \"$\"))\n", + "display(Latex(\"$ P D P^{-1} = \" + latexp(P*D*P**-1) + \"$\"))\n" ] }, { "cell_type": "code", - "execution_count": 84, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "Le polynome caractéristique de la matrice $A = \\left(\\begin{matrix}0 & -1 & 0 & 0\\\\0 & -1 & -1 & -1\\\\-1 & 0 & 0 & -1\\\\-1 & 0 & -1 & 0\\end{matrix}\\right)$ est $ c_A (\\lambda) = \\left(\\lambda - 1\\right) \\left(\\lambda + 2\\right) \\left(\\lambda - i\\right) \\left(\\lambda + i\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Les valeurs propres de A sont donc: $-2$, $1$, $- i$ et $i$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Pour chaque valeur propre $\\lambda$, on calcule une base de l'espace propre associé ($\\ker (A -\\lambda I)$). On se sert ensuite des vecteurs propres (vecteur de base de l'espaces propre) pour diagonaliser la matrice." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Pour la valeur propres $\\lambda = -2$, on trouve une base de l'espace propre associé. On obtient comme base: $\\left(\\begin{matrix}1\\\\2\\\\1\\\\1\\end{matrix}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Pour la valeur propres $\\lambda = 1$, on trouve une base de l'espace propre associé. On obtient comme base: $\\left(\\begin{matrix}0\\\\0\\\\-1\\\\1\\end{matrix}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Pour la valeur propres $\\lambda = - i$, on trouve une base de l'espace propre associé. On obtient comme base: $\\left(\\begin{matrix}-1 + i\\\\-1 - i\\\\1\\\\1\\end{matrix}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Pour la valeur propres $\\lambda = i$, on trouve une base de l'espace propre associé. On obtient comme base: $\\left(\\begin{matrix}-1 - i\\\\-1 + i\\\\1\\\\1\\end{matrix}\\right)$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "Avec la matrice $D= \\left(\\begin{matrix}-2 & 0 & 0 & 0\\\\0 & 1 & 0 & 0\\\\0 & 0 & - i & 0\\\\0 & 0 & 0 & i\\end{matrix}\\right)$ on obtient la matrice $P = \\left(\\begin{matrix}1 & 0 & -1 + i & -1 - i\\\\2 & 0 & -1 - i & -1 + i\\\\1 & -1 & 1 & 1\\\\1 & 1 & 1 & 1\\end{matrix}\\right)$." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "La matrice $A$ se diagonalise donc avec comme $A = P D P^{-1}$" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/latex": [ - "$P D P^{-1} = \\left(\\begin{matrix}1 & 0 & -1 + i & -1 - i\\\\2 & 0 & -1 - i & -1 + i\\\\1 & -1 & 1 & 1\\\\1 & 1 & 1 & 1\\end{matrix}\\right)\\left(\\begin{matrix}-2 & 0 & 0 & 0\\\\0 & 1 & 0 & 0\\\\0 & 0 & - i & 0\\\\0 & 0 & 0 & i\\end{matrix}\\right)\\left(\\begin{matrix}\\frac{1}{5} & \\frac{1}{5} & \\frac{1}{5} & \\frac{1}{5}\\\\0 & 0 & - \\frac{1}{2} & \\frac{1}{2}\\\\- \\frac{1}{10} - \\frac{3 i}{10} & - \\frac{1}{10} + \\frac{i}{5} & \\frac{3}{20} - \\frac{i}{20} & \\frac{3}{20} - \\frac{i}{20}\\\\\\frac{i \\left(3 + i\\right)}{10} & \\frac{i \\left(-2 + i\\right)}{10} & \\frac{3}{20} + \\frac{i}{20} & \\frac{3}{20} + \\frac{i}{20}\\end{matrix}\\right) = \\left(\\begin{matrix}0 & -1 & 0 & 0\\\\0 & -1 & -1 & -1\\\\-1 & 0 & 0 & -1\\\\-1 & 0 & -1 & 0\\end{matrix}\\right) = A$ " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ + "# Cette fonction affiche la correction étape par étape pour la matrice A.\n", "diagonalizeComplex(A)" ] - }, - { - "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.7.2" } }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/Ch8_lib.py b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/Ch8_lib.py index a12a9cb..628ab11 100644 --- a/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/Ch8_lib.py +++ b/Chapitre 8 - Valeurs propres, vecteurs propres, diagonalisation/Ch8_lib.py @@ -1,829 +1,962 @@ import sys, os sys.path.append('../Librairie') import AL_Fct as al import numpy as np import sympy as sp from IPython.utils import io from IPython.display import display, Latex, Markdown import plotly import plotly.graph_objects as go +from sympy import I as I_sym + + +def vector_plot(v, b): + """ + Show plot of a two vector v and b to identify if a vector is an eigenvector. (b is equal to A*v with A a matrix) + @param v: numpy array of shape (2,) or (3,) + @param b: numpy array of shape as v + """ + if not isinstance(v, np.ndarray) or not isinstance(b, np.ndarray): + raise ValueError('Both vector should be numpy array') + + if v.shape != b.shape or len(v.shape)>1: + raise ValueError('Both vector should be of same shape (2,) or (3,)') + + if v.shape[0]==3: + vector_plot_3D(v, b) + elif v.shape[0] == 2: + vector_plot_2D(v, b) + else: + raise ValueError('Vector should 2D or 3D') + + def vector_plot_3D(v, b): """ Show 3D plot of a vector (v) and of b = A * v @param v: numpy array of shape (3,) @param b: numpy array of shape (3,) @return: """ fig = go.Figure() fig.add_trace(go.Scatter3d(x=[0, v[0]], y=[0, v[1]], z=[0, v[2]], line=dict(color='red', width=4), mode='lines+markers', name='$v$')) fig.add_trace(go.Scatter3d(x=[0, b[0]], y=[0, b[1]], z=[0, b[2]], line=dict(color='royalblue', width=4, dash='dash'), mode='lines+markers', name='$A \ v$')) fig.show() +def vector_plot_2D(v, b): + """ + Show 2D plot of a vector (v) and of b = A * v + @param v: numpy array of shape (2,) + @param b: numpy array of shape (2,) + @return: + """ + fig = go.Figure() + + fig.add_trace(go.Scatter(x=[0, v[0]], y=[0, v[1]], + line=dict(color='red', width=4), + mode='lines+markers', + name='$v$')) + + fig.add_trace(go.Scatter(x=[0, b[0]], y=[0, b[1]], + line=dict(color='royalblue', width=4, dash='dash'), + mode='lines+markers', + name='$A \ v$')) + + fig.show() + def CheckEigenVector(A, v): """ Check if v is an eigenvector of A, display step by step solution @param A: square sympy Matrix of shape (n,n) @param v: 1D sympy Matrix of shape (n,1) @return: """ + + if not isinstance(A, sp.Matrix) or not isinstance(v, sp.Matrix): + raise ValueError('A and v should be of type sympy matrix') + # Check Dimensions if A.shape[0] != A.shape[1] or v.shape[0] != A.shape[1]: raise ValueError('Dimension problem, A should be square (n x n) and v (n x 1)') if v == sp.zeros(v.shape[0], 1): display(Latex("$v$ est le vecteur nul, il ne peut pas être un vecteur propre par définition.")) else: # Matrix Multiplication b = A * v # Print some explanation about the method display(Latex("On voit que $ b = A v = " + latexp(b) + "$")) display(Latex("On cherche alors un nombre $\lambda \in \mathbb{R}$ tel que $b = \lambda v" \ + "\Leftrightarrow" + latexp(b) + " = \lambda" + latexp(v) + '$')) # Symbol for lambda l = sp.symbols('\lambda', real=True) # Check if there is a solution lambda of eq: A*v = lambda * v eq = sp.Eq(b, l * v) sol = sp.solve(eq, l) # If there is l st b = l*v if sol: display(Latex("Il existe bien une solution pour $\lambda$. Le vecteur $v$ est donc un vecteur \ propre de la matrice $A$.")) display(Latex("La valeur propre associée est $\lambda = " + sp.latex(sol[l]) + "$.")) # Otherwise else: display(Latex("L'equation $b = \lambda v$ n'a pas de solution.")) display(Latex("Le vecteur $v$ n'est donc pas un vecteur propre de la matrice $A$.")) def ch8_1_exo_2(A, l, vp, v): """ Display step by step @param A: Square sympy matrix @param l: eigenvalue (float or int) @param vp: Boolean, given answer to question is l an eigenvalue of A @param v: proposed eigenvector @return: """ + if not isinstance(A, sp.Matrix): + raise ValueError("A should be a sympy matrix") + # Check Dimensions if A.shape[0] != A.shape[1] or v.shape[0] != A.shape[1]: raise ValueError('Dimension problem, A should be square (n x n) and v (n x 1)') n = A.shape[0] eig = list(A.eigenvals().keys()) for i, w in enumerate(eig): eig[i] = float(w) eig = np.array(eig) if np.any(abs(l-eig) < 10**-10): if vp: display(Latex("$\lambda = " + str(l) + "$ est bien une valeur propre de la matrice $A$.")) else: display(Latex("Non, $\lambda = " + str(l) + "$ est bien une valeur propre de la matrice $A$.")) if v != sp.zeros(n, 1): # Check the eigen vector v z = sp.simplify(A * v - l * v) if z == sp.zeros(n, 1): display(Latex("$v$ est bien un vecteur propre de $A$ associé à $\lambda = " + str(l) + "$ car on a:")) display(Latex("$$" + latexp(A) + latexp(v) + "= " + str(l) + "\cdot " + latexp(v) + "$$")) else: display(Latex("$v$ n'est pas un vecteur propre de $A$ associé à $\lambda = " + str(l) + "$ car on a:")) display(Latex("$$" + latexp(A) + latexp(v) + "\\neq \lambda" + latexp(v) + "$$")) else: display(Latex("$v$ est le vecteur nul et ne peut pas être par définition un vecteur propre.")) else: if vp: display(Latex("En effet, $\lambda$ n'est pas une valeur propre de $A$.")) else: display(Latex("Non, $\lambda = " + str(l) + "$ n'est pas une valeur propre de $A$.")) def red_matrix(A, i, j): """ Return reduced matrix (without row i and col j)""" row = [0, 1, 2] col = [0, 1, 2] row.remove(i - 1) col.remove(j - 1) return A[row, col] def pl_mi(i, j, first=False): """ Return '+', '-' depending on row and col index""" if (-1) ** (i + j) > 0: if first: return "" else: return "+" else: return "-" def brackets(expr): """Takes a sympy expression, determine if it needs parenthesis and returns a string containing latex of expr with or without the parenthesis.""" expr_latex = sp.latex(expr) if '+' in expr_latex or '-' in expr_latex: return "(" + expr_latex + ")" else: return expr_latex def Determinant_3x3(A, step_by_step=True, row=True, n=1): """ Step by step computation of the determinant of a 3x3 sympy matrix strating with given row/col number @param A: 3 by 3 sympy matrix @param step_by_step: Boolean, True: print step by step derivation of det, False: print only determinant @param row: True to compute determinant from row n, False to compute determinant from col n @param n: row or col number to compute the determinant from (int between 1 and 3) @return: display step by step solution for """ + if not isinstance(A, sp.Matrix): + raise ValueError("A should be a sympy matrix") if A.shape != (3, 3): raise ValueError('Dimension of matrix A should be 3x3. The input A must be a sp.Matrix of shape (3,3).') if n < 1 or n > 3 or not isinstance(n, int): raise ValueError('n should be an integer between 1 and 3.') # Construc string for determinant of matrix A detA_s = sp.latex(A).replace('[', '|').replace(']', '|') # To print all the steps if step_by_step: # If we compute the determinant with row n if row: # Matrix with row i and col j removed (red_matrix(A, i, j)) A1 = red_matrix(A, n, 1) A2 = red_matrix(A, n, 2) A3 = red_matrix(A, n, 3) detA1_s = sp.latex(A1).replace('[', '|').replace(']', '|') detA2_s = sp.latex(A2).replace('[', '|').replace(']', '|') detA3_s = sp.latex(A3).replace('[', '|').replace(']', '|') line1 = "$" + detA_s + ' = ' + pl_mi(n, 1, True) + brackets(A[n - 1, 0]) + detA1_s + pl_mi(n, 2) + \ brackets(A[n - 1, 1]) + detA2_s + pl_mi(n, 3) + brackets(A[n - 1, 2]) + detA3_s + '$' line2 = '$' + detA_s + ' = ' + pl_mi(n, 1, True) + brackets(A[n - 1, 0]) + "\cdot (" + sp.latex(sp.det(A1)) \ + ")" + pl_mi(n, 2) + brackets(A[n - 1, 1]) + "\cdot (" + sp.latex(sp.det(A2)) + ")" + \ pl_mi(n, 3) + brackets(A[n - 1, 2]) + "\cdot (" + sp.latex(sp.det(A3)) + ')$' line3 = '$' + detA_s + ' = ' + sp.latex(sp.simplify(sp.det(A))) + '$' # If we compute the determinant with col n else: # Matrix with row i and col j removed (red_matrix(A, i, j)) A1 = red_matrix(A, 1, n) A2 = red_matrix(A, 2, n) A3 = red_matrix(A, 3, n) detA1_s = sp.latex(A1).replace('[', '|').replace(']', '|') detA2_s = sp.latex(A2).replace('[', '|').replace(']', '|') detA3_s = sp.latex(A3).replace('[', '|').replace(']', '|') line1 = "$" + detA_s + ' = ' + pl_mi(n, 1, True) + brackets(A[0, n - 1]) + detA1_s + pl_mi(n, 2) + \ brackets(A[1, n - 1]) + detA2_s + pl_mi(n, 3) + brackets(A[2, n - 1]) + detA3_s + '$' line2 = '$' + detA_s + ' = ' + pl_mi(n, 1, True) + brackets(A[0, n - 1]) + "\cdot (" + sp.latex(sp.det(A1))\ + ")" + pl_mi(n, 2) + brackets(A[1, n - 1]) + "\cdot (" + sp.latex(sp.det(A2)) + ")" + \ pl_mi(n, 3) + brackets(A[2, n - 1]) + "\cdot (" + sp.latex(sp.det(A3)) + ')$' line3 = '$' + detA_s + ' = ' + sp.latex(sp.simplify(sp.det(A))) + '$' # Display step by step computation of determinant display(Latex(line1)) display(Latex(line2)) display(Latex(line3)) # Only print the determinant without any step else: display(Latex("$" + detA_s + "=" + sp.latex(sp.det(A)) + "$")) def valeurs_propres(A): + if not isinstance(A, sp.Matrix): + raise ValueError("A should be a sympy matrix") + + if A.shape[0] != A.shape[1]: raise ValueError("A should be a square matrix") l = sp.symbols('\lambda') n = A.shape[0] poly = sp.det(A - l * sp.eye(n)) poly_exp = sp.expand(poly) poly_factor = sp.factor(poly) det_str = sp.latex(poly_exp) + "=" + sp.latex(poly_factor) display(Latex("On cherche les valeurs propres de la matrice $ A=" + latexp(A) + "$.")) display(Latex("Le polynome caractéristique de $A$ est: $$\det(A- \lambda I)= " + det_str + "$$")) eq = sp.Eq(poly, 0) sol = sp.solve(eq, l) if len(sol) > 1: display(Latex("Les racines du polynôme caractéristique sont $" + sp.latex(sol) + "$.")) display(Latex("Ces racines sont les valeurs propres de la matrice $A$.")) else: display(Latex("L'unique racine du polynôme caractéristique est" + str(sol[0]))) def texVector(v): """ Return latex string for vertical vector Input: v, 1D np.array() """ n = v.shape[0] return al.texMatrix(v.reshape(n, 1)) def check_basis(sol, prop): """ Checks if prop basis is equivalent to sol basis @param sol: verified basis, 2D numpy array, first dim: vector indexes, second dim: idx of element in a basis vect @param prop: proposed basis @return: boolean """ prop = np.array(prop, dtype=np.float64) # number of vector in basis n = len(sol) # Check dimension of proposed eigenspace if n != len(prop): display(Latex("Le nomber de vecteur(s) propre(s) donné(s) est incorrecte. " + "La dimension de l'espace propre est égale au nombre de variable(s) libre(s).")) return False else: # Check if the sol vector can be written as linear combination of prop vector # Do least squares to solve overdetermined system and check if sol is exact A = np.transpose(prop) lin_comb_ok = np.zeros(n, dtype=bool) for i in range(n): x, _, _, _ = np.linalg.lstsq(A, sol[i], rcond=None) res = np.sum((A @ x - sol[i]) ** 2) lin_comb_ok[i] = res < 10 ** -13 return np.all(lin_comb_ok) def eigen_basis(A, l, prop_basis=None, disp=True, return_=False, dispA=True): """ Display step by step method for finding a basis of the eigenspace of A associated to eigenvalue l Eventually check if the proposed basis is correct. Display or not @param A: Square sympy Matrix with real coefficients @param l: real eigen value of A (float or int) @param prop_basis: Proposed basis: list of base vector (type list of list of floats) @param disp: boolean if display the solution. If false it displays nothing @param return_: boolean if return something or nothing @return: basis: a correct basis for the eigen space (2D numpy array) basic_idx: list with indices of basic variables of A - l*I free_idx: list with indices of free variables of A - l*I """ - if not A.is_Matrix: + if not isinstance(A, sp.Matrix): raise ValueError("A should be a sympy Matrix.") # Check if A is square n = A.shape[0] if n != A.shape[1]: raise ValueError('A should be a square matrix.') # Compute eigenvals in symbolic eig = A.eigenvals() eig = list(eig.keys()) # Deal with complex number (removal) complex_to_rm = [] for idx, el in enumerate(eig): if not el.is_real: complex_to_rm.append(idx) for index in sorted(complex_to_rm, reverse=True): del eig[index] eig = np.array(eig) # evaluate symbolic expression eig_eval = np.array([float(el) for el in eig]) # Check that entered eigenvalue is indeed an eig of A if np.all(abs(l - eig_eval) > 1e-10) and len(eig) > 0: display(Latex("$\lambda$ n'est pas une valeur propre de $A$.")) return None, None, None # Change value of entered eig to symbolic expression (for nice print) l = eig[np.argmin(np.abs(l - eig))] I = sp.eye(n) Mat = A - l * I b = np.zeros(n) if disp: if dispA: display(Latex("On a $ A = " + latexp(A) + "$.")) display(Latex("On cherche une base de l'espace propre associé à $\lambda = " + str(l) + "$.")) # ER matrix e_Mat, basic_idx = Mat.rref() # Idx of basic and free varialbe basic_idx = list(basic_idx) basic_idx.sort() free_idx = [idx for idx in range(n) if idx not in basic_idx] free_idx.sort() n_free = len(free_idx) # String to print free vars free_str = "" for i in range(n): if i in free_idx: free_str += "x_" + str(i + 1) + " \ " # Display echelon matrix if disp: display(Latex("On échelonne la matrice du système $A -\lambda I = 0 \Rightarrow " + al.texMatrix(np.array(Mat), np.reshape(b, (n, 1))) + "$")) display(Latex("On obtient: $" + al.texMatrix(np.array(e_Mat[:, :n]), np.reshape(b, (n, 1))) + "$")) display(Latex("Variable(s) libre(s): $" + free_str + "$")) # Build a list of n_free basis vector: # first dim: which eigenvector (size of n_free) # second dim: which element of the eigenvector (size of n) basis = np.zeros((n_free, n)) for i in range(n_free): basis[i, free_idx[i]] = 1.0 for idx, j in enumerate(free_idx): for i in basic_idx: basis[idx, i] = - float(e_Mat[i, j]) # Show calculated basis basis_str = "" for idx, i in enumerate(free_idx): basis_str += "x_" + str(i + 1) + " \cdot" + texVector(basis[idx]) if idx < n_free - 1: basis_str += " + " if disp: display(Latex("On peut donc exprimer la base de l'espace propre comme: $" + basis_str + "$")) if prop_basis is not None and disp: correct_answer = check_basis(basis, prop_basis) if correct_answer: display(Latex("La base donnée est correcte car on peut retrouver la base calculée ci-dessus" \ " avec une combinaison linéaire de la base donnée. " "Aussi les deux bases ont bien le même nombre de vecteurs.")) else: display(Latex("La base donnée est incorrecte.")) if return_: return basis, basic_idx, free_idx def generate_eigen_vector(basis, l, limit): """ Function to generate a random eigenvector associated to a eigenvalue given a basis of the eigenspace The returned eigenvector is such that itself and its multiplication with the matrix will stay in range of limit in order to have a nice plot @param basis: basis of eigenspace associated to eigenvalue lambda @param l: eigenvalue @param limit: limit of the plot: norm that the engenvector or its multiplication with the matrix will not exceed @return: eigen vector (numpy array) """ n = len(basis) basis_mat = np.array(basis).T basis_mat = basis_mat.astype(np.float64) coeff = 2 * np.random.rand(n) - 1 vect = basis_mat @ coeff if abs(l) <= 1: vect = vect / np.linalg.norm(vect) * (limit - 1) else: vect = vect / np.linalg.norm(vect) * (limit - 1) / l return vect def plot3x3_eigspace(A, xL=-10, xR=10, p=None, plot_vector=False): # To have integer numbers if p is None: p = xR - xL + 1 n = A.shape[0] # Check 3 by 3 if n != 3 or n != A.shape[1]: raise ValueError("A should be 3 by 3") w = A.eigenvals() w = list(w.keys()) # Deal with complex number (removal) complex_to_rm = [] for idx, el in enumerate(w): if not el.is_real: complex_to_rm.append(idx) for index in sorted(complex_to_rm, reverse=True): del w[index] display("Des valeurs propres sont complexes, on les ignore.") if len(w)==0: display("Toute les valeurs propres sont complexes.") return gr = 'rgb(102,255,102)' org = 'rgb(255,117,26)' # red = 'rgb(255,0,0)' blue = 'rgb(51, 214, 255)' colors = [blue, gr, org] s = np.linspace(xL, xR, p) t = np.linspace(xL, xR, p) tGrid, sGrid = np.meshgrid(s, t) data = [] A_np = np.array(A).astype(np.float64) for i, l in enumerate(w): l_eval = float(l) basis, basic_idx, free_idx = eigen_basis(A, l_eval, disp=False, return_=True) n_free = len(basis) if n_free != len(free_idx): raise ValueError("len(basis) and len(free_idx) should be equal.") gr = 'rgb(102,255,102)' colorscale = [[0.0, colors[i]], [0.1, colors[i]], [0.2, colors[i]], [0.3, colors[i]], [0.4, colors[i]], [0.5, colors[i]], [0.6, colors[i]], [0.7, colors[i]], [0.8, colors[i]], [0.9, colors[i]], [1.0, colors[i]]] X = [None] * 3 if n_free == 2: X[free_idx[0]] = tGrid X[free_idx[1]] = sGrid X[basic_idx[0]] = tGrid * basis[0][basic_idx[0]] + sGrid * basis[1][basic_idx[0]] plot_obj = go.Surface(x=X[0], y=X[1], z=X[2], showscale=False, showlegend=True, colorscale=colorscale, opacity=1, name="$ \lambda= " + sp.latex(l) + "$") elif n_free == 1: plot_obj = go.Scatter3d(x=t * basis[0][0], y=t * basis[0][1], z=t * basis[0][2], line=dict(colorscale=colorscale, width=4), mode='lines', name="$\lambda = " + sp.latex(l) + "$") elif n_free == 3: display(Latex("La dimension de l'espace propre de l'unique valeur propre est 3: tous les vecteurs" \ "$v \in \mathbb{R}^3 $ appartiennent à l'espace propre de la matrice $A$." \ "On ne peut donc pas reprensenter sous la forme d'un plan ou d'une droite.")) return else: print("error") return data.append(plot_obj) if (plot_vector): v1 = generate_eigen_vector(basis, l_eval, xR) v2 = A_np @ v1 data.append(go.Scatter3d(x=[0, v1[0]], y=[0, v1[1]], z=[0, v1[2]], line=dict(width=6), marker=dict(size=4), mode='lines+markers', name='$v_{' + sp.latex(l) + '}$')) data.append(go.Scatter3d(x=[0, v2[0]], y=[0, v2[1]], z=[0, v2[2]], line=dict(width=6, dash='dash'), marker=dict(size=4), mode='lines+markers', name="$A \ v_{" + sp.latex(l) + "}$")) layout = go.Layout( showlegend=True, # not there WHY???? --> LEGEND NOT YET IMPLEMENTED FOR SURFACE OBJECTS!! legend=dict(orientation="h"), autosize=True, width=800, height=800, scene=go.layout.Scene( xaxis=dict( gridcolor='rgb(255, 255, 255)', zerolinecolor='rgb(255, 255, 255)', showbackground=True, backgroundcolor='rgb(230, 230,230)', range=[xL, xR] ), yaxis=dict( gridcolor='rgb(255, 255, 255)', zerolinecolor='rgb(255, 255, 255)', showbackground=True, backgroundcolor='rgb(230, 230,230)', range=[xL, xR] ), zaxis=dict( gridcolor='rgb(255, 255, 255)', zerolinecolor='rgb(255, 255, 255)', showbackground=True, backgroundcolor='rgb(230, 230,230)', range=[xL, xR] ), aspectmode="cube", ) ) fig = go.Figure(data=data, layout=layout) plotly.offline.iplot(fig) return def plot2x2_eigspace(A, xL = -10, xR = 10, p=None): if p is None: p = xR - xL + 1 w = A.eigenvals() w = list(w.keys()) # Deal with complex number (removal) complex_to_rm = [] for idx, el in enumerate(w): if not el.is_real: complex_to_rm.append(idx) for index in sorted(complex_to_rm, reverse=True): del w[index] display("Une valeur propre est complexe, on l'ignore.") if len(w) == 0: display("Toute les valeurs propres sont complexes.") return data = [] for i, l in enumerate(w): l_eval = float(l) basis, basic_idx, free_idx = eigen_basis(A, l_eval, disp=False, return_=True) n_free = len(basis) if n_free != len(free_idx): raise ValueError("len(basis) and len(free_idx) should be equal.") if n_free == 2: display(Latex("Tous les vecteurs du plan appartiennent à l'espace propre de A associé à $\lambda = " \ + sp.latex(l) + "$. On ne peut donc pas le représenter.")) return else: t = np.linspace(xL, xR, p) trace = go.Scatter(x=t*basis[0][0], y=t*basis[0][1], marker=dict(size=6), mode='lines+markers', name="$\lambda = " + sp.latex(l) + "$") data.append(trace) layout = go.Layout(showlegend=True, autosize=True) fig = go.Figure(data=data, layout=layout) plotly.offline.iplot(fig) return def plot_eigspace(A, xL=-10, xR=10, p=None): """ Plot the eigenspaces associated to all eigenvalues of A @param A: Sympy matrix of shape (2,2) or (3,3) @param xL: Left limit of plot @param xR: Right limit of plot @param p: Number of points to use """ + + if not isinstance(A, sp.Matrix): + raise ValueError("A should be a sympy Matrix.") + n = A.shape[0] # Check 3 by 3 or 2 by 2 if (n != 2 and n!=3) or n != A.shape[1]: raise ValueError("A should be 2 by 2 or 3 by 3.") - if not A.is_Matrix: - raise ValueError("A should be a sympy Matrix.") + if n==2: plot2x2_eigspace(A, xL, xR, p) else: plot3x3_eigspace(A, xL, xR, p) def latexp(A): """ Function to output latex expression of a sympy matrix but with round parenthesis @param A: sympy matrix @return: latex string """ return sp.latex(A, mat_delim='(', mat_str='matrix') def ch8_8_ex_1(A, prop_answer): """ Check if a matrix is diagonalisable. @param A: sympy square matrix @param prop_answer: boolean, answer given by the student @return: """ - if not A.is_Matrix: + if not isinstance(A, sp.Matrix): raise ValueError("A should be a sympy Matrix.") n = A.shape[0] if n != A.shape[1]: raise ValueError('A should be a square matrix.') eig = A.eigenvects() dim_geom = 0 for x in eig: dim_geom += len(x[2]) answer = dim_geom == n if answer: display(Latex("Oui la matrice $A = " + latexp(A) + "$ est diagonalisable.")) else: display(Latex("Non la matrice $A = " + latexp(A) + "$ n'est pas diagonalisable.")) if answer == prop_answer: display(Latex("Votre réponse est correcte !")) else: display(Latex("Votre réponse est incorrecte.")) def isDiagonalizable(A): """ Step by step method to determine if a given matrix is diagonalizable. This methods uses always (I think) the easiest way to determine it (as seen in the MOOC) @param A: sympy matrix @return: nothing """ - if not A.is_Matrix: + if not isinstance(A, sp.Matrix): raise ValueError("A should be a sympy Matrix.") n = A.shape[0] if n != A.shape[1]: raise ValueError('A should be a square matrix.') display(Latex("On cherche à déterminer si la matrice $A=" + latexp(A) + "$ de taille $n \\times n$ avec $n = " + str(n) + "$ est diagonalisable.")) if A.is_lower or A.is_upper: display(Latex("Les valeurs propres sont simple à trouver, ce sont les éléments diagonaux.")) else: valeurs_propres(A) # Check if eigenvalue are all distincts eig = A.eigenvects() if len(eig) == n: display(Latex("On a $n$ valeurs propres distinctes. La matrice est donc diagonalisable.")) return else: display(Latex("Les valeurs propres ne sont pas toutes distinctes. On va donc vérifier la multiplicité " + "géométrique des valeurs propres ayant une multiplicité algébrique supérieur à 1.")) # Some list to have info about eigenvalues with algebraic mult > 1 idx = [] eigenvalues = [] mult_al = [] mult_geo = [] for i in range(len(eig)): if eig[i][1] > 1: idx.append(i) eigenvalues.append(eig[i][0]) mult_al.append(eig[i][1]) mult_geo.append(len(eig[i][2])) display(Latex("L'ensemble des valeurs propres ayant une multiplicité algébrique supérieur à 1 est " + str( eigenvalues) + ".")) for i, l in enumerate(eigenvalues): display(Markdown("**On calcule la multiplicité géométrique pour $\lambda= " + sp.latex(l) + "$ ayant une multiplicité algébrique de " + str(mult_al[i]) + ".**")) basis, basic, free = eigen_basis(A, l, prop_basis=None, disp=True, return_=True) display(Markdown("**La multiplicité géométrique pour $\lambda= " + sp.latex(l) + "$ est de " + str(len(free)) + ".**")) if (len(free) < mult_al[i]): display(Markdown("**La multiplicité géométrique est strictement inférieur à la multiplicité" + "algébrique pour cette valeur propre. La matrice n'est donc pas diagonalisable.**")) return else: display(Latex("On a bien multiplicité algébrique = multiplicité géométrique pour cette valeur propre.")) display(Markdown("**Toutes les valeurs propres ont une multiplicité algébrique et géométrique égales." + " La matrice $A$ est donc bien diagonalisable !**")) def find_P_D(A, P_user, D_user, step_by_step=True): """ :param A: sympy square matrix :param P_user: sympy square matrix :param D_user: sympa sqaure matrix :param step_by_step: Print step by step solution :return: """ - if not A.is_Matrix or not P_user.is_Matrix or not D_user.is_Matrix: + if not isinstance(A, sp.Matrix) or not isinstance(P_user, sp.Matrix) or not isinstance(D_user, sp.Matrix): raise ValueError("A, P and D should be a sympy Matrix.") n = A.shape[0] if n != A.shape[1] or P_user.shape[0] != n or P_user.shape[1] != n or D_user.shape[0] != n or D_user.shape[1] != n: raise ValueError('A, P and D should be a square matrix of the same size.') if not D_user.is_diagonal(): raise ValueError("D should be a diagonal matrix.") if not A.is_diagonalizable(): raise ValueError("A is not diagonalizable.") if step_by_step: display(Latex("On cherche à déterminer les matrices $P$ et $D$ telles que $A=" + latexp(A) + "= P D P^{-1}$.")) if A.is_lower or A.is_upper: display(Latex("Les valeurs propres sont simple à trouver, ce sont les éléments diagonaux.")) else: valeurs_propres(A) display( Latex("Pour chaque valeur propre $\lambda_i$, on cherche $n_i$ vecteurs propres linéairement indépendants" + " (avec $n_i = \dim E_{\lambda_i}$). On trouve ces vecteurs on calculant une base pour " + "chaque espace propre. On peut ensuite utiliser les vecteurs de base comme colonnes pour la " + "matrice $P$.")) eig = A.eigenvects() # Some list to have info about eigenvalues with algebraic mult > 1 idx = [] eigenvalues = [] mult_al = [] mult_geo = [] D = sp.zeros(n) for i in range(len(eig)): idx.append(i) eigenvalues.append(eig[i][0]) mult_al.append(eig[i][1]) mult_geo.append(len(eig[i][2])) P = [] k = 0 for i, l in enumerate(eigenvalues): basis, _, _ = eigen_basis(A, l, return_=True, disp=step_by_step, dispA=False) for j in range(len(basis)): D[k, k] = l k += 1 P.append(basis[j]) P = np.transpose(np.array(P)) if np.all(np.mod(P, 1) == 0): P = P.astype(int) P = sp.Matrix(P) display(Latex("En utilisant les vecteurs de base trouvés ci dessus pour les colonnes de la matrice $P$ et en " + "plaçant les valeurs propres de $A$ correspondantes sur la diagonal de $D$, on obtient " + "les matrices $P$ et $D$.")) display(Latex("$P = " + latexp(P) + "$, " + "$D = " + latexp(D) + "$")) - - P_1_user = P_user ** -1 + + if (P.det()!=0): + P_1_user = P_user ** -1 if ((A - P_user * D_user * P_1_user).norm() < 1e-10): display(Latex("Votre réponse est correcte, on a bien $A = PDP^{-1}$")) else: display(Latex("Votre réponse est incorrecte, $A \\neq PDP^{-1}$")) + +def diagonalizeComplex(A): + """ + @param A: + """ + + if not isinstance(A, sp.Matrix): + raise ValueError("A should be a sympy matrix") + + if not A.is_diagonalizable(): + display(Latex("A n'est pas diagonalisable.")) + return + + lamda = sp.symbols('lamda') + poly = A.charpoly(lamda) + poly = sp.factor(poly, extension=[I_sym]) + eig = A.eigenvects() + + eigenval = [] + mult = [] + + for el in eig: + eigenval.append(sp.simplify(el[0])) + mult.append(el[1]) + + display(Latex("Le polynome caractéristique de la matrice $A = " + latexp(A) + "$ est $ c_A (\lambda) = " + sp.latex( + poly) + "$")) + + display(Latex("Les valeurs propres de A sont donc: " + listsp_to_str(eigenval))) + + display(Latex("Pour chaque valeur propre $\lambda$, on calcule une base de l'espace propre associé " + "($\ker (A -\lambda I)$). On se sert ensuite des vecteurs propres (vecteur de base de l'espaces" + + " propre) pour diagonaliser la matrice.")) + + k = 0 + P = sp.zeros(A.shape[0], A.shape[0]) + D = sp.zeros(A.shape[0], A.shape[0]) + for i, l in enumerate(eigenval): + display(Latex( + "Pour la valeur propres $\lambda = " + sp.latex(l) + "$, on trouve une base de l'espace propre associé. " + + "On obtient comme base: " + listsp_to_str(eig[i][2]))) + + for vec in eig[i][2]: + P[:, k] = vec + D[k, k] = l + k += 1 + + P = sp.simplify(P) + D = sp.simplify(D) + + display(Latex("Avec la matrice $D= " + latexp(D) + "$ on obtient la matrice $P = " + latexp(P) + "$.")) + + display(Latex("La matrice $A$ se diagonalise donc avec comme $A = P D P^{-1}$")) + + display(Latex("$P D P^{-1} = " + latexp(P) + latexp(D) + latexp(sp.simplify(P ** -1)) + " = " + + latexp(sp.simplify(P * D * P ** -1)) + " = A$ ")) + + +def listsp_to_str(splist): + out = "$" + sp.latex(sp.simplify(splist[0]), mat_delim='(') + "$" + + if len(splist) == 1: + return out + + for i in range(1, len(splist) - 1): + out += ", $" + sp.latex(sp.simplify(splist[i]), mat_delim='(') + "$" + + out += " et $" + sp.latex(sp.simplify(splist[-1]), mat_delim='(') + "$" + return out + + +