• Aucun résultat trouvé

La variable aléatoire binomiale

Pour 100 millions de lancers, on obtient : fréquence de la face 1 : 0.16670938

fréquence de la face 2 : 0.16662856 fréquence de la face 3 : 0.16663721 fréquence de la face 4 : 0.16666619 fréquence de la face 5 : 0.16670928 fréquence de la face 6 : 0.16664938

soit des valeurs relativement proches de 16.

3.2

3.2 Deux dés

On lance simultanément deux dés ; calculer la probabilité que les deux faces amenées soient des entiers consécutifs.

Il faudra dans ce cas tester si la valeur absolue de la différence des deux valeurs est égale à 1 ; un seul compteur suffira.

# deux-des.rb

# proba 2 entiers consécutifs

#

Pour 100 millions de lancers, on obtient : 0,27771426

La réponse exacte est 1036= 0,2777777. . . que l’on trouve facilement en faisant un tableau à deux entrées.

3.3

3.3 La variable aléatoire binomiale

On lance cinq fois une pièce de monnaie ; calculer la probabilité d’amener 0 fois pile, 1 fois pile, 2 fois pile, ?, 5 fois pile.

Commençons par compter le nombre de pile sur cinq lancers :

# 1piece-5fois.rb

#

---c=0.0 # compteur de pile for k in 1..5

if rand<0.5 c=c+1 end

end

puts "nompre de pile : #{c}"

Aves le même canevas que dans l’exemple précédent, on va exécuter plusieurs parties, avec cumul des résultats dans six compteurs (les six valeurs possibles de nombre de pile amenés).

# binomiale5.rb

Pour 10 millions de parties : nb pile fréquence

Ces résultats sont à comparer avec ceux obtenus en utilisant la formule d’une loi binomiale de paramètres 5 et 12

X est la variable aléatoire « nombre de pile amenés sur cinq lancers ».

On peut facilement généraliser l’algorithme en y remplaçant 5 par n.

4

4 Deux dés encore, on corse un peu

On lance simultanément deux dés ; calculer le nombre de lancers nécessaires, en moyenne, avant d’amener un double six.

Commençons par gérer une seule partie : on compte le nombre de lancers jusqu’à ce qu’on obtienne un double six, en utilisant une répétitive à test d’arrêt final(10) puisqu’on doit lancer au moins une fois les deux dés.

10. Desbonnez J.-M., Algorithmique élémentaire et Ruby,Losanges, n°28, mars 2015, p.53.

# double-six.rb

# lancer jusqu’au premier double 6

#

end while !(jet1==6 and jet2==6) puts compteur

Si on exécute plusieurs fois l’algorithme (à échelle humaine), on obtient des résultats très disparates, tout comme leurs moyennes. Voyons.

Programmons plusieurs parties (de plus en plus) ; pour calculer une moyenne, il suffit de cu-muler la somme des nombres de jets (variablesomme) et de diviser cette somme par le nombre de parties (variable nbparties).

# double-six-moyenne.rb

# lancer jusqu’au premier double 6

#

end while !(jet1==6 and jet2==6) somme=somme+compteur

Il semble que 36 soit une bonne approximation de la réponse cherchée ?

Vérification

Le problème est relativement simple à traiter avec Ruby, sa vérification l’est un peu moins ; on est en effet ici face à une variable aléatoire géométrique, dite « du premier succès ». On vient en fait de calculer son espérance mathématique.

Notons X la variable aléatoire « Obtenir un double six après n expériences ».

P(X= 1) = 1

36 (facile à voir sur un tableau à 2 entrées) P(X= 2) = 35

36 (2 échecs puis 1 succès)

···

P(X =n) =✓35 36

n 1

· 1

36 (n-1 échecs puis 1 succès)

On a bien une distribution de probabilité, car la somme des probabilités vaut 1 : 1

⇣somme des termes d’une suite géométrique de raison 3536⌘ . Pour le calcul de l’espérance mathématique :

E(X) =X dont voici une démonstration :

si |x|<1, alors 11x = 1 +x+x2+x3+···+xk+···

