diff --git "a/Chapitre 2 - Algebre matricielle/2.11 D\303\251composition en blocs.ipynb" "b/Chapitre 2 - Algebre matricielle/2.11 D\303\251composition en blocs.ipynb" new file mode 100644 index 0000000..7fec515 --- /dev/null +++ "b/Chapitre 2 - Algebre matricielle/2.11 D\303\251composition en blocs.ipynb" @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Chapitre 2 - Algebre matricielle/Corrections/corrections.py b/Chapitre 2 - Algebre matricielle/Corrections/corrections.py index 20eb4b4..ebb4efa 100644 --- a/Chapitre 2 - Algebre matricielle/Corrections/corrections.py +++ b/Chapitre 2 - Algebre matricielle/Corrections/corrections.py @@ -1,978 +1,1059 @@ import sys sys.path.insert(0, './../') import numpy as np import plotly plotly.offline.init_notebook_mode(connected=True) import ipywidgets as widgets from IPython.display import display, Latex from ipywidgets import interact_manual, Layout from Librairie.AL_Fct import printA, texMatrix, isDiag, isSym def Ex2Chapitre2_1(): """Provides the correction of exercise 2 of notebook 2_1 """ a = widgets.Checkbox( value=False, description=r'Il existe \(\lambda\in \mathbb{R}\) tel que \((A-\lambda B)^T\) soit échelonnée réduite', disabled=False, layout=Layout(width='80%', height='30px') ) b = widgets.Checkbox( value=False, description=r'Il existe \(\lambda\in \mathbb{R}\) tel que \((A-\lambda B)^T\) soit échelonnée (mais pas réduite)', disabled=False, layout=Layout(width='80%', height='30px') ) c = widgets.Checkbox( value=False, description=r"Il n'existe pas de \(\lambda\in \mathbb{R}\) tel que \((A-\lambda B)^T\) soit échelonnée", disabled=False, layout=Layout(width='80%', height='30px') ) def correction(a, b, c): if a and not c and not b: display(Latex("C'est correct! Pour $\lambda=-3$ La matrice échelonnée réduite est:")) A = [[1, 0, -2, 3], [0, 1, -1, 7]] printA(A) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c) return def Ex3Chapitre2_1(): """Provides the correction of exercise 3 of notebook 2_1 """ a = widgets.Checkbox( value=False, description=r'\(C_{32}\) vaut -14', disabled=False, layout=Layout(width='80%', height='30px') ) b = widgets.Checkbox( value=False, description=r'\(C_{32}\) vaut 14', disabled=False, layout=Layout(width='80%', height='30px') ) c = widgets.Checkbox( value=False, description=r'\(C_{32}\) vaut -10', disabled=False, layout=Layout(width='80%', height='30px') ) d = widgets.Checkbox( value=False, description=r"\(C_{32}\) n'existe pas", disabled=False, layout=Layout(width='80%', height='30px') ) def correction(a, b, c, d): if c and not a and not b and not d: display(Latex("C'est correct! La matrice C vaut:")) A = [[-6, 64], [-32, -22], [28, -10], [-2, 6]] printA(A) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d) return def Ex1Chapitre2_2(): """Provides the correction of exercise 1 of notebook 2_2 """ a = widgets.Checkbox( value=False, description=r'Le produit $A \cdot B$ vaut:
' r'\begin{equation*} \qquad A \cdot B = \begin{bmatrix}-1 & 4\\-3& -3\\2 & 0\end{bmatrix}\end{equation*}', disabled=False, layout=Layout(width='100%', height='110px') ) b = widgets.Checkbox( value=False, description=r'Le produit $A \cdot B$ vaut:
' r'\begin{equation*} \qquad A \cdot B =\begin{bmatrix}-1 & 8\\-3& 3\\-2 & 4\end{bmatrix}\end{equation*}', disabled=False, layout=Layout(width='100%', height='110px') ) c = widgets.Checkbox( value=False, description=r'Le produit $A \cdot B$ vaut:
' r'\begin{equation*} \qquad A \cdot B =\begin{bmatrix}5 & -4\\1 & 0\end{bmatrix}\end{equation*}', disabled=False, layout=Layout(width='100%', height='90px') ) d = widgets.Checkbox( value=False, description=r"Le produit $A \cdot B$ n'est pas définie", disabled=False, layout=Layout(width='100%', height='60px') ) def correction(a, b, c, d): if b and not a and not c and not d: display(Latex("C'est correct!")) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d) return def Ex2Chapitre2_2(): """Provides the correction of exercise 2 of notebook 2_2 """ a = widgets.Checkbox( value=False, description=r'Le produit $A \cdot B$ appartient à $M_{3 \times 3}(\mathbb{R})$', disabled=False, layout=Layout(width='80%', height='50px') ) b = widgets.Checkbox( value=False, description=r'Le produit $A \cdot B$ appartient à $M_{3 \times 2}(\mathbb{R})$', disabled=False, layout=Layout(width='80%', height='50px') ) c = widgets.Checkbox( value=False, description=r'Le produit $A \cdot B$ appartient à $M_{2 \times 1}(\mathbb{R})$', disabled=False, layout=Layout(width='80%', height='50px') ) d = widgets.Checkbox( value=False, description=r"$A \cdot B$ n'est pas définie", disabled=False, layout=Layout(width='80%', height='50px') ) def correction(a, b, c, d): if c and not a and not b and not d: A = [[14], [6]] texA = '$' + texMatrix(A) + '$' display(Latex(r"C'est correct! Le produit $ A \cdot B$ vaut: $A \cdot B$ = " + texA)) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d) return def Ex3Chapitre2_2(): """Provides the correction of exercise 3 of notebook 2_2 """ display(Latex("Insert the values of a and b as floating point numbers")) a = widgets.FloatText( value=0.0, step=0.1, description='a:', disabled=False ) b = widgets.FloatText( value=0.0, step=0.1, description='b:', disabled=False ) display(a) display(b) def f(): A = np.array([[-1, 2], [5, -2]]) B = np.array([[-1, 1], [a.value, b.value]]) AB = np.dot(A,B) texAB = '$' + texMatrix(AB) + '$' BA = np.dot(B,A) texBA = '$' + texMatrix(BA) + '$' if a.value == 5/2 and b.value == -3/2: display(Latex(r"Correcte! Le produits $A \cdot B$ et $B \cdot A$ valent chacun: " + texAB)) else: display(Latex(r"Incorrecte! Le produit $A \cdot B$ vaut " + texAB + r"et par contre le produit " r"$B \cdot A$ vaut " + texBA + r" Entrez de nouvelles valeurs!")) interact_manual(f) return def Ex1Chapitre2_3(A, B, C): """Provides the correction to exercise 1 of notebook 2_3 :param A: original matrix :type A: list[list] or numpy.ndarray :param B: matrix such that A+B should be diagonal :type B: list[list] or numpy.ndarray :param C: matrix such that A+C should be symmetric and not diagonal :type C: list[list] or numpy.ndarray :return: :rtype: """ if not type(A) is np.ndarray: A = np.array(A) if not type(B) is np.ndarray: B = np.array(B) if not type(C) is np.ndarray: C = np.array(C) ans1 = isDiag(A+B) ans2 = isSym(A+C) and not isDiag(A+C) if ans1 and ans2: display(Latex('Correcte!')) else: display(Latex('Incorrecte! Entrez des nouvelles valeurs pur le matrices B et C!\n')) if ans1: display(Latex("A+B est bien diagonale!")) else: display(Latex("A+B est n'est pas diagonale!")) texAB = '$' + texMatrix(A+B) + '$' display(Latex(r"A+B=" + texAB)) if ans2: display(Latex("A+C est bien symétrique et non diagonale!")) elif isSym(A + C) and isDiag(A + C): display(Latex("A+C est bien symétrique mais elle est aussi diagonale!")) else: display(Latex("A + C n'est pas symétrique")) texAC = '$' + texMatrix(A + C) + '$' display(Latex(r"A+C=" + texAC)) return def Ex2Chapitre2_3(): """Provides the correction to exercise 2 of notebook 2_3 """ a = widgets.Checkbox( value=False, description=r'$(A^{-1})^T$ et $(A^T)^{-1}$ sont triangulaires supérieures mais différentes', disabled=False, layout=Layout(width='80%', height='40px') ) b = widgets.Checkbox( value=False, description=r'$(A^{-1})^T$ et $(A^T)^{-1}$ sont triangulaires inférieures mais différentes', disabled=False, layout=Layout(width='80%', height='40px') ) c = widgets.Checkbox( value=False, description=r'$(A^{-1})^T$ et $(A^T)^{-1}$ sont triangulaires inférieures et identiques', disabled=False, layout=Layout(width='80%', height='40px') ) d = widgets.Checkbox( value=False, description=r'$(A^{-1})^T$ et $(A^T)^{-1}$ sont triangulaires supérieures et identiques', disabled=False, layout=Layout(width='80%', height='40px') ) def correction(a, b, c, d): if d and not a and not c and not b: A = np.array(([-1, 0, 0], [3, 1/2, 0], [1, 2, 1])) res = np.transpose(np.linalg.inv(A)) texAres = '$' + texMatrix(res) + '$' display(Latex("C'est correct! $(A^T)^{-1}$ est donnée par: $\quad$" + texAres)) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d) return def Ex1Chapitre2_4(): """Provides the correction to exercise 2 of notebook 2_4 """ a = widgets.Checkbox( value=False, description=r'Le système admet une solution unique et elle est:' r'$$\qquad \qquad x = \begin{bmatrix} 1&4/3&4/3\end{bmatrix}^T$$', disabled=False, layout=Layout(width='80%', height='70px') ) b = widgets.Checkbox( value=False, description=r"Le système n'admet aucune solution", disabled=False, layout=Layout(width='80%', height='40px') ) c = widgets.Checkbox( value=False, description=r'Le système admet une solution unique et elle est:' r'$$\qquad \qquad x = \begin{bmatrix} 1&4/3&8/3\end{bmatrix}^T$$', disabled=False, layout=Layout(width='80%', height='70px') ) d = widgets.Checkbox( value=False, description=r'Le système admet plusieurs solutions', disabled=False, layout=Layout(width='80%', height='40px') ) e = widgets.Checkbox( value=False, description=r'$A$ est inversible et son inverse est:
' r'$$\qquad \qquad A^{-1} = \begin{bmatrix} 1/2&0&1/2\\1/2&-1/3&5/3\\1/2&-2/3&5/6\end{bmatrix}$$', disabled=False, layout=Layout(width='80%', height='100px') ) f = widgets.Checkbox( value=False, description=r"$A$ n'est pas inversible", disabled=False, layout=Layout(width='80%', height='40px') ) g = widgets.Checkbox( value=False, description=r'$A$ est inversible et son inverse est:' r'$$\qquad \qquad A^{-1} = \begin{bmatrix} 1/2&0&1/2\\1/2&-1/3&5/3\\1/2&-2/3&-1/2\end{bmatrix}$$', disabled=False, layout=Layout(width='80%', height='100x') ) def correction(a, b, c, d, e, f, g): if c and e and not a and not b and not d and not f and not g: display(Latex("C'est correct!")) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d, e=e, f=f, g=g) return def Ex2Chapitre2_4(): """Provides the correction to exercise 3 of notebook 2_4 """ a = widgets.Checkbox( value=False, description=r"Le système n'admet une solution unique que si $\alpha < 2$", disabled=False, layout=Layout(width='80%', height='40px') ) b = widgets.Checkbox( value=False, description=r"Le système n'admet une solution unique que si $\alpha \geq 2$", disabled=False, layout=Layout(width='80%', height='40px') ) c = widgets.Checkbox( value=False, description=r'Le système admet une solution unique $\forall \alpha \in \mathbb{R}$', disabled=False, layout=Layout(width='80%', height='40px') ) d = widgets.Checkbox( value=False, description=r"Le système n'admet aucune solution si $\alpha < 2$, alors qu'il admet une solution unique si " r"$\alpha \geq 2$", disabled=False, layout=Layout(width='80%', height='40px') ) e = widgets.Checkbox( value=False, description=r"Le système admet plusieurs solutions si $\alpha \neq 2$, alors qu'il admet une solution unique si" r" $\alpha = 2$", disabled=False, layout=Layout(width='80%', height='40px') ) f = widgets.Checkbox( value=False, description=r"Le système n'admet jamais une solution unique, quelle que soit $\alpha \in \mathbb{R}$", disabled=False, layout=Layout(width='80%', height='40px') ) def correction(a, b, c, d, e, f): if f and not a and not b and not c and not d and not e: display(Latex("C'est correct!")) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d, e=e, f=f) return def Ex1aChapitre2_5(): """Provides the correction to exercise 1a of notebook 2_5 """ a = widgets.Checkbox( value=False, description=r'\(E_1E_2\) multiplie la ligne 4 par -6 et échange les lignes 2 et 3', disabled=False, layout=Layout(width='80%', height='40px') ) b = widgets.Checkbox( value=False, description=r'\(E_1E_2\) ajoute 6 fois la ligne 4 à la ligne 2 et échange les lignes 1 et 3', disabled=False, layout=Layout(width='80%', height='40px') ) c = widgets.Checkbox( value=False, description=r'\(E_1E_2\) échange les lignes 1 et 3 et ajoute -6 fois la ligne 4 à la ligne 2', disabled=False, layout=Layout(width='80%', height='40px') ) d = widgets.Checkbox( value=False, description=r"\(E_1E_2\) ajoute -6 fois la ligne 4 à la ligne 2 et échange les lignes 1 et 2", disabled=False, layout=Layout(width='80%', height='40px') ) def correction(a, b, c, d): if c and not(a) and not(d) and not(b): display(Latex("C'est correct! Par exemple, si on applique le produit à la matrice ci-dessous")) A=[[1,-1,0,0], [0,0,0,1], [1,2,1,2], [1,0,0,1]] B=[[1,0,0,0], [0,1,0,-6], [0,0,1,0], [0,0,0,1]] C=[[0,0,1,0], [0,1,0,0], [1,0,0,0], [0,0,0,1]] BCA = np.linalg.multi_dot([B,C,A]) texA = '$' + texMatrix(A) + '$' texBCA = '$' + texMatrix(BCA) + '$' display(Latex('$\qquad A = $' + texA)) display(Latex("on obtient")) display((Latex('$\qquad \hat{A} = $' + texBCA))) else: display(Latex("C'est faux.")) interact_manual(correction,a=a,b=b,c=c,d=d) return def Ex1bChapitre2_5(inv): """Provides the correction to exercise 1b of notebook 2_5 :param inv: inverse of the matrix to be calculated :type inv: list[list] """ if inv == [[0, 0, 1, 0], [0, 1, 0, 6], [1, 0, 0, 0], [0, 0, 0, 1]]: display(Latex("C'est correct!")) else: display(Latex("C'est faux.")) return def Ex2aChapitre2_5(A, B, T, D, L): """Provides the correction to exercise 2a of notebook 2_5 :param A: starting matrix :type A: list[list] :param B: target matrix :type B: list[list] :param T: permutation (type I) matrix :type T: list[list] :param D: scalar multiplication (type II) matrix :type D: list[list] :param L: linear combination (type III) matrix :type L: list[list] """ if ~(B - np.linalg.multi_dot([L, D, T, A])).any(): display(Latex("C'est correct!")) else: display(Latex("C'est faux.")) str = 'Il faut entrer la/les matrice(s) {' if (np.asmatrix(T) - np.asmatrix([[0, 0, 1], [0, 1, 0], [1, 0, 0]])).any(): str = str + ' T, ' if (np.asmatrix(D) - np.asmatrix([[1, 0, 0], [0, 1, 0], [0, 0, 5]])).any(): str = str + ' D, ' if (np.asmatrix(L) - np.asmatrix([[1, 0, 0], [-4, 1, 0], [0, 0, 1]])).any(): str = str + ' L, ' str = str + '}. Le produit des matrices entrées vaut:' display(Latex(str)) tmp = np.linalg.multi_dot([L, D, T, A]) texM = '$' + texMatrix(tmp) + '$' display(Latex('$\qquad \hat{B} = $' + texM)) return def Ex2bChapitre2_5(inv): """Provides the correction to exercise 2b of notebook 2_5 :param inv: inverse of the matrix to be calculated :type inv: list[list] """ if inv == [[0, 0, 1/5], [4, 1, 0], [1, 0, 0]]: display(Latex("C'est correct!")) else: display(Latex("C'est faux.")) return def Ex1Chapitre2_6_7(): """Provides the correction to exercise 1 of notebook 2_6-7 """ a = widgets.Checkbox( value=False, description=r'$A^{-1}$ existe et le système admet plusieurs solutions, quelle que soit la valeur de $b$', disabled=False, layout=Layout(width='80%', height='40px') ) b = widgets.Checkbox( value=False, description=r'$A^{-1}$ existe et le système admet une solution unique ou plusieurs solutions en fonction ' r'de la valeur de $b$', disabled=False, layout=Layout(width='80%', height='40px') ) c = widgets.Checkbox( value=False, description=r'$A$ est inversible et le système admet une solution unique, quelle que soit la valeur de $b$', disabled=False, layout=Layout(width='80%', height='40px') ) d = widgets.Checkbox( value=False, description=r'$A^{-1}$ existe et le système admet au moins une solution, quelle que soit la valeur de $b$', disabled=False, layout=Layout(width='80%', height='40px') ) e = widgets.Checkbox( value=False, description=r"$A$ n'est pas inversible et le système admet une unique solution ou plusieurs solutions, " r"selon la valeur de $b$ ", disabled=False, layout=Layout(width='80%', height='40px') ) f = widgets.Checkbox( value=False, description=r"$A$ n'est pas inversible et le système admet une solution unique, " r"quelle que soit la valeur de $b$", disabled=False, layout=Layout(width='80%', height='40px') ) g = widgets.Checkbox( value=False, description=r"Le système admet une solution unique et $A$ n'est pas inversible", disabled=False, layout=Layout(width='80%', height='40px') ) h = widgets.Checkbox( value=False, description=r'Le système admet une solution unique et $A$ est inversible', disabled=False, layout=Layout(width='80%', height='40px') ) def correction(a, b, c, d, e, f, g, h): if c and d and h and not a and not b and not e and not f and not g: display(Latex("C'est correct!")) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d, e=e, f=f, g=g, h=h) return def Ex2Chapitre2_6_7(): """Provides the correction to exercise 2 of notebook 2_6-7 """ a = widgets.Checkbox( value=False, description=r'$A_1$ est inversible', disabled=False, layout=Layout(width='80%', height='40px') ) b = widgets.Checkbox( value=False, description=r'$A_2$ est inversible', disabled=False, layout=Layout(width='80%', height='40px') ) c = widgets.Checkbox( value=False, description=r'$A_3$ est inversible', disabled=False, layout=Layout(width='80%', height='40px') ) def correction(a, b, c): if a and not b and not c: A1 = np.array([[2, 0, 1], [0, 6, 4], [2, 2, 1]]) A1_inv = np.linalg.inv(A1) texA1inv = '$' + texMatrix(A1_inv) + '$' display(Latex("C'est correct! $A_1$ est la seule matrice inversible et son inverse est: $\quad A_1^{-1} = $" + texA1inv)) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c) return def Ex3Chapitre2_6_7(): """Provides the correction to exercise 3 of notebook 2_6-7 """ style = {'description_width': 'initial'} a = widgets.Checkbox( value=False, description=r"Si $\alpha = 4$ et $\beta = 2$, alors $A$ n'est pas inversible et le système linéaire " r"admet une infinité de solutions", disabled=False, style=style, layout=Layout(width='80%', height='40px') ) b = widgets.Checkbox( value=False, description=r"Si $\alpha=8$ et $\beta=-1$, alors $A$ n'est pas inversible et le système linéaire n'admet pas de" r" solutions", disabled=False, style=style, layout=Layout(width='80%', height='40px') ) c = widgets.Checkbox( value=False, description=r"Si $\alpha=-2$ et $\beta=-4$, alors $A$ n'est pas inversible et le système linéaire admet " r"une infinité de solutions", disabled=False, style=style, layout=Layout(width='80%', height='40px') ) d = widgets.Checkbox( value=False, description=r"Si $\alpha=8$ et $\beta=1$, alors $A$ n'est pas inversible et le système linéaire admet " r"une infinité de solutions", disabled=False, style=style, layout=Layout(width='80%', height='40px') ) e = widgets.Checkbox( value=False, description=r"Si $\alpha=-4$ et $\beta=-2$, alors $A$ n'est pas inversible et le système linéaire n'admet pas" r"de solutions", disabled=False, style=style, layout=Layout(width='80%', height='40px') ) f = widgets.Checkbox( value=False, description=r'Si $\alpha=4$ et $\beta=1$, alors $A$ est inversible et le système linéaire admet une infinité ' r'de solutions', disabled=False, style=style, layout=Layout(width='80%', height='40px') ) g = widgets.Checkbox( value=False, description=r'Si $\alpha=4$ et $\beta=1$, alors $A$ est inversible et le système linéaire admet une solution' r' unique', disabled=False, style=style, layout=Layout(width='80%', height='40px') ) h = widgets.Checkbox( value=False, description=r"Pour infinite de valeurs de $\alpha$ et $\beta$ $A$ n'est pas inversible, mais seulement pour l'un" r" d'eux le système admet une infinité de solutions", disabled=False, style=style, layout=Layout(width='100%', height='40px') ) def correction(a, b, c, d, e, f, g, h): if c and e and h and not a and not b and not d and not f and not g: display(Latex(r"C'est correct! En effet $A$ n'est pas inversible si $\alpha = \dfrac{8}{\beta}$ (résultat " r"obtenu en divisant par élément les lignes de A les unes par les autres et en imposant que " r"les résultats des divisions soient les mêmes). De plus, si $\alpha = -2$ et $\beta = -4$, " r"alors le système admet une infinité de solutions, puisque les rapports obtenus par la " r"division est $-\dfrac{1}{2}$).")) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d, e=e, f=f, g=g, h=h) return def Ex4Chapitre2_6_7(): """Provides the correction of exercise 4 of notebook 2_6-7 """ display(Latex("Insert the values of a and b as floating point numbers")) a = widgets.FloatText( value=0.0, step=0.1, description='a:', disabled=False ) b = widgets.FloatText( value=0.0, step=0.1, description='b:', disabled=False ) display(a) display(b) def f(): A = np.array([[0.5, a.value, 1], [0, 2, -1], [-2, 1, b.value]]) B = np.array([[-6, -2, -2], [4, 2, 1], [8, 3, 2]]) AB = np.dot(A, B) texAB = '$' + texMatrix(AB) + '$' BA = np.dot(B, A) texBA = '$' + texMatrix(BA) + '$' if a.value == -1 and b.value == -2: display(Latex(r"Correcte! Le produits $A \cdot B$ et $B \cdot A$ valent chacun: $I$ = " + texAB)) else: display(Latex(r"Incorrecte! Le produit $A \cdot B$ vaut " + texAB + r" et le produit " r"$B \cdot A$ vaut " + texBA + r" donc, $A$ ne peut pas être l'inverse de $B$. " r"Entrez de nouvelles valeurs!")) interact_manual(f) return def Ex1Chapitre2_8_9(E1, E2, E3, E4): """Provides the correction of exercise 2 of notebook 2_8_9 :param E1: :type E1: :param E2: :type E2: :param E3: :type E3: :param E4: :type E4: :return: :rtype: """ # MATRIX A1 E_pre_1 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] E_post_1 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [-1, 0, 0, 1]] # MATRIX A2 E_pre_2 = [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]] E_post_2 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1/2, 0], [0, 0, 0, 1]] # MATRIX A3 E_pre_3 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] E_post_3 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -1], [0, 0, 0, 1]] # MATRIX A4 E_pre_4 = [[1/2, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] E_post_4 = [[1, 0, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 1]] E_bool = np.zeros(4).astype(bool) E_bool[0] = E1[0] == E_pre_1 and E1[1] == E_post_1 E_bool[1] = E2[0] == E_pre_2 and E2[1] == E_post_2 E_bool[2] = E3[0] == E_pre_3 and E3[1] == E_post_3 E_bool[3] = E4[0] == E_pre_4 and E4[1] == E_post_4 correct = set(np.where(E_bool)[0]+1) wrong = set(np.arange(1,5)) - correct if wrong: display(Latex(f"Corrects: {correct}")) display(Latex(f"Manqué: {wrong}")) else: display(Latex("C'est correcte.")) return def Ex3Chapitre2_8_9(): """Provides the correction of exercise 3 of notebook 2_8_9 """ a_1 = widgets.Checkbox( value=False, description=r'La matrice $A_1$ admet la décomposition LU', disabled=False, layout=Layout(width='80%', height='30px') ) a_2 = widgets.Checkbox( value=False, description=r'La matrice $A_2$ admet la décomposition LU', disabled=False, layout=Layout(width='80%', height='30px') ) a_3 = widgets.Checkbox( value=False, description=r'La matrice $A_3$ admet la décomposition LU', disabled=False, layout=Layout(width='80%', height='30px') ) def correction(a_1, a_2, a_3): if not a_1 and a_2 and not a_3: display(Latex("C'est correct! Plus précisément, la matrice $A_1$ n'admet pas décomposition LU car elle n'est pas inversible, la matrice $A_2$ admet décomposition LU et la matrice $A_3$ n'admet pas décomposition LU car elle ne peut pas être réduite sans échanger deux lignes pendant la méthode d'élimination de Gauss")) else: display(Latex("C'est faux.")) interact_manual(correction, a_1=a_1, a_2=a_2, a_3=a_3) return def Ex1Chapitre2_10(): """Provides the correction to exercise 1 of notebook 2_10 """ a = widgets.Checkbox( value=False, description=r"Le système linéaire n'admet aucune solution", disabled=False, layout=Layout(width='80%', height='40px') ) b = widgets.Checkbox( value=False, description=r"Le système linéaire admet une solution unique", disabled=False, layout=Layout(width='80%', height='40px') ) c = widgets.Checkbox( value=False, description=r"Le système linéaire admet deux solutions distinctes", disabled=False, layout=Layout(width='80%', height='40px') ) d = widgets.Checkbox( value=False, description=r"Le système linéaire admet une infinité de solutions", disabled=False, layout=Layout(width='80%', height='40px') ) e = widgets.Checkbox( value=False, description=r"La décomposition LU de $A$ ne peut pas être calculée", disabled=False, layout=Layout(width='80%', height='40px') ) f = widgets.Checkbox( value=False, description=r"La dernière colonne de $U$ est entièrement composée de zéros", disabled=False, layout=Layout(width='80%', height='40px') ) g = widgets.Checkbox( value=False, description=r'La dernière ligne de $U$ est entièrement composée de zéros', disabled=False, layout=Layout(width='80%', height='40px') ) h = widgets.Checkbox( value=False, description=r'La première entrée de la première ligne de $L$ est égale à 1', disabled=False, layout=Layout(width='80%', height='40px') ) def correction(a, b, c, d, e, f, g, h): if not a and not b and not c and d and not e and not f and g and not h: display(Latex("C'est correct. En effet, $A$ n'est clairement pas inversible, car la dernière ligne est " "égale à la seconde moins la première, et il en va de même pour le vecteur de droite $b$. " "Par conséquent, la dernière ligne de $U$ est entièrement composée de zéros (réponse 7) et la " "dernière entrée du vecteur de droite $b$, après l'application de la méthode d'élimination de " "Gauss, est également égale à 0. Ainsi, la dernière équation du système linéaire résultant a " "tous les coefficients égaux à 0, ce qui donne lieu à une infinité de solutions " "(réponse 4).")) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d, e=e, f=f, g=g, h=h) return def Ex2Chapitre2_10(L, U, b, x, y): """Provides the correction to exercise 2 of notebook 2_10 :param L: lower triangular matrix from LU decomposition :type L: list[list] :param U: upper triangular matrix from LU decomposition :type U: list[list] :param b: right-hand side vector :type b: list[list] :param x: system solution :type x: list[list] :param y: temporary variable :type y: list[list] """ if type(L) is list: L = np.array(L) if type(U) is list: U = np.array(U) if type(x) is list: x = np.array(x) if type(y) is list: y = np.array(y) y_true = np.linalg.solve(L, b) x_true = np.linalg.solve(U, y) res_x = np.linalg.norm(x - x_true) / np.linalg.norm(x_true) <= 1e-4 res_y = np.linalg.norm(y - y_true) / np.linalg.norm(y_true) <= 1e-4 if res_x and res_y: display(Latex("C'est correct")) else: display(Latex("C'est faux")) return +def Ex3Chapitre2_10(): + """Provides the correction to exercise 3 of notebook 2_10 + + :return: + :rtype: + """ + + a = widgets.Checkbox( + value=False, + description=r"If L is such that all its diagonal elements equal 1, then the temporary variable y is a vector " + r"of ones as well", + disabled=False, + layout=Layout(width='80%', height='40px') + ) + + b = widgets.Checkbox( + value=False, + description=r"Matrix L is diagonal", + disabled=False, + layout=Layout(width='80%', height='40px') + ) + + c = widgets.Checkbox( + value=False, + description=r"Matrix U is diagonal", + disabled=False, + layout=Layout(width='80%', height='40px') + ) + + d = widgets.Checkbox( + value=False, + description=r"The second entry of the solution is always 2.5 times the fourth one", + disabled=False, + layout=Layout(width='80%', height='40px') + ) + + e = widgets.Checkbox( + value=False, + description=r"The second entry of the solution is always 5 times the fourth one", + disabled=False, + layout=Layout(width='80%', height='40px') + ) + + f = widgets.Checkbox( + value=False, + description=r"The sum of all the entries always equals 2.5", + disabled=False, + layout=Layout(width='80%', height='40px') + ) + + g = widgets.Checkbox( + value=False, + description=r"The sum of all the entries but the second one always equals 0", + disabled=False, + layout=Layout(width='80%', height='40px') + ) + + h = widgets.Checkbox( + value=False, + description=r"The vector [1, 0 -1, 0] is one of the solutions to the linear system", + disabled=False, + layout=Layout(width='80%', height='40px') + ) + + def correction(a, b, c, d, e, f, g, h): + if a and not b and not c and d and not e and not f and g and h: + display(Latex("C'est correct. Indeed the set of all possible solutions can be written as " + "$x = [1-4a, 2.5a, 3a-1, a]$. From this, it is clear that the second entry is 2.5 times the " + "fourth one (answer 4), that the sum of all the entries but the second one equals $0$ " + "(answer 7) and that $x^* = [1,0,-1,0]$ is a solution, in case $a$ is set to 0 (answer 8). " + "Also, if L is computed so that it has ones on its diagonal, it is immediate to deduce that " + "the temporary vector $y$ that solves the system $Ly=b$ is actually all made of ones.")) + else: + display(Latex("C'est faux.")) + + interact_manual(correction, a=a, b=b, c=c, d=d, e=e, f=f, g=g, h=h) + + return + + + diff --git a/Librairie/AL_Fct.py b/Librairie/AL_Fct.py index f6c5c20..c49af86 100644 --- a/Librairie/AL_Fct.py +++ b/Librairie/AL_Fct.py @@ -1,1503 +1,1512 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Wed Mar 13 16:42:29 2019 @author: jecker """ from __future__ import division import numpy as np from IPython.display import display, Latex, display_latex import plotly import plotly.graph_objs as go plotly.offline.init_notebook_mode(connected=True) from IPython.core.magic import register_cell_magic from IPython.display import HTML import ipywidgets as widgets import random from ipywidgets import interact_manual, Layout import sympy as sp @register_cell_magic def bgc(color): script = ( "var cell = this.closest('.jp-CodeCell');" "var editor = cell.querySelector('.jp-Editor');" "editor.style.background='{}';" "this.parentNode.removeChild(this)" ).format(color) display(HTML(''.format(script))) ############################################################################### ## PRINTS Equations, systems, matrix def printMonomial(coeff, index=None, include_zeros=False): """Prints the monomial coeff*x_{index} in optimal way :param coeff: value of the coefficient :type coeff: float :param index: index of the monomial. If None, only the numerical value of the coefficient is displayed :type index: int or NoneType :param include_zeros: if True, monomials of type 0x_n are printed. Defaults to False :type include_zeros: bool :return: string representative of the monomial :rtype: str """ if index is not None: coeff = abs(coeff) if coeff % 1: return str(round(coeff, 3)) + ('x_' + str(index) if index is not None else "") elif not coeff: if index is None: return str(0) else: return str(0) + 'x_' + str(index) if include_zeros else "" elif coeff == 1: return 'x_' + str(index) if index is not None else str(int(coeff)) elif coeff == -1: return 'x_' + str(index) if index is not None else str(int(coeff)) else: return str(int(coeff)) + ('x_' + str(index) if index is not None else "") def printPlusMinus(coeff, include_zeros=False): """Prints a plus or minus sign, depending on the sign of the coefficient :param coeff: value of the coefficient :type coeff: float :param include_zeros: if True, 0-coefficients are assigned a "+" sign :type include_zeros: bool :return: "+" if the coefficient is positive, "-" if it is negative, "" if it is 0 :rtype: str """ if coeff > 0: return "+" elif coeff < 0: return "-" else: return "+" if include_zeros else "" def strEq(n, coeff): """Method that provides the Latex string of a linear equation, given the number of unknowns and the values of the coefficients. If no coefficient value is provided, then a symbolic equation with `n` unknowns is plotted. In particular: * **SYMBOLIC EQUATION**: if the number of unknowns is either 1 or 2, then all the equation is displayed while, if the number of unknowns is higher than 2, only the first and last term of the equation are displayed * **NUMERICAL EQUATION**: whichever the number of unknowns, the whole equation is plotted. Numerical values of the coefficients are rounded to the third digit :param n: number of unknowns of the equation :type n: int :param coeff: coefficients of the linear equation. It must be [] if a symbolic equation is desired :type: list[float] :return: Latex string representing the equation :rtype: str """ Eq = '' if not len(coeff): if n is 1: Eq = Eq + 'a_1x_1 = b' elif n is 2: Eq = Eq + 'a_1x_1 + a_2x_2 = b' else: Eq = Eq + 'a_1x_1 + \ldots + ' + 'a_' + str(n) + 'x_' + str(n) + '= b' else: all_zeros = len(set(coeff[:-1])) == 1 and not coeff[0] # check if all lhs coefficients are 0 start_put_sign = all_zeros if n is 1: Eq += "-" if coeff[0] < 0 else "" Eq += printMonomial(coeff[0], index=1, include_zeros=all_zeros) + "=" + printMonomial(coeff[-1]) else: Eq += "-" if coeff[0] < 0 else "" Eq += printMonomial(coeff[0], index=1, include_zeros=all_zeros) start_put_sign = start_put_sign or coeff[0] is not 0 for i in range(1, n): Eq += printPlusMinus(coeff[i], include_zeros=all_zeros) if start_put_sign \ else "-" if coeff[i] < 0 else "" Eq += printMonomial(coeff[i], index=i+1, include_zeros=all_zeros) start_put_sign = start_put_sign or coeff[i] is not 0 Eq += "=" + printMonomial(coeff[-1]) return Eq def printEq(coeff, b, *args): """Method that prints the Latex string of a linear equation, given the values of the coefficients. If no coefficient value is provided, then a symbolic equation with `n` unknowns is plotted. In particular: * **SYMBOLIC EQUATION**: if the number of unknowns is either 1 or 2, then all the equation is displayed while, if the number of unknowns is higher than 2, only the first and last term of the equation are displayed * **NUMERICAL EQUATION**: whichever the number of unknowns, the whole equation is plotted. Numerical values of the coefficients are rounded to the third digit :param coeff: coefficients of the left-hand side of the linear equation :type: list[float] :param b: right-hand side coefficient of the linear equation :type b: float :param *args: optional; if passed, it contains the number of unknowns to be considered. If not passed, all the unknowns are considered, i.e. n equals the length of the coefficients list :type: *args: list """ if len(args) == 1: n = args[0] else: n = len(coeff) coeff = coeff + b texEq = '$' texEq = texEq + strEq(n, coeff) texEq = texEq + '$' display(Latex(texEq)) return def printSyst(A, b, *args): """Method that prints a linear system of `n` unknowns and `m` equations. If `A` and `b` are empty, then a symbolic system is printed; otherwise a system containing the values of the coefficients stored in `A` and `b`, approximated up to their third digit is printed. :param A: left-hand side matrix. It must be [] if a symbolic system is desired :type: list[list[float]] :param b: right-hand side vector. It must be [] if a symbolic system is desired :type b: list[float] :param args: optional; if not empty, it is a list of two integers representing the number of equations of the linear system (i.e. `m`) and the number of unknowns of the system (i.e. `n`) :type: list """ if (len(args) == 2) or (len(A) == len(b)): # ensures that MatCoeff has proper dimensions if len(args) == 2: m = args[0] n = args[1] else: m = len(A) n = len(A[0]) texSyst = '$\\begin{cases}' Eq_list = [] if len(A) and len(b): if type(b[0]) is list: b = np.array(b).astype(float) A = np.concatenate((A, b), axis=1) else: A = [A[i] + [b[i]] for i in range(0, m)] # becomes augmented matrix A = np.array(A) # just in case it's not for i in range(m): if not len(A) or not len(b): Eq_i = '' if n is 1: Eq_i = Eq_i + 'a_{' + str(i + 1) + '1}' + 'x_1 = b_' + str(i + 1) elif n is 2: Eq_i = Eq_i + 'a_{' + str(i + 1) + '1}' + 'x_1 + ' + 'a_{' + str(i + 1) + '2}' + 'x_2 = b_' + str( i + 1) else: Eq_i = Eq_i + 'a_{' + str(i + 1) + '1}' + 'x_1 + \ldots +' + 'a_{' + str(i + 1) + str( n) + '}' + 'x_' + str(n) + '= b_' + str(i + 1) else: Eq_i = strEq(n, A[i, :]) # attention A is (A|b) Eq_list.append(Eq_i) texSyst = texSyst + Eq_list[i] + '\\\\' texSyst = texSyst + '\\end{cases}$' display(Latex(texSyst)) else: print("La matrice des coefficients n'a pas les bonnes dimensions") return def texMatrix(*args): """Method which produces the Latex string corresponding to the input matrix. .. note:: if two inputs are passed, they represent A and b respectively; as a result the augmented matrix A|B is plotted. Otherwise, if the input is unique, just the matrix A is plotted :param args: input arguments; they could be either a matrix and a vector or a single matrix :type args: list[list] or list[numpy.ndarray] :return: Latex string representing the input matrix or the input matrix augmented by the input vector :rtype: str """ if len(args) == 2: # matrice augmentée if not type(args[0]) is np.ndarray: A = np.array(args[0]).astype(float) else: A = args[0].astype(float) if len(A.shape) <= 1: raise ValueError("If two input arguments are passed, the first one must be either a matrix or a column " "vector! Row vectors or empty vectors are not accepted.") m = A.shape[1] if not type(args[1]) is np.array: b = np.array(args[1]).astype(float) else: b = args[1].astype(float) if len(b.shape) <= 1: raise ValueError("If two input arguments are passed, the second one must be either a matrix or a column " "vector! Row vectors or empty vectors are not accepted.") try: assert A.shape[0] == b.shape[0] except AssertionError: raise ValueError(f"If two input arguments are passed, they must both be either matrices or column vectors, " f"with the same number of rows. In this case, instead, the first input argument has " f"{A.shape[0]} rows, while the second one has {b.shape[0]}") A = np.concatenate((A, b), axis=1) - texApre = '\\left(\\begin{array}{' + texApre = '\\left[\\begin{array}{' texA = '' for i in np.asarray(A): texALigne = '' texALigne = texALigne + str(round(i[0], 4) if i[0] % 1 else int(i[0])) if texA == '': texApre = texApre + 'c' for j in i[1:m]: if texA == '': texApre = texApre + 'c' texALigne = texALigne + ' & ' + str(round(j, 4) if j % 1 else int(j)) if texA == '': texApre = texApre + '| c' for j in i[m:]: if texA == '': texApre = texApre + 'c' texALigne = texALigne + ' & ' + str(round(j, 4) if j % 1 else int(j)) texALigne = texALigne + ' \\\\' texA = texA + texALigne - texA = texApre + '} ' + texA[:-2] + ' \\end{array}\\right)' + texA = texApre + '} ' + texA[:-2] + ' \\end{array}\\right]' elif len(args) == 1: # matrice des coefficients if not type(args[0]) is np.ndarray: A = np.array(args[0]).astype(float) else: A = args[0].astype(float) - texApre = '\\left(\\begin{array}{' - texApost = ' \\end{array}\\right)' + texApre = '\\left[\\begin{array}{' + texApost = ' \\end{array}\\right]' texA = '' if len(A.shape) == 0 or A.shape[0] == 0: return texApre + '}' + texA + texApost elif len(A.shape) == 1: A = np.expand_dims(A, 0) for i in np.asarray(A): texALigne = '' texALigne = texALigne + str(round(i[0], 4) if i[0] % 1 else int(i[0])) if texA == '': texApre = texApre + 'c' for j in i[1:]: if texA == '': texApre = texApre + 'c' texALigne = texALigne + ' & ' + str(round(j, 4) if j % 1 else int(j)) texALigne = texALigne + ' \\\\' texA = texA + texALigne texA = texApre + '} ' + texA[:-2] + texApost else: print("Ce n'est pas une matrice des coefficients ni une matrice augmentée") texA = '' return texA def printA(*args, name=None): """Method which prints the input matrix. .. note:: if two inputs are passed, they represent A and b respectively; as a result the augmented matrix A|B is plotted. Otherwise, if the input is unique, just the matrix A is plotted :param args: input arguments; they could be either a matrix and a vector or a single matrix :type args: list[numpy.ndarray] or list[list] :param name: if not None, it is the name of the matrix; what is printed is then {name} = {value}. If None, only the matrix value is displayed. Defaults to None :type name: str or NoneType """ if name is not None and type(name) is str: texA = '$' + name + ' = ' + texMatrix(*args) + '$' else: texA = '$' + texMatrix(*args) + '$' display(Latex(texA)) return def printEquMatrices(*args): """Method which prints the list of input matrices. .. note:: if two inputs are passed, they represent the list of coefficient matrices A and the list of rhs b respectively; as a result the augmented matrices A|B are plotted. Otherwise, if the input is unique, just the matrices A are plotted :param args: input arguments; they could be either a list of matrices and a list of vectors or a single list of matrices :type args: list """ # list of matrices is M=[M1, M2, ..., Mn] where Mi=(Mi|b) if len(args) == 2: listOfMatrices = args[0] listOfRhS = args[1] texEqu = '$' + texMatrix(listOfMatrices[0], listOfRhS[0]) for i in range(1, len(listOfMatrices)): texEqu = texEqu + '\\quad \\sim \\quad' + texMatrix(listOfMatrices[i], listOfRhS[i]) texEqu = texEqu + '$' display(Latex(texEqu)) else: listOfMatrices = args[0] texEqu = '$' + texMatrix(listOfMatrices[0]) for i in range(1, len(listOfMatrices)): texEqu = texEqu + '\\quad \\sim \\quad' + texMatrix(listOfMatrices[i]) texEqu = texEqu + '$' display(Latex(texEqu)) return def printLUMatrices(LList, UList): """Method which prints the list of L and U matrices, constructed during an interactive LU decomposition routine :param LList: list of lower triangular matrices :type LList: list[numpy.ndarray] :param UList: list of upper triangular matrices :type UList: list[numpy.ndarray] """ try: assert len(LList) == len(UList) except AssertionError: print("The lists of lower and upper traingular matrices must have the same length!") raise ValueError texEqu = '\\begin{align*}' for i in range(len(LList)): texEqu += 'L &= ' + texMatrix(LList[i]) + '\\qquad & U &= ' + texMatrix(UList[i]) if i < len(LList) - 1: texEqu += ' \\\\ ' texEqu += '\\end{align*}' display(Latex(texEqu)) return # %% Functions to enter something def EnterInt(n=None): """Function to allow the user to enter a non-negative integer :param n: first integer, passed to the function. If null or negative or None, an integer is requested to the user. Defaults to None :type n: int or NoneType :return: positive integer :rtype: int """ while type(n) is not int or (type(n) is int and n <= 0): try: n = int(n) if n <= 0: print("Le nombre ne peut pas être négatif o zero!") print("Entrez à nouveau: ") n = input() except: if n is not None: print("Ce n'est pas un entier!") print("Entrez à nouveau:") n = input() else: print("Entrez un entier positif") n = input() return n def EnterListReal(n): """Function which allows the user to enter a list of `n` real numbers :param n: number of real numbers in the desired list :type n: int :return: list of `n` real numbers :rtype: list[float] """ if n < 0: print(f"Impossible de générer une liste de {n} nombres réels") elif n == 0: return [] else: print(f"Entrez une liste de {n} nombres réels") coeff = None while type(coeff) is not list: try: coeff = input() coeff = [float(eval(x)) for x in coeff.split(',')] if len(coeff) != n: print("Vous n'avez pas entré le bon nombre de réels!") print("Entrez à nouveau : ") coeff = input() except: print("Ce n'est pas le bon format!") print("Entrez à nouveau") coeff = input() return coeff def SolOfEq(sol, coeff, i): """Method that verifies if `sol` is a solution to the linear equation `i`with coefficients `coeff` :param sol: candidate solution vector :type sol: list :param coeff: coefficients of the linear equation :type coeff: list :param i: index of the equation :type i: int :return: True if `sol` is a solution, False otherwise :rtype: bool """ try: assert len(sol) == len(coeff)-1 except AssertionError: print(f"La suite entrée n'est pas une solution de l'équation {i}; Les dimensions ne correspondent pas") return False A = np.array(coeff[:-1]) isSol = abs(np.dot(A, sol) - coeff[-1]) < 1e-8 if isSol: print(f"La suite entrée est une solution de l'équation {i}") else: print(f"La suite entrée n'est pas une solution de l'équation {i}") return isSol def SolOfSyst(solution, A, b): """Method that verifies if `solution` is a solution to the linear system with left-hand side matrix `A` and right-hand side vector `b` :param solution: candidate solution vector :type solution: list :param A: left-hand side matrix of the linear system :type A: list[list[float]] or numpy.ndarray :param b: right-hand side vector of the linear system :type b: list[float] or numpy.ndarray :return: True if `sol` is a solution, False otherwise :rtype: bool """ try: assert len(solution) == (len(A[0]) if type(A) is list else A.shape[1]) except AssertionError: print(f"La suite entrée n'est pas une solution du système; Les dimensions ne correspondent pas") return False A = [A[i] + [b[i]] for i in range(0, len(A))] A = np.array(A) isSol = [SolOfEq(solution, A[i, :], i+1) for i in range(len(A))] if all(isSol): print("C'est une solution du système") return True else: print("Ce n'est pas une solution du système") return False # PLOTS WITH PLOTLY # def drawLine(p, d): """Method which allows to plot lines, points and arrows in the 2D-place or 3D-space, using plotly library :param p: point :type p: list[list[float]] :param d: direction vector. If made of all zeros, just the reference point is plotted; if different from 0 a line passing through `p` and with direction `d` is plotted :type d: list[list[float]] :return: generated plot """ blue = 'rgb(51, 214, 255)' colors = [blue] colorscale = [[0.0, colors[0]], [0.1, colors[0]], [0.2, colors[0]], [0.3, colors[0]], [0.4, colors[0]], [0.5, colors[0]], [0.6, colors[0]], [0.7, colors[0]], [0.8, colors[0]], [0.9, colors[0]], [1.0, colors[0]]] vec = 0.9 * np.array(d) if len(p) == 2: data = [] t = np.linspace(-5, 5, 51) s = np.linspace(0, 1, 10) if all(dd == [0] for dd in d): vector = go.Scatter(x=p[0] + s*0, y=p[1] + s*0, marker=dict(symbol=6, size=12, color=colors[0]), name ='Point') else: trace = go.Scatter(x=p[0] + t * d[0], y=p[1] + t * d[1], name='Droite') peak = go.Scatter(x=d[0], y=d[1], marker=dict(symbol=6, size=12, color=colors[0]), showlegend=False) vector = go.Scatter(x=p[0] + s * d[0], y=p[1] + s * d[1], mode='lines', line=dict(width=5, color=colors[0]), name='Vecteur directeur') zero = go.Scatter(x=t*0, y=t*0, name='Origine', marker=dict(symbol=6, size=12, color=colors[0]), showlegend=False) data.append(vector) data.append(zero) if not all(dd == [0] for dd in d): data.append(trace) data.append(peak) fig = go.FigureWidget(data=data) plotly.offline.iplot(fig) elif len(p) == 3: data = [ { 'type': 'cone', 'x': [1], 'y': vec[1], 'z': vec[2], 'u': d[0], 'v': d[1], 'w': d[2], "sizemode": "absolute", 'colorscale': colorscale, 'sizeref': 1, "showscale": False, 'hoverinfo': 'none' } ] t = np.linspace(-5, 5, 51) s = np.linspace(0, 1, 10) zero = go.Scatter3d(x=t*0, y=t*0, z=t*0, name='Origine', marker=dict(size=3), showlegend=False) if all(dd == [0] for dd in d): vector = go.Scatter3d(x=p[0] + s*0, y=p[1] + s*0, z=p[2] + s*0, marker=dict(size=5), name='Point') else: trace = go.Scatter3d(x=p[0] + t * d[0], y=p[1] + t * d[1], z=p[2] + t * d[2], mode='lines', name='Droite') vector = go.Scatter3d(x=p[0] + s * d[0], y=p[1] + s * d[1], z=p[2] + s * d[2], mode='lines', line=dict(width=5,color=colors[0], dash='solid'), name='Vecteur directeur', hoverinfo='none') data.append(zero) data.append(vector) if not all(dd == [0] for dd in d): data.append(trace) layout = { 'scene': { 'camera': { 'eye': {'x': -0.76, 'y': 1.8, 'z': 0.92} } } } fig = go.FigureWidget(data=data, layout=layout) plotly.offline.iplot(fig) return fig def Plot2DSys(xL, xR, p, A, b): """Function for the graphical visualization of a 2D system of equations, plotting the straight lines characterizing the different equations appearing in the system :param xL: left limit of the plot in both coordinates :type xL: int or float :param xR: right limit of the plot in both coordinates :type xR: int or float :param p: number of points used to draw the straight lines :type p: int :param A: matrix of the linear system :type A: list[list[float]] or numpy.ndarray :param b: right-hand side vector of the linear system :type b: list[float] or numpy.ndarray """ A = [A[i] + [b[i]] for i in range(0, len(A))] A = np.array(A) t = np.linspace(xL, xR, p) data = [] for i in range(1, len(A) + 1): if (abs(A[i - 1, 1])) > abs(A[i - 1, 0]): # p0=[0,A[i-1,2]/A[i-1,1]] # p1=[1,(A[i-1,2]-A[i-1,0])/A[i-1,1]] trace = go.Scatter(x=t, y=(A[i-1, 2] - A[i-1, 0] * t) / A[i-1, 1], name='Droite %d' % i) else: trace = go.Scatter(x=(A[i-1, 2] - A[i-1, 1] * t) / A[i-1, 0], y=t, name='Droite %d' % i) data.append(trace) fig = go.Figure(data=data) plotly.offline.iplot(fig) return def Plot3DSys(xL, xR, p, A, b): """Function for the graphical visualization of a 3D system of equations, plotting the straight lines characterizing the different equations appearing in the system :param xL: left limit of the plot in all coordinates :type xL: int or float :param xR: right limit of the plot in all coordinates :type xR: int or float :param p: number of points used to draw the straight lines :type p: int :param A: matrix of the linear system :type A: list[list[float]] or numpy.ndarray :param b: right-hand side vector of the linear system :type b: list[float] or numpy.ndarray """ A = np.array(A) b = np.array(b) 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 = [] for i in range(len(A)): 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]]] j = i + 1 arg = np.argmax(np.abs(A[i,:])) # All the coefficient of equation are 0: b==0 -> every combinations are solution, b!=0 -> No solution if A[i, arg]==0: if b[i] == 0: print("No constraints on equation", j, "of the system.") else: print("No solution for equation", j, "of the system.") # A least a coefficient is different from 0, plot the one with largest coeff in mag else: if arg==2: # z en fonction de x,y x = sGrid y = tGrid surface = go.Surface(x=x, y=y, z=(b[i] - A[i, 0] * x - A[i, 1] * y) / A[i, 2], showscale=False, showlegend=True, colorscale=colorscale, opacity=1, name='Plan %d' % j) elif arg==1: # y en fonction de x,z x = sGrid z = tGrid surface = go.Surface(x=x, y=(b[i]-A[i, 0]*x - A[i, 2]*z)/A[i, 1], z=z, showscale=False, showlegend=True, colorscale=colorscale, opacity=1, name='Plan %d' % j) elif arg==0: # x en fonction de y,z y = sGrid z = tGrid surface = go.Surface(x=(b[i] - A[i, 1] * y - A[i,2] * z)/A[i, 0], y=y, z=z, showscale=False, showlegend=True, colorscale=colorscale, opacity=1, name='Plan %d' % j) data.append(surface) 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)' ), yaxis=dict( gridcolor='rgb(255, 255, 255)', zerolinecolor='rgb(255, 255, 255)', showbackground=True, backgroundcolor='rgb(230, 230,230)' ), zaxis=dict( gridcolor='rgb(255, 255, 255)', zerolinecolor='rgb(255, 255, 255)', showbackground=True, backgroundcolor='rgb(230, 230,230)' ) ) ) fig = go.Figure(data=data, layout=layout) plotly.offline.iplot(fig) return def isDiag(M): """Method which checks if a matrix is diagonal :param M: input matrix :type M: list[list[float]] or numpy.ndarray :return: True if M is diagonal else False :rtype: bool """ if not type(M) is np.ndarray: M = np.array(M) i, j = M.shape try: assert i == j except AssertionError: print("A non-squared matrix cannot be diagonal!") return False test = M.reshape(-1)[:-1].reshape(i - 1, j + 1) return ~np.any(test[:, 1:]) def isSym(M): """Method which checks if a matrix is symmetric :param M: input matrix :type M: list[list[float]] or numpy.ndarray :return: True if M is symmetric else False :rtype: bool """ if not type(M) is np.ndarray: M = np.array(M) i, j = M.shape try: assert i == j except AssertionError: print("A non-squared matrix cannot be symmetric!") return False return ~np.any(M - np.transpose(M)) # ECHELONNAGE # def echZero(indice, M): """Method which sets to zero the entries of matrix M that correspond to a True value in the boolean vector indice :param indice: vector of booleans; if an element is True, it means that the element with the corresponding index in matrix M must be set to 0 :type indice: list[bool] :param M: matrix to be processed :type: numpy.ndarray :return: processed matrix M, where the given entries have been properly set to 0 :rtype: numpy.ndarray """ Mat = M[np.logical_not(indice), :].ravel() Mat = np.concatenate([Mat, M[indice, :].ravel()]) Mat = Mat.reshape(len(M), len(M[0, :])) return Mat def Eij(M, i, j, get_E_inv=False): """Method to swap line `i` and line `j` of matrix `M` :param M: matrix to be processed :type M: numpy.ndarray :param i: first line index :type i: int :param j: second line index :type j: int :param get_E_inv: if True, the inverse matrix of the applied elementary operation is returned. Defaults to False :type get_E_inv: bool :return: processed matrix, with line `i` and `j` having been swapped :rtype: numpy.ndarray """ M = np.array(M) M[[i, j], :] = M[[j, i], :] if get_E_inv: L = np.eye(M.shape[0], M.shape[0]).astype(float) L[[i, j]] = L[[j, i]] if get_E_inv: return M, L else: return M def Ealpha(M, i, alpha, get_E_inv=False): """Method to multiply line `i` of matrix `M` by the scalar coefficient `alpha` :param M: matrix to be processed :type M: numpy.ndarray :param i: reference line index :type i: int :param alpha: scalar coefficient :type alpha: float :param get_E_inv: if True, the inverse matrix of the applied elementary operation is returned. Defaults to False :type get_E_inv: bool :return: processed matrix, with line `i` multiplied by the scalar `alpha` :rtype: numpy.ndarray """ M = np.array(M) M[i, :] = alpha * M[i, :] if get_E_inv: L = np.eye(M.shape[0], M.shape[0]).astype(float) L[i ,i] = 1 / alpha if get_E_inv: return M, L else: return M def Eijalpha(M, i, j, alpha, get_E_inv=False): """Method to add to line `i` of matrix `M` line `j` of the same matrix, multiplied by the scalar coefficient `alpha` :param M: matrix to be processed :type M: numpy.ndarray :param i: line to be modified :type i: int :param j: line whose multiple has tobe added to line `i` :type j: int :param alpha: scalar coefficient :type alpha: float :param get_E_inv: if True, the inverse matrix of the applied elementary operation is returned. Defaults to False :type get_E_inv: bool :return: processed matrix, with line `i` being summed up with line `j` multiplied by `alpha` :rtype: numpy.ndarray """ M = np.array(M) M[i, :] = M[i, :] + alpha * M[j, :] if get_E_inv: L = np.eye(M.shape[0], M.shape[0]).astype(float) L[i, j] = -alpha if get_E_inv: return M, L else: return M def echelonMat(ech, *args): """Method to perform Gauss elimination on either the matrix of the coefficients (if `len(args)==1`) or on the augmented matrix (if `len(args)==2`); the elimination can be either in standard form (if `ech=='E` or in reduced form (if `ech=='ER'`). :param ech: :type ech: :param args: :type args: :return: :rtype: """ if len(args) == 2: # matrice augmentée A = np.array(args[0]).astype(float) m = A.shape[0] n = A.shape[1] b = np.array(args[1]) b = np.reshape(b, (n, 1)) A = np.concatenate((A, b), axis=1) else: # matrice coeff A = np.array(args[0]).astype(float) m = A.shape[0] n = A.shape[1] if ech == 'E': # Echelonnée Mat = np.array(A) Mat = Mat.astype(float) # in case the array in int instead of float. numPivot = 0 for i in range(len(Mat)): j = i while all(abs(Mat[j:, i]) < 1e-15) and j != len(Mat[0, :]) - 1: # if column (or rest of) is 0, take next j += 1 if j == len(Mat[0, :]) - 1: if len(Mat[0, :]) > j: Mat[i + 1:len(Mat), :] = 0 break if abs(Mat[i, j]) < 1e-15: Mat[i, j] = 0 zero = abs(Mat[i:, j]) < 1e-15 M = echZero(zero, Mat[i:, :]) Mat[i:, :] = M Mat = Ealpha(Mat, i, 1 / Mat[i, j]) # usually Mat[i,j]!=0 for k in range(i + 1, len(A)): Mat = Eijalpha(Mat, k, i, -Mat[k, j]) # Mat[k,:]=[0 if abs(Mat[k,l])<1e-15 else Mat[k,l] for l in range(len(MatCoeff[0,:]))] numPivot += 1 Mat[abs(Mat) < 1e-15] = 0 print("La matrice est sous la forme échelonnée") if len(args) == 2: printEquMatrices([A[:, :n], Mat[:, :n]], [A[:, n:], Mat[:, n:]]) else: printEquMatrices([A, Mat]) elif ech == 'ER': # Echelonnée réduite Mat = np.array(A) Mat = Mat.astype(float) # in case the array in int instead of float. numPivot = 0 for i in range(len(Mat)): j = i while all(abs(Mat[j:, i]) < 1e-15) and j != len( Mat[0, :]) - 1: # if column (or rest of) is zero, take next column j += 1 if j == len(Mat[0, :]) - 1: # ADD ZERO LINES BELOW!!!!!! if len(Mat[0, :]) > j: Mat[i + 1:len(Mat), :] = 0 break if abs(Mat[i, j]) < 1e-15: Mat[i, j] = 0 zero = abs(Mat[i:, j]) < 1e-15 M = echZero(zero, Mat[i:, :]) Mat[i:, :] = M Mat = Ealpha(Mat, i, 1 / Mat[i, j]) # normalement Mat[i,j]!=0 for k in range(i + 1, len(A)): Mat = Eijalpha(Mat, k, i, -Mat[k, j]) # Mat[k,:]=[0 if abs(Mat[k,l])<1e-15 else Mat[k,l] for l in range(len(MatCoeff[0,:]))] numPivot += 1 Mat[abs(Mat) < 1e-15] = 0 print("La matrice est sous la forme échelonnée") if len(args) == 2: printEquMatrices([A[:, :n], Mat[:, :n]], [A[:, n:], Mat[:, n:]]) else: printEquMatrices([np.asmatrix(A), np.asmatrix(Mat)]) Mat = np.array(Mat) i = (len(Mat) - 1) while i >= 1: while all( abs(Mat[i, :len(Mat[0]) - 1]) < 1e-15) and i != 0: # if ligne (or rest of) is zero, take next ligne i -= 1 # we have a lign with one non-nul element j = i # we can start at pos ij at least the pivot is there if abs(Mat[i, j]) < 1e-15: # if element Aij=0 take next one --> find pivot j += 1 # Aij!=0 and Aij==1 if echelonMat worked for k in range(i): # put zeros above pivot (which is 1 now) Mat = Eijalpha(Mat, k, i, -Mat[k, j]) i -= 1 print("La matrice est sous la forme échelonnée réduite") if len(args) == 2: printEquMatrices([A[:, :n], Mat[:, :n]], [A[:, n:], Mat[:, n:]]) else: printEquMatrices([A, Mat]) else: print(f"Méthode d'échelonnage non reconnue {ech}. Méthodes disponibles: 'E' (pour la forme échelonnée standard)" f", 'ER' (pour la forme échelonnée réduite))") return np.asmatrix(Mat) def randomA(): """Method which generates a random matrix with rows and columns within 1 and 10 and integer entries between -100 and 100 :return: generated random matrix :rtype: numpy.ndarray """ n = random.randint(1, 10) m = random.randint(1, 10) A = [[random.randint(-100, 100) for i in range(n)] for j in range(m)] printA(A) return np.array(A) def dimensionA(A): """Method which allows the user to enter the matrix dimensions and verifies whether they are correct or not :param A: reference matrix :type A: numpy.ndarray """ m = widgets.IntText( value=1, step=1, description='m:', disabled=False ) n = widgets.IntText( value=1, step=1, description='n:', disabled=False ) display(m) display(n) def f(): if m.value == A.shape[0] and n.value == A.shape[1]: print('Correct!') else: print('Incorrect, entrez de nouvelles valeurs') interact_manual(f) return def manualEch(*args): """Method which allows the user to perform the Gauss elimination method on the given input matrix, eventually extended by the right-hand side vector. :param args: :type args: :return: :rtype: """ if len(args) == 2: # matrice augmentée A = np.array(args[0]).astype(float) m = A.shape[0] b = args[1] if type(b[0]) is list: b = np.array(b).astype(float) A = np.concatenate((A, b), axis=1) else: b = [b[i] for i in range(m)] A = [A[i] + [b[i]] for i in range(m)] else: A = np.array(args[0]).astype(float) m = A.shape[0] j = widgets.BoundedIntText( value=1, min=1, max=m, step=1, description='Ligne j:', disabled=False ) i = widgets.BoundedIntText( value=1, min=1, max=m, step=1, description='Ligne i:', disabled=False ) r = widgets.RadioButtons( options=['Eij', 'Ei(alpha)', 'Eij(alpha)', 'Revert'], description='Opération:', disabled=False ) alpha = widgets.Text( value='1', description='Coeff. alpha:', disabled=False ) print("Régler les paramètres et évaluer la cellule suivante") print("Répéter cela jusqu'à obtenir une forme échelonnée réduite") display(r) display(i) display(j) display(alpha) return i, j, r, alpha def echelonnage(i, j, r, alpha, A, m=None, *args): """Method which performs the Gauss elimination method step described by `r.value` with parameters `ì`, `j` and `alpha` on matrix `A` :param i: first reference line :type i: ipywidgets.Text :param j: second reference line :type j: ipywidgets.Text :param r: RadioButton describing the elementary matricial operation to be performed :type r: ipywidgets.radioButton :param alpha: scalar coefficient :type alpha: ipywidgets.Text :param A: starting matrix :type A: numpy.ndarray :param m: starting augmented matrix. If None, it equals A. Defaults to None. :type m: numpy.ndarray or NoneType :param args: either the list of matrices or both the list of matrices and rhs having bee built during the application of the methos :type args: list[numpy.ndarray] or tuple(list[numpy.ndarray], list[numpy.ndarray]) :return: processed matrix :rtype: numpy.ndarray """ if m is None: m = A.copy() m = np.array(m).astype(float) if alpha.value == 0 and r.value in {'Ei(alpha)', 'Eij(alpha)'}: print('Le coefficient alpha doit être non-nul!') if r.value == 'Eij': m = Eij(m, i.value-1, j.value-1) if r.value == 'Ei(alpha)': m = Ealpha(m, i.value-1, eval(alpha.value)) if r.value == 'Eij(alpha)': m = Eijalpha(m, i.value-1, j.value-1, eval(alpha.value)) if len(args) == 2: A = np.asmatrix(A) MatriceList = args[0] RhSList = args[1] if r.value != 'Revert': MatriceList.append(m[:, :A.shape[1]]) RhSList.append(m[:, A.shape[1]:]) else: if len(MatriceList) > 1 and len(RhSList) > 1: MatriceList.pop() RhSList.pop() mat = MatriceList[-1] rhs = RhSList[-1] m = np.concatenate((mat,rhs), axis=1) else: print("Impossible de revenir sur l'opération!") printEquMatrices(MatriceList, RhSList) elif len(args) == 1: MatriceList = args[0] if r.value != 'Revert': MatriceList.append(m) else: if len(MatriceList) > 1: MatriceList.pop() m = MatriceList[-1] else: print("Impossible de revenir sur l'opération!") printEquMatrices(MatriceList) else: print("La liste des matrices ou des matrices et des vecteurs connus doit être donnée en entrée de la fonction!") raise ValueError return m def LU_interactive(i, j, r, alpha, *args): """Method which performs the Gauss elimination method step described by `r.value` with parameters `ì`, `j` and `alpha` on matrix `A` :param i: first reference line :type i: ipywidgets.Text :param j: second reference line :type j: ipywidgets.Text :param r: RadioButton describing the elementary matricial operation to be performed :type r: ipywidgets.radioButton :param alpha: scalar coefficient :type alpha: ipywidgets.Text :param A: starting matrix :type A: numpy.ndarray :param m: starting augmented matrix. If None, it equals A. Defaults to None. :type m: numpy.ndarray or NoneType :param args: either the list of matrices or both the list of matrices and rhs having bee built during the application of the method :type args: list[numpy.ndarray] or tuple(list[numpy.ndarray], list[numpy.ndarray]) :return: processed matrix :rtype: numpy.ndarray """ if len(args) == 2: U = np.array(args[1][-1]).astype(float) else: print("La liste des matrices diagonales inférieures et supérieures déjà calculées doit être donnée en entrée de" " la fonction") raise ValueError if alpha.value == 0 and r.value in {'Ei(alpha)', 'Eij(alpha)'}: print('Le coefficient alpha doit être non-nul!') is_valid_operation = True if r.value == 'Eij': print("Exchanging two lines is not a valid operation, if LU decomposition WITHOUT pivoting has to be computed") is_valid_operation = False if r.value == 'Ei(alpha)': U, L = Ealpha(U, i.value-1, eval(alpha.value), get_E_inv=True) if r.value == 'Eij(alpha)': U, L = Eijalpha(U, i.value-1, j.value-1, eval(alpha.value), get_E_inv=True) if is_valid_operation: LList = args[0] UList = args[1] if r.value != 'Revert': UList.append(U) LList.append(np.dot(LList[-1], L)) else: if len(UList) > 1 and len(LList) > 1: UList.pop() U = UList[-1] LList.pop() L = LList[-1] else: print("Impossible de revenir sur l'opération!") printLUMatrices(LList, UList) else: L = args[0][-1] U = args[1][-1] return L, U def LU_no_pivoting(A, ptol=1e-5): """Method that computes the LU decomposition of a matrix, without using pivoting. If the matrix cannot be decomposed, the method raises a ValueError. :param A: matrix to be decomposed :type A: list[list] or numpy.ndarray :param ptol: tolerance on the pivot values; if a pivot with value smaller (in absolute value) than ptol is found, a ValueError is raised. Defaults to 1e-5 :type ptol: float :return: lower triangular matrix L and upper triangular matrix U such that A = LU, if they exist :rtype: tuple(numpy.ndarray, numpy.ndarray) or NoneType """ A = np.array(A).astype(float) m, n = A.shape + n_op = 0 + try: assert m <= n except AssertionError: raise ValueError("La décomposition LU n'est pas implémentée pour les matrices rectangulaires " "ayant plus de lignes que de colonnes") for i in range(m): if (A[i+1:, :] == 0).all(): break pivot = A[i, i] if abs(pivot) <= ptol: print("Pivot avec la valeur 0 rencontré. Cette matrice n'admet pas de décomposition LU (sans pivoting)") return None, None for k in range(i+1, m): lam = A[k, i] / pivot + n_op += 1 A[k, i+1:n] = A[k, i+1:n] - lam * A[i, i+1:n] + n_op += 2*(n-i-1) A[k, i] = lam L = np.eye(m) + np.tril(A, -1)[:m, :m] U = np.triu(A) + + n_op += m**2 + + print(f"Nombre d'opérations élémentaires: {n_op}") + return L, U def manualOp(*args): """Method which allows the user to perform elementary operations on the given input matrix, eventually extended by the right-hand side vector. :param args: :type args: :return: :rtype: """ if len(args) == 2: # matrice augmentée A = np.array(args[0]).astype(float) M = A.shape[0] b = args[1] if type(b[0]) is list: b = np.array(b).astype(float) A = np.concatenate((A, b), axis=1) else: b = [b[i] for i in range(M)] A = [A[i] + [b[i]] for i in range(M)] else: A = np.array(args[0]).astype(float) M = A.shape[0] A = np.array(A) # just in case it's not i = widgets.BoundedIntText( value=1, min=1, max=M, step=1, description='Ligne i:', disabled=False ) j = widgets.BoundedIntText( value=1, min=1, max=M, step=1, description='Ligne j:', disabled=False ) r = widgets.RadioButtons( options=['Eij', 'Ei(alpha)', 'Eij(alpha)'], description='Opération:', disabled=False ) alpha = widgets.Text( value='1', description='Coeff. alpha:', disabled=False ) print("Régler les paramètres et cliquer sur RUN INTERACT pour effectuer votre opération") def f(r, i, j, alpha): m = A MatriceList = [A[:, :len(A[0])-1]] RhSList = [A[:, len(A[0])-1:]] if alpha == 0 and r != 'Eij': print('Le coefficient alpha doit être non-nul!') if r == 'Eij': m = Eij(m, i-1, j-1) if r == 'Ei(alpha)': m = Ealpha(m, i-1, eval(alpha)) if r == 'Eij(alpha)': m = Eijalpha(m, i-1, j-1, eval(alpha)) MatriceList.append(m[:, :len(A[0])-1]) RhSList.append(m[:, len(A[0])-1:]) printEquMatricesAug(MatriceList, RhSList) return interact_manual(f, r=r, i=i, j=j, alpha=alpha) return ######################################## OBSOLETE #################################################################### def printEquMatricesAug(listOfMatrices, listOfRhS): # list of matrices is M=[M1, M2, ..., Mn] where Mi=(Mi|b) texEqu = '$' + texMatrix(listOfMatrices[0], listOfRhS[0]) for i in range(1, len(listOfMatrices)): texEqu = texEqu + '\\quad \\sim \\quad' + texMatrix(listOfMatrices[i], listOfRhS[i]) texEqu = texEqu + '$' display(Latex(texEqu)) def echelonMatCoeff(A): # take echelonMAt but without b. b = [0 for _ in range(len(A))] Mat = [A[i] + [b[i]] for i in range(len(A))] Mat = np.array(Mat) Mat = Mat.astype(float) # in case the array in int instead of float. numPivot = 0 for i in range(len(Mat)): j = i while all(abs(Mat[j:, i]) < 1e-15) and j != len( Mat[0, :]) - 1: # if column (or rest of) is zero, take next column j += 1 if j == len(Mat[0, :]) - 1: # ADD ZERO LINES BELOW!!!!!! if len(Mat[0, :]) > j: Mat[i + 1:len(Mat), :] = 0 print("La matrice est sous la forme échelonnée") printEquMatrices(np.asmatrix(A), np.asmatrix(Mat[:, :len(A[0])])) break if abs(Mat[i, j]) < 1e-15: Mat[i, j] = 0 zero = abs(Mat[i:, j]) < 1e-15 M = echZero(zero, Mat[i:, :]) Mat[i:, :] = M Mat = Ealpha(Mat, i, 1 / Mat[i, j]) # normalement Mat[i,j]!=0 for k in range(i + 1, len(A)): Mat = Eijalpha(Mat, k, i, -Mat[k, j]) # Mat[k,:]=[0 if abs(Mat[k,l])<1e-15 else Mat[k,l] for l in range(len(MatCoeff[0,:]))] numPivot += 1 Mat[abs(Mat) < 1e-15] = 0 # printA(np.asmatrix(Mat[:, :len(A[0])])) return np.asmatrix(Mat) def echelonRedMat(A, b): Mat = echelonMat('ER', A, b) Mat = np.array(Mat) MatAugm = np.concatenate((A, b), axis=1) # MatAugm = [A[i]+[b[i]] for i in range(0,len(A))] i = (len(Mat) - 1) while i >= 1: while all(abs(Mat[i, :len(Mat[0]) - 1]) < 1e-15) and i != 0: # if ligne (or rest of) is zero, take next ligne i -= 1 # we have a lign with one non-nul element j = i # we can start at pos ij at least the pivot is there if abs(Mat[i, j]) < 1e-15: # if element Aij=0 take next one --> find pivot j += 1 # Aij!=0 and Aij==1 if echelonMat worked for k in range(i): # put zeros above pivot (which is 1 now) Mat = Eijalpha(Mat, k, i, -Mat[k, j]) i -= 1 printA(Mat) print("La matrice est sous la forme échelonnée réduite") printEquMatrices(MatAugm, Mat) return np.asmatrix(Mat) def printEquMatricesOLD(listOfMatrices): # list of matrices is M=[M1, M2, ..., Mn] texEqu = '$' + texMatrix(listOfMatrices[0]) for i in range(1, len(listOfMatrices)): texEqu = texEqu + '\\quad \\sim \\quad' + texMatrix(listOfMatrices[i]) texEqu = texEqu + '$' display(Latex(texEqu)) return def texMatrixAug(A, b): # return tex expression of one matrix (A|b) where b can also be a matrix m = len(A[0]) A = np.concatenate((A, b), axis=1) texApre = '\\left(\\begin{array}{' texA = '' for i in np.asarray(A): texALigne = '' texALigne = texALigne + str(round(i[0], 3) if i[0] % 1 else int(i[0])) if texA == '': texApre = texApre + 'c' for j in i[1:m]: if texA == '': texApre = texApre + 'c' texALigne = texALigne + ' & ' + str(round(j, 3) if j % 1 else int(j)) if texA == '': texApre = texApre + '| c' for j in i[m:]: if texA == '': texApre = texApre + 'c' texALigne = texALigne + ' & ' + str(round(j, 3) if j % 1 else int(j)) texALigne = texALigne + ' \\\\' texA = texA + texALigne texA = texApre + '} ' + texA[:-2] + ' \\end{array}\\right)' return texA def printAAug(A, b): # Print matrix (A|b) texA = '$' + texMatrixAug(A, b) + '$' display(Latex(texA)) return def printEquMatricesOLD(*args): # M=[M1, M2, ..., Mn] n>1 VERIFIED OK texEqu = '$' + texMatrix(args[0]) for i in range(1, len(args)): texEqu = texEqu + '\\quad \\sim \\quad' + texMatrix(args[i]) texEqu = texEqu + '$' display(Latex(texEqu)) return def Ex1Chapitre1_5_6(): style = {'description_width': 'initial'} e=widgets.Textarea( value='', placeholder='Utilisez des lettres majuscules', description='Matrices échelonnées:', layout=Layout(width='60%', height='50px'), style=style, disabled=False ) er=widgets.Textarea( value='', placeholder='Utilisez des lettres majuscules', description='Matrices échelonnées-réduites:', layout=Layout(width='60%', height='50px'), style=style, disabled=False ) r=widgets.Textarea( value='', placeholder='Utilisez des lettres majuscules', description='Aucun des deux:', layout=Layout(width='60%', height='50px'), style=style, disabled=False ) display(e) display(er) display(r) return e,er,r \ No newline at end of file