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.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 11f258e..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,1689 +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": 3,
+ "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 = 7$",
- "type": "scatter",
- "x": [
- -5,
- -4.5,
- -4,
- -3.5,
- -3,
- -2.5,
- -2,
- -1.5,
- -1,
- -0.5,
- 0,
- 0.5,
- 1,
- 1.5,
- 2,
- 2.5,
- 3,
- 3.5,
- 4,
- 4.5,
- 5
- ],
- "y": [
- -10,
- -9,
- -8,
- -7,
- -6,
- -5,
- -4,
- -3,
- -2,
- -1,
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10
- ]
- },
- {
- "marker": {
- "size": 6
- },
- "mode": "lines+markers",
- "name": "$\\lambda = -1$",
- "type": "scatter",
- "x": [
- 15,
- 13.5,
- 12,
- 10.5,
- 9,
- 7.5,
- 6,
- 4.5,
- 3,
- 1.5,
- 0,
- -1.5,
- -3,
- -4.5,
- -6,
- -7.5,
- -9,
- -10.5,
- -12,
- -13.5,
- -15
- ],
- "y": [
- -10,
- -9,
- -8,
- -7,
- -6,
- -5,
- -4,
- -3,
- -2,
- -1,
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10
- ]
- }
- ],
- "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": 5,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/latex": [
- "Oui la matrice $A = \\left(\\begin{matrix}1 & 3\\\\4 & 5\\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": [
"# 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": 12,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/latex": [
- "$\\displaystyle \\left[\\begin{matrix}3 & 5 & -10\\\\1 & 7 & 2\\\\-2 & 2 & 4\\end{matrix}\\right]$"
- ],
- "text/plain": [
- "Matrix([\n",
- "[ 3, 5, -10],\n",
- "[ 1, 7, 2],\n",
- "[-2, 2, 4]])"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "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",
"A = A1\n",
"display(A)"
]
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/latex": [
- "On cherche à déterminer si la matrice $A=\\left(\\begin{matrix}3 & 5 & -10\\\\1 & 7 & 2\\\\-2 & 2 & 4\\end{matrix}\\right)$ de taille $n \\times n$ avec $n = 3$ est diagonalisable."
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "On cherche les valeurs propres de la matrice $ A=\\left(\\begin{matrix}3 & 5 & -10\\\\1 & 7 & 2\\\\-2 & 2 & 4\\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} + 14 \\lambda^{2} - 32 \\lambda - 128=- \\left(\\lambda - 8\\right)^{2} \\left(\\lambda + 2\\right)$$"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "Les racines du polynôme caractéristique sont $\\left[ -2, \\ 8\\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": [
- "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 [8]."
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/markdown": [
- "**On calcule la multiplicité géométrique pour $\\lambda= 8$ ayant une multiplicité algébrique de 2.**"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "On a $ A = \\left(\\begin{matrix}3 & 5 & -10\\\\1 & 7 & 2\\\\-2 & 2 & 4\\end{matrix}\\right)$."
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "On cherche une base de l'espace propre associé à $\\lambda = 8$."
- ],
- "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} -5 & 5 & -10 & 0 \\\\1 & -1 & 2 & 0 \\\\-2 & 2 & -4 & 0 \\end{array}\\right)$"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "On obtient: $\\left(\\begin{array}{ccc| cc} 1 & -1 & 2 & 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} 1 \\\\1 \\\\0 \\end{array}\\right) + x_3 \\cdot\\left(\\begin{array}{c} -2 \\\\0 \\\\1 \\end{array}\\right)$"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/markdown": [
- "**La multiplicité géométrique pour $\\lambda= 8$ est de 2.**"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "On a bien multiplicité algébrique = multiplicité géométrique pour cette valeur propre."
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/markdown": [
- "**Toutes les valeurs propres ont une multiplicité algébrique et géométrique égales. La matrice $A$ est donc bien 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(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": 16,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/latex": [
- "$\\displaystyle \\left[\\begin{matrix}2 & 3\\\\1 & 4\\end{matrix}\\right]$"
- ],
- "text/plain": [
- "Matrix([\n",
- "[2, 3],\n",
- "[1, 4]])"
- ]
- },
- "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 = A1\n",
"display(A)\n"
]
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/latex": [
- "On cherche à déterminer les matrices $P$ et $D$ telles que $A=\\left(\\begin{matrix}2 & 3\\\\1 & 4\\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}2 & 3\\\\1 & 4\\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^{2} - 6 \\lambda + 5=\\left(\\lambda - 5\\right) \\left(\\lambda - 1\\right)$$"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "Les racines du polynôme caractéristique sont $\\left[ 1, \\ 5\\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}{cc| cc} 1 & 3 & 0 \\\\1 & 3 & 0 \\end{array}\\right)$"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "On obtient: $\\left(\\begin{array}{cc| cc} 1 & 3 & 0 \\\\0 & 0 & 0 \\end{array}\\right)$"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "Variable(s) libre(s): $x_2 \\ $"
- ],
- "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 \\end{array}\\right)$"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "On cherche une base de l'espace propre associé à $\\lambda = 5$."
- ],
- "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} -3 & 3 & 0 \\\\1 & -1 & 0 \\end{array}\\right)$"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "On obtient: $\\left(\\begin{array}{cc| cc} 1 & -1 & 0 \\\\0 & 0 & 0 \\end{array}\\right)$"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/latex": [
- "Variable(s) libre(s): $x_2 \\ $"
- ],
- "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} 1 \\\\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}-3 & 1\\\\1 & 1\\end{matrix}\\right)$, $D = \\left(\\begin{matrix}1 & 0\\\\0 & 5\\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"
- }
- ],
+ "outputs": [],
"source": [
"# 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",
"find_P_D(A, P_user, D_user)"
]
}
],
"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 a968bd9..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,963 +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 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 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 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 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 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) + "$"))
- if (P.det()!=0)
+ if (P.det()!=0):
P_1_user = P_user ** -1
- else
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