In diesem Beitrag zu Matplotlib befassen wir uns mit dem Zeichnen von Quadratic Map Attraktoren. Es handelt sich dabei um eine Gruppe von seltsamen Attraktoren, die von Julien C. Sprott bekannt gemacht wurden (Link zur Webseite). Das Zeichnen dieser Attraktoren erfolgt mit Hilfe zweier Polynome der Ordnung 2. Grades.
Die Form dieser Attraktoren hängt stark von den jeweiligen Parametern ab. Aus diesem Grund werden wir mehrere Varianten mit unterschiedlichen Parametern zeichnen. Eine mögliche Variante ist nachfolgend abgebildet.
Zur Erstellung von Quadratic Map Attraktoren sind folgende Formeln notwendig.
Der Wert der nächsten Gliedes in der Folge ermittelt sich aus einem quadratischen Polynom. Dazu werden die Werte der aktuellen Position (xn und yn) benötigt. Zusätzlich sind Werte für 12 Konstanten (a1 – a12) erforderlich.
Um verschiedene Parametersätze praktisch testen zu können, hat Julien C. Sprott die Werte von -1,2 bis +1,3 im Abstand von 0,1 als Buchstaben des lateinischen Alphabets codiert. Jede Variante kann somit durch eine Kette von zwölf Buchstaben beschrieben werden. Die oben gezeigte Variante ist des Ergebnis der Zeichenkette „GIIETPIQRRUL„. Der erste Parameter (G = a1) hat laut Codierung den Wert -0,6, der zweite (I=a2) den Wert -0.4 usw. Verschiedene Beispiele und deren Zeichencode können unter diesem Link zu Wolfram Alpha gefunden werden.
Zur Umsetzung des Programms binden wir zuerst die notwendigen Module ein. Als Stil unserer Plots wählen wir 'seaborn'
.
1 2 3 4 5 6 |
# Module importieren import numpy as np import matplotlib.pyplot as plt # Stil 'seaborn' verwenden plt.style.use('seaborn') |
Im nächsten Schritt implementieren wir die Zeichencodierung von Sprott als Python Dictionary (coeff
). Dabei werden den Buchstaben A-Z die entsprechenden Werte zugewiesen. Zusätzlich definieren wir die Funktion get_coefficient()
, um für jede Variante die zugeordneten Zahlenwerte zu ermitteln zu können. Diese Funktion gibt in unserem Beispiel eine Liste mit jeweils zwölf Koeffizienten zurück.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Dictionary mit Koeffizienten coeff = {'A': -1.2, 'B': -1.1, 'C': -1.0, 'D': -0.9, 'E': -0.8, 'F': -0.7, 'G': -0.6, 'H': -0.5, 'I': -0.4, 'J': -0.3, 'K': -0.2, 'L': -0.1, 'M': 0.0, 'N': 0.1, 'O': 0.2, 'P': 0.3, 'Q': 0.4, 'R': 0.5, 'S': 0.6, 'T': 0.7, 'U': 0.8, 'V': 0.9, 'W': 1.0, 'X': 1.1, 'Y': 1.2, 'Z': 1.3} # Funktion zur Ermittlung der Koeffizienten aus Zeichenkette def get_coefficient(str, coeff): c = [] for value in str: c.append(coeff.get(value)) return c |
Wir benötigen eine Funktion, die die zuvor beschriebenen Formeln umsetzt. Dazu definieren wir qardratic_map()
. Als Parameter dienen die aktuellen und y Positionen sowie eine Liste (c
) mit den Koeffizienten. Die Funktion gibt die neu berechneten Werte für x und y zurück.
1 2 3 4 5 |
# Funktion zur Berechnung der Werte von x und y def qardratic_map(x, y, c): dx = c[0] + c[1]*x + c[2]*x*x + c[3]*x*y + c[4]*y + c[5]*y*y dy = c[6] + c[7]*x + c[8]*x*x + c[9]*x*y + c[10]*y + c[11]*y*y return dx, dy |
Als Nächstes legen wir eine Liste mit Zeichenketten (qmaps
) an, von denen bekannt ist, dass sie ansprechende Darstellungen von Quadratic Map Attraktoren erzeugen (Link zu diversen Beispielen). Wir definieren die Anzahl von Berechnungsschritten (numSteps
) und initialisieren die Arrays für die x und y Werte.
1 2 3 4 5 6 7 8 9 10 11 |
# Liste mit Koeffizienten als Buchstaben codiert qmaps = ['GIIETPIQRRUL', 'GLXOESFTTPSV', 'UWACXDQIGKHF', 'VBWNBDELYHUL', 'EYYMKTUMXUVC', 'ENWUQSLHYSAT', 'GOSXRBRCBSPM', 'IFVQJFOOLVDV', 'CVQKGHQTPHTE'] # Anzahl zu berechnender Punkte numSteps = 200000 # Arrays für Koordinaten initialisieren X = np.zeros(numSteps + 1) Y = np.zeros(numSteps + 1) |
Wir haben nun alle Voraussetzungen um in einer Schleife alle neun Varianten unseres Attraktors zu zeichnen und als PNG auszugeben.
Im ersten Schritt ermitteln wir die Parameter aus der Zeichenkette und speichern die Liste in c
ab. Dann initialisieren wir die Startwerte für die Arrays (X
und Y
). Mit Hilfe einer for Schleife berechnen wir die festgelegte Anzahl an Punkten. In jedem Schritt wird die Funktion qardratic_map()
aufgerufen und dabei werden die aktuellen x und y Werte sowie die Koeffizienten Liste übergeben. Die Punkte werden mit einem Streudiagramm (englisch: scatter plot) visualisiert. Wir beschriften das Diagramm und geben das Bild im PNG Format aus. Es ist wichtig, das aktuelle Diagramm mit plt.cla()
zu löschen. Es würde sonst zu einer Überlagerung der nachfolgenden Grafiken kommen. Da die Ausgabe der Bilder mehrere Sekunden in Anspruch nimmt, geben wir aus, welches Bild gerade bearbeitet wird und wie viele insgesamt erstellt werden.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# Alle Maps zeichnen und als PNG ausgeben for index, attractor in enumerate(qmaps): # aktuelle Koeffizienten ermitteln c = get_coefficient(attractor, coeff) # Startwerte initialisieren X[0], Y[0] = (0.1, 0.1) # x und y Koordinaten berechnen for i in range(numSteps): dx, dy = qardratic_map(X[i], Y[i], c) X[i + 1] = dx Y[i + 1] = dy # Streudiagramm zeichnen plt.scatter(X, Y, c='b', marker='.', s=0.1) # Diagramm beschriften plt.xlabel("X Achse") plt.ylabel("Y Achse") plt.title("Quadratic Map Attraktor\n" + attractor) # Plot als PNG ausgeben plt.savefig('Quadratic_Map_Attraktor_'+attractor + '.png') # Plot löschen plt.cla() # Statusanzeige print('Bild Nr. {} von {} erzeugt - {}'.format(index+1, len(qmaps), attractor)) |
Nach Ausführung von python3 matplotlib_quad_map_attraktor.py
erhalten wir folgende Ausgabe:
Bild Nr. 1 von 9 erzeugt - GIIETPIQRRUL
Bild Nr. 2 von 9 erzeugt - GLXOESFTTPSV
Bild Nr. 3 von 9 erzeugt - UWACXDQIGKHF
Bild Nr. 4 von 9 erzeugt - VBWNBDELYHUL
Bild Nr. 5 von 9 erzeugt - EYYMKTUMXUVC
Bild Nr. 6 von 9 erzeugt - ENWUQSLHYSAT
Bild Nr. 7 von 9 erzeugt - GOSXRBRCBSPM
Bild Nr. 8 von 9 erzeugt - IFVQJFOOLVDV
Bild Nr. 9 von 9 erzeugt - CVQKGHQTPHTE
Im Ordner, in dem sich das Skript befindet, liegen nun 9 Bilder im PNG Format, welche verschiedene Varianten von Quadratic Map Attraktoren zeigen.
Das erste Bild befindet sich am Beginn des Artikels. Die restlichen Bilder sind nachfolgend (nicht in der Reihenfolge der Erstellung) dargestellt.
Das komplette Beispiel herunterladen: matplotlib_quad_map_attraktor.zip
Hinterlasse jetzt einen Kommentar