Problème du collectionneur de vignettes
PARTIE II : Résolution mathématique
Quelques prérequis indispensables
A propos des suites géométriques
Suite géométrique définie par relation de récurence :
Suite géométrique définie en fonction de n :
Somme des termes d'une suite géométrique
Il est important d'avoir en tête, la formule suivante : .
Démonstration
Il existe plusieurs manières de démontrer ce résultat, en voici une. Considérons les 2 égalités suivantes :
On les soustrait l'une avec l'autre :
On obtient donc : , c'est à dire
A propos de la loi géométrique
C'est une loi de probabilité discrète définie telle que :
La probabilité que X = k correspond à la probabilité d'obtenir k-1 echecs et 1 succès sur un ensemble de k épreuves de Bernoulli indépendantes avec :
- q : probabilité d'obtenir un echec
- p : probabilité d'obtenir un succès tel que
Espérance de la loi géométrique
L'espérance de la loi géométrique est donnée par la formule : .
Démonstration
Nous avons démontré plus haut que or pour , , ainsi .
Soit . La dérivée de f est .
Soit X, une variable aléatoire discrète suivant une loi géométrique tel que :
Nous avons donc .
Variance de la loi géométrique
La variance de la loi géométrique est donnée par la formule :
Démonstration
Tout d'abord reprenons la dérivée de la fonction f définie plus haut :
Nous dérivons f une seconde fois :
Soit l'égalité A définie telle que :
On obtient donc
Selon le théorême de König-Huygens :
Dans notre cas nous avons :
On a donc
Fonction de répartition d'une loi géométrique
X suit la loi géométrique de paramètre p. Soit F la fonction de répartition de la variable X. On a alors :
Démonstration
Nous savons que , par conséquent :
On sait que , donc .
class LoiGeometric :
def __init__(self, p):
self.q = 1 - p
self.p = p
def calcEsperance(self):
self.esperance = 1/self.p
return self.esperance
def calcVariance(self):
self.variance = self.q/self.p**2
return self.variance
def calcEcartType(self):
self.ecartType = sqrt(self.q)/self.p
return self.ecartType
def calcProbability(self, k):
return (self.q**(k-1))*self.p
def calcFctRepartition(self, k):
return 1 - self.q**k
def calcFctRepartitionReverse(self, pct):
r= 0
while self.q**r >= 1-pct :
r+=0.0001
return r+1
def reprLoiGeometric (self, kmax):
x = np.arange(1,kmax)
y = self.calcProbability(x)
fig = plt.figure(figsize = (12,6))
axes1 = fig.add_axes([0.1,0.1,0.9,0.9])
axes1.scatter(x,y)
axes1.grid()
axes1.set_ylabel('Probabilité d\'obtenir une nouvelle bille avec X tirages')
axes1.set_xlabel('Nbr de tirage')
axes1.set_title('Loi géométrique avec probabilité {} de succés'.format(self.p))
def reprFctRepartition (self, kmax):
x = np.arange(1,kmax)
y = self.calcFctRepartition(x)
fig = plt.figure(figsize = (12,6))
axes2 = fig.add_axes([0.1,0.1,0.9,0.9])
axes2.scatter(x,y)
axes2.grid()
axes2.set_ylabel('Probabilité d\'obtenir une nouvelle bille')
axes2.set_xlabel('Nbr de tirage')
axes2.set_title('Fct de répartition d\'une loi géométrique avec probabilité {} de succés'.format(self.p))
#Exemple de loi géométrique avec p = 2/20. Cela représente le cas où notre collectionneur possède déjà 18 billes
#différentes et essaie d'en obtenir une 19ème.
newLaw = LoiGeometric (2/20)
newLaw.reprLoiGeometric(25)
newLaw.reprFctRepartition(25)


Revenons au problème de notre collection de bille
Soit la variable aléatoire T suivante :
- T : le nombre de tirage avec remise nécessaire pour obtenir toutes les billes. On peut considérer T comme le temps nécessaire pour obtenir toutes les billes en supposant que à chaque pas de temps, on tire une nouvelle bille.
- n : le nombre de billes différentes à collectionner. Ici n = 20.
- : temps supplémentaire pour obtenir une i-ème bille sachant que le collectionneur en a déjà i-1. Cela signifie que si le collectionneur possède déjà i-1 billes sur les 20 billes à collectionner alors la probabilité d'en obtenir une nouvelle au tirage suivant est :
suit une loi géométrique de paramètre , ainsi nous savons que
Par linéarité de l'espérance :
La solution à notre problème est le résultat du calcul :
#La classe collection permet de calculer le nombre de tirage à faire en moyenne pour obtenir toutes les billes
#Elle permet également de calculer la variance sur ce nombre de tirage
class Collection :
def __init__(self, nbr_billes):
self.nbr_billes = nbr_billes # le seul parametre de la classe est le nombre de billes à collectionner
self.list_esperance = list()
self.list_variance = list()
self.list_geometricLaws = [LoiGeometric(b/nbr_billes) for b in range(1, nbr_billes + 1)]
def calculEsperance (self):
esperanceTot = 0
for law in self.list_geometricLaws :
e = law.calcEsperance() #objets LoiGeometric stockés dans une liste pour calculer l'esperance
self.list_esperance.append(e)
esperanceTot += e
return esperanceTot
def calculVariance (self):
varianceTot = 0
for law in self.list_geometricLaws :
v = law.calcVariance()
self.list_variance.append(v)
varianceTot += v
return varianceTot
collection = Collection(20)
mean20 = collection.calculEsperance()
print('Le nombre de tirage moyen nécessaire pour obtenir toutes les billes est {}.'.format(mean20))
print('Empiriquement, nous avions calculés {} tirages pour obtenir les 20 billes.'.format(meanEmp))
Le nombre de tirage moyen nécessaire pour obtenir toutes les billes est 71.95479314287363.
Empiriquement, nous avions calculés 72.0168 tirages pour obtenir les 20 billes.
Var20 = collection.calculVariance()
EcarT20 = math.sqrt(Var20)
print('La variance pour 20 billes est {}, experimentalement nous avions obtenus {}.'.format(Var20,varianceEmp))
print('Pour l\'ecart-type, nous avions obtenus {} experimentalement et nous avonss {} par calcul.'.format(EcarT20,
ecartTypeEmp))
La variance pour 20 billes est 566.5105044223355, experimentalement nous avions obtenus 571.5000677667767.
Pour l'ecart-type, nous avions obtenus 23.801481139255504 experimentalement et nous avonss 23.906067593119047 par calcul.
#Pour le plaisir voici le graphique montrant l'évolution du nombre de tirage et de la variance en fonction
# du nombre de billes à collectionner
list_e = list()
list_v = list()
for c in range(1,30) :
newCollection = Collection(c)
list_e.append(newCollection.calculEsperance())
list_v.append(newCollection.calculVariance())
df_study = pd.DataFrame(list_e, columns = ['esperance'], index = [_ for _ in range(1,30)])
df_study['variance'] = list_v
df_study.plot(figsize = (16,8), title = 'Variance et Esperance selon le nombre de bille à collectionner')

#Tableau du nombre de tirage et de la variance selon le nombre de bille à collectionner
df_study