Page MenuHomec4science

Ch10_lib.py
No OneTemporary

File Metadata

Created
Sat, May 4, 00:30

Ch10_lib.py

import sys
import 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
import ipywidgets as widgets
from ipywidgets import interact_manual, Layout
from sympy import sqrt
import random
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 A.shape[0] != 2 or A.shape[1] != 2:
raise ValueError("A should be a 2 by 2 numpy array")
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."))
if np.allclose(A @ A.transpose(), np.eye(2)):
display(Latex("La matrice $A = " + al.texMatrix(A) + "$ est une matrice orthogonale."))
else:
display(Latex("La matrice $A = " + al.texMatrix(A) + "$ n'est pas une matrice orthogonale."))
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):
A = sp.Matrix(A)
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."))
def interactive_is_orthogonal(A):
A = sp.Matrix(A)
n = A.shape[0]
if n != A.shape[1]:
raise ValueError("A should be a square matrix")
display(Latex("La matrice suivante est-elle orthogonale ? $A = " + latexp(A) + "$"))
answer = widgets.RadioButtons(options=["Oui", "Non"], description="Réponse : ", disabled=False)
sol = A.transpose() * A - sp.eye(n) == sp.zeros(n)
display(answer)
def f():
if answer.value == "Oui":
answer_bool = True
else:
answer_bool = False
if answer_bool == sol:
display(Latex("Correct !"))
else:
display(Latex("Incorrect"))
interact_manual(f)
display(Latex("Si vous n'arrivez pas à trouver la solution, vous pouvez afficher la solution détaillée en"
" cliquant ici"))
def f_sol():
is_orthogonal(A)
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def ortho_diag(A):
A = sp.Matrix(A)
n = A.shape[0]
if A - A.transpose() != sp.zeros(n):
display(Latex("La matrice $A = " + latexp(A) + "$ n'est pas orthogonalement diagonalisable car elle n'est pas "
"symétrique."))
return
eig = A.eigenvals()
eig_list = list(eig.keys())
eig_list.sort()
display(Latex("On cherche à diagonaliser orthogonalement la matrice $ A = " + latexp(A) + "$."))
default_value_P = str(np.ones(A.shape, dtype=np.int16).tolist())
default_value_P = default_value_P.replace("],", "],\n")
default_value_D = str(np.ones(A.shape[0], dtype=np.int16).tolist())
answer_P = widgets.Text(value=default_value_P, description='P: ', disabled=False)
answer_D = widgets.Text(value=default_value_D, description='D: ', disabled=False)
display(Latex("Pour les réponses aux questions suivantes, ne faites pas d'approximations numériques, "
"toutes les valeurs doivent être exactes. Pour les racines carrées "
"(utiles pour normaliser les vecteurs), utilisez 'sqrt('votre valeur')', ex: sqrt(2)."))
display(Latex("Donnez les éléments diagonaux de la matrice $D$"))
display(answer_D)
display(Latex("Donnez la matrice P permettant de diagonaliser orthogonalement la matrice $A$ de sorte que "
"$ A = PDP^T = PDP^{-1} $"))
display(answer_P)
def f():
P_user = eval(answer_P.value)
P_user = sp.Matrix(P_user)
D_diag = eval(answer_D.value)
D_diag_order = set(D_diag.copy())
D_diag_order = list(D_diag_order)
D_diag_order.sort()
D_user = sp.zeros(n)
for i in range(n):
D_user[i, i] = D_diag[i]
D_user = sp.Matrix(D_user)
if np.allclose(np.array(D_diag_order, dtype=np.float64), np.array(eig_list, dtype=np.float64)):
if P_user * P_user.transpose() - sp.eye(n) == sp.zeros(n):
if P_user * D_user * P_user.transpose() - A == sp.zeros(n):
display(Latex("Correct !"))
else:
display(Latex("Incorrect. On a $PDP^{T}\\neq A$ avec $P = " + latexp(P_user) + "$ et $D =" +
latexp(D_user) + "$."))
else:
display(Latex("La matrice $P = " + latexp(P_user) + "$ n'est pas orthogonale, i.e. $P P^{T} \\neq I$."))
else:
display(Latex("Incorrect. "
"Les éléments diagonaux de $D$ ne correspondent pas aux valeurs propres de la matrice $A$."))
return
interact_manual(f)
def correction_ortho_diag():
display(Latex(
"Pour diagonaliser orthogonalement une matrice, on a applique la méthode donnée dans le cours et rappelée plus haut"))
lamda = sp.symbols('lamda')
poly_char_exp = sp.expand(A.charpoly(lamda).as_expr())
poly_char_fac = sp.factor(A.charpoly(lamda).as_expr())
poly_char_exp_str = sp.latex(poly_char_exp)
poly_char_fac_str = sp.latex(poly_char_fac)
display(Latex("Le polynôme caractéristique de $A$ s'exprime comme: $c_A (t) = " + poly_char_exp_str + "$."))
display(Latex("On trouve les racines du polynôme caractéristique et on factorise. On obtient $c_A (t) = "
+ poly_char_fac_str + "$."))
eig_list_ = list(eig.keys())
mult_list_ = list(eig.values())
display(Latex("On obtient donc les valeurs propres $\lambda$ et leur multiplicité respective $m$: "
" $ \lambda = " + sp.latex(eig_list_) + " \hspace{10mm} m = " + sp.latex(mult_list_) + "$."))
display(Markdown("**On trouve une base orthonormée pour tous les espaces propres.**"))
final_basis = []
P = sp.Matrix([])
k = 0
for l in eig_list_:
basis_orthonorm = []
basis, basic_idx, free_idx = eigen_basis(A, l, prop_basis=None, disp=True, return_=True, dispA=False)
for v in basis:
if np.all(v == np.round(v)):
v = v.astype(np.int16)
basis_orthonorm.append(sp.Matrix(v))
basis_orthonorm = sp.GramSchmidt(basis_orthonorm, True)
for v in basis_orthonorm:
final_basis.append(v)
P = P.col_insert(k, v)
k += 1
display(Latex("On applique le procédé de Gram-Schmidt pour obtenir des vecteurs de norme 1 et orthogonaux. "
"On obtient $" + sp.latex(basis_orthonorm) + "$"))
display(Latex("Finalement, on construit la matrice $P$ en utilisant chaque vecteur de base "
"trouvé précedemment comme colonne de cette matrice. Cette dernière est bien orthogonale car "
"les vecteurs de base sont orthogonaux entre eux et tous de norme unitaire. "
"On construit la matrice $D$ en plaçant les valeurs propres de $A$ sur la diagonale. "
"Le placement des valeurs propres sur la diagonale de $D$ "
"doit correspondre avec celui des vecteurs propres dans $P$."))
D = sp.zeros(n)
i = 0
for idx in range(len(eig_list_)):
for _ in range(mult_list_[idx]):
D[i, i] = eig_list_[idx]
i += 1
display(Latex("On obtient $P = " + latexp(P) + "\hspace{5mm} \mbox{et} \hspace{5mm} D = " + latexp(D) + "$"))
display(Latex("On vérifie le résultat par un calcul :"))
display(Latex(
"$P D P^T = " + latexp(P) + latexp(D) + latexp(P.transpose()) + " = " + latexp(P * D * P.transpose()) +
"=A$"))
display(Latex("Si vous n'arrivez pas à résoudre l'exercice, vous pouvez afficher la solution étape "
"par étape en cliquant ici."))
im = interact_manual(correction_ortho_diag)
im.widget.children[0].description = 'Solution'
def nl():
return "$$ $$"
def sol_is_ortho(A):
A = sp.Matrix(A)
n = A.shape[0]
if n != A.shape[1]:
display(Latex("La matrice $A = " + latexp(A) + "$ n'est pas carrée !"))
return
display(Latex("Pour vérifier si la matrice $A$ est orthogonale, on effectue dans cette correction "
"le produit de $A$ et de sa transposée $A^T$."
" On vérifie ensuite si l'on obtient la matrice identité."))
if sp.simplify(A * A.transpose() - sp.eye(n)) == sp.zeros(n):
display(
Latex("On a que : $A A^T = " + latexp(A) + latexp(A.transpose()) + "= " + latexp(sp.eye(n)) + "= I_n $"))
display(Latex("La matrice $A$ est donc orthogonale."))
else:
display(Latex("On a que : $A A^T = " + latexp(A) + latexp(A.transpose()) + "\\neq I_n $"))
display(Latex("Par consequent, la matrice $A$ n'est pas orthogonale."))
return
def is_ortho_10_2(A):
A = sp.Matrix(A)
n = A.shape[0]
display(Latex("La matrice $A =" + latexp(A) + "$ est-elle orthogonale ?"))
answer = widgets.RadioButtons(options=["Oui", "Non"], description="Réponse : ", disabled=False)
display(answer)
sol = sp.simplify(A * A.transpose() - sp.eye(n)) == sp.zeros(n)
if n != A.shape[1]:
sol = False
def f():
if answer.value == "Oui":
answer_bool = True
else:
answer_bool = False
if answer_bool == sol:
display(Latex("Correct !"))
else:
display(Latex("Incorrect"))
if sol:
display(Latex("La matrice $A$ est orthogonale."))
else:
display(Latex("La matrice $A$ n'est pas orthogonale."))
interact_manual(f)
def f_sol():
sol_is_ortho(A)
display(Latex("Pour afficher la solution, cliquez-ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def vf_10_2_2():
display(Latex("Soit $A \in M_{n \\times n}(\mathbb{R})$ une matrice orthogonale. On construit la matrice"
" $B \in M_{n \\times n}(\mathbb{R})$ en réarrangeant les colonnes de $A$ dans un ordre quelquonque. "
"La matrice $B$ est aussi orthogonale."))
answer = widgets.RadioButtons(options=["Vrai", "Faux"], description="Réponse : ", disabled=False)
display(answer)
def f():
if answer.value == "Vrai":
display(Latex("Correct ! En effet, si l'ordre des colonnes est modifié, l'ensemble de ces dernières reste "
"toujours une base orthonormée de l'espace $V$. "
"La proposition (5) est donc vérifiée pour la matrice $B$."))
else:
display(Latex("Incorrect, changez votre réponse !"))
interact_manual(f)
def vf_10_2_3():
display(Latex("Soit $A \in M_{n \\times n}(\mathbb{R})$ une matrice orthogonale. On construit la matrice"
" $B \in M_{n \\times n}(\mathbb{R})$ en réarrangeant les lignes de $A$ dans un ordre quelquonque. "
"La matrice $B$ est aussi orthogonale."))
answer = widgets.RadioButtons(options=["Vrai", "Faux"], description="Réponse : ", disabled=False)
display(answer)
def f():
if answer.value == "Vrai":
display(Latex("Correct ! En effet, si l'ordre des lignes est modifié, l'ensemble de ces dernières reste "
"toujours une base orthonormée de l'espace $V$. "
"La proposition (4) est donc vérifiée pour la matrice $B$."))
else:
display(Latex("Incorrect, changez votre réponse !"))
interact_manual(f)
def vf_10_2_1():
display(Latex("Soit $A \in M_{n \\times n}(\mathbb{R})$ une matrice orthogonale. $A^T$ est aussi orthogonale."))
answer = widgets.RadioButtons(options=["Vrai", "Faux"], description="Réponse : ", disabled=False)
display(answer)
def f():
if answer.value == "Vrai":
display(Latex("Correct ! En effet, comme $A$ est orthogonale, on sait que ses colonnes forment "
"une base orthonormée de l'espace $V$. Comme les lignes de $A^T$ sont les colonnes de $A$, "
"alors la proposition (4) est vérifiée pour $A^T$, i.e. les lignes de $A^T$ forment une base "
"orthonormée de $V$. $A^T$ est donc une matrice orthogonale."))
else:
display(Latex("Incorrect, changez votre réponse !"))
interact_manual(f)
def vf_10_2_4():
display(Latex("Soit $A \in M_{n \\times n}(\mathbb{R})$ une matrice ayant une valeur propre $\lambda = 2$. "
"Il est possible que $A$ soit orthogonale."))
answer = widgets.RadioButtons(options=["Vrai", "Faux"], description="Réponse : ", disabled=False)
display(answer)
def f():
if answer.value == "Faux":
display(
Latex("Correct ! Etant donné que $A$ a pour valeur propre $\lambda=2$, cela signifique qu'il existe "
"un vecteur $v$ tel que $A v = 2 v$. Donc la matrice $A$ ne conserve pas toujours les longeurs lors "
"d'une multiplication avec un vecteur. La proposition (1) n'est pas vérifiée."
" $A$ ne peut donc pas être orthogonale."))
else:
display(Latex("Incorrect, changez votre réponse !"))
interact_manual(f)
def vf_10_4_1():
display(Markdown("**Dire si l'affirmation suivante est vraie ou fausse.**"))
display(Latex("La matrice $A$ est orthogonalement diagonalisable."))
n_pos = [3, 4, 5]
n = random.choice(n_pos)
sym = bool(random.getrandbits(1))
A = sp.randMatrix(n, symmetric=sym, percent=70, min=-20, max=20)
if sp.simplify(A - A.transpose()) == sp.zeros(n):
sol = True
else:
sol = False
display(Latex("$A = " + latexp(A) + "$"))
answer = widgets.RadioButtons(options=["Vrai", "Faux"], description="Réponse : ", disabled=False)
display(answer)
def f():
if answer.value == "Vrai":
answer_value = True
else:
answer_value = False
if answer_value == sol:
display(Latex("Correct ! "))
if sol:
display(Latex("La matrice $A$ est orthogonalement diagonalisable car elle est symétrique."))
else:
display(Latex("La matrice $A$ n'est pas orthogonalement diagonalisable car elle n'est pas symétrique."))
else:
display(Latex("Incorrect, changez votre réponse."))
interact_manual(f)
def quest_10_4_2():
A = sp.Matrix([[2, -4], [1, -1]])
charpol = A.charpoly().as_expr() * -1
display(Latex("Soit $A$ une matrice carrée ayant pour polynome caractéristique $c_A(\lambda) = " +
sp.latex(charpol) + "$"))
display(Latex("La matrice $A$ est-elle symétrique ?"))
answer = widgets.RadioButtons(options=["Oui", "Pas nécessairement", "Non"], description="Réponse : ",
disabled=False)
display(answer)
sol = "Non"
def f():
if answer.value == sol:
display(Latex("Correct !"))
else:
display(Latex("Incorrect."))
interact_manual(f)
def f_sol():
display(Latex("Le polynome caractéristique de $A$ admet une ou des racine(s) non réelle(s). "
"Donc la matrice $A$ ne peut pas être symétrique."))
display(Latex("Pour afficher la solution détaillée, cliquez-ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def quest_10_4_3():
# Non symmetric values
A = sp.Matrix([[0, -1, -4], [0, 0, -2], [0, -2, 0]])
charpol = A.charpoly().as_expr() * -1
charpol = charpol.factor()
display(Latex(
"Soit $A$ une matrice carrée ayant pour polynome caractéristique $c_A(\lambda) = " + sp.latex(charpol) + "$"))
display(Latex("La matrice $A$ est-elle symétrique ?"))
answer = widgets.RadioButtons(options=["Oui", "Pas nécessairement", "Non"], description="Réponse : ",
disabled=False)
display(answer)
sol = "Pas nécessairement"
def f():
if answer.value == sol:
display(Latex("Correct !"))
else:
display(Latex("Incorrect."))
interact_manual(f)
def f_sol():
A2 = sp.Matrix([[0, 0, 0], [0, 2, 0], [0, 0, -2]])
display(Latex(
"On sait que le polynome caractéristique d'une matrice symétrique admet uniquement des racines réelles. "
"Or la réciproque est fausse, i.e., les polynomes caractéristiques à racines réelles peuvent être issus de matrices non symétriques. " + nl() +
"On voit que le polynome caractéristique $c_A(\lambda)$ a uniquement des racines réelles mais cela ne suffit pas pour conclure que $A$ est symétrique. "))
display(Latex("La bonne réponse est donc: Pas nécessairement"))
display(Latex("Dans ce cas précis, les matrices $A_1 =" + latexp(A) + "$ et $A_2 = " + latexp(A2) + "$ ont "
"toutes les deux $c_A(\lambda)$ pour polynome caractéristique. On voit que une des matrices est symétrique et l'autre pas."))
display(Latex("Pour afficher la solution détaillée, cliquez-ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def exo_2_1_10_4():
v1 = sp.Matrix([3, 4])
v2 = sp.Matrix([-1, 1 / 2])
display(Latex("La matrice $A \in M_{2 \\times 2}$ ( $\mathbb{R}$ ) a pour valeur propres $3$ et $-2$. "
"$" + latexp(v1) + "\mbox{ et } " + latexp(v2) + "$ sont des vecteurs propres de $A$ respectivement "
"associés aux valeurs propres $3$ et $-2$. "))
display(Latex("La matrice $A$ est-elle symétrique ?"))
answer = widgets.RadioButtons(options=["Oui", "Non", "Manque d'informations"], description="Réponse : ",
disabled=False)
display(answer)
sol = "Non"
def f():
if answer.value == sol:
display(Latex("Correct !"))
else:
display(Latex("Incorrect."))
interact_manual(f)
def f_sol():
display(Latex("Les vecteurs propres $" + latexp(v1) + "$ et $" + latexp(v2) +
"$ sont associés à des valeurs propres différentes mais ne sont pas orthogonaux. "
"La matrice $A$ ne peut donc pas être symétrique."))
display(Latex("Pour afficher la solution détaillée, cliquez ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def exo_2_2_10_4():
v1 = sp.Matrix([1, 0, 2])
v2 = sp.Matrix([-2, 0, -4])
v3 = sp.Matrix([2, 5, -1])
display(Latex("La matrice $A \in M_{3 \\times 3}$ ( $\mathbb{R}$ ) a pour valeur propres $4$ et $2$. "
"$" + latexp(v1) + ", " + latexp(v2) + "\mbox{ et } " + latexp(
v3) + "$ sont des vecteurs propres de $A$ respectivement "
"associés aux valeurs propres $4$, $4$ et $-2$. "))
display(Latex("La matrice $A$ est-elle symétrique ?"))
opt = ["Oui", "Non", "Manque d'informations"]
answer = widgets.RadioButtons(options=opt, description="Réponse : ", disabled=False)
display(answer)
sol = opt[2]
def f():
if answer.value == sol:
display(Latex("Correct !"))
else:
display(Latex("Incorrect."))
interact_manual(f)
def f_sol():
display(Latex("Les vecteurs propres associés à des valeurs propres différentes sont bien orthogonaux. "
"Mais on ne connait pas la dimension de l'espace propre associé à $\lambda = 4$ car les deux "
"vecteurs donnés dans l'énoncé, $ " + latexp(v1) + " \mbox{ et } " + latexp(v2) + "$, "
"sont colinéaires." + nl() +
"Pour connaitre la dimension de cette espace, il faudrait une base de ce dernier. "
"Cela permettrait de vérifier si la dimension de l'espace est de 2 et si tous les vecteurs de "
"cet espace sont orthogonaux aux vecteurs composant l'espace propre associé à $\lambda = 2$. "
"Si ces deux conditions étaient vérifiées, la matrice $A$ serait symétrique."))
display(Latex("Il manque donc d'informations pour répondre."))
display(Latex("Pour afficher la solution détaillée, cliquez ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def exo_2_3_10_4():
v1 = sp.Matrix([1, 0, 1])
v2 = sp.Matrix([-2, 0, 1])
v3 = sp.Matrix([0, 3, 0])
display(Latex("La matrice $A \in M_{3 \\times 3}$ ( $\mathbb{R}$ ) a pour valeur propres $-1$, $2$ et $4$. "
"$" + latexp(v1) + ", " + latexp(v2) + "\mbox{ et } " + latexp(
v3) + "$ sont des vecteurs propres de $A$ respectivement "
"associés aux valeurs propres $-1$, $2$ et $4$. "))
display(Latex("La matrice $A$ est-elle symétrique ?"))
opt = ["Oui", "Non", "Manque d'informations"]
answer = widgets.RadioButtons(options=opt, description="Réponse : ", disabled=False)
display(answer)
sol = opt[1]
def f():
if answer.value == sol:
display(Latex("Correct !"))
else:
display(Latex("Incorrect."))
interact_manual(f)
def f_sol():
display(Latex("Les vecteurs propres $" + latexp(v1) + "$ et $" + latexp(v2) +
"$ sont associés à des valeurs propres différentes mais ne sont pas orthogonaux. "
"La matrice $A$ ne peut donc pas être symétrique."))
display(Latex("Pour afficher la solution détaillée, cliquez ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def exo_2_4_10_4():
v1 = sp.Matrix([1, 0, 1])
v2 = sp.Matrix([-2, 0, 1])
v3 = sp.Matrix([0, 3, 0])
display(Latex("La matrice $A \in M_{3 \\times 3}$ ( $\mathbb{R}$ ) a pour valeur propres $-1$, et $4$. "
"$" + latexp(v1) + ", " + latexp(v2) + "\mbox{ et } " + latexp(
v3) + "$ sont des vecteurs propres de $A$ respectivement "
"associés aux valeurs propres $-1$, $-1$ et $4$. "))
display(Latex("La matrice $A$ est-elle symétrique ?"))
opt = ["Oui", "Non", "Manque d'informations"]
answer = widgets.RadioButtons(options=opt, description="Réponse : ", disabled=False)
display(answer)
sol = opt[0]
def f():
if answer.value == sol:
display(Latex("Correct !"))
else:
display(Latex("Incorrect."))
interact_manual(f)
def f_sol():
base_1 = sp.GramSchmidt([v1, v2], orthonormal=True)
base_4 = sp.GramSchmidt([v3], orthonormal=True)
display(Latex("Les vecteurs propres $" + latexp(v1) + "$ et $" + latexp(
v2) + "$ associés à $\lambda = -1$ sont linéairement indépendant "
"et orthogonaux au vecteur propre $" + latexp(v3) + "$ associé à $\lambda = 4$. "
"On peut utiliser ces deux ensembles de vecteurs propres pour former des bases des espaces propres "
"associés à $\lambda = -1$ et $\lambda = 4$, respectivement. "
"On peut othogonaliser et normaliser ces bases avec le schema de Gram-Schmidt."))
display(Latex(
"On obtient les bases des espaces propres associées respectivement à $\lambda = -1$ et $\lambda = 4$"))
display(Latex("$ " + latexp(base_1[0]) + ", " + latexp(base_1[1]) + "\hspace{15mm} " + latexp(base_4[0]) + "$"))
display(Latex(
"On voit que l'espace $V = \mathbb{R}^3$ possède une base othornormée composée de vecteurs propres de $A$. "
"La transformation associée à la matrice $A$ est donc orthogonalement diagonalisable et $A$ est donc symétrique."))
display(Latex("Pour afficher la solution détaillée, cliquez ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def ex_3_1_10_4():
l_1 = 2
l_2 = -1
v_1 = sp.Matrix([1, -1])
display(Latex("Trouver une matrice $A \in M_{2 \\times 2} (\mathbb{R})$ symétrique ayant pour valeurs propres 2 "
"et -1 et $" + latexp(v_1) + "$ comme vecteur propres associé à $\lambda = 2$."))
default_value_A = str(np.ones((2, 2), dtype=np.int16).tolist())
answer = widgets.Text(value=default_value_A, description='A: ', disabled=False, display='flex')
display(answer)
def f():
A = eval(answer.value)
A = sp.Matrix(A)
if A.shape[0] != 2 or A.shape[1] != 2:
display(Latex("Incorrect, la matrice doit être carrée et 2x2."))
return
if sp.simplify(A - A.transpose()) != sp.zeros(2):
display(Latex("Incorrect, la matrice n'est pas symétrique !"))
return
eig = A.eigenvals()
eig_list = list(eig.keys())
if l_1 not in eig_list or l_2 not in eig_list:
if l_1 not in eig_list:
display(Latex("Incorrect, 2 n'est pas une valeur propre de la matrice rentrée."))
if l_2 not in eig_list:
display(Latex("Incorrect, -1 n'est pas une valeur propre de la matrice rentrée."))
return
A_v = A * v_1
if sp.simplify(A_v - l_1 * v_1) != sp.zeros(2, 1):
display(Latex("Incorrect, le vecteur $" + latexp(v1) + "$ n'est pas un vecteur propre de $A$ associé à "
"la valeur propre $\lambda = 2$."))
return
display(Latex("Correct !"))
interact_manual(f)
def f_sol():
display(Latex("On utilise la formule $A=PDP^T$ pour constuire la matrice symetrique $A$. $P$ est une matrice "
"orthogonale composée de vecteurs propres de $A$ et $D$ est une matrice diagonale avec les valeurs"
" propres de $A$ sur la diagonale. "))
D = sp.Matrix([[2, 0], [0, -1]])
display(Latex("On construit simplement la matrice $D =" + latexp(D) + "$"))
v_2 = sp.Matrix([1, 1])
display(Latex("On ne dispose pas d'informations sur les vecteurs propres associés à $\lambda = -1$. "
"Mais pour obtenir une matrice symétrique on sait que $P$ est orthogonale, "
"donc il faut trouver un vecteur propre orthogonal à $" + latexp(
v_1) + "$. Simplement, on prend $" + latexp(v_2) + "$."))
display(Latex("On normalise les deux vecteurs propres orthogonaux et on forme les colonnes de $P$. "
"Chaque vecteur est placé dans la même colonne que sa valeur propre correspondante dans $D$."))
P = sp.Matrix([[1, 1], [-1, 1]]) / sp.sqrt(2)
display(Latex("On obtient $P = " + latexp(P) + "$."))
A = P * D * P.transpose()
display(Latex("$A = P D P^T = " + latexp(P) + latexp(D) + latexp(P.transpose()) + "=" + latexp(A) + "$"))
display(Latex("Pour afficher la solution détaillée, cliquez ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def ch10_7_ex_1_1():
x1, x2, x3, x4 = sp.symbols("x_1 x_2 x_3 x_4")
Q = x1 ** 2 - 5 * x1 * x2 + x1 * x3 - x1 * x4 + 4 * x2 ** 2 + 2 * x2 * x3 - 4 * x2 * x4 + x3 ** 2 + x3 * x4 - x4 ** 2
sol = "Oui"
display(Latex("Le polynôme $Q = " + sp.latex(Q) + "$ est-il une forme quadratique ?"))
answer = widgets.RadioButtons(options=["Oui", "Non"], description="Réponse : ", disabled=False)
display(answer)
def f():
if answer.value == sol:
display(Latex("Correct ! "))
display(Latex("Le polynôme $Q = " + sp.latex(Q) + "$ est une forme quadratique car "
"il contient uniquement des termes d'ordre 2."))
else:
display(Latex("Incorrect, changez votre réponse."))
interact_manual(f)
def ch10_7_ex_1_2():
x1, x2, x3 = sp.symbols("x_1 x_2 x_3")
Q = (x1 + x2) ** 2 + (x3 - 1) ** 2
sol = "Non"
display(Latex("Le polynôme $Q = " + sp.latex(Q) + "$ est-il une forme quadratique ?"))
answer = widgets.RadioButtons(options=["Oui", "Non"], description="Réponse : ", disabled=False)
display(answer)
def f():
if answer.value == sol:
display(Latex("Correct ! "))
display(Latex("Le polynôme $Q = " + sp.latex(Q) + "$ n'est pas une forme quadratique car "
"il ne contient pas uniquement des termes d'ordre 2."))
display(Latex("On peut developper $Q$ pour expliciter l'ordre de chaque terme."))
display(Latex("$$ Q = " + sp.latex(Q.expand()) + "$$"))
else:
display(Latex("Incorrect, changez votre réponse."))
interact_manual(f)
def ch10_7_ex_1_3():
x1, x2, x3 = sp.symbols("x_1 x_2 x_3")
Q = 3 * x1 ** 2 + x1 * x2 + x2 ** 2 + 2 * x2 * x3 - x1 * x3 + x3 ** 3
sol = "Non"
display(Latex("Le polynôme $Q = " + sp.latex(Q) + "$ est-il une forme quadratique ?"))
answer = widgets.RadioButtons(options=["Oui", "Non"], description="Réponse : ", disabled=False)
display(answer)
def f():
if answer.value == sol:
display(Latex("Correct ! "))
display(Latex("Le polynôme $Q = " + sp.latex(Q) + "$ n'est pas une forme quadratique car "
"il ne contient pas uniquement des termes d'ordre 2."))
else:
display(Latex("Incorrect, changez votre réponse."))
interact_manual(f)
def ch10_7_ex_2(n):
x1, x2, x3, x4, x5 = sp.symbols("x_1 x_2 x_3 x_4 x_5")
x_list = [sp.Matrix([x1, x2]), sp.Matrix([x1, x2, x3]), sp.Matrix([x1, x2, x3, x4])]
A1 = sp.Matrix([[-2, 3], [3, 4]])
A2 = sp.Matrix([[1, 0, 3], [0, -2, -1 / 4], [3, -1 / 4, 4]])
A3 = sp.Matrix([[-1, -1, 3, 0],
[-1, -2, 0, 4],
[3, 0, 0, -1],
[0, 4, -1, 2]])
A_list = [A1, A2, A3]
A = A_list[n - 1]
x = x_list[n - 1]
Q = x.dot(A * x).expand()
display(Latex("Rentrez la matrice symétrique $A$ telle que $\mathbf{x}^T A \mathbf{x} = Q(\mathbf{x})$ "
"avec $\mathbf{x} = " + latexp(x) + "$"))
display(Latex("où $Q(\mathbf{x}) = " + sp.latex(Q) + "$"))
default_value_A = str(np.ones(A.shape, dtype=np.int16).tolist())
answer = widgets.Text(value=default_value_A, description='A = ', disabled=False,
layout=widgets.Layout(width='600px'))
display(answer)
def f():
A_user = eval(answer.value)
A_user = sp.Matrix(A_user)
display(Latex("Vous avez rentré la matrice $A_{user} = " + latexp(A_user) + "$"))
if A_user.shape != A.shape:
display(Latex("Incorrect, la matrice $A$ n'a pas les bonnes dimensions."))
return
if sp.simplify(A_user - A_user.transpose()) != sp.zeros(A.shape[0]):
display(Latex("Incorrect, la matrice rentrée n'est pas symétrique. "))
return
Q_user = x.dot(A_user * x).expand()
if sp.simplify(Q_user - Q) == 0:
display(Latex("Correct !"))
else:
display(Latex("Incorrect, avec votre matrice on obtient $ Q_{user}(\mathbf{x}) = "
+ sp.latex(Q_user) + "\\neq Q(\mathbf{x}) $"))
interact_manual(f)
def f_sol():
display(Latex("La matrice $A = " + latexp(A) + "$ est telle que $Q(\mathbf{x}) = \mathbf{x}^T A \mathbf{x} $"))
display(Latex("Pour afficher la solution, cliquez ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def plot_quad(A, n_points=50j, lims=2):
A_sp = sp.Matrix(A)
eig = A_sp.eigenvects()
# Create list with principal axis
p_axis = []
for x in eig:
v_list = sp.GramSchmidt(x[2], orthonormal=True)
for v in v_list:
p_axis.append(np.array(v).astype(np.float64).flatten())
A = np.array(A)
if A.shape == (3, 3):
X, Y, Z = np.mgrid[-lims:lims:n_points, -lims:lims:n_points, -lims:lims:n_points]
# ellipsoid
values = A[0, 0] * X * X + A[1, 1] * Y * Y + A[2, 2] * Z * Z + (A[0, 1] + A[1, 0]) * X * Y + (
A[0, 2] + A[2, 0]) * X * Z + (A[1, 2] + A[1, 2]) * Y * Z
layout = go.Layout(scene=go.layout.Scene(aspectmode="cube"))
fig = go.Figure(data=go.Isosurface(
x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
value=values.flatten(),
isomin=1,
isomax=1,
showscale=False,
opacity=0.5,
caps=dict(x_show=False, y_show=False),
showlegend=True,
name='Quadrique'
),
layout=layout)
fig.add_trace(go.Scatter3d(x=[0, p_axis[0][0]],
y=[0, p_axis[0][1]],
z=[0, p_axis[0][2]],
line=dict(width=2, color='black'),
mode='lines+markers',
marker=dict(size=3),
showlegend=True,
name='Axes principaux',
))
fig.add_trace(go.Scatter3d(x=[0, p_axis[1][0]],
y=[0, p_axis[1][1]],
z=[0, p_axis[1][2]],
line=dict(width=2, color='black'),
mode='lines+markers',
marker=dict(size=3),
showlegend=False,
name='Principal axis 2',
))
fig.add_trace(go.Scatter3d(x=[0, p_axis[2][0]],
y=[0, p_axis[2][1]],
z=[0, p_axis[2][2]],
mode='lines+markers',
line=dict(width=2, color='black'),
marker=dict(size=3),
showlegend=False,
name='Principal axis 3',
))
elif A.shape == (2, 2):
eigenvals = A_sp.eigenvals()
eig_list = []
for _lambda in eigenvals:
eig_list += [_lambda] * eigenvals[_lambda]
if eig_list[0] <= 0 and eig_list[1] <= 0:
display(Latex(
"Les valeurs propres sont toutes négatives ou nulles. La forme quadratique n'a donc pas de solution."))
return
X, Y = np.mgrid[-lims:lims:n_points, -lims:lims:n_points]
Z = A[0, 0] * X * X + A[1, 1] * Y * Y + (A[1, 0] + A[0, 1]) * X * Y
fig = go.Figure(data=go.Contour(
x=X[:, 0],
y=Y[0, :],
z=Z,
contours=dict(start=1, end=1),
contours_coloring='lines',
line_width=2,
opacity=0.5,
showscale=False, showlegend=True,
name='Conique'),
)
fig.update_layout(xaxis=dict(range=[-lims, lims], constrain="domain", ),
yaxis=dict(scaleanchor="x", scaleratio=1, ))
fig.add_trace(go.Scatter(x=[0, p_axis[0][0]],
y=[0, p_axis[0][1]],
mode='lines+markers',
line=dict(width=2, color='black'),
marker=dict(size=3),
showlegend=True,
name='Axes principaux',
))
fig.add_trace(go.Scatter(x=[0, p_axis[1][0]],
y=[0, p_axis[1][1]],
mode='lines+markers',
line=dict(width=2, color='black'),
marker=dict(size=3),
showlegend=False,
name='Principal axis 2',
))
else:
return
fig.show()
def ex1_10_8(n):
A_list = [sp.Matrix([[5, 2], [2, 5]]), sp.Matrix([[3, 2, 0], [2, 0, 0], [0, 0, 2]])]
x1, x2, x3 = sp.symbols("x_1 x_2 x_3")
x_list = [sp.Matrix([x1, x2]), sp.Matrix([x1, x2, x3])]
A = A_list[n - 1]
x = x_list[n - 1]
Q = x.dot(A * x).expand()
display(Latex("$Q(x) = " + sp.latex(Q) + "$"))
display(Latex("Donnez les coefficients $d_1, ..., d_n$ et la matrice $S$ de changement de variable tel "
"que $x = Sy$. "))
default_value_d = str(np.ones(A.shape[0], dtype=np.int16).tolist())
default_value_S = str(np.ones(A.shape, dtype=np.int16).tolist())
answer_d = widgets.Text(value=default_value_d, description='d = ', disabled=False,
layout=widgets.Layout(width='600px'))
answer_S = widgets.Text(value=default_value_S, description='S = ', disabled=False,
layout=widgets.Layout(width='600px'))
display(answer_d)
display(answer_S)
def f():
d_user = eval(answer_d.value)
d_user = np.array(d_user, dtype=np.int16)
D_user = np.diag(d_user)
D_user = sp.Matrix(D_user)
S_user = eval(answer_S.value)
S_user = sp.Matrix(S_user)
display(Latex("Vous avez rentré la matrice suivante: $S_{user} = " + latexp(S_user) + "$"))
A_user = S_user * D_user * S_user.transpose()
if sp.simplify(A - A_user) == sp.zeros(A.shape[0]):
display(Latex("Correct !"))
else:
display(Latex("Incorrect."))
interact_manual(f)
def f_sol():
display(Latex("On commence par trouver la matrice symétrique $A$ telle que $Q(x) = x^T A x$ avec "
"$x = " + latexp(x) + "$."))
display(Latex("Par identification, on trouve $A = " + latexp(A) + "$."))
display(Latex("Ensuite, l'exercice consiste simplement à diagonaliser orthogonalement la matrice symétrique "
"$A$."))
display(Latex("En effet, si on a $D = S^T A S$, avec $D$ diagonale, en effectuant le changement de variable "
"$x = Sy$, on obtient : " + nl() + " $Q(x) = x^T A x = (Sy)^T A (Sy) = y^T S^T A S y = y^T D y = "
"d_1 y_1^2 + d_2 y_2^2 + ... + d_n y_n^2 $ "))
lamda = sp.symbols('lamda')
poly_char_exp = sp.expand(A.charpoly(lamda).as_expr())
poly_char_fac = sp.factor(A.charpoly(lamda).as_expr())
poly_char_exp_str = sp.latex(poly_char_exp)
poly_char_fac_str = sp.latex(poly_char_fac)
display(Latex("Le polynôme caractéristique de $A$ s'exprime comme: $c_A (t) = " + poly_char_exp_str + "$."))
display(Latex("On trouve les racines du polynôme caractéristique et on factorise. On obtient $c_A (t) = "
+ poly_char_fac_str + "$."))
eig = A.eigenvals()
eig_list_ = list(eig.keys())
mult_list_ = list(eig.values())
display(Latex("On obtient donc les valeurs propres $\lambda$ et leur multiplicité respective $m$: "
" $ \lambda = " + sp.latex(eig_list_) + " \hspace{10mm} m = " + sp.latex(mult_list_) + "$."))
display(Markdown("**On trouve une base orthonormée pour tous les espaces propres.**"))
final_basis = []
P = sp.Matrix([])
k = 0
for l in eig_list_:
basis_orthonorm = []
basis, basic_idx, free_idx = eigen_basis(A, l, prop_basis=None, disp=True, return_=True, dispA=False)
for v in basis:
# if all ints
if np.all(v == np.round(v)):
v = v.astype(np.int16)
# if there is some float
else:
for idx, el in enumerate(v):
v = sp.Matrix(v)
q = sp.Rational(el)
# If rational are not too high and weird
if abs(q.numerator()) < 100 and abs(q.denominator()) < 100:
v[idx] = q
basis_orthonorm.append(sp.Matrix(v))
basis_orthonorm = sp.GramSchmidt(basis_orthonorm, True)
for v in basis_orthonorm:
final_basis.append(v)
P = P.col_insert(k, v)
k += 1
display(
Latex("On applique le procédé de Gram-Schmidt pour obtenir des vecteurs de norme 1 et orthogonaux. "
"On obtient $" + sp.latex(basis_orthonorm) + "$"))
display(Latex("Finalement, on construit la matrice $S$ en utilisant chaque vecteur de base "
"trouvé précedemment comme colonne de cette matrice. Cette dernière est bien orthogonale car "
"les vecteurs de base sont orthogonaux entre eux et tous de norme unitaire. "
"On construit la matrice $D$ en plaçant les valeurs propres de $A$ sur la diagonale. "
"Le placement des valeurs propres sur la diagonale de $D$ "
"doit correspondre avec celui des vecteurs propres dans $S$."))
D = sp.zeros(A.shape[0])
i = 0
for idx in range(len(eig_list_)):
for _ in range(mult_list_[idx]):
D[i, i] = eig_list_[idx]
i += 1
display(
Latex("On obtient $S = " + latexp(P) + "\hspace{5mm} \mbox{et} \hspace{5mm} D = " + latexp(D) + "$"))
display(Latex("On vérifie le résultat par un calcul :"))
display(Latex(
"$S D S^T = " + latexp(P) + latexp(D) + latexp(P.transpose()) + " = " + latexp(P * D * P.transpose()) +
"=A$"))
display(Latex("Pour afficher la solution, cliquez ici."))
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'
def f_plot():
A_np = np.array(A, dtype=np.float64)
plot_quad(A_np)
if A.shape[0] == 2 or A.shape[0] == 3:
display(Latex("Pour visualiser la quadrique associée et les axes principaux, cliquez ici"))
im = interact_manual(f_plot)
im.widget.children[0].description = 'Plot'
def ex1_1_10_9():
A = sp.Matrix([[1, -1 / 2, 0],
[-1 / 2, 0, -1],
[0, -1, 1]])
ex1_10_9(A)
def ex1_2_10_9():
A = sp.Matrix([[-1, -1, 0],
[-1, -2, 1],
[0, 1, -1]])
ex1_10_9(A)
def ex1_3_10_9():
A = sp.Matrix([[2, 1, 0, 1],
[1, 1, 0, 0],
[0, 0, 4, 0],
[1, 0, 0, 1]])
ex1_10_9(A)
def ex1_4_10_9():
A = sp.Matrix([[3, 2, 1],
[2, 3, 1],
[1, 1, 4]])
ex1_10_9(A)
def ex1_10_9(A):
options = ['définie postive', 'positive', 'définie négative', 'négative','non définie']
n = A.shape[0]
v = sp.zeros(n, 1)
for i in range(n):
symb_name = "x_" + str(i + 1)
v[i] = sp.symbols(symb_name, real=True)
Q = sp.expand(v.T * A * v)
eigval = list(A.eigenvals().keys())
if all([x >= 0 for x in eigval]):
if all([x > 0 for x in eigval]):
sol = options[0]
else:
sol = options[1]
elif all([x <= 0 for x in eigval]):
if all([x < 0 for x in eigval]):
sol = options[2]
else:
sol = options[3]
else:
sol = options[4]
display(Latex("Classez la forme quadratique suivante. Bien qu'il se peut que plusieurs réponses soient correctes, "
"donnez l'ensemble le plus restreint."))
display(Latex("$ Q(x) = " + latexp(Q) + "$"))
answer = widgets.RadioButtons(
options=['définie postive', 'positive', 'négative', 'définie négative', 'non définie'],
description='Réponse:', disabled=False)
display(answer)
def callback():
if answer.value == sol:
display(Latex("Correct !"))
else:
display(Latex("Incorrect. Vous pouvez afficher la solution si vous ne trouvez pas votre erreur."))
def f_sol():
display(Latex("Par identification, on trouve d'abord la matrice $A$ tel que $Q(\mathbf{x}) = \mathbf{x}^T A \mathbf{x}$."))
display(Latex("On obtient $A = " + latexp(A) + "$"))
display(Latex("On trouve ensuite les valeurs propres de $A$ et on observe leur signe."))
display(Latex("Les valeurs propres sont: " + ', '.join(["$" + latexp(x) + "$" for x in eigval])))
if sol == options[0]:
display(Latex("La forme quadratique est définie positive car toutes les valeurs propres de $A$ sont strictement positives."))
elif sol == options[1]:
display(Latex("La forme quadratique est positive car toutes les valeurs propres de $A$ sont positives."))
elif sol == options[2]:
display(Latex("La forme quadratique est définie négative car toutes les valeurs propres de $A$ sont strictement négative."))
elif sol == options[3]:
display(Latex("La forme quadratique est négative car toutes les valeurs propres de $A$ sont négatives."))
elif sol == options[4]:
display(Latex("La forme quadratique est non définie car $A$ possède des valeurs propres positives et négatives."))
interact_manual(callback)
im = interact_manual(f_sol)
im.widget.children[0].description = 'Solution'

Event Timeline