Outils pour utilisateurs

Outils du site


tp:python:montecarlo

📓 Méthode de Monté Carlo

Méthode de Monte Carlo (Solution)

Il y a aussi un Notebook pour ce TP

Objectif

Les méthodes de Monté Carlo sont des méthodes probabilistes basées sur l'observation d'un grand nombre d'évènements.

Pour illustrer la méthode, nous allons construire une fonction permettant de calculer l'aire d'une surface du plan définie par une équation implicite. La méthode de Monté Carlo employée permettra de trouver une approximation de l'aire de la surface.

Les outils suivants vous seront peut être utiles :

Travail à rendre

Le détail des choses à rendre est disponible sur Updago.

1. Principe

Pour expliquer le principe, nous allons prendre comme exemple de surface un disque de rayon 1 (pour réfléchir au problème, il est utile de le faire avec un exemple pour lequel la réponse est vérifiable…). La surface de ce disque étant connue, et égale à $\pi$, la méthode nous permettra donc de calculer une approximation de $\pi$.

Fonctionnement général

En premier lieu, il faut chercher une zone simple (de préférence rectangulaire) d'aire $A$ connue, qui contient entièrement la surface à évaluer. Dans notre exemple, la zone rectangulaire sera : $-1\le x\le1$ et $-1\le y\le1$. Elle est délimitée par le carré dans lequel est inscrit notre disque de rayon 1.

Puis, on choisira $N$ points au hasard dans cette zone (c'est très facile pour une zone rectangulaire) et nous vérifierons combien sont dans la surface à évaluer. Cette opération de vérification doit être facile à faire. Ce sera effectivement le cas si la surface à calculer est définie par une équation implicite du type de $f(x,y)\leq a$ (dans l'exemple du disque : $f(x,y)=x^2+y^2 \leq 1$).

Admettons que sur les $N$ points choisis dans la zone rectangulaire, $n$ soient dans la surface définie par l'équation implicite.

L'aire cherchée vaudra approximativement : $\frac{n\timesA}{N}$

Plus $N$ sera grand, plus l'approximation sera précise.

Exemples

Essayons sur notre exemple :

Avec N=10 (10 point) :

Monte carlo avec 10 points

Nous trouvons 7 points sur 10 dans le disque. La surface du rectangle est 4. L'aire du disque est donc $4\times\frac{7}{10}=2.8$

Avec 30 points :

Monte carlo avec 30 points

Nous trouvons 24 points sur 30 dans le disque. La surface du rectangle est 4. L'aire du disque est donc $4\times\frac{24}{30}=3.2$

Avec 10000 points nous pourrions par exemple obtenir 7784 points dans le disque, ce qui nous donnerait une aire de : 3.1136

2. Programmation

Toutes les fonctions seront entrées dans un fichier, que vous nommerez login_montecarlo.py. Ce fichier devra contenir uniquement des importations de module et vos fonctions, mais pas de script (le module pourra être importé silencieusement). De même, vos fonctions doivent avoir le nom indiqué dans le sujet. Enfin, pensez à donner une docstring claire pour chaque fonction écrite

Équation implicite de la surface

Commencez par programmer l'équation implicite du disque. Pour cela, écrivez une fonction disque qui prend en paramètre x et y et renvoie 1 si le point (x,y) est dans le disque centré en 0 de rayon 1 et 0 sinon ((le choix des valeurs renvoyées simplifiera le comptage)) :

def  disque(x,y) :
    ''' Renvoie 1 si (x,y) est dans le disque
    centré en 0 de rayon 1 et renvoie 0 sinon.
    '''
    # Complétez ici...

Dans le shell, testez ensuite votre fonction sur quelques points pour vérifier qu'elle est correcte.

disque(0,0)
# => 1
disque(1.1,0) 
# => 0
disque(0.6,0.6) 
# => 1
disque(0.8,0.75) 
# => 0

Toute l'équipe vous remercie de bien vouloir indiquer les numéros des questions dans vos rapports, car cela facilite grandement le travail de correction. LOL