... Ou une marche aléatoire de Pólya(11) qualifiée aussi de « marche de l’ivrogne ».

On dispose côte à côte onze boîtes numérotées de 1 à 11(12); une puce s’installe dans la boîte centrale (n°6), commence à boire sans modération, puis démarre une ballade de cinq sauts aléatoires, soit d’une boîte à sa gauche, soit d’une boîte à sa droite.

11. George Polya, mathématicien d’origine hongroise, 1887–1985.

12. Libre au lecteur d’imaginer la taille, la forme, la couleur et le contenu des boîtes.

Calculer la probabilité qu’elle revienne dans la boîte de départ. Et plus encore si affinité.

Algorithme

Comme d’habitude, on va observer les ballades de beaucoup de puces (variable nbpuces) ; à chaque saut, on mémorise la position (variable pos), initialement fixée à 6, on y retire 1 ou on y ajoute 1 selon qu’il y a un saut à gauche ou un saut à droite. Enfin, après les cinq sauts, on ajoute 1 au compteur correspondant au numéro de la boîte atteinte (variablecompteur[pos]).

# polya-5puces.rb

if rand<0.5 # saut à gauche pos=pos-1

Après observation de 10 millions de puces,(13)

Il semblerait que les puces soient allergiques aux boîtes paires.

En fait, il est impossible de rejoindre une boîte paire, et par conséquent de revenir dans la boîte de départ (n°6) ; la probabilité demandée est donc nulle.

13. Et beaucoup de démangeaisons ?

Notons G le nombre de sauts à gauche, et D le nombre de sauts à droite ; il est évident queD= 5 G.

La position finale atteinte se calcule par l’expression 6 G+D= 6 G+ (5 G) = 11 2G

.2G est toujours pair, et donc 11 2G est toujours impair.

G D 11 2G

Pour le calcul des probabilités de rejoindre les boîtes impaires, on applique une loi binomiale

« nombre de sauts à gauches », par exemple, qui est une Bin⇣ 5,12

Pour qui se plait à généraliser,

P(rejoindre boîte n°k) =P 11 k

6 Just for fun, une martingale ?

Les différents exemples traités précédemment montrent que l’algorithmique permet de faire des simulations rapides, en usant sans modération des nombres aléatoires.

Voici maintenant un calcul où toute ressemblance avec une situation existante(14) est tout sauf fortuite.

On choisit au hasard cinq nombres naturels distincts entre 1 et 50.

Quelle est, en moyenne, leur moyenne?

Algorithme

La difficulté est d’engendrer cinq nombres distincts; une solution consiste à placer tous les nombres dans un tableau, puis d’y supprimer le nombre qui a éte engendré aléatoirement, (Ruby propose l’instruction tableau.delete_at(position)) sans oublier de l’enregistrer dans le tableau des nombres retenus, et de mémoriser la taille du tableau réduit pour le tirage suivant.

L’utilisation d’un nombre important de tirages et le calcul de la moyenne ont déjà été utilisés dans les algorithmes précédents.

14. Une grille de l’euro-millions.

# just-for-fun.rb

# ---nbessais=10000000 som=0.0

for t in 1..nbessais

n=Array.new(51){0} # pour les 50 nbres de 1 à 50 grille=Array.new(6){0} # pour les 5 nbres au hasard

# remplissage du tableau des 50 nombres for k in 1..50

n[k]=k end

# tirage aléatoire de 5 nbres distincts taille=50

for j in 1..5

x=rand(1..taille) grille[j]=n[x]

n.delete_at(x)# suppression du nbre choisi

taille=taille-1 # ajustement de la taille du tableau end

# calcul moyenne moy=0.0

for j in 1..5 moy=moy+grille[j]

end

som=som+moy/5 end

puts som/nbessais

Le résultat obtenu avec 10 millions d’essais est 25,5 ; il ne permet malheureusement pas d’aug-menter la probabilité à laquelle tout le monde pense ! Le mathématicien, lui aussi, peut rêver ! Merci à PhilippeTilleuilpour l’article — à paraître — sur la loi symétrique, qui explique et démontre le résultat obtenu.

