Soit $\alpha > 0$ un paramètre. On considère la courbe paramétrée définie par :
$$ x(t) = (1 - \alpha) \cos(t) + \alpha \cos\left(\frac{(1-\alpha)}{\alpha} t\right) $$
$$ y(t) = (1 - \alpha) \sin(t) - \alpha \sin\left(\frac{(1-\alpha)}{\alpha} t\right) $$
pour $t\in\mathbb{R}$.
Pour $\alpha= \frac 1 5$, tracer la courbe, en prenant $0 \le t \le 2\pi$. Puis, remplacer $\frac 1 n$ par d'autres valeurs de la forme $\frac 1 n$ avec $n$ entier.
Correction.
from matplotlib import pyplot as plt
import numpy as np
import math
Faisons une fonction (ce n'est pas obligatoire!).
def courbe(alpha, nb_points, t_min, t_max):
"""
Trace la courbe avec matplotlib, pour t entre t_min et t_max,
en prenant 'nb_points' sur la courbe.
"""
t= np.linspace(t_min, t_max, nb_points)
x= (1-alpha)*np.cos(t) + alpha*np.cos( ((1-alpha)/alpha) *t)
y= (1-alpha)*np.sin(t) - alpha*np.sin( ((1-alpha)/alpha) *t)
plt.plot(x,y)
courbe(1/5, 100, 0, 2*math.pi)
courbe(1/7, 100, 0, 2*math.pi)
Pour $\alpha = \frac{1}{\sqrt{2}}$, tracer la courbe en prenant $0 \le t \le R$, où on augmentera $R$ progressivement. Commenter.
courbe(1/math.sqrt(2), 100, 0, 2*math.pi)
courbe(1/math.sqrt(2), 100, 0, 20*math.pi)
courbe(1/math.sqrt(2), 100, 0, 100*math.pi)
A ce stade, il est bon de remarquer que sur un intervalle aussi grand que $[0, 100\pi]$, il est probablement insuffisant de ne prendre que 100 points! essayons :
courbe(1/math.sqrt(2), 1000, 0, 100*math.pi)
C'est effectivement très différent! On se dit qu'on va augmenter le nombre de points avec la longueur de l'intervalle. Par exemple :
test= lambda N : courbe(1/math.sqrt(2), 10*N, 0, N*math.pi)
test(100)
test(250)
test(1000)
Dans cet exercice, nous aurons besoin de la fonction de Numpy pour produire des tableaux de nombres tirés au sort entre 0 et 1 :
import numpy as np
A= np.random.rand(2,6)
print(A)
Ici la matrice tirée au sort comporte 2 lignes et 6 colonnes. On peut y penser comme à une suite de 6 vecteurs tirés au hasard, avec A[0,i]
et A[1,i]
qui sont les coordonnées du $i$-ième vecteur.
Ecrire une fonction compte(N)
qui fait les choses suivantes :
A[0,i]**2 + A[1,i]**2 < 1
, et on renvoie ce nombre.Bonus pour ceux qui arrivent à écrire une fonction rapide.
Correction.
def compte(N):
A= np.random.rand(2,N)
# pour le plaisir, voici une version entièrement "en numpy", qui est très rapide
# (ci-dessous une version plus simple)
x= A[0,:] # première ligne
y= A[1,:] # deuxième ligne
test= x**2 + y**2 < 1
return np.sum(test)
# ou alors, beaucoup plus simplement (et c'est ce que j'attends)
def compte2(N):
A= np.random.rand(2,N)
total= 0
for i in range(N):
if A[0,i]**2 + A[1,i]**2 < 1 :
total= total + 1
return total
%time compte2(1000000)
%time compte(1000000)
Ah! la première version est beaucoup plus rapide.
Observez la valeur de 4*compte(N)/N
, pour $N$ de plus en plus grand. Puis (et c'est beaucoup plus difficile), expliquez, même sans être trop rigoureux.
essai= lambda N : 4*compte(N)/N
essai(10)
essai(100)
essai(1000)
essai(1000000)
Ça m'a tout l'air de converger vers $\pi$. Pourquoi?
Chaque nombre tiré au hasard est entre 0 et 1, donc chaque vecteur tiré au hasard est un point dans le carré $[0,1] \times [0,1]$. Sans entrer dans le détail, on imagine facilement que la probabilité que le point tiré au hasard tombe dans une zone donnée $Z$ est donné par l'aire de $Z$ (notez que l'aire du carré est 1).
En comptant le nombre de points moyen dans une zone $Z$, on devrait donc trouver une approximation de l'aire (c'est la loi des grands nombres, en fait, que vous ne connaissez pas bien).
Dans l'exercice on a compté les points dans le quart de disque de rayon 1 et de centre $(0,0)$. Son aire est $\frac \pi 4$. D'où les valeurs observées.
Et oui, cette méthode pour calculer les aires s'appelle méthode de Monte-Carlo, parce qu'elle s'appuie sur le hasard (qui est également présent au casino).
Prenons une variable formelle $X$ grâce à sympy (vous devez faire la même chose dans votre notebook):
import sympy as sp
sp.init_printing()
X= sp.Symbol("X")
Les polynômes de Hermite $(H_n)_{n\ge 0}$ sont définis par récurrence de la manière suivante :
Ecrire une fonction H(n)
qui renvoie le polynôme $H_n$, comme une expression formelle sympy développée.
Note: il est normal que ça soit lent pour des valeurs de $n$ supérieures à 25. On ne vous demande pas d'optimiser tout ça.
Correction.
def H(n):
if n == 0:
return 1
elif n == 1:
return X
else:
return (X * H(n-1) - (n-1)*H(n-2)).expand()
for i in range(10):
display(H(i))
H(2)
H(3)
H(25)
En regardant des exemples, devinez une relation entre $H_n'$ (la dérivée de $H_n$) et $H_{n-1}$. On ne vous demande pas de la démontrer.
Correction.
N= 10
for n in range(1,N):
print("dérivée de H_", n,"=", sp.diff(H(n), X), "et H_", n-1, "=", H(n-1))
Ma foi, il semble que $H'_n = n H_{n-1}$. Essayons :
N= 30
for n in range(1,N):
if sp.diff(H(n), X) != n*H(n-1):
print("ça ne marche pas pour n=", n)
else:
print(".", end= "")
print("Toutes les valeurs jusqu'à n=", N, "ont été testées")