PC & PC* 2014–2015 – Informatique pour tous TP – Marche aléatoire TP – Marche aléatoire Table des matières 1 Outils python 1 2 Marche au hasard 1D non biaisée 2.1 Étude du mouvement d’une particule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Étude avec plusieurs particules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 4 3 Marche au hasard 1D avec biais 5 4 Diffusion de particules sur un segment fermé 5 1 Outils python Rappelons quelques notions de python qui seront utiles pour faire le TP. Importer une bibliothèque Ce qui fait le grand intérêt du langage de programmation python est sa communauté d’utilisateurs qui est très nombreuse et très active. Ainsi de nombreux compléments au langage ont été développés et mis à disposition au fur et à mesure du temps. Ceux–ci prennent la forme de bibliothèque. Ce sont des programmes faits par d’autres que l’on peut incorporer à son code grâce à la commande import. Les bibliothèques sont très largement documentées sur internet, il ne faut pas hésiter à consulter la documentation. La commande import peut être utilisée de plusieurs façons : si on veut importer la bibliothèque math par exemple, • import math. Pour utiliser les fonctions de la bibliothèque, comme arctan par exemple, il faut taper math.arctan • import math as mt. Cette fois–ci la fonction arctan s’obtiendra par mt.arctan • from math import *. Ici plus besoin de syntaxe spéciale, les fonctions de la bibliothèque sont directement accessible dans le programme. Ainsi la fonction arctan est directement accessible. Q1. Importer par une des trois méthodes la bibliothèque math et calculer ln(arctan(3) + e1 ). Q2. Importer la bibliothèque random et afficher la documentation du module sur internet. Trouver comment tirer au sort un nombre compris entre 2 et 98 inclus. Trouver comment tirer « au hasard » un réel dans le segment [0, 1]. En déduire une manière de simuler un jeu de pile ou face biaisé avec probabilité p = 0.3 d’apparition de « face ». Les fonctions Pour pouvoir programmer de manière efficace, il est très fortement conseillé d’avoir une approche modulaire. : plutôt que faire un gros programme d’un seul tenant, il vaut mieux découper son programme en plusieurs petits programmes effectuant des tâches simples et précises. De cette manière, on peut tester plus facilement chacun des petits sous–programmes et ce qui aide beaucoup à détecter les erreurs. Par ailleurs, cette approche permet d’éviter d’écrire plusieurs fois les mêmes lignes de code : une fois le programme écrit dans une fonction, on peut utiliser la fonction sans la réécrire. Ceci facilite grandement la maintenance du code ainsi que son optimisation éventuelle : peu importe comment est programmée la fonction, si elle fait le travail qui lui est demandé. Une fonction en python se comporte de la manière suivante : • elle mange un certain nombre d’arguments, éventuellement aucun. • Étant donnés ces arguments, elle effectue une ou plusieurs tâches. Ce sont les instructions mises dans le corps de la fonction. • Elle renvoie éventuellement une ou plusieurs valeurs. Plus précisément, une fonction se définit ainsi, attention l’indentation est obligatoire : def nom_de_fonction(arg1, arg2) : commande_1 commande_2 ... return résultat La dernière ligne (return résultat) n’est nécessaire que si on souhaite que la fonction renvoie un résultat. Pour préciser les choses, voyons un exemple : Lycée Louis Thuillier 1 11 septembre 2014 PC & PC* 2014–2015 – Informatique pour tous def exemple(p,q): res = p//q return res TP – Marche aléatoire # l’opération // est la division entière La fonction exemple, calcule le quotient de la division euclidienne de p par q et renvoie le résultat. Ainsi pour obtenir le quotient de la division euclidienne de 344 par 7 il suffit de taper exemple(344,7). On peut, si on le souhaite, renvoyer plusieurs valeurs : def exemple2(p,q): quotient = p//q # l’opération // est la division entière reste = p % q return quotient, reste La fonction exemple2 renvoie le couple quotient reste. Ainsi les commandes : q,r = exemple2(344,7) print(q*7+r) enregistre le quotient et le reste de la division euclidienne de 344 par 7 dans les variables q et r et imprime q*7+r ce qui doit donner 344. Il est possible de donner des valeurs par défauts aux derniers arguments. . .on pourra alors omettre ces arguments lors de l’appel de la fonction. Ainsi avec def exemple3(p,q=1): quotient = p//q # l’opération // est la division entière reste = p % q return quotient, reste si on lance exemple3(344) sans préciser le second argument q, alors q prendra par défaut la valeur 1 et la fonction renverra donc le couple (344,0). Il est à noter que les variables définies dans le corps de la fonction ne sont valables que dans la fonction. Ainsi, dans l’exemple précédent, les variables quotient et reste n’existent pas en dehors de la fonction, elles n’auront une existence que lors de l’exécution de celle–ci. Il en est de même pour les arguments : ce n’est pas parce que les arguments p et q ont des valeurs en dehors de la fonction qu’elles seront prises en compte lors de l’exécution de la fonction. Par contre, si des variables sont définies en dehors du corps de la fonction et utilisées dans la fonction sans qu’elles y soient définies, alors la fonction utilisera les valeurs des variables. Il faut éviter au maximum de programmer de la sorte. Q3. Écrire une fonction aléatoire bernouilli(p) renvoyant 0 avec une probabilité p et 1 avec une probabilité 1 − p. Q4. Modifier la fonction précédente pour que lorsqu’on ne précise par p, celui–ci prenne la valeur 21 . Les boucles Comme dans tous les langages de programmation, il y a deux types de boucles en python : les boucles for et while. Commençons par le plus simple, la boucle for. Par exemple : for k in range(20): print(k) va donner successivement à k les valeurs 0, 1, . . ., 19 et exécuter le corps de la boucle pour chacune de ces valeurs de k (ici afficher k). On peut boucler sur une plage d’entier, par exemple les lignes : for k in range(5,20): print(k) vont faire prendre à k les valeurs 5, 6, . . ., 19. On peut aussi parcourir directement une liste : L = ["c’est", " chouette", " python", 3] for mot in L: print(mot) La boucle while s’utilise quand on veut répéter une chose tant qu’ une condition n’est pas satisfaite. Attention, avant de se lancer dans l’élaboration d’une boucle while, il faut s’assurer que la condition va être satisfaite au bout d’un temps fini ! Sinon, la boucle ne s’arrêtera pas tant que l’ordinateur est allumé, on dit qu’on a une boucle infinie. Prenons par exemple le calcul du pgcd à l’aide de l’algorithme d’Euclide : on effectue des divisions euclidiennes du plus grand par le plus petit tant que le reste n’est pas nul. Le dernier reste non nul est le pgcd : Lycée Louis Thuillier 2 11 septembre 2014 PC & PC* 2014–2015 – Informatique pour tous p=3564 r=122 while r != 0 : p,r = r, p % r TP – Marche aléatoire # p % r renvoie p modulo r, c’est à dire le reste de la division euclidienne de p La boucle s’arrête quand r devient nul. On voit que lors de l’exécution, p prend la valeur du reste précédent. Ainsi, à la fin de l’exécution de cette boucle, le pgcd est donné par p. Les listes Les listes sont intensivement utilisées en python, elles permettent de stocker des collections d’objets. Python propose plusieurs fonctions pour manipuler les listes : L = ["mot", 3, 1.4, "pi"] print(L) # L.append("autre") # L.remove("pi") # len(L) # L.count(1.4) # print(L[1]) # L[1] = L[1]+3 # P = ["une", "autre", "liste"] L + P # imprimer la liste ajout d’un élément à la fin d’une liste retire la première occurence de "pi" dans la liste longueur de la liste compte le nombre d’occurence de 1.4 dans la liste les indices commencent à 0 !!!!! on peut modifier les éléments d’une liste concatène les listes L et P Il existe encore d’autres fonctions que vous pouvez consulter dans la documentation en ligne de python. En ce qui concerne la copie de tableau, il s’agit d’être précautionneux. Dans le listing précédent, la commande L = ["mot", 3, 1.4, "pi"] ne donne pas à L la valeur du tableau, juste l’adresse mémoire où celui–ci est stocké dans l’ordinateur. Ainsi la commande autre = L affecte à la variable autre la même adresse mémoire, donc si on modifie la liste pointée par autre. . .cela modifie aussi la liste pointée par L : c’est la même adresse mémoire ! Pour copier une liste, il faut la recopier. On peut utiliser la commande : autre = L[:] Il est possible de créer des listes avec une boucle for, par exemple la commande L = [ k**2 for k in range(10) ] donne la liste des carrés des 20 premiers entiers (à partir de 0). Tracer des courbes Il y a plusieurs moyens pour tracer des courbes en python. Nous n’en présenterons qu’une, l’utilisation de la bibliothèque pyplot du module matplotlib. Pour l’importer il faut par exemple taper : import matplotlib.pyplot as plt La bibliothèque contient beaucoup de fonctions, nous n’en présenterons que quelques-unes, notamment la fonction plot. Étant donné une suite de points P1 , P2 , . . ., PN , la commande plot permet de tracer la ligne brisée [P1 , P2 , . . . , PN ] : x = [1.2, 4, 5, 8] y = [3, -1, -3, -2] plt.plot(x,y) plt.show() # # # # liste des abscisses liste des ordonnées Crée le graphique... mais ne l’affiche pas !! affiche le graphique On peut préciser la couleur, par exemple plot(x,y,’r’) tracera en rouge (’b’ en bleu, ’g’ en vert etc. . .). Si on souhaite ne tracer que les points sans les relier, il suffit de remplacer par plot(x,y,’o’). On peut combiner ces dernières options, par exemple : x = [ 0.01*k for k in range(200) ] y = [ t**2 for t in x] plt.plot(x,y,’ro’) tracera en rouge et uniquement les points Pk de la parabole y = x2 d’abscisse 0.01k avec k ∈ J0, 199K. Nous aurons aussi besoin de fixer l’intervalle de l’axe des abscisses et des ordonnées. Pour cela, on peut utiliser les commandes xlim et ylim : Lycée Louis Thuillier 3 11 septembre 2014 PC & PC* 2014–2015 – Informatique pour tous TP – Marche aléatoire plt.xlim( -20, 10) plt.ylim( -2, 30) plt.plot([1,2],[2,3]) plt.show() Ces commandes fixe l’intervalle en x et y et trace la ligne reliant P1 (1, 2) et P2 (2, 3). Q5. Écrire une fonction polygone(N) traçant un polygone régulier de taille N. Pour les fonctions trigonométriques, on utilisera la bibliothèque math. Q6. Tracer sur un même graphique le graphe de la fonction sin et arctan sur [−2, 2]. Rappel : Modèle de la marche au hasard unidimensionnelle On considère des particules qui diffusent à une dimension dans un milieu (direction (Ox)). Pour étudier cette diffusion, on considère que les particules font toutes des « sauts de puce », soit vers la droite, soit vers la gauche, de la même longueur `∗ (distance quadratique moyenne) à la même vitesse v ∗ (vitesse quadratique moyenne), chaque saut durant ∗ τ ∗ = v` ∗ . En raison du grand nombre de particules et d’étapes à étudier, l’étude de la marche au hasard, même unidimensionnelle, est difficile à étudier sans ordinateur et se prête particulièrement à une étude informatique. Pour simplifier la modélisation informatique, on adimensionnera toutes ces grandeurs en prenant `∗ = 1 et τ ∗ = 1 (les positions et les instants sont numérotés au lieu d’être mesurés). 2 2.1 Marche au hasard 1D non biaisée Étude du mouvement d’une particule On considère une particule qui part de x = 0 à t = 0. On notera n le numéro du saut, un le déplacement de la particule durant le saut numéro n et xn la position de la particule après le saut numéro n. À chaque étape, elle se déplace de 1 vers la gauche ou de 1 vers la droite avec la même probabilité. Ainsi un vaut +1 ou −1 avec une probabilité 1/2. Q7. Quelle est la valeur minimale de xn ? Sa valeur maximale ? Q8. Écrire une fonction un_saut(x) qui modifie la position de la particule pendant 1 saut et qui renvoie x. Q9. Écrire une fonction position(n) qui donne la position de la particule après n sauts. Déterminer cette position pour 10 particules pour 10 sauts. Comparer les résultats. La prévision de Q1 est-elle vérifiée ? Q10. On va maintenant tracer l’évolution de la position d’une particule dans le temps. Écrire une fonction graphe1(n) qui trace xn en fonction de n. Utiliser cette fonction pour n = 50. Si vous tracez plusieurs fois ce même graphe, vous vous apercevez que le résultat est à chaque fois différent. 2.2 Étude avec plusieurs particules La diffusion de particules ne se conçoit pas pour une particule unique, mais pour une collection importante de particules. On notera p le nombre de particules utilisées. Q11. Écrire un programme graphe2(p,n) qui permette de tracer les trajectoires de p particules pendant n étapes. Tracer alors la trajectoire de 10 particules pour n = 50. Le problème est que ça devient très vite fouillis. On va donc envisager une autre façon de représenter la diffusion des particules : on va tracer la répartition des p particules en fonction de l’instant n. Q12. Étant donné un tableau X donnant la position des particules après n évolutions, écrire une fonction Repartition(X,n) renvoyant une liste R de taille 2n + 1 telle que pour k ∈ J0, 2nK ; R[k] donne le nombre de particules à la position −n + k. En déduire une fonction trace(X,n) traçant la répartition des particules. Tracer la répartition pour p = 500 et n = 50. Q13. À quoi ressemble cette répartition ? La tracer à nouveau pour p= 50 et p = 5000. Commenter. Sur quelle valeur de p va-t-on travailler parmi les 3 proposées ? Q14. On a vu dans le cours qu’on pouvait déterminer des distances caractéristiques de la répartition : la distance moyenne parcourue et la distance quadratique moyenne. Que doit valoir la distance moyenne ? Il est possible de calculer la moyenne d’un tableau de nombre à l’aide de la commande mean de la bibliothèque numpy. Ainsi les commandes : Lycée Louis Thuillier 4 11 septembre 2014 PC & PC* 2014–2015 – Informatique pour tous TP – Marche aléatoire T = [1,3,5,4,7] np.mean(T) renverra la moyenne des valeurs de T c’est à dire 4. Vérifier le résultat théorique précédent. Écrire une fonction d_quad(X) qui calcule la distance quadratique moyenne. Q15. Dans le cours, nous avons vu la relation entre la distance quadratique moyenne et le coefficient de diffusion : ∆x2n = D × ∆t où ∆t est le temps écoulé. Ici, ça reviendrait à d quad2 = n. Tracer (d_quad)**2 en fonction de n pour le vérifier. Q16. On veut maintenant comparer la répartition des particules avec la gaussienne théorique attendue, de la forme : 2p − x2 N (x, n) = √ e 2n 2πn où N (x, n) est le nombre de particules en x au temps n. Le faire pour différentes valeurs de p et n. 3 Marche au hasard 1D avec biais On considère maintenant que la probabilité d’aller vers la gauche n’est pas la même que celle d’aller vers la droite (celle d’aller vers la droite sera notée a, avec 0 < a < 1). Q17. Écrire une fonction position_avec_biais(n,a) qui donne la position de la particule après n sauts. Pour les exemples, on prendra a = 0.60. Q18. Reprendre les fonctions précédentes pour tracer la répartition des particules à différents instants n et pour différents nombres p de particules, déterminer la distance moyenne et la distance quadratique moyenne (on pourra les tracer en fonction de n pour p assez grand). Que peut-on dire ? Réécrire l’équation de la gaussienne en tenant compte de cette remarque et la tracer sur le même graphe que la répartition. Vérifier avec une autre valeur de a. 4 Diffusion de particules sur un segment fermé On considère un segment formé de c cases, contenant des particules. Q19. Il s’agit tout d’abord de répartir les p particules sur les c cases avec une probabilité croissant linéairement (aucune particule en 0, le maximum en c). Créer une fonction S_initialisation(N) qui génère un ensemble de N particules réalisant cette répartition. Les conditions d’évolution des particules dans le segment sont les mêmes que précédemment (pas de biais) et sur bords on convient : • les particules des extrémités ont 1 chance sur 2 de rester où elles sont • 1 chance sur 2 de se déplacer. Q20. Écrire une fonction S_evolution(n) qui réalise n étapes. Q21. On peut maintenant réutiliser la fonction trace pour tracer les répartitions initiale et finale, ou l’adapter pour tracer les 2 d’un coup. Commenter les graphes obtenus. Lycée Louis Thuillier 5 11 septembre 2014