QUESTION 1 Indiquez dans le rapport les tests effectués pour vérifier le fonctionnement de la fonction disque. Comment savoir si les résultats donnés par la fonction sont corrects ?

Passage d'une fonction en paramètre

Avant d'aborder le calcul de l'aire, nous allons voir comment passer une fonction en paramètre d'une autre fonction. Voici un exemple (inutile de le mettre dans votre fichier, il s'agit juste d'un exemple pour vous aidez à comprendre. Si toutefois vous voulez l'essayer, faites le dans un autre fichier, que vous ne rendrez pas) :

def foisdeux(x) :
    return 2*x
 
def foistrois(x) :
    return 3*x
 
def evaluation(fonc,x) :
    return fonc(x)

Nous pouvons ensuite écrire :

evaluation(foisdeux,4) 
# => 8
evaluation(foistrois,4) 
# => 12

Le premier paramètre de evaluation est une fonction

Si le passage d'une fonction en paramètre n'est pas parfaitement compris avec cet exemple, n'hésitez pas demander plus d'explications à l'encadrant.

Calcul de l'aire

La fonction de calcul d'aire que nous allons écrire devra marcher pour n'importe quelle équation implicite, du moment que cette équation est écrite sous forme d'une fonction prenant en paramètres x et y et renvoyant 0 ou 1 (c'est le cas de la fonction disque).

La fonction de calcul d'aire, que nous appellerons calcul_aire, aura donc pour paramètres :

  • la fonction contenant l'équation implicite
  • le nombre de points à utiliser pour calculer l'aire
  • les bornes du rectangle englobant

Le rectangle englobant sera donné sous la forme d'une séquence (tuple ou liste) contenant : (xmin,xmax,ymin,ymax)

Nous pouvons à présent nous concentrer sur l'écriture de la fonction calcul_aire :

def calcul_aire(f,N,bornes) :
    ''' Calcule l'aire de la surface définie
        par l'équation implicite f(x,y), et incluse
        dans le rectangle défini par 'bornes'.
        Le calcul est réalisé en utilisant N points
    '''
    # Calculer l'aire du rectangle englobant => A
    # Initialiser le compteur de points nb à 0
    # Répéter N fois :
        # prendre un couple (x,y) au hasard dans les bornes
        # ajouter f(x,y) à nb (f(x,y) vaut 0 ou 1)
    # retourner nb/N*A    

Le module random contient, entre autres, les trois fonctions :

  • random() qui renvoie un float entre 0 et 1
  • randint(a,b) qui renvoie un entier entre a et b (bornes incluses)
  • uniform(a,b) qui renvoie un float compris entre a et b

QUESTION 2 Complétez la fonction calcul_aire, puis vérifiez son fonctionnement en calculant une approximation de $\pi$ : calcul_aire(disque,10000,(-1,1,-1,1)).

Indiquez dans le rapport tous les tests que vous avez effectué pour vérifier le bon fonctionnement de calcul_aire.

Vérification graphique

Avec le module Matplotlib, vous avez la possibilité de visualiser facilement à l'écran les points dans et hors surface. Vous pouvez pour ceci refaire une fonction, similaire à calcul_aire, mais qui tracera un graphique au lieu de calculer l'aire numériquement. Pour réaliser ce graphique, vous aurez besoin de comprendre le code suivant :

import matplotlib.pyplot as plt
x=(1,2,4,5)        # abcisses
y=(1.2,1.3,0.5,-1) # ordonnées
plt.plot(x,y,'.b') # Trace les points dans le style '.b'
plt.show()

Dans le paramètre à plot qui définit le style, «.» indique qu'on trace des points, et b donne la couleur (blue). La liste des styles est disponible ici : [[http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.plot]]

Vous pouvez afficher deux séries de points dans deux styles différents ainsi :

import matplotlib.pyplot as plt
xb,yb=(1,2,4,5) , (1.2,1.3,0.5,-1) 
xa,ya=(1.3,2.2,3.8,5.2) , (1.2,1.3,0.5,-1) 
plt.plot(xb,yb,'.b',xa,ya,'.r')
plt.show()

