#!/usr/bin/env python # coding: utf-8 #
#
TP n°7 : les bibliothèques en Python - éléments de correction
# $\require{color}$ # $\require{xcolor}$ # $\require{cancel}$ # $\newcommand{\myfbox}[1]{\fcolorbox{red}{white}{$\textrm{#1}$}}$ # $\require{stmaryrd}$ # $\newcommand{\ient}{[\![}$ # $\newcommand{\rrbracket}{]\!]}$ # $\newcommand{\llbracket}{[\![}$ # $\newcommand{\fient}{]\!]}$ # $\newcommand{\R}{\mathbb R}$ # $\newcommand{\K}{\mathbb K}$ # $\newcommand{\N}{\mathbb N}$ # $\newcommand{\C}{\mathbb C}$ # $\newcommand{\P}{\mathbb P}$ # $\newcommand{\E}{\mathbb E}$ # $\newcommand{\V}{\mathbb V}$ # $\newcommand{\Z}{\mathbb Z}$ # $\newcommand{\dt}{\mathrm d}$ # $\newcommand{\sh}{\operatorname{sh}}$ # $\newcommand{\ch}{\operatorname{ch}}$ # $\newcommand{\th}{\operatorname{th}}$ # $\newcommand{\e}{\operatorname{e}}$ # $\newcommand{\id}{\operatorname{Id}}$ # $\newcommand{\mat}{\operatorname{mat}}$ # $\newcommand{\sp}{\operatorname{Sp}}$ # $\newcommand{\In}{\operatorname{I}}$ # $\newcommand{\vect}{\operatorname{Vect}\ }$ # $\newcommand{\rg}{\operatorname{rg}}$ # $\newcommand{\tr}{\operatorname{Tr}}$ # $\newcommand{\dis}{\displaystyle}$ # $\renewcommand{\Im}{\operatorname{Im}}$ # $\newcommand{\im}{\operatorname{Im}}$ # $\newcommand{\bordermatrix}[3]{ \begin{matrix} \begin{matrix}#1\end{matrix} & \\ #3 & \hspace{-1em} \begin{matrix}#2\end{matrix} \end{matrix}}$ # $\newcommand{\fonction}[5]{#1\ \colon \left\{\begin{array}{ccl}#2 & \longrightarrow & #3\\#4 & \longmapsto & #5\end{array}\right.}$ # $\newcommand{\fonctionsansnom}[4]{\left\{\begin{array}{ccl}#1 & \longrightarrow & #2\\#3 & \longmapsto & #4\end{array}\right.}$ # $\newcommand{\revdots}{\mathinner{\mkern1mu\raise1pt{\kern7pt\hbox{.}}\mkern2mu\raise4pt\hbox{.}\mkern2mu\raise7pt\hbox{.}\mkern1mu}}$ # $\newcommand{\tendvers}[2]{\xrightarrow[#1\to#2]{}}$ # $\newcommand{\q}[1]{\mathbf{Q#1}\ \triangleright}$ # $\newcommand{\nicefrac}[2]{^{#1}/_{#2}}$ # In[1]: import matplotlib.pyplot as plt import numpy as np import math as m import random as rd # # 1 - Matplotlib #
# Exercice 1 #
# On trace le polygône à $10$ côtés demandé : # In[2]: n = 10 X = [m.cos(2 * k * m.pi / n) for k in range(n + 1)] Y = [m.sin(2 * k * m.pi / n) for k in range(n + 1)] plt.plot(X, Y) plt.axis("equal") # pour un repère orthonormé plt.show() # On trace maintenant les différents polygônes demandés sur la même graphique : # In[3]: for p in range(2, 11): n = 2**p X = [m.cos(2 * k * m.pi / n) for k in range(n + 1)] Y = [m.sin(2 * k * m.pi / n) for k in range(n + 1)] plt.plot(X, Y, label="p=" + str(p)) plt.axis("equal") plt.legend(loc="upper right") plt.show() # Avec $p=6$, on a déjà une bonne approximation "visuelle" du cercle unité. # Puisque ```m``` est déjà utilisé (c'est l'alias du module ```math```), on utilise un autre nom de variable : # In[4]: p = 24 q = 7 X = [m.cos(2 * q * k * m.pi / p) for k in range(p + 1)] Y = [m.sin(2 * q * k * m.pi / n) for k in range(p + 1)] plt.plot(X, Y) plt.axis("equal") plt.title("Un joli dessin") plt.show() # # 2 - Numpy #
# Exercice 3 #
# In[5]: def f(x): return x * np.sqrt(1 - x**2) X = np.linspace(-1, 1, 100) plt.plot(X, f(X), 'k', linewidth=16) T = np.linspace(0, 2 * np.pi, 100) plt.plot(np.cos(T), np.sin(T), 'k', linewidth=16) plt.axis('equal') plt.axis([-1.2, 1.2, -1.2, 1.2]) plt.show() # # 3 - Applications #
# Exercice 4 #
# In[6]: def x(t): return np.sin(t)**3 def y(t): return np.cos(t) - np.cos(t)**4 L = np.linspace(0, 2 * m.pi, 1000) plt.plot(x(L), y(L)) plt.axis("equal") plt.show() #
# Exercice 5 #
# In[7]: def f(x): return np.floor(x) def g(x): return np.floor(x) + (x - np.floor(x))**2 L = np.linspace(-2, 5, 1000) plt.plot(L, f(L)) plt.plot(L, g(L)) plt.show() # **Remarque :** On remarquera que ```Python``` trace des lignes brisées, et donc des segments (quasi)verticaux dans le graphe de $f$, ce qui n'a pas lieu d'être théoriquement pour une fonction... #
# Exercice 6 #
# In[8]: L = np.linspace(-3, 3, 1000) plt.plot(L, np.sin(L), label=r'$f_0$') plt.plot(L, L, label=r'$f_1$') plt.plot(L, L - L**3 / 6, label=r'$f_2$') plt.plot(L, L - L**3 / 6 + L**5 / 120, label=r'$f_3$') plt.legend() plt.axis('equal') plt.grid() plt.show() #
# Exercice 7 #
# In[9]: g, p, n = 1, 1, 10000 # à faire varier X, Y = [], [] total = 0 for k in range(n): resultat = rd.randint(0, 1) if resultat == 0: total += g else: total -= p X.append(k) Y.append(total) plt.plot(X, Y) plt.title("Évolution des gains au cours du temps pour g={0}, p={1} et n={2}".format(g, p, n)) plt.grid() plt.show() #
# Exercice 8 #
# On écrit d'abord une fonction ```bernoulli(p)``` qui simule une variable aléatoire de Bernoulli de paramètre $p\in[0,1]$ : elle renvoie ```1``` avec une probabilité $p$, et ```0``` sinon. # In[10]: def bernoulli(p): q = rd.random() if q < p: return 1 else: return 0 # On peut même faire plus court : # In[11]: def bernoulli(p): return int(rd.random() < p) # On écrit maintenant le script souhaité : # In[12]: p = rd.random() N = 1000 S = 0 X, Y = [], [] for k in range(1, N): S += bernoulli(p) X.append(k) Y.append(S / k) plt.plot(X, Y) plt.title(r"Évolution de la moyenne quand $p=${}".format(round(p, 2))) plt.show() # Il semble qu'il y ait convergence de la moyenne empirique vers $p$. #
# Exercice 9 #
# In[13]: n = 10 X = [m.cos(2 * k * m.pi / n) for k in range(n + 1)] Y = [m.sin(2 * k * m.pi / n) for k in range(n + 1)] plt.scatter(X, Y) plt.axis("equal") # pour un repère orthonormé plt.show() # Pour la fonction ```pgdp(n)```, on peut s'inspirer, pour plus d'efficacité, du crible d'Eratosthène, donc on rappelle une implémentation possible : # In[14]: def crible(n): """ Implémente le crible d'Eratosthene """ C = [True for k in range(n)] C[0] = False C[1] = False for k in range(2, n): if C[k]: for i in range(2 * k, n, k): C[i] = False return C # In[15]: def pgdp(n): M = 1 C = [True for k in range(n + 1)] C[0] = False C[1] = False for k in range(2, n + 1): if C[k]: for i in range(2 * k, n + 1, k): C[i] = False if n % k == 0: M = k return M # In[16]: pgdp(2*3**3*5*7*11**2) # In[17]: pgdp(5) # On crée une sous-fonction ```cercle``` pour tracer des points équirépartis sur le cercle unité : # In[18]: def cercle(n): X = [m.cos(2 * k * m.pi / n) for k in range(n)] Y = [m.sin(2 * k * m.pi / n) for k in range(n)] return X, Y # La fonction suivante est dite *récursive*, en ce sens où elle s'appelle elle-même : # In[19]: def diagramme(n): if n == 1: return [0], [0] else: d = pgdp(n) L.append(d) # L est une variable globale... if d == n: # n est premier return cercle(n) else: Xd, Yd = cercle(d) X, Y = diagramme(n // d) Xn = [xd + x / d for xd in Xd for x in X] Yn = [yd + y / d for yd in Yd for y in Y] return Xn, Yn # In[20]: N = 2023 L = [] P = diagramme(N) # on crée le titre du diagramme à afficher titre = str(N) + " = " for d in L: titre = titre + str(d) + " * " titre = titre[:-2] plt.scatter(P[1], P[0], s=0.01) plt.axis('equal') plt.xticks([], []) plt.yticks([], []) plt.title(titre) plt.show() # On peut créer une image plus grande, pour mieux voir les points, puis enregistrer l'image sur votre ordinateur pour l'ouvrir dans un logiciel dédié et zoomer sur les "petits ronds" # In[21]: plt.rcParams["figure.figsize"] = (18, 18) # In[22]: N = 2023 L = [] P = diagramme(N) # on crée le titre du diagramme à afficher titre = str(N) + " = " for d in L: titre = titre + str(d) + " * " titre = titre[:-2] plt.scatter(P[1], P[0], s=0.2) plt.axis('equal') plt.title(titre) plt.savefig("diagramme.png")