Seite 2 von 3
Verfasst: Sonntag 25. April 2010, 12:53
von HerrHagen
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.
Verfasst: Sonntag 25. April 2010, 14:04
von numerix
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.
Verfasst: Sonntag 25. April 2010, 22:01
von Huy
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.
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)
MfG
Verfasst: Montag 26. April 2010, 07:32
von HerrHagen
So geths schon mal wesentlich schneller als am Anfang:
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()
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
Verfasst: Montag 26. April 2010, 09:33
von Huy
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?
Verfasst: Montag 26. April 2010, 15:30
von BlackJack
@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.
Verfasst: Montag 26. April 2010, 15:46
von Huy
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
Verfasst: Montag 26. April 2010, 15:54
von EyDu
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?
Ja, und? Es ist immer noch eine Liste, die ändert ihre Attribute ja nicht einfach.
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.
Dann baue eben eine neue Liste auf, welche diese Form hat.
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.
Indem du eine Liste im lokalen Namensraum erstellst.
Verfasst: Montag 26. April 2010, 15:58
von Huy
Indem du eine Liste im lokalen Namensraum erstellst.
Und wie soll ich ausserhalb der Funktion dann auf diese Liste zugreifen?
MfG
Verfasst: Montag 26. April 2010, 16:00
von EyDu
Huy hat geschrieben:Und wie soll ich ausserhalb der Funktion dann auf diese Liste zugreifen?
Rückgabewerte
Verfasst: Montag 26. April 2010, 16:03
von Huy
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?
MfG
Verfasst: Montag 26. April 2010, 16:04
von EyDu
Huy 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?
Tupel

Verfasst: Montag 26. April 2010, 16:06
von Huy
Sind Tupel nicht unveränderbar? Oo
MfG
Verfasst: Montag 26. April 2010, 16:08
von EyDu
Huy hat geschrieben:Sind Tupel nicht unveränderbar? Oo
MfG
Hast du das Tutorial eigentlich jemals gelesen?
Code: Alles auswählen
def spam():
res = [1, 2, 3]
eggs = 42
return res, eggs
a, b = spam()
print a
print b
Verfasst: Montag 26. April 2010, 16:10
von Huy
Wo ist in deinem Code bitteschön ein Tupel?
MfG
Verfasst: Montag 26. April 2010, 16:11
von EyDu
Huy hat geschrieben:Wo ist in deinem Code bitteschön ein Tupel?
Und das steht im Tutorial

Verfasst: Montag 26. April 2010, 16:13
von Huy
Ich habe zwar nach wie vor keine Ahnung, was ich mit Tupel soll, wo in deinem Code ein Tupel ist und von welchem allerleuchtenden Tutorial du sprichst, aber ich probier' halt dann mal selber weiter...
MfG
Verfasst: Montag 26. April 2010, 16:37
von Leonidas
Huy hat geschrieben:Ich habe zwar nach wie vor keine Ahnung, was ich mit Tupel soll,
Mehrere Werte gleichzeitig zurückgeben...
Huy hat geschrieben:wo in deinem Code ein Tupel ist
... Zeile 5...
Huy hat geschrieben:und von welchem allerleuchtenden Tutorial du sprichst
... das aus den
offiziellen Python-Docs.
Verfasst: Montag 26. April 2010, 16:40
von Huy
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.
Verfasst: Montag 26. April 2010, 16:43
von Dav1d
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.