Rechenzeit minimieren?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Sans
User
Beiträge: 19
Registriert: Dienstag 28. September 2010, 16:31

Guten Tag,

als kleine praktische Übung versuche ich aktuell Langtons Ameisen Fraktal mit Tkinter umzusetzen. Ich bin nun gerade dabei dazu ein Gitter zu erstellen. Dazu benutze ich ein Dict das zu jedem Feld dessen x Koordinate, Y Koordinate und seinen Zustand speichert. Wenn ich dieses Netz nun erzeuge dann funktioniert das alles solange ich mich im Rahmen von 10-20 x 10-20 Feldern bewege. Für das Fraktal werde ich allerdings mehr als 100x100 benötigen. Wenn ich versuche das mit meiner aktuellen Methode zu tun, dann rechnet er und rechnet und rechnet ... und stürzt ab.
Ich wende mich an euch in der Hoffnung dass jemandem eine Methode mit weniger Rechenlast einfällt - oder jemandem auffällt was die Rechenlast so exponentiell explodieren lässt.

Ich benötige KEINE Ratschläge zu meiner sonstigen bisherigen Umsetzung, so lieb diese auch gemeint sind ;)

Code: Alles auswählen

#THIS IS GOING TO BE A VISUALIZED ALGORITHM OF LANGTONS ANTS

import tkinter as tk

class Interface(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self,master)

        self.env = Environment(100,100,"black")
        
        self.grid()
        self.createNet(self.env.getX(), self.env.getY())


    def createNet(self, x, y):
        envGrid = self.env.getFields()
        for field in envGrid:
            newfield = tk.Label(self, bg=envGrid.get(field)[2], height=1, width=1)
            newfield.grid(row = envGrid.get(field)[0], column = envGrid.get(field)[1],padx=2,pady=2)
        

    
    
class Environment(object):
    def __init__(self, fields_x, fields_y, stand_cond):
        self.x = fields_x
        self.y = fields_y
        self.stand_cond = stand_cond

        self.fields = self.createFields()

    #GETS
    def getFields(self):
        return self.fields

    def getX(self):
        return self.x

    def getY(self):
        return self.y

    #METHODS
    def createFields(self):
        '''Creating Fields by following Pattern:
        {fieldname: [x_value, y_value, condition]'''
        if self.x > 100:
            self.x = 100
        if self.y > 100:
            self.y = 100

        self.fields = {}

        for curX in range(self.x):
            for curY in range(self.y):
                fieldname = str(curX)+"x|y"+str(curY)
                self.fields[fieldname] = [curX, curY, self.stand_cond]
        print (self.fields)
        return self.fields


app = Interface()
app.master.title("Langtons Ants")
app.mainloop()
Danke
Sans
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Was versprichst Du Dir vom Ansatz, einen "künstlichen" Schlüssel für das Dictionary zu erstellen? Wieso nimmst Du keine Listen von Listen - oder ein Array aus ``numpy``?

Generell ist es schwer dazu etwas zu sagen; kannst Du genauer eingrenzen, *wo* die Rechenzeit flöten geht? Geht es ohne Einbettung in die GUI flott?

- Getter und Setter sind in Python übrigens unnötig und daher verpönt. Wenn man Logik für den Zugriff braucht, kann man Properties benutzen.

- Deine Namensgebung weicht teilweise von PEP8 ab. Das solltest Du ändern (``curX`` sollte ``cur_x`` heißen z.B.).

- ``print`` ist (in Python 3.x) eine Funktion; daher solltest Du die Klammern *direkt* an das Ende des Namens schreiben ohne Leerzeichen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Sans
User
Beiträge: 19
Registriert: Dienstag 28. September 2010, 16:31

Der künstliche Schlüssel war was rein optisches für mich und du hast recht der ist wirklich überflüssig. Habe ihn mal entfernt und jetzt die Listen in Listen erstellt. Leider stoße ich noch immer auf das selbe Problem. Es entsteht schon vor der Umsetzung mit Tkinter. Also dieser Code reicht:

Code: Alles auswählen