On peut déjà lever un coin du voile : le résultat obtenu ne provient pas du calcul 1+502 . A suivre.

7

7 Un mouvement brownien

Robert Brown (1773–1858), botaniste anglais, a observé un mouvement désordonné(15) de particules de pollen en suspension dans l’eau. De nombreux scientifiques s’y sont intéressés, dont Monsieur Einstein, Albert de son prénom, excusez du peu...

Avec de modestes moyens, et pour rester dans le canevas des expériences précédentes, imaginons une particule qui se déplace k fois d’une distance rectiligne d dans une direction aléatoire↵.

Calculons la distance moyenne parcourue entre sa position de départ et sa position d’arrivée.

15. D’où le nom demouvement brownien.

Algorithme

Pour l’expérience, on va fixer d à 1 et k à 10, pour commencer. La direction sera un nombre aléatoire dans l’intervalle [0,2⇡].

On supposera un repère orthonormé ; le point de départ est le point de coordonnée (0,0). Si (x, y)est la coordonnée du point d’arrivée, la distanced séparant les deux points vaut p

x2+y2. A chaque « pas », on incrémente la position précédente ded·cos pour l’abscisse et ded·sin pour l’ordonnée.

Et, comme précédemment, pour obtenir une moyenne représentative, on observe un grand nombre de particules (variable nbparticules).

# mvt-brownien.rb

#

---d=1 # distance parcourue à chaque déplacement k=10 # nombre de déplacements élémentaires nbparticules=1000000 end # les k déplacements distance=Math.sqrt(x**2+y**2) moyenne=moyenne+distance end

puts moyenne/nbparticules

On peut aisément faire varier les paramètresd etk, le temps d’exé-cution de l’algorithme étant direc-tement proportionnel à k.

Pour les accrocs du chrono, et en guise de conclusion

Pour calculer le temps d’exécution d’un algorithme, il suffit de mémoriser (dans deux variables distinctes) le temps-système au début de l’algorithme, puis à la fin, la différence des deux fournissant un intervalle de temps en secondes.

start=Time.now

... toutes les instructions ...

stop=Time.now

puts "exécuté en #{stop-start} seconde(s)"

Programmation Ruby

Chapitre 4

Algorithmique et langage Ruby, cuisiner les tableaux. . . bon appétit !

Résumé.Lorsqu’il faut calculer (et mémoriser) de nombreux résultats, l’utilisation de variables simples est chose impossible, simplement à cause de leur nom. En effet, comment « inventer » mille noms de variables pour mémoriser, par exemple, mille nombres premiers, sans compter les mille lignes de code pour les affectations.

Les tableaux sont des variables dont les composantes sont identifiées par un nom et un numéro appelé indice. Mathématiquement parlant, c’est une matrice ligne (ou colonne, selon la manière dont on la visualise).

Les quelques exemples traités dans cet article relèvent à la fois du domaine de l’informatique (création de mots de passe, tri), du domaine de la gestion (recherche dichotomique, fusion de tableaux, recherche de doublons), et aussi, quand-même, du domaine mathématique (crible d’Eratosthène, une méthode originale de calcul d’un plus grand commun diviseur, et un peu de calcul vectoriel).

Le tout accompagné d’algorithmique, et de sauce Ruby.

1

1 Mise en bouche

Un tableau est une liste d’éléments désignée par un nom unique, chaque élément étant repéré dans la liste par saposition(appelée aussiindice). On se limitera ici aux tableaux de dimension1.

On peut l’assimiler à une « commode à tiroirs », où chaque tiroir est une variable, qui porte le nom de la commode, et un numéro qui indique sa position dans la commode.

Dans le domaine informatique, on l’appellearray; dans le domaine mathématique, on l’appelle matrice ou vecteur.

Si x est le nom générique du tableau, on notera x[k] l’élément d’indice k.

Soit x un tableau de taille 5, on peut le représenter par

x x[0] x[1] x[2] x[3] x[4]

Tous les langages de programmation permettent la manipulation de tels objets, mais la syntaxe de leur utilisation diffère d’un langage à l’autre. Voici pour Ruby.