Mandelbrot - Optimierung
Ich kenn mich wiederum nicht mit Mandelbrot-Mengen aus. Aber wie wärs wenn du den array an diesen Stellen einfach mit NaN (numpy.NAN) belegst? Das ganze lässt sich dann sogar mit NAN noch plotten und du weisst außerdem genau an welcher Stelle es nicht konvergierte.
Ich kenne mich mit numpy-arrays und matplotlib nicht aus ...
Dimensioniere dein array doch so, dass die Länge auch bei "ungünstigen" Startwerten ausreicht. Um die jeweils nächste Zelle zu befüllen, wirst du ja einen Zeiger mitführen, der am Ende auch die Gesamtlänge der tatsächlich zu plottenden Punkte angibt. Dann erzeugst du daraus per slicing ein entsprechend verkürztes array und übergibst dies zum Plotten.
Dimensioniere dein array doch so, dass die Länge auch bei "ungünstigen" Startwerten ausreicht. Um die jeweils nächste Zelle zu befüllen, wirst du ja einen Zeiger mitführen, der am Ende auch die Gesamtlänge der tatsächlich zu plottenden Punkte angibt. Dann erzeugst du daraus per slicing ein entsprechend verkürztes array und übergibst dies zum Plotten.
Ok, ich verzweifle inzwischen fast den ganzen Nachmittag / Abend, da ich das mit den Arrays überhaupt nicht gebacken kriege. Das Script hört auf zu laufen; ohne Fehlermeldung oder so. Sehr wahrscheinlich liegt's an mir. ^^ Wäre um jede Art von Hilfe dankbar.
MfG
Code: Alles auswählen
#!/usr/bin/python
# Filename: mandelbrot.py
from numpy import *
import matplotlib.pyplot as plt
import pylab
def mandelbrot(start, steps, stepx, stepy, iterations):
c = start
c0 = start
a = zeros((1,2))
for h in xrange(0,steps):
for k in xrange(0,steps): # do this for all points in the selected area
if abs(c) >= 2: # check divergence
start += stepx
else:
for i in xrange(0,iterations):
c = c * c + c0
if abs(c) >= 2: # check divergence of value
break
else:
b = array([round(c0.real,2),round(c0.imag,2)])
vstack((a,b))
start += stepx
c = start
c0 = start
start = start + stepy - complex(steps * stepx.real,0)
pylab.imshow(a)
pylab.show
mandelbrot(complex(-3,-3), 601, complex(0.01,0), complex(0,0.01), 100)
So geths schon mal wesentlich schneller als am Anfang:
Die Daten werden zwar jetzt erst in einer Python-Liste gespeichert, aber das ist, wenn vorher die Größe nicht bekannt ist vielleicht sogar die bessere Wahl.
Der wesentliche unterschied ist das du nicht für jeden Punkt ein matplotlib.lines.Line2D-Object erstellst sondern nur eine relativ kompaktes Python-complex-Objekt. Die Daten werden dann als Ganzes zum Plotten ühbergeben. Das geht wesentlich schneller als einzeln. Das ist wie wenn du in einer GUI-Library statt ein Bild zu laden jeden Punkt einzeln mit einer kurzen Linie zeichnest.
Das es noch wesentlich schneller geht zeigt das Beispiel was oben schon mal erwähnt wurde.
MFG HerrHagen
Code: Alles auswählen
import numpy
import matplotlib.pyplot as plt
def mandelbrot(steps, start, stepx, stepy, iterations):
c = start
c0 = start
res = []
for h in xrange(steps):
for k in xrange(steps): # do this for all points in the selected area
if abs(c) >= 2: # check divergence
start += stepx
else:
for i in xrange(iterations):
if abs(c * c + c0) >= 2: # check divergence of value
break
else:
c = c * c + c0
else:
res.append(c0)
start += stepx
c = start
c0 = start
start = start + stepy - complex(steps * stepx.real,0)
return res
if __name__ == "__main__":
res = mandelbrot(601, complex(-3,-3), complex(0.01,0), complex(0,0.01), 100)
res = numpy.array(res)
plt.plot(res.real, res.imag, "k,")
plt.xlabel(r'$re(z)$')
plt.ylabel(r'$i \cdot im(z)$')
plt.title('The Mandelbrot Set')
plt.axis([-3,2,-2,2])
plt.grid(True)
plt.show()
Der wesentliche unterschied ist das du nicht für jeden Punkt ein matplotlib.lines.Line2D-Object erstellst sondern nur eine relativ kompaktes Python-complex-Objekt. Die Daten werden dann als Ganzes zum Plotten ühbergeben. Das geht wesentlich schneller als einzeln. Das ist wie wenn du in einer GUI-Library statt ein Bild zu laden jeden Punkt einzeln mit einer kurzen Linie zeichnest.
Das es noch wesentlich schneller geht zeigt das Beispiel was oben schon mal erwähnt wurde.
MFG HerrHagen
Ok, danke vielmals. Wusste gar nicht, dass man bei Python komplexe Zahlen in Listen speichern kann. Gehe ich richtig davon aus, dass das if __name__ == "__main__": nicht essentiell ist, sondern nur existiert, damit die Funktion mandelbrot in anderen Files wiederverwendbar ist und nur bei Aufruf von mandelbrot.py geplottet wird?
Gibt es ansonsten nichts, was noch suboptimal ist und die Geschwindigkeit beeinflusst? Inzwischen braucht das Programm etwa 1-4 Sekunden; als ich noch jeden Punkt einzeln plottete, bedurfte es gerne mal 15-20 Sekunden. Und wie kann ich das vorgefertigte Interface von matplotlib verändern? Also einzelne Aktionen verändern oder rausnehmen?
MfG
//e: Noch eine Verständnisfrage: Warum muss ich die Liste in ein numpy.array transformieren? Habe die Zeile res = numpy.array(res) mal auskommentiert und bemerkt, dass es dann nichts mit den Angaben real und imag anfangen kann; d.h. eine Fehlermeldung ausgibt. Warum ist das so? Warum funktioniert das Script mit dem numpy.array, nicht aber mit den Python-Listen?
Gibt es ansonsten nichts, was noch suboptimal ist und die Geschwindigkeit beeinflusst? Inzwischen braucht das Programm etwa 1-4 Sekunden; als ich noch jeden Punkt einzeln plottete, bedurfte es gerne mal 15-20 Sekunden. Und wie kann ich das vorgefertigte Interface von matplotlib verändern? Also einzelne Aktionen verändern oder rausnehmen?
MfG
//e: Noch eine Verständnisfrage: Warum muss ich die Liste in ein numpy.array transformieren? Habe die Zeile res = numpy.array(res) mal auskommentiert und bemerkt, dass es dann nichts mit den Angaben real und imag anfangen kann; d.h. eine Fehlermeldung ausgibt. Warum ist das so? Warum funktioniert das Script mit dem numpy.array, nicht aber mit den Python-Listen?
@Huy: Die Funktion der ``if __name__``-Abfrage hast Du richtig erkannt, nur ihre Wichtigkeit für sauberen Code noch nicht. Also ich finde sie "essentiell", weil man das Modul dadurch ohne Nebeneffekte importieren kann. Um es zu testen, um Dokumentation generieren zu lassen und so weiter.
Zum Edit: Listen haben halt keine Attribute die `real` und `imag` heissen.
Zum Edit: Listen haben halt keine Attribute die `real` und `imag` heissen.
Aber ich speichere ja komplexe Zahlen, dh. in der Liste müsste c0 als complex(x,y) gespeichert sein, oder etwa nicht? BTW versuche ich gerade, das ganze farblich etwas ansprechender zu gestalten, also wie hier:
http://www.scipy.org/Tentative_NumPy_Tu ... et_Example
Nur habe ich keine Ahnung, wie ich das machen soll. plot() verlangt ja eine Eingabe in Form von plot(x1,y1,color1,x2,y2,color2...), wenn ich nun aber die einzelnen Farben in einer Liste colour speichere (da die RGB Werte von i abhängig sein sollen) und anschliessend schreibe plt.plot(res.real, res.imag, c=colour), kommen dutzende von Fehlermeldungen. Ausserdem - gibt es eine Möglichkeit, spät-divergierende Punkte (die zB i = 80 erreichen) in einer Liste zu speichern, ohne globale Variablen zu benutzen? Habe das nämlich mal mit globalen Variablen versucht zu machen, nur soll ja dann die Rechnerei länger dauern oder so.
MfG
http://www.scipy.org/Tentative_NumPy_Tu ... et_Example
Nur habe ich keine Ahnung, wie ich das machen soll. plot() verlangt ja eine Eingabe in Form von plot(x1,y1,color1,x2,y2,color2...), wenn ich nun aber die einzelnen Farben in einer Liste colour speichere (da die RGB Werte von i abhängig sein sollen) und anschliessend schreibe plt.plot(res.real, res.imag, c=colour), kommen dutzende von Fehlermeldungen. Ausserdem - gibt es eine Möglichkeit, spät-divergierende Punkte (die zB i = 80 erreichen) in einer Liste zu speichern, ohne globale Variablen zu benutzen? Habe das nämlich mal mit globalen Variablen versucht zu machen, nur soll ja dann die Rechnerei länger dauern oder so.
MfG
Ja, und? Es ist immer noch eine Liste, die ändert ihre Attribute ja nicht einfach.Huy hat geschrieben:Aber ich speichere ja komplexe Zahlen, dh. in der Liste müsste c0 als complex(x,y) gespeichert sein, oder etwa nicht?
Dann baue eben eine neue Liste auf, welche diese Form hat.Huy hat geschrieben:Nur habe ich keine Ahnung, wie ich das machen soll. plot() verlangt ja eine Eingabe in Form von plot(x1,y1,color1,x2,y2,color2...), wenn ich nun aber die einzelnen Farben in einer Liste colour speichere (da die RGB Werte von i abhängig sein sollen) und anschliessend schreibe plt.plot(res.real, res.imag, c=colour), kommen dutzende von Fehlermeldungen.
Indem du eine Liste im lokalen Namensraum erstellst.Huy hat geschrieben:Ausserdem - gibt es eine Möglichkeit, spät-divergierende Punkte (die zB i = 80 erreichen) in einer Liste zu speichern, ohne globale Variablen zu benutzen? Habe das nämlich mal mit globalen Variablen versucht zu machen, nur soll ja dann die Rechnerei länger dauern oder so.
Das Leben ist wie ein Tennisball.
TupelHuy hat geschrieben:Ehm, aber ich gebe doch bei mandelbrot() schon res aus. Da käme doch alles ziemlich durcheinander, wenn ich zusätzlich noch die Farben ausgebe, oder etwa nicht?
Das Leben ist wie ein Tennisball.
Hast du das Tutorial eigentlich jemals gelesen?Huy hat geschrieben:Sind Tupel nicht unveränderbar? Oo
MfG
Code: Alles auswählen
def spam():
res = [1, 2, 3]
eggs = 42
return res, eggs
a, b = spam()
print a
print b
Das Leben ist wie ein Tennisball.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Mehrere Werte gleichzeitig zurückgeben...Huy hat geschrieben:Ich habe zwar nach wie vor keine Ahnung, was ich mit Tupel soll,
... Zeile 5...Huy hat geschrieben:wo in deinem Code ein Tupel ist
... das aus den offiziellen Python-Docs.Huy hat geschrieben:und von welchem allerleuchtenden Tutorial du sprichst
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Ich dachte, es sei von einem Tupel in diesem Sinne die Rede:
http://de.wikibooks.org/wiki/Python-Pro ... ngen#Tupel
Wie dem auch sei, ich les' dann halt noch etwas mehr und versuche es selber noch ein bisschen. Danke für die Aufklärung.
MfG
//e: Jaaaa, ich bin dumm, kthx.
http://de.wikibooks.org/wiki/Python-Pro ... ngen#Tupel
Wie dem auch sei, ich les' dann halt noch etwas mehr und versuche es selber noch ein bisschen. Danke für die Aufklärung.
MfG
//e: Jaaaa, ich bin dumm, kthx.
Zuletzt geändert von Huy am Montag 26. April 2010, 16:45, insgesamt 1-mal geändert.
lol? Da stehts sogar gleich am Anfang
Um die Lesbarkeit zu erhöhen, sollten Tuple immer mit runden Klammern erzeugt werden. Dabei ist ein Spezialfall zu beachten: Um ein Tupel mit nur einem Eintrag zu erhalten, wird ein abschließendes Komma verwendet.Code: Alles auswählen
>>> 1, 2, 3 (1, 2, 3)
the more they change the more they stay the same