#!/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")