class Environment(object):
    def __init__(self, fields_x, fields_y, stand_cond):
        self.x = fields_x
        self.y = fields_y
        self.stand_cond = stand_cond

        self.fields = self.createFields()

    #GETS
    def getFields(self):
        return self.fields

    def getX(self):
        return self.x

    def getY(self):
        return self.y

    #METHODS
    def createFields(self):
        '''Creating Fields by following Pattern:
        {[x_value, y_value, condition]'''
        if self.x > 100:
            self.x = 100
        if self.y > 100:
            self.y = 100

        self.fields = []

        for curX in range(self.x):
            for curY in range(self.y):
                fieldname = str(curX)+"x|y"+str(curY)
                self.fields.append([curX, curY, self.stand_cond])
        print (self.fields)
        return self.fields

env = Environment(100,100,"white")

- Getter und Setter sind in Python übrigens unnötig und daher verpönt. Wenn man Logik für den Zugriff braucht, kann man Properties benutzen.

- Deine Namensgebung weicht teilweise von PEP8 ab. Das solltest Du ändern (``curX`` sollte ``cur_x`` heißen z.B.).
Mjaa Getter und Setter habe ich vor meinem Studium auch nicht benutzt, die hat mir mein Dozent dann aber eingebläut. Selbiges gilt für die Schreibweise ;) Ich werd mir das wieder abgewöhnen sobald der mich nicht mehr bewertet ...


Danke schonmal, vllt. fällt dir ja beim anlick des kürzeren Codes was auf :D
BlackJack

@Sans: Das Problem kann ich nicht nachvollziehen. Der Code läuft bei mir in einem Sekundenbruchteil problemlos durch.

Ein bisschen komisch ist allenfalls das die `createFields()`-Methode `self.fields` an eine Liste bindet, die füllt, und am Ende zurück gibt, damit `self.fields` dann beim Aufrufer noch mal an die Liste gebunden wird an die das Attribut sowieso schon gebunden war. Das ist irgendwie ein bisschen wirr. Verursacht aber keine Probleme mit der Laufzeit.

Edit: Und die Laufzeit zum erstellen des nun nicht mehr verwendeten Schlüssels kann man sich sparen. ;-)
Sans
User
Beiträge: 19
Registriert: Dienstag 28. September 2010, 16:31

Hmm, ich sitze aktuell zwar nicht an meinem PC sondern an nem iMac, der sollte aber auch leistungsfähig sein ... seltsam. Mal sehen Was passiert wenn ich das probier sobald ich wieder daheim bin ;) Danke für die versuchte Reproduktion :D
BlackJack

Ich glaube der RaspberryPi ist der schwächste Rechner auf dem ich Python installiert habe:

Code: Alles auswählen

pi@raspberrypi ~ $ time python ants.py > /dev/null

real    0m0.728s
user    0m0.650s
sys     0m0.070s

pi@raspberrypi ~ $ cat /proc/cpuinfo 
Processor       : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS        : 697.95
Features        : swp half thumb fastmult vfp edsp java tls 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xb76
CPU revision    : 7

Hardware        : BCM2708
Revision        : 000e
An fehlender Rechenleistung kann es also eher nicht liegen. :-)
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sans: Du kannst Deinen Dozenten gerne auf die unzähligen Diskussionen über das Thema PEP8, bzw. getter/setter aufmerksam machen. Oder ihm sagen, dass er Python und nicht Java lehren soll. Du solltest Deine Liste mit einer List-Comprehension erstellen und die drei Werte in ein Tuple packen (Ehrlich: das ist eigentlich ein Fall für ein »numpy.array«).
Und Tk ist mit mehreren tausend Labels einfach überfordert. Du solltest Dir also eine andere Art der Darstellung ausdenken.
Sans
User
Beiträge: 19
Registriert: Dienstag 28. September 2010, 16:31

Ja ich hab noch bis das Semester zuende ist Python, dann kommt eh Java also was solls. Dann darf ich mit Python wieder machen was ich will :D

Das mit den Tupeln würde mir ja aber den Sinn meines Gitters verwehren, den Status zu ändern (white/black in meinem Fall), da Tutel ja immutable sind. numpy.array kenn ich nicht ... mal sehen ;)

@BlackJack: Es wird wohl an der MacVersion von Python liegen. Hatte ja schon Probleme sie auf dem neuen iOS zu installieren.
BlackJack

@Sans: Das wird sicher *nicht* an der Mac-Version liegen.
Antworten