QUESTION 3 Écrivez une fonction nommée trace_aire, qui prend les même paramètres que calcul_aire, mais trace les points tirés à l'écran en plus de calculer une valeur approchée de l'aire. Vous tracerez en bleu les points qui tombent dans la surface et en rouge les points qui sont hors de la surface.

Vous devez, dans la boucle qui choisit aléatoirement les points, construire les listes des coordonnées des points à afficher en bleu et en rouge. Ce n'est qu'après la boucle que vous utilisez plt.plot en donnant les listes de points en paramètres

3. Utilisation du programme, améliorations

Quelques calculs d'aire

Vous pouvez maintenant utiliser votre fonction pour d'autres surface :

  1. ellipse centrée en 0, et de rayons 2 et 1 (la fonction implicite sera codée dans ellipse(x,y)). L'ellipse soit être dans le sens horizontal (plus étalée sur l'axe des abscisses que des ordonnées)
  2. cardioïde obtenue avec des cercles de rayon 2 (la fonction s'appellera cardioide(x,y), orientée dans ce sens :

Attention pour la cardioïde, il est facile de se tromper sur les valeurs du paramètre $a$. Vérifiez votre travail.

QUESTION 4 Donnez dans votre rapport les équations des différentes surfaces (ellipse et cardioïde), et la manière dont vous les avez obtenues

QUESTION 5 Quel rectangle englobant allez vous prendre pour chacune ?

QUESTION 6 Avec au moins 5000 tirages aléatoires, quelle aire obtenez-vous pour l'ellipse ? Vérifiez votre résultat.

QUESTION 7 Avec au moins 5000 tirages aléatoires, calculez l'aire obtenez-vous pour la cardioïde ? Vérifiez votre résultat.

QUESTION 8 Indiquez les valeurs des aires obtenues en faisant varier le nombre de points tirés et confrontez ces résultats avec les résultats obtenus analytiquement. Présentez vos résultats de manière synthétique et commentez.

4. Évaluation de l'aire d'un objet complexe

La fin de ce TP est un peu plus difficile… Il est conseillé, avant de faire la suite, de relire 8-O le travail déjà effectué et de le soigner tout particulièrement, quitte à ne pas avoir le temps de finir le TP.

En particulier, assurez-vous d'avoir bien numéroté les questions… Merci.

Calculez l'aire de l'ensemble de Mandelbrot, dans le rectangle $-2\le x\le 0.5$ et $-1.25\le y\le 1.25$ (fonction ''mandel(x,y)'').

Un point de coordonnées (x,y) appartient à l'ensemble de Mandelbrot si la suite définie par : $$\left\{\begin{array}{l}u_0=0\\u_n=u_{n-1}^2+(x+iy)\end{tabular}\right.$$ a un module qui reste fini.

Ce fait peut être testé de manière approximative ainsi : Nous dirons qu'un point de coordonnées $(x,y)$ est dans l'ensemble de Mandelbrot si les 100 premiers termes de la suite précédente ont tous un module strictement inférieur à 2.

 Image de l'ensemble de Mandelbrot (Wikimedia)

Vous pouvez utiliser des nombres complexes en Python. Des exemples sont donnés dans la documentation : [[stu:python:python_notes#nombres_complexes|Aide mémoire / Notes sur Python 3]].

Pour tester, vous pouvez essayer les points suivants qui sont dans l'ensemble de Mandelbrot :

x y
0.17746 -0.46674
-1.12786 0
-0.13640 0.74147

Et les points suivants qui n'y sont pas :

x y
-0.9752 -0.61951
0.57464 -0.47508
-0.49192 0.86368

Il vous faudra environ 50000 tirages pour avoir une aire assez précise.

QUESTION 9 Quelle aire trouvez-vous pour l'ensemble de Mandelbrot ?

QUESTION 10 Comment pouvez-vous vérifier ce résultat ?

QUESTION 11 Que pensez vous de la valeur que vous trouvez comparée aux valeurs standard ? Commentez.

tp/python/montecarlo.txt · Dernière modification: 2021/05/04 15:12 (modification externe)