diff --git a/Chapitre 9 - Produits scalaires et espaces euclidens/Corrections/corrections.py b/Chapitre 9 - Produits scalaires et espaces euclidens/Corrections/corrections.py index 1e40ff0..f51f705 100644 --- a/Chapitre 9 - Produits scalaires et espaces euclidens/Corrections/corrections.py +++ b/Chapitre 9 - Produits scalaires et espaces euclidens/Corrections/corrections.py @@ -1,369 +1,559 @@ import sys sys.path.insert(0, './../') import numpy as np import matplotlib.pyplot as plt import ipywidgets as widgets from ipywidgets import interact_manual, Layout, widgets, HBox from IPython.display import display, Latex -from Librairie.AL_Fct import get_couple_vectors_info_2D +from Librairie.AL_Fct import get_couple_vectors_info_2D, multiple_formatter def Ex1Chapitre9_1(): """Provides the correction of exercise 1 of notebook 9_1 """ a = widgets.Checkbox( value=False, description=r'$$\qquad u_1 \cdot u_2 \cdot [\dots] \cdot u_n = u_n \cdot [\dots] \cdot u_2 \cdot u_1$$', disabled=False, layout=Layout(width='90%', height='50px') ) b = widgets.Checkbox( value=False, description=r'$$\qquad (u_1 + u_2) \cdot (u_1 + u_2) = ||u_1|| + ||u_2|| + 2 (u_1 \cdot u_2)$$', disabled=False, layout=Layout(width='90%', height='50px') ) c = widgets.Checkbox( value=False, description=r"$$ \qquad \left(\sum\limits_{i=1}^nu_i\right) \cdot \left(\sum\limits_{i=1}^nu_i\right) = " r"\sum\limits_{i=1}^n ||u_i||^2 + 2\sum\limits_{i=1}^n\sum\limits_{j=1}^{i-1}u_i \cdot u_j$$", disabled=False, layout=Layout(width='100%', height='80px') ) d = widgets.Checkbox( value=False, description=r'\begin{align*}' r'\qquad (\lambda_1u_1 + \lambda_2u_2) \cdot (\lambda_3u_3 + \lambda_4u_4) =&' r'\lambda_1\lambda_3(u_1 \cdot u_3) + \lambda_1\lambda_4(u_1 \cdot u_4) \ + \\' r' \qquad \quad & \lambda_2\lambda_3(u_2 \cdot u_3) + \lambda_2\lambda_4(u_2 \cdot u_4)' r'\end{align*}', disabled=False, layout=Layout(width='90%', height='80px') ) e = widgets.Checkbox( value=False, description=r'$$\qquad u_1 \cdot u_2 = 0 \implies u_1 \perp u_2 \ \forall \ u_1, u_2 \in \mathbb{R}^2$$', disabled=False, layout=Layout(width='80%', height='50px') ) def correction(a, b, c, d, e): if a and not b and c and d and not e: display(Latex(r"C'est correct! En particulier: " "1. Vrai, en raison de la symétrie du produit scalaire. " "2. Faux, car les normes du côté gauche doivent être au carré. " "3. Vrai, en raison de l'additivité (la formule peut être prouvée par induction. Essaie! " "4. Vrai, en raison de la bilinéarité du produit scalaire. " "5. Faux, car il faut préciser que $u_1$ et $u_2$ ne peuvent pas être des vecteurs nuls.")) else: display(Latex("C'est faux.")) interact_manual(correction, a=a, b=b, c=c, d=d, e=e) return def Ex2Chapitre9_1(vec1, vec2): """Provides the correction of exercise 2 of notebook 9_1 """ display(Latex("Insérez les valeurs des quantités listées ci-dessous. " "Entrez les valeurs avec 4 chiffres après la virgule! Si l'angle n'est pas défini, entrez -999!")) norm_u = widgets.FloatText( value=0.0, step=0.0001, description='||u||:', disabled=False ) norm_v = widgets.FloatText( value=0.0, step=0.0001, description='||v||:', disabled=False ) u_dot_v = widgets.FloatText( value=0.0, step=0.0001, description=r'$u \cdot v$:', disabled=False ) theta_u_v = widgets.FloatText( value=0.0, step=0.0001, description=r'$\Delta\theta$', disabled=False ) solution_button = widgets.Button(description='Solution', disabled=True) box = HBox(children=[solution_button]) out = widgets.Output() @out.capture() def solution(e): out.clear_output() get_couple_vectors_info_2D(vec1, vec2, show=True, return_results=False) display(norm_u) display(norm_v) display(u_dot_v) display(theta_u_v) norm_u_true, norm_v_true, u_dot_v_true, theta_u_v_true = get_couple_vectors_info_2D(vec1, vec2, show=False, return_results=True) def f(): threshold = 1e-4 u_correct, v_correct, u_dot_v_correct, theta_correct = tuple(np.zeros((4,1)).astype(bool)) if np.abs(norm_u.value - norm_u_true) < threshold: display(Latex(r"La norme de $u$ est correcte!")) u_correct = True else: display(Latex(f"La norme de $u$ n'est pas correcte! L'erreur est supérieure au seuil de {threshold}. " f"Entrez les valeurs avec 4 chiffres après la virgule!")) if np.abs(norm_v.value - norm_v_true) < threshold: display(Latex(r"La norme de $v$ est correcte!")) v_correct = True else: display(Latex(f"La norme de $v$ n'est pas correcte! L'erreur est supérieure au seuil de {threshold}. " f"Entrez les valeurs avec 4 chiffres après la virgule!")) if np.abs(u_dot_v.value - u_dot_v_true) < threshold: display(Latex(r"Le produit scalaire est correct!")) u_dot_v_correct = True else: display(Latex(f"Le produit scalaire n'est pas correct! L'erreur est supérieure au seuil de {threshold}. " f"Entrez les valeurs avec 4 chiffres après la virgule!")) if not np.isnan(theta_u_v_true) and np.abs(theta_u_v.value - theta_u_v_true) < threshold: display(Latex(r"L'angle est correct!")) theta_correct = True elif np.isnan(theta_u_v_true) and theta_u_v.value == -999: display(Latex(r"Correct! L'angle n'est pas defini!")) theta_correct = True else: display(Latex(f"L'angle n'est pas correcte! L'erreur est supérieure au seuil de {threshold}. " f"Entrez les valeurs avec 4 chiffres après la virgule!")) if u_correct and v_correct and u_dot_v_correct and theta_correct: display(Latex(r"RÉSULTATS")) get_couple_vectors_info_2D(vec1, vec2, show=True, return_results=False) else: solution_button.disabled = False interact_manual(f) solution_button.on_click(solution) display(box) display(out) return def Ex3Chapitre9_1(case=1): """Provides the correction of exercise 3 of notebook 9_1 :param case: number of the case. Available: {1,2,3}. Defaults to 1 :type case: int """ fig = plt.figure(figsize=(5, 5)) ax = fig.gca() origin = [0], [0] if case == 1: theta = np.hstack((np.linspace(0, np.pi/4, 100), np.linspace(5*np.pi/4, 3*np.pi/2, 100))) x1 = 2 * np.cos(theta) x2 = 2 * np.sin(theta) limit = 2.5 for i in range(2): plt.plot(x1[i*100: (i+1)*100], x2[i*100: (i+1)*100], '-', color='r', linewidth=2) elif case == 2: theta_ref = np.linspace(0, 2*np.pi, 13) theta = np.hstack([np.linspace(theta_ref[i], theta_ref[i+1], 50) if not i%2 else np.array([]) for i in range(12)]) vals = [1, 3, 5, 7, 9, 11] x1 = np.hstack([vals[i] * np.cos(theta[i*50:(i+1)*50]) for i in range(6)]) x2 = np.hstack([vals[i] * np.sin(theta[i*50:(i+1)*50]) for i in range(6)]) limit = 12 for i in range(6): plt.plot(x1[i*50:(i+1)*50], x2[i*50:(i+1)*50], '-', color='r', linewidth=2) elif case == 3: theta = np.linspace(0, 8*np.pi, 800) vals = np.logspace(-2, 0, 800) x1 = vals * np.cos(theta) x2 = vals * np.sin(theta) limit = 1.2 plt.plot(x1, x2, '-', color='r', linewidth=2) else: raise ValueError(f"Le cas {case} n'est pas défini. Cas disponibles: {1, 2, 3}") ax.plot(*origin, marker='o', color='b') ax.set_xlim(-limit, limit) ax.set_ylim(-limit, limit) ax.grid() # Move left y-axis and bottom x-axis to centre, passing through (0,0) ax.spines['left'].set_position('center') ax.spines['bottom'].set_position('center') # Eliminate upper and right axes ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') # Show ticks in the left and lower axes only ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') plt.show() if case == 1: a = widgets.Checkbox( value=False, description=r"L'ensemble peut être exprimé comme: " r" $$\qquad S=\Bigl\{v \in \mathbb{R}^2: ||v||=2 \land \theta \ \% \ \pi \in " r"\Bigl[0; \dfrac{\pi}{4}\Bigr]\Bigr\}$$", disabled=False, layout=Layout(width='80%', height='60px') ) b = widgets.Checkbox( value=False, description=r"L'ensemble peut être exprimé comme: " r" $$\qquad S=\Bigl\{v \in \mathbb{R}^2: ||v||=2 \land \Bigl\lfloor\dfrac{\theta}{\pi}\Bigr\rfloor " r"in [0; 1]\Bigr\}$$", disabled=False, layout=Layout(width='80%', height='60px') ) c = widgets.Checkbox( value=False, description=r"$v = \Bigl[\dfrac{\sqrt{2}}{2}; \dfrac{\sqrt{2}}{2}\Bigr]$ appartient à l'ensemble", disabled=False, layout=Layout(width='80%', height='50px') ) d = widgets.Checkbox( value=False, description=r"$v = -\dfrac{1}{2}\Bigl[\sqrt{2}; \sqrt{6}\Bigr]$ appartient à l'ensemble", disabled=False, layout=Layout(width='80%', height='50px') ) def correction(a, b, c, d): if a and not b and not c and d: display((Latex(r"C'est correct! En effet l'ensemble S est fait d'éléments de norme égale à 2 $ et d'angles " r"dans $\Bigl[0; \dfrac{\pi}{4}\Bigr]$ ou dans " r"$\Bigl[\dfrac{5\pi}{4}; \dfrac{3\pi}{2}\Bigr]$, ce qui est indiqué par la réponse 1. " r"La réponse 2 est erronée car le calcul de $\Bigl\lceil\dfrac{\theta}{\pi}\Bigr\rceil$" r"n'a aucun sens dans ce contexte. Enfin, " r"$v_1 = \Bigl[\dfrac{\sqrt{2}}{2}; \dfrac{\sqrt{2}}{2}\Bigr]$ n'appartient pas à l'ensemble " r"puisque sa norme est égale à $1$ et non à $2$ (réponse 3); inversement " r"$v_2 = -\dfrac{1}{2}\Bigl[\sqrt{2}; \sqrt{6}\Bigr]$ fait partie à l'ensemble,appartenant " r" à l'arc dans le troisième quadrant (réponse 4)."))) else: display(Latex("C'est faux.")) elif case == 2: a = widgets.Checkbox( value=False, description=r"L'ensemble peut être exprimé comme: " r"$$\qquad S= \Bigl\{v \in \mathbb{R}^2: \Bigl\lceil \dfrac{\theta}{\pi / 6} \Bigr\rceil \ is \ odd \ \land ||v|| = \Bigl\lfloor \dfrac{\theta}{\pi / 6} \Bigr\rfloor \Bigr\}$$", disabled=False, layout=Layout(width='90%', height='60px') ) b = widgets.Checkbox( value=False, description=r"L'ensemble peut être exprimé comme: " r"$$\qquad S= \Bigl\{v \in \mathbb{R}^2: \Bigl\lfloor \dfrac{\theta}{\pi / 6} \Bigr\rfloor \ is \ even \ \land ||v|| = \Bigl\lceil \dfrac{\theta}{\pi / 6} \Bigr\rceil \Bigr\}$$", disabled=False, layout=Layout(width='90%', height='60px') ) c = widgets.Checkbox( value=False, description=r"$v = \dfrac{1}{2}\Bigl[\sqrt{3}; 3\Bigr]$ appartient à l'ensemble", disabled=False, layout=Layout(width='100%', height='60px') ) d = widgets.Checkbox( value=False, description=r"$v = \Bigl[-\sqrt{3}; \sqrt{3}\Bigr]$ appartient à l'ensemble", disabled=False, layout=Layout(width='100%', height='60px') ) def correction(a, b, c, d): if not a and b and c and not d: display((Latex(r"C'est correct! En effet l'ensemble est fait par tous les éléments tels que la partie entière de " r"a division de leur angle (supposée être en radians et en $[0;2\pi]$ par " r"$\dfrac{\pi}{6}$ est pair et avec norme égale à" r"$\Bigl\lceil\dfrac{\theta}{\pi / 6}\Bigr\rceil$ (réponse 2). La réponse 1 est erronée car" r"la norme des éléments de l'ensemble est égale à $\Bigl\lceil\dfrac{\theta}{\pi / 6}\Bigr\rceil$" r"et non à $\Bigl\lfloor\dfrac{\theta}{\pi / 6}\Bigr\rfloor$; la condition '" r"$\Bigl\lceil\dfrac{\theta}{\pi / 6}\Bigr\rceil \ is \ odd$' est plutôt vrai. Enfin, " r"$v_1 = \dfrac{1}{2}\bigl[\sqrt{3}; 3\bigr]$ appartient à S (c'est l'élément le plus à droite " r"du deuxième arc du premier quadrant) (réponse 3), tandis que" r" $v_2 = \bigl[-\sqrt{3}; \sqrt{3}\bigr]$ ne fait pas partie de S puisque sa norme est égale à $3$, " r"et il devrait être égal à $5$ pour faire partie de l'arc dans le deuxième quadrant (réponse 4)."))) else: display(Latex("C'est faux.")) elif case == 3: a = widgets.Checkbox( value=False, description=r"L'élément de l'ensemble $S$ avec la norme maximale a une norme égale à $1$", disabled=False, layout=Layout(width='90%', height='50px') ) b = widgets.Checkbox( value=False, description=r'Ce qui suit est valable: ' r'$$ \qquad \nexists \ v_1, v_2 \in S: v_1 \cdot v_2 = 0 \land ||v_1|| = ||v_2||$$', disabled=False, layout=Layout(width='90%', height='50px') ) c = widgets.Checkbox( value=False, description=r"Ce qui suit est valable: " r"$$ \qquad \forall \alpha \in [0;2\pi] \ \exists v \in S: \theta = \alpha$$", disabled=False, layout=Layout(width='100%', height='50px') ) d = widgets.Checkbox( value=False, description=r"Tous les couples d'élémets de S sont une base de $\mathbb{R}^2$", disabled=False, layout=Layout(width='100%', height='50px') ) def correction(a, b, c, d): if a and b and c and not d: display((Latex(r"C'est correct! En effet, cet ensemble est en fait constitué de vecteurs dont les angles s'étendent sur " r"$[0;8\pi]$ et dont les normes augmentent logarithmiquement de $10^{-2}$ (if $\theta = 0$) à " r"$10$ if $\theta = 8\pi$. Pour cette raison, l'élément avec la norme maximale a une norme égale à " r"$1$ (answer 1) et tous les angles dans $[0; 2\pi]$ sont représentés par un vecteur dans l'ensemble " r"(answer 3). (réponse 3). De plus, l'ensemble ne contient aucun couple d'éléments orthogonaux " r"et qui ont la même norme (en fait, il ne contient pas deux éléments avec le même " r"norme du tout!) (réponse 2). Au lieu de cela, tout couple d'éléments ayant le même angle est " r"dépend linéairement et ne peut donc pas être une base de $\mathbb{R}^2$ (réponse 4)."))) else: display(Latex("C'est faux.")) else: raise ValueError(f"Le cas {case} n'est pas défini. Cas disponibles: {1,2,3}") interact_manual(correction, a=a, b=b, c=c, d=d) return +def Ex1Chapitre9_2(): + """Provides the correction to exercise 1 of notebook 9_2 + """ + + print("Cliquer sur CTRL pour sélectionner plusieurs réponses") + + style = {'description_width': 'initial'} + ans1 = widgets.SelectMultiple( + options=['1', '2', '3', '4', '5', '6'], + description="L'opérateur est un produit scalaire dans les cas:", + style=style, + layout=Layout(width='70%', height='120px'), + disabled=False, + ) + ans2 = widgets.SelectMultiple( + options=['1', '2', '3', '4', '5', '6'], + description=r"L' $\mathbb{R}$-espace vectoriel, équipé avec l'operateur donné, " + r"est un espace Euclidien dans le cas", + style=style, + layout=Layout(width='70%', height='120px'), + disabled=False, + ) + + def correction(ans1, ans2): + res_ans = np.zeros(2).astype(bool) + res_ans[0] = '1' not in ans1 and '2' in ans1 and '3' in ans1 and \ + '4' not in ans1 and '5' in ans1 and '6' not in ans1 + res_ans[1] = '1' not in ans2 and '2' in ans2 and '3' in ans2 and \ + '4' not in ans2 and '5' not in ans2 and '6' not in ans2 + + if res_ans.all(): + display(Latex(r"C'est correct! En effet: CAS 1: l'opérateur n'est pas un produit scalaire " + r"parce qu'il n'est pas défini positif; donc l'espace vectoriel ne peut pas être " + r"un espace Euclidien. CAS 2: l'opérateur est en fait un produit scalaire (" + r"il s'avère respecter toutes les propriétés requises); en plus l'espace vectoriel " + r"à une dimension finie (3), et c'est donc un espace Euclidien une fois équipé " + r"avec l'opérateur donné. CAS 3: l'opérateur est un produit scalaire; l'espace vectoriel " + r"à une dimension finie (3, égal au nombre de coefficients caractérisants) " + r"et c'est donc un espace Euclidien s'il est équipé de l'opérateur donné. CAS 4: l'opérateur " + r"est le même que dans le cas 2, mais dans ce cas ce n'est PAS un produit scalaire car " + r"il n'est pas défini positif (notez, en effet, que chaque polynôme de degré égal à 3 " + r"à un produit scalaire nul avec lui-même, bien qu'il n'est pas le polynôme nul); " + r"donc l'espace vectoriel ne peut alors pas être un espace Eucliden. " + r"CAS 5: l'opérateur donné définit un produit scalaire. En particulier, definiè " + r"positivitè vient du fait que, si $\langle a, a \rangle = 0$, alors $a(x_0) = 0$ " + r"et $a'(x)^2=0 \ \forall x \in [x_0; x_1]$; en conséquence $a$ doit être constant dans $[x_0; x_1]$ " + r"et égal à $0$ en $x_0$. En raison de la continuité, cela implique qu'en fait $a \equiv 0$, comme " + r"souhaité. Cependant, la dimensionnalité de l'espace vectoriel est infinie; il ne peut donc pas " + r"être un espace Euclidien. CAS 6: l'opérateur ne définit pas un produit scalaire car il n'est pas " + r"défini positif; en effet, si $\langle a, a \rangle=0$ alors $a$ doit être $0$ à $x_0$ et il doit avoir " + r"dérivée seconde nulle dans $[x_0; x_1]$. Ainsi, toute fonction linéaire égale à $0$ à $x_0$ " + r"conduirait à avoir $ \langle a, a \rangle=0$, ce qui prouve que l'opérateur n'est pas " + r"défini positif. Facilement, l'espace vectoriel ne peut pas être un espace Euclidien, aussi parce que " + r"sa dimension est infinie.")) + else: + display(Latex("C'est faux.")) + if not res_ans[0]: + display((Latex("La réponse à la première question est fausse"))) + if not res_ans[1]: + display((Latex("La réponse à la deuxième question est fausse"))) + + interact_manual(correction, ans1=ans1, ans2=ans2) + + return + + +def Ex2Chapitre9_2(): + """Provides the correction to exercise 2 of notebook 9_2 + """ + + print("Cliquer sur CTRL pour sélectionner plusieurs réponses") + + style = {'description_width': 'initial'} + ans = widgets.SelectMultiple( + options=['1', '2', '3', '4'], + description='Les matrices sont orthogonales dans les cas:', + style=style, + layout=Layout(width='40%', height='80px'), + disabled=False, + ) + + def correction(ans): + res_ans = '1' in ans and '2' not in ans and \ + '3' in ans and '4' not in ans + + if res_ans: + display(Latex(r"C'est correct!")) + else: + display(Latex("C'est faux.")) + + interact_manual(correction, ans=ans) + + return + + +def Ex3Chapitre9_2(): + """Provides the correction to exercise 3 of notebook 9_2 + """ + + print("Cliquer sur CTRL pour sélectionner plusieurs réponses") + + style = {'description_width': 'initial'} + ans = widgets.SelectMultiple( + options=['1', '2', '3', '4', '5', '6'], + description='Les fonctions sont orthogonales dans les cas:', + style=style, + layout=Layout(width='40%', height='110px'), + disabled=False, + ) + + def correction(ans): + res_ans = '1' in ans and '2' not in ans and '3' not in ans and \ + '4' in ans and '5' in ans and '6' not in ans + + if res_ans: + display(Latex(r"C'est correct!")) + else: + display(Latex("C'est faux.")) + + interact_manual(correction, ans=ans) + + return + + +def Ex3Chapitre9_2_plotter(case_nb=1): + """Helper function that allows to plot the functions involved in Ex 3 of notebook 9_2 + + :param case_nb: test case number. Defaults to 1 + :type case_nb: int + """ + + if case_nb in {1, 2}: + x = np.linspace(-1, 1, 1000) + f = lambda x: 1 - x ** 2 + g = lambda x: -(x - 1) ** 2 + elif case_nb in {3, 4}: + x = np.linspace(0, 1, 1000) + f = lambda x: x - 1/2 + g = lambda x: x**2 - x - 1/6 + elif case_nb in {5, 6}: + x = np.linspace(-np.pi, np.pi, 1000) + f = lambda x: np.sin(x) + g = lambda x: np.cos(x) + else: + raise ValueError(f"Cas test nombre {case_nb} n'est pas disponible. " + f"Cas disponibles: [1,2,3,4,5,6]") + + fg = lambda x: f(x) * g(x) + + fig, axs = plt.subplots(1, 2, figsize=(16, 8)) + + axs[0].plot(x, f(x), label='f', color='b') + axs[0].plot(x, g(x), label='g', color='r') + axs[0].grid(linestyle='--', linewidth=0.5) + axs[0].set_title('Fonctions f et g') + axs[0].legend(loc='best', fontsize=10) + axs[0].spines['left'].set_position('center') + axs[0].spines['bottom'].set_position('center') + axs[0].spines['right'].set_color('none') + axs[0].spines['top'].set_color('none') + axs[0].xaxis.set_ticks_position('bottom') + axs[0].yaxis.set_ticks_position('left') + + if case_nb in {5, 6}: + axs[0].xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2)) + axs[0].xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 12)) + axs[0].xaxis.set_major_formatter(plt.FuncFormatter(multiple_formatter())) + axs[0].xaxis.set_tick_params(labelsize=13) + + axs[1].plot(x, fg(x), color='g') + axs[1].grid(linestyle='--', linewidth=0.5) + axs[1].set_title('Produit entre f et g') + axs[1].spines['left'].set_position('center') + axs[1].spines['bottom'].set_position('center') + axs[1].spines['right'].set_color('none') + axs[1].spines['top'].set_color('none') + axs[1].xaxis.set_ticks_position('bottom') + axs[1].yaxis.set_ticks_position('left') + + if case_nb in {5, 6}: + axs[1].xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2)) + axs[1].xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 12)) + axs[1].xaxis.set_major_formatter(plt.FuncFormatter(multiple_formatter())) + axs[1].xaxis.set_tick_params(labelsize=13) + + fig.suptitle(f"Tracés pour le cas test nombre {case_nb}") + + return + +