#!/usr/bin/env python # coding: utf-8 # # Ensembles de Mandelbrot et Julia # Nous allons découvrir dans cette activité un ensemble fascinant : l'ensemble de Mandelbrot. Cet ensemble est un ensemble *fractal* découvert à la fin des années 70. Il a la propriété d'offrir de superbes images quelque soit le niveau de zoom que l'on opère sur lui, et ce, à l'infini. # ![](http://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Mandelpart2.jpg/320px-Mandelpart2.jpg) # # Ce qui est encore plus étonnant, c'est que cette complexité infinie du graphisme est issue d'une formule mathématique des plus simples ! Pour construire cet ensemble extraordinaire, revenons sur les nombres complexes en introduisant la notion de ***module*** : # ## Module d'un nombre complexe # Soit $z\in \mathbb C$ un nombre complexe. On appelle ***module*** de $z$ le nombre **réel** défini par # # $$|z|=\sqrt{a^2+b^2}$$ # # Où $z=a+ib$ est l'écriture algébrique de $z$. # # Géométriquement, le module de $z$ n'est autre que la **distance d'un point** d'affixe $z$ **à l'origine**. # # # ### Remarque # Si $z\in\mathbb R$, $|z|$ coïncide avec la valeur absolue que vous conaissez. La valeur absolue peut aussi s'interpréter sur la droite des réels comme la distance d'un point d'abscisse $z\in\mathbb R$ à l'origine # ### Exemple # Calculer $|3-2i|$ puis vérifiez en validant la cellule ci-dessous. Vous remarquerez au passage que Python s'accomode très bien nativement des nombres complexes, à ceci près que le nombre imaginaire est noté $j$ comme en physique ... # # La fonction pour calculer les modules est ***abs()*** ce qui et cohérent car le module coïncide avec la valeur absolue sur les réels. # In[ ]: abs(3-2j) # # A la découverte de l'ensemble de Julia # Soit $c\in \mathbb C$ un nombre complexe. # # On considère pour un nombre $a\in\mathbb C$ donné la suite à valeurs complexes $(z_n)$ définie par # $$\left \{\begin{array}{rcl} # z_0 &=& a\\ # z_{n+1}&=&z_n^2+c # \end{array}\right.$$ # On s'intéresse à l'ensemble $\mathscr J_c$ des points du plan d'affixe $a$ pour lesquels la suite $(|z_n|)$ est bornée. # ## Compréhension du problème # On suppose dans cette section que c = −1 # # 1. Écrire pour $a=0$ la suite $(z_n)$. Calculer les 5 premiers termes de la suite $(z_n)$. # 2. Le point $O(0;0)$ semble-t-il appartenir à l'ensemble de Julia $\mathscr J_{-1}$ ? # 3. Écrire pour $a=i$ la suite $(z_n)$. Calculer les 5 premiers termes de la suite $(z_n)$. # 4. Le point $A(0;1)$ semble-t-il appartenir à l'ensemble de Julia $\mathscr J_{-1}$ ? # # Répondez dans cette cellule ... # ## Algorithme # On considère l'algorithme suivant : # # a et c sont des nombres complexes donnés # n prend la valeur 0 # z prend la valeur a # tant que |z|<2 et n<100 Faire # n prend la valeur ... # z prend la valeur ... # Fin Tantque # Si n=100 Alors retourner -1 # Sinon retourner n # # 1. Compléter l'algorithme # 2. Que renvoie cet algorithme si $a\in \mathscr J_c$ ? # 3. Expliquer la méthode utilisée pour détecter si la suite $|z_n|$ est bornée # Votre réponse ici ... # Programmer cet algorithme dans la fonction **Julia** ci-dessous # In[ ]: def Julia(a,c): n=... z=... while ... and ... : ... ... if ... : return ... else : return ... # Tester votre fonction avec les points $O$ et $A$ de la section précédente. # In[ ]: # Testez votre fonction ici print("Test du point O : ",Julia(...,...)) print("Test du point A : ",Julia(...,...)) # En utilisant votre fonction Julia, Testez si le point $B\left(\dfrac 1 2 ; \dfrac 1 2 \right)\in \mathscr J_{-0.47+0.15i}$ # In[ ]: # Testez votre fonction ici print("Test du point B : ",Julia(...,...)) # Tapez votre conclusion ici : # ## Assez de théorie !! # Les jolis dessins vont apparaître quand pour chaque point $A$ d'affixe $a$ on associera # - la couleur noire si $A \in \mathscr J_c$ # - une autre couleur dépendant du rang de sortie du disque si $A \notin \mathscr J_c$ # # C'est le rôle du programme suivant. Essayez d'en comprendre les grandes lignes grâce aux commentaires. Il n'y a rien à modifier. # In[ ]: get_ipython().run_line_magic('pylab', 'inline') ########## Le programme commence ici : ########## w,h=320,240 # On définit la résolution de l'image xMin,xMax=-2,2 # Paramétrage de l'échelle. yCentre=0 # A modifier si besoin pour zoomer sur des zones # On règle automatiquement l'échelle sur y yMin=yCentre-(xMax-xMin)*h/w/2 # On conserve le ration largeur/longueur yMax=yCentre+(xMax-xMin)*h/w/2 # en fonciton de la résolution pasX=(xMax-xMin)/w # pas sur x pasY=(yMax-yMin)/h # pas sur y c=-1 # paramètre de l'ensemble de Julia # On fabrique une grille de 320x240 contenant la sortie de notre fonction Julia grille=[] y=yMax # On commence par la ligne du haut for ligne in range(h): x=xMin # On se replace à gauche ligne_grille=[] for colonne in range(w): ## C'est ici que tout se joue !!! ## a=x+1j*y # On calcule l'affixe du point A(x+iy) ligne_grille.append(Julia(a,c)) # On ajoute le résultat de Julia dans la ligne x+=pasX y-=pasY grille.append(ligne_grille) # On ajoute notre ligne à la grille # Les commentaires intégrés à ce programme expliquent les grandes lignes des actions effectuées. Les manipulations sont assez simples mais ne vous seront pas familières si vous n'avez pas suivi la spécialité ISN. Les ISN, en revanche, reconnaîtront le même algorithme que celui utilisé pour créer la grille de démineur !! # # Nous avons donc un tableau de 320x240 entiers. Chaque entrée de ce tableau est un pixel d'une image. Appelons la fonction ***imshow*** pour visualiser l'image qui ressort. Tadaaaaa !!!! # In[ ]: plt.imshow(grille) # Whaou ! que c'est beau les maths ! # # La partie bleue centrale correspond aux valeurs -1 retournées par la fonction Julia. C'est donc l'ensemble $\mathscr J_c$. # # - plus on est proche de la frontière de cet ensemble, plus le rang d'échappement du disque sera grand car *la suite est presque bornée*. On aura donc des valeurs de retour de Julia élevées, se traduisant par des couleurs claires. # - plus on s'éloigne de l'ensemble de Julia, plus la divergence est rapide et donc la valeur de retour proche de 0. Cela se traduit par des couleurs plus sombres au fur à mesure qu'on s'éloigne. # Zoomons un peu ... # Vous choisirez # - x compris entre -1.08 et 1.05 # - y centré en 0.34 # In[ ]: # Copiez coller votre code ici : # ## Le lapin de Douady # Le lapin de douady dont il est fait référence dans les vidéos d'introduction au chapitre des complexes correspond à la valeur $c \approx -0.123 + 0.745 i$ # # Modifiez le programme ci-dessus pour afficher le lapin. Vous choisirez # - x compris entre -1.6 et 1.6 # - y centré en 0 # In[ ]: # Copiez coller votre code ici : # ## L'ensemble de Mandelbrot # On considère pour un nombre $a\in\mathbb C$ donné la suite à valeurs complexes $(z_n)$ définie par # # $$\left \{\begin{array}{rcl} # z_0 &=& a\\ # z_{n+1}&=&z_n^2+a # \end{array}\right.$$ # # On s'intéresse à l'ensemble $\mathscr M$ des points du plan d'affixe $a$ pour lesquels la suite $(|z_n|)$ est bornée. # # Dans la cellule ci-dessous, recopiez en la modifiant la fonction Julia afin qu'elle teste l'appartenance à l'ensemble de Mandelbrot # In[ ]: # Votre nouvelle fonciton ici # Tracez à présent cet ensemble avec les paramètres d'échelle suivants : # - x compris entre -2 et 0,5 # - y centré en 0 # In[ ]: # Copiez coller votre code ici : # ### Les éléphants # Vous voulez voir les éléphants du départ ? ils sont ici : # - x compris entre 0.30 et 0.32 # - y centré sur -0.03 # In[ ]: # Copiez coller votre code ici : # In[ ]: