#! /usr/bin/env python3 # -*- coding: utf-8; mode: python -*- r""" Correction d'un exercice de maths avec Python, issu des annales pour les oraux du concours Centrale-Supélec. - *Sujet :* PSI 1, http://www.concours-centrale-supelec.fr/CentraleSupelec/MultiY/C2015/PSI-Mat2-2015-24.pdf - *Dates :* séances de révisions, vendredi 10 et samedi 11 juin (2016). - *Auteur :* Lilian Besson, pour le cours d'informatique pour tous en prépa MP au Lycée Lakanal (http://perso.crans.org/besson/infoMP/), - *Licence :* MIT Licence (http://lbesson.mit-license.org). ----------------------------------------------------------------------------- """ from __future__ import print_function, division # Python 2 compatibility import numpy as np import matplotlib.pyplot as plt from scipy.integrate import quad # %% Question 0. def q0(): r""" Préliminaires : - Comme pour tous ces exercices, on commence par **importer** les modules requis, ici `numpy `_ et `matplotlib `_ : >>> import numpy as np >>> import matplotlib.pyplot as plt - En question 4 on a besoin de :py:func:`scipy.integrate.quad`, on l'importe ici : >>> from scipy.integrate import quad """ pass # %% Question 1. def q1(): r""" Question 1. On nous demandait de tracer, pour :math:`n = 2 \dots 7`, ces courbes :math:`\mathcal{C}_n = \{ (x_n(t), y_n(t)), t \in [0, 2\pi] \}`, définies par : .. math:: x_n(t) &= 4 \cos(t) - \cos(nt) \\ y_n(t) &= 4 \sin(t) - \sin(nt) Cela suggère d'utiliser une boucle ``for n in range(2, 7+1)`` et les fonctions généralisées :py:func:`numpy.cos` et :py:func:`numpy.sin` : :: N = 300 # Nb points t = np.arange(0, 2*np.pi, N) # t = 0 .. 2*pi avec 300 points plt.hold(True) # Mettre tous les dessins sur la même figure for n in range(2, 7 + 1): # Rappel: range(a, b) = [a, a+1, .., a+b-1] borne b non incluse ! x = 4 * np.cos(t) - np.cos(n * t) y = 4 * np.sin(t) - np.sin(n * t) plt.plot(x, y, label=("n = %d" % n)) # et pas (t, x) ou (t, y) plt.legend() # Afficher la légende, décrite avec les label=... plus haut plt.title("Cn pour n = 2..7") # On met un joli titre plt.show() # On montre la figure ! Cela donne une figure comme celle ci-dessous : .. image:: PSI_Mat2_2015_24__figure1.png """ N = 300 # Nb points t = np.linspace(0, 2 * np.pi, N) # t = 0 .. 2*pi avec 300 points # Attention, np.arange ne fait pas du tout pareil ! plt.figure() # Nouvelle figure plt.hold(True) # Mettre tous les dessins sur la même figure plt.grid(True) # Activer les quadrillages for n in range(2, 7 + 1): # Rappel: range(a, b) = [a, a+1, .., a+b-1] borne b non incluse ! x = 4 * np.cos(t) - np.cos(n * t) y = 4 * np.sin(t) - np.sin(n * t) plt.plot(x, y, label=(r"$n = %d$" % n)) # et pas (t, x) ou (t, y) plt.legend() # Afficher la légende, décrite avec les label=... plus haut plt.title(r"$C_n$ pour $n = 2 ... 7$") # On met un joli titre plt.savefig("PSI_Mat2_2015_24__figure1.png", dpi=180) # On la sauvegarde plt.show() # On montre la figure ! # %% Question 2. def q2(): r""" Question 2. À l'aide de la figure, on observe les symétries suivantes : - symétrie par rapport à l'axe :math:`x`, car :math:`t \mapsto 4 \sin(t)` et :math:`t \mapsto - \sin(n t)` sont symétriques par rapport à :math:`\pi`, - pour :math:`n` impaire (vert, cyan, doré sur notre figure 1), symétrie par rapport à l'axe :math:`y`, car :math:`t \mapsto 4 \cos(t)` et :math:`t \mapsto - \cos(n t)` sont symétriques par rapport à :math:`\pi` si :math:`n` est impaire (mais :math:`t \mapsto - \cos(n t)` ne l'est pas si :math:`n` est pair). """ pass # %% Question 3. def q3(): r""" Question 3. À l'aide de la figure, on observe que seule la courbe rouge (:math:`n = 4`) admet des points non-réguliers, et qu'elle en a trois, correspondant à :math:`t = 0, 2\pi/3, 4\pi/3`. Il faudrait aussi prouver la même chose, faites le sur papier (c'est un bon exercice). Si besoin, cf. `le chapitre 24.3.3 de ce cours de MPSI (§24.3.3 p692) `_. Les deux fonctions :math:`t \mapsto x_n(t)` et :math:`t \mapsto y_n(t)` sont de classes :math:`\mathcal{C}^{\infty}`, mais pour étudier les points non-réguliers (aussi appelés singuliers), il faut trouver les points où le vecteur vitesse :math:`v(t) = [x_n'(t), y_n'(t)]` s'annule. On calcule d'abord le vecteur vitesse : .. math:: v(t) = [x_n'(t), y_n'(t)] = [ -4 \sin(t) + n \sin(nt), +4 \cos(t) - n \cos(nt)]. On cherche à avoir :math:`n'(t) = 0`, soit :math:`4 \sin(t) = n \sin(n t)` et :math:`4 \cos(t) = n \cos(n t)`. En prenant la somme des carrés des deux côtés, on obtient d'abord que :math:`n'(t) = 0 \implies 4^2 = n^2 \implies n = 4` : c'est déjà pas mal, on vient de prouver que seule la courbe :math:`n = 4` peut avoir des points non-réguliers. Désormais, pour :math:`n = 4`, :math:`n'(t) = 0` *ssi* :math:`\sin(t) = \sin(4 t)` et :math:`\cos(t) = \cos(4 t)`. On remarque déjà que les trois points observés, :math:`t = 0, 2\pi/3, 4\pi/3`, fonctionnent, mais on doit montrer que ce sont les seuls. Si :math:`\sin(t) = \sin(4 t)` et :math:`\cos(t) = \cos(4 t)`, alors en utilisant l'identité d'Euler, cela implique que :math:`\mathrm{e}^{it} = \mathrm{e}^{4it}` qui implique que :math:`\mathrm{e}^{3it} = 1`, et donc :math:`3t = 0 \;\mathrm{mod}\; 2\pi`, or :math:`t \in [0, 2\pi]`, donc cela implique que :math:`t \in \{0, 2\pi/3, 4\pi/3\}`. Et voilà. """ pass # %% Question 4. def l(n): r""" Calcule la longueur :math:`l_n` de façon approchée via la fonction :py:func:`scipy.integrate.quad` (``quad(f, a, b)``), appliquée à :py:func:`dOM_sur_dt` définie **dans le corps de la fontion** ``def l(n): ...``. En effet, :py:func:`dOM_sur_dt` **doit** dépendre de ``n``, mais :py:func:`scipy.integrate.quad` a besoin d'une fonction qui n'accepte qu'un seul paramètre : si ``f`` est :math:`t \mapsto f(t)`, alors ``quad(f, a, b)`` :math:`\simeq \int_{a}^{b} f(t) \; \mathrm{d}t`. .. note:: En fait, :py:func:`scipy.integrate.quad` accepte une fonction du genre :math:`g : (t, n) \mapsto g(t, n)` si on l'appelle comme ``quad(g, 0, 1, args=(8))`` (qui sera une approximation de :math:`\int_{a = 0}^{b = 1} g(t, n = 8) \; \mathrm{d}t)`. """ def dOM_sur_dt(t): """ Fonction exacte pour calculer || d OM / dt || = sqrt(x'(t) + y'(t)).""" return np.sqrt((- 4 * np.sin(t) + n * np.sin(n * t))**2 + (4 * np.cos(t) - n * np.cos(n * t))**2) # Maintenant on l'utilise avec scipy.integrate.quad return quad(dOM_sur_dt, 0, 2 * np.pi)[0] def q4(): r""" Question 4. Il faut se souvenir de la formule donnant la longueur d'un arc paramétré. Encore une fois, si besoin, cf. `le chapitre 24.1 de ce cours de MPSI (§24.1 p680) `_. La formule a connaître est : .. math:: l_n = \int_{t = 0}^{t = 2\pi} \left\| \frac{\overrightarrow{OM}(t)}{\mathrm{d} t} \right\|_2 \mathrm{d} t. 1. On définit une fonction `dOM_sur_dt(t)` qui calcule :math:`\left\| \frac{\overrightarrow{OM}(t)}{\mathrm{d} t} \right\|_2 = \sqrt{x_n'(t)^2 + y_n'(t)^2}` (note : c'est une fonction *exacte*), 2. On utilise ensuite la fonction :py:func:`scipy.integrate.quad` pour calculer l'intégrale de façon *numérique*, 3. On met tout ça dans une fonction :math:`l(n)` qui donnera la longueur de la courbe en fonction de n, 4. On calcule la liste des valeurs de :math:`l(n)` par une liste en compréhension, avec :math:`n = 1 .. 20`, 5. On affiche ces valeurs (avec :py:func:`matplotlib.pyplot.plot`). Cela donne une figure comme celle ci-dessous : .. image:: PSI_Mat2_2015_24__figure2.png """ # Valeurs M_n = (n, l_n) demandées valeurs_n = [n for n in range(1, 20 + 1)] valeurs_M = [l(n) for n in range(1, 20 + 1)] # print("valeurs_M =", valeurs_M) asymptote = [2 * np.pi * n for n in range(1, 20 + 1)] # print("asymptote =", asymptote) # On crée la figure plt.figure() plt.grid(True) plt.hold(True) plt.title(r"$M_n = (n, l_n)$ pour $n = 1 ... 20$") # On met un joli titre plt.plot(valeurs_n, valeurs_M, 'r*-', label=r'$n \mapsto l_n$', lw=2, ms=5) # Trait rouge, continu avec des * plt.plot(valeurs_n, asymptote, 'b:', label=r'Asymptote : $n \mapsto 2 \pi n$', lw=2) # Trait bleu, discontinu avec des - - - plt.legend(loc='upper left') # On affiche la légende plt.savefig("PSI_Mat2_2015_24__figure2.png", dpi=180) # On la sauvegarde plt.show() return valeurs_n, valeurs_M # %% Question 5. def q5(): r""" Question 5. On s'inspire de la figure précédente pour deviner une forme que peut avoir :math:`l_n` pour :math:`n \to +\infty`. Son comportement semble parfaitement linéaire... En lisant la figure précédente, on trouve :math:`l_n \simeq 2 \pi \times n`. On calcule : .. math:: &\left\| \frac{\overrightarrow{OM}(t)}{\mathrm{d} t} \right\|_2 \\ &= \sqrt{x_n'(t)^2 + y_n'(t)^2} \\ &= \sqrt{(- 4 \sin(t) + n \sin(n t))^2 + (4 \cos(t) - n \cos(n t))^2} Donc pour :math:`n \to +\infty`, :math:`- 4 \sin(t) + n \sin(n t) = \mathcal{O}(n \sin(n t))`, :math:`4 \cos(t) - n \cos(n t) = \mathcal{O}(- n \cos(n t))`, puisque :math:`- 4 \sin(t), 4 \cos(t) \in [-4, 4]` sont bornés. Donc pour :math:`n \to +\infty` : .. math:: \sqrt{((- 4 \sin(t) + n \sin(n t))^2 + (4 \cos(t) - n \cos(n t))^2} \\ \simeq \sqrt{n^2 \sin^2(n t) + n^2 \cos^2(n t)} \\ = n \sqrt{\sin^2(n t) + \cos^2(n t)} \\ = n. Ainsi, :math:`\int_{0}^{2\pi} \lim_{n\to\infty} \left\| \frac{\overrightarrow{OM}(t)}{\mathrm{d} t} \right\|_2 \mathrm{d}t = \int_{0}^{2\pi} n \mathrm{d}t = 2 \pi n`. Reste à justifier comment on peut inverser l'intégrale et la limite. On se souvient du théorème de convergence dominée, et sur papier on ferait proprement un calcul justifiant qu'on a une borne uniforme qui convient (comme :math:`|4 \cos(t) - n \cos(nt)| \leq 4 + n` et :math:`|- 4 \sin(t) + n \sin(nt)| \leq 4 + n` c'est assez rapide). **Conclusion :** :math:`l_n \simeq_{n \to \infty} 2 \pi n`. .. note:: Au tableau et sur papier, vous devriez justifier mieux, surtout les :math:`\simeq` et :math:`\mathcal{O}`. (J'ai juste la flemme.) """ pass # %% Fin de la correction. if __name__ == '__main__': from doctest import testmod print("Test automatique de toutes les doctests ecrites dans la documentation (docstring) de chaque fonction :") testmod(verbose=True) # testmod() print("\nPlus de details sur ces doctests peut etre trouve dans la documentation de Python:\nhttps://docs.python.org/3/library/doctest.html (en anglais)") # Fin de PSI_mat2_2015_24.py