Psi 945 – 2015/2016 http://blog.psi945.fr DS 5 – 23/01/2016 Le sujet est composé d’un exercice (probabilités pour analyser un programme Python) et d’un problème (séries entières, intégration) complètement indépendants. 1 Probabilités Pour ce problème, on donne le programme Python suivant : 1 2 3 4 5 6 7 8 9 10 def injective(p, N): valeurs_prises = [False for _ in range(N)] images = [] for compteur in range(p): y = randint(0, N-1) while valeurs_prises[y]: y = randint(0, N-1) images.append(y) valeurs_prises[y] = True return images On rappelle que randint(a, b) renvoie un entier aléatoire de [[a, b]] (chacun avec la même probabilité). 1. Analyse du fonctionnement du programme : On suppose qu’on exécute injective(p, N), avec 2 6 p 6 N . (a) Lors du premier passage à la ligne 6 : – Quelles sont les valeurs des variables valeurs_prises, images, compteur, y ? – Que vaut valeur_prises[y] ? Est-ce que la ligne 7 est exécutée après ce premier passage à la ligne 6 ? (b) Lors du deuxième passage à la ligne 6, expliquer ce qui peut se passer, selon la valeur de y qui aura été affectée juste avant (au deuxième passage à la ligne 5). (c) On suppose qu’au deuxième passage dans la boucle 4 → 9 on passe à la ligne 8. Que vaut images avant et après l’exécution de cette ligne ? (d) On suppose que l’exécution conduit à la ligne 10. Que dire alors de la valeur retournée ? Donner un exemple possible si (p, N ) = (5, 10). 2. Analyse de la complexité du programme : L’exécution du programme étant soumise à l’aléa des randint, son temps d’exécution n’est pas constant. Pour évaluer la complexité temporelle, on peut s’intéresser au nombre d’appels à la fonction randint, qui peut être vu comme une variable aléatoire, qu’on notera X. On va par ailleurs noter, pour 0 6 c < p, Xc le nombre d’appels à la p−1 P fonction randint lorsque compteur vaut c. On a donc X = Xc . c=0 (a) Montrer que l’exécution de injective(p, N) peut ne pas terminer. La variable aléatoire X est donc seulement définie lorsque le programme termine. (b) Montrer qu’en cas de terminaison, on a X > p, et que pour p > 2, il n’existe pas de majorant a priori de X. 1 (c) Que vaut X0 ? (d) Lorsque compteur vaut 1, montrer qu’on passe une première fois à la ligne 7 avec probabilité N1 · Pour k > 1 fixé, quelle est la probabilité pour qu’on y passe au moins k fois ? Et exactement k fois ? Identifier précisément la loi de X1 . (e) Donner (avec une rapide justification) la loi de X2 , puis celle de Xc , pour 1 6 c < p. (f) Donner, pour 0 6 c < p, la valeur de E(Xc ) en fonction de c, p et N . Exprimer enfin E(X) en fonction de p et N (et simplifier l’expression obtenue). C’est l’espérance de X qu’on peut raisonnablement prendre comme « complexité moyenne » du programme. 3. Deux cas particuliers : (a) Lorsque N = 2p, montrer : E(X) ∼ Kp lorsque p tend vers +∞, avec K une constante qu’on précisera. (b) Lorsque N = p, que dire du résultat retourné par injective(p, N) ? Donner alors un équivalent simple de X lorsque p tend vers +∞. 4. Terminaison : On suppose qu’on exécute injective(p, N) avec 2 6 p 6 N . (a) Lorsque compteur vaut 0, montrer qu’on passe de façon certaine à la ligne 8. (b) Lorsque compteur vaut 1, montrer qu’avec probabilité 1 on passe à la ligne 8. (c) Montrer que si p > 4, alors avec probabilité 1, compteur passera à la valeur 3 lors de l’exécution du programme. (d) Conclure ! 5. Un petit malin explique « qu’on aurait pu s’en sortir sans le tableau de booléen, via un test de la forme while y in images: ce qui aurait eu le bon goût d’améliorer la lisibilité et la complexité de ce programme. » Commenter la remarque de cet impertinent ! 2 Intégration : extrait de CCP 2012 PC (maths 2) 2 3 4