TP 1 : Fractales en Python. Complexes / réels, Itératif

publicité
T.P. 1 : Fractales en Python.
Complexes / réels,
Itératif / Récursif.
Introduction
A la fin de ce T.P., si tout va bien, vous saurez obtenir des dessins de ce genre avec Python :
1.0
3.0
0.8
2.5
0.6
2.0
0.4
1.5
0.2
1.0
0.0
0.5
0.2
0.4
0.0
0.5
0.0
1.0
1.0
0.5
0.0
0.5
1.0
1.5
2.0
Mais qu’importe le trésor, flocon ou chou, l’essentiel est la quête. Les vrais buts de ce T.P. sont en
fait les suivants :
● Rafraı̂chir vos connaissance sur la gestion des tableaux numpy qui peuvent ensuite être
affichés via matplotlib.pyplot. Pour ceux et celles qui ont fait du SciLab, le gros module
pylab est un module python qui simplifie beaucoup l’utilisation de Python à la manière
de SciLab en incluant directement aussi bien les fonctions de numpy que de matplotlib.
● Comparer les points de vue : utilisation des transformations complexes ou des matrices 2 × 2
pour la gestion d’opérations géométriques dans le plan.
● Comparer les points de vue : algorithme itératif (boucles vues en premières années) et
algorithme récursif : notion qui n’était pas au programme d’I.P.T. en première année, et
que nous reprendrons en cours.
1
1.1
La courbe de Von Koch, en coordonnées complexes, et en
itératif
Construction mathématique de la courbe de Von Koch
L’idée de base de la construction d’une courbe de Von Koch, sur le dessin suivant à partir du
segment [A, B] ⊂ C avec A d’affixe 0 et B d’affixe 1, est de transformer ce segment en la ligne
brisée suivante où C est d’affixe 1/3, E d’affixe 2/3 et CDE est équilatéral :
1
Ensuite, on itère cette opération sur chacun des quatre segments de la figure précédente, ce qui
donne :
0.5
0.4
0.3
0.2
0.1
0.0
0.1
0.2
0.0
0.2
0.4
0.6
0.8
1.0
On peut alors recommencer autant de fois qu’on veut, par exemple après cinq itérations :
0.5
0.4
0.3
0.2
0.1
0.0
0.1
0.2
0.0
1.2
0.2
0.4
0.6
0.8
1.0
Rappels de Python avec pylab
Dans toute la suite, nous considérons que nous avons rentré la commande :
2
import pylab as pl
Le gros module pylab contient numpy, matplotlib (mais pas scipy).
Néanmoins, à cause de l’importance de numpy en lui-même et pour respecter les habitudes,
on importera aussi numpy via import numpy as np pour invoquer les fonctions numpy avec
le préfixe np.
1.2.1
Comment manipuler des nombres complexes en Python ?
Il y a au moins deux façons de rentrer un nombre complexe en Python :
>>>z=1+2j
>>>z=complex(1,2)
En pratique l’entrée sous forme a+bj n’est pas très commode (syntaxe pénible : coller la partie
imaginaire à j ...), et on recommande plutôt la commande complex.
Pour un nombre complexe z, avec z.real et z.imag on aura ce que vous pensez.
Remarque : Le help(complex) ne vous renseignera que si vous savez déjà des choses sur les
classes en Python... nous en reparlerons.
1.2.2
Comment afficher des points reliés par des segments ? plot, exemple :
Pour tracer des points reliés par des segments, on va utiliser la commande pl.plot, à laquelle
on doit donner à manger deux tableaux : l’un sera la liste des abscisses des points successifs, l’autre
celle des ordonnées des points successifs. Voici un :
Exemple très simple : tracé du segment [A, B] où A = (1, 2) et B = (3, 4).
X=[1,3]
Y=[2,4]
pl.plot(X,Y,color="blue") # color est un argument optionnel...
pl.show() # provoque l’affichage si vous ^
etes chanceux
pl.savefig(’Desktop/segment.pdf’) # enregistre dans un pdf. : marche mieux
Quelques fonctions graphiques utiles :
pl.axis(’equal’) # pour travailler en repère orthonormé
pl.clf() # pour effacer la figure courante.
1.2.3
Les tableaux qu’on peut donner à manger à plot
Outre les listes du Python de base, plot gère les array de numpy. Ces array sont gérés par
l’importation de pylab donc on peut taper :
X=pl.array([1,3])
Y=pl.array([2,4])
pl.plot(X,Y)
On peut aussi, si on a l’habitude d’importer numpy faire import numpy as np et déclarer des
np.array.
L’avantage des tableaux numpy, pl.array ou np.array comme on veut, vient des opérations
qu’on peut faire sur ces tableaux : on peut appliquer des fonctions mathématiques (fonctions
numpy) à un tableau numpy.
Un np.array peut être réduit à une ligne comme A=np.array([1,2]) Il peut être formé de plusieurs lignes comme M=np.array([[1,2],[3,4]]) On obtient un joli affichage avec print(A) et
print(M).
3
1.2.4
Tracé à partir d’un tableau de nombres complexes
On reprend l’exemple du 1.2.2 où cette fois on a stocké A et B dans un tableau contenant deux
complexes.
A=complex(1,2)
B=complex(3,4)
L=np.array([A,B])
Cette fois pour faire le même tracé, nous devons d’abord fabriquer des tableaux d’abscisses et
d’ordonnées et là, on voit la puissance de numpy.
X=np.real(L)
Y=np.imag(L)
pl.clf() # clf pour clearfigure
pl.plot(X,Y)
pl.savefig(’Desktop/segment2.pdf’)
1.3
1.3.1
A vous de jouer !
Fonction transformant un segment
Ecrire une fonction TSC (pour Transformation Segment Complexe), qui prend en argument
deux complexes A et B, et renvoie la liste formée des complexes A,C,D,E de la construction de la
courbe de Von Koch donnée au § 1.1.
Indications :
● Les coordonnées complexes de C, D, E sont relatives à celles de A et B.
● Une méthode simple, qui fait l’intérêt des nombres complexes, est de considérer que le segment
[C,D] s’obtient par rotation d’angle π/3 (utiliser np.pi), qui se code bien en complexes.
● On pourra vérifier le résultat en le plottant comme indiqué dans les paragraphes précédents.
1.3.2
Fonction donnant une transformation globale
Ecrire une fonction TGC (pour Transformation Globale Complexe) qui prend en argument une
liste L de nombres complexes et qui retourne une liste qu’on appellera LT dans la fonction, qui
est la liste obtenue à partir de L en intercalant entre deux nombres successifs A,B de la liste, les
nombres C,D,E de la construction de Von Koch.
1.3.3
Fonction d’affichage avec choix du nombre d’itérations
Ecrire une fonction VonKochIC (pour Von Koch par Itération en coordonnées Complexes) qui
prend comme argument obligatoire un entier n et comme argument facultatif une liste L de nombres
complexes, avec la valeur par défaut L=[0,1] et qui affiche la courbe de Von Koch obtenue en n
itérations à partir du segment L grâce à la fonction TGC précédente.
1.4
Passage de la courbe de Von Koch au triangle de Von Koch
En appliquant la fonction VonKochIC précédente aux trois côtés d’un triangle équilatéral, obtenir
le flocon de neige de l’introduction.
2
Le même travail avec des coordonnées réelles
2.1
Mémo : La multiplication matricielle avec numpy
En numpy, pour coder la matrice R de la rotation vectorielle d’angle α, on donne :
R=np.array([[np.cos(alpha),-np.sin(alpha)],[np.sin(alpha),np.cos(alpha)]])
4
Une façon de faire la multiplication matricielle M.N, si M et N sont des np.array de taille
compatible :
np.dot(M,N)
Attention : Ne pas faire M ∗ N .
Cette fois, les points A et B de départ seront codés par des matrices colonnes 2 × 1 autrement
dit, par exemple :
A=np.array([[0],[0]])
2.2
2.2.1
A vous de jouer :
Même départ
Ecrire une fonction TSR (pour Transformation Segment Réelle) faisant la même chose que TSC
mais en coordonnées réelles et de même une fonction TGR analogue à TGC.
2.2.2
Une petite gymnastique supplémentaire nécessaire pour l’affichage
Ecrire une fonction Affichage qui prend en argument une liste L=[A1,...,An] dont les
éléments Ai sont chacun des np.array représentant des vecteurs colonnes 2×1 et affiche (éventuellement
dans un fichier pdf) la ligne brisée [A1 , A2 ] ∪ ⋅ ⋅ ⋅ ∪ [An−1 , An ].
2.2.3
Même fin
Ecrire alors une fonction VonKochIR avec les mêmes spécifications que VonKochIC sauf que la
liste par défaut est une liste de points de R2 .
3
Le point de vue récursif sur Von Koch réel :
def KochRec(n,A=np.array([[0],[0]]),B=np.array([[1],[0]])):
alpha=np.pi/3
R=np.array([[np.cos(alpha),-np.sin(alpha)],
[np.sin(alpha),np.cos(alpha)]])
if n==0:
pl.plot([A[0],B[0]],[A[1],B[1]])
pl.axis(’equal’)
pl.savefig(’Desktop/essai-VonKoch.pdf’)
else :
Ecart=(B-A)/3
C=A+Ecart
E=B-Ecart
D=C+np.dot(R,Ecart)
KochRec(n-1,A,C)
KochRec(n-1,C,D)
KochRec(n-1,D,E)
KochRec(n-1,E,B)
Que fait ce code ? exécutez-le et appelez cette fonction avec de petites valeurs de n.
Que pensez vous du résultat ?
5
4
Le Brocoli en récursif
On se donne quatre points A,B,C,D qui sont les quatre sommets d’un carré. Ecrire une fonction
récursive appelée Brocoli qui prend ces quatre points en argument, et un argument n et qui
effectue les taches suivantes :
D’abord la fonction trace le carré A,B,C,D.
Ensuite si n > 0 la fonction définit les points E,F,G,I,H déduit de A,B,C,D pour former la figure
̂ vaut π/6 et appelle :
suivante (où A,B,C,D sont les sommets du gros carré) où l’angle α = CDE
brocoli(D,E,G,F,n-1)
brocoli(E,C,I,H,n-1)
Appelez cette fonction pour n = 6 et vous obtiendrez la seconde figure de l’introduction.
6
Téléchargement