Programm wird immer langsamer (graphics.py)

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
PatBass
User
Beiträge: 3
Registriert: Freitag 31. Juli 2020, 08:47

Hallo liebes Forum,
ich programmiere noch nicht sehr lang mit Python und bin eher unter Beginner einzuordnen.
Ich wollte gern meinen evolutionären Algorithmus oder besser dessen output grafisch anzeigen lassen und habe mich mit der Bibo graphics.py befasst. Diese über Pycharm installiert und ein kleinen Anzeigeprogramm geschrieben um zu testen wie es reagiert.

fall jemand die Bibo sucht ... einfach graphic py (ohne Punkt) suchen lassen!
hier ist die Doku dazu
https://mcsp.wartburg.edu/zelle/python/ ... /graphics/

Beim Programmstart funktioniert meines Erachtens alles gut, allerdings wird die anzeige sowie das Programm nach ca. 50 Schleifendurchgängen immer langsammer und langsamer. Woran kann das liegen?
Werden die Grafiken immer wieder oben drüber gezeichnet und die alten im Speicher belassen , so das irgendein speicher voll läuft?
Ich bin noch nicht so vertraut mit dem Debugger in PyCharm. Eigentlich bin ich mit einem Debugger und dessen Umgang gar nicht vertraut und würde dies gern ein wenig mehr lernen. Wie kann ich mir im Debugger den benutzten Speicher anzeigen lassen?
Kann sich bitte Jemensch mal den Code anschauen und mir sagen was ich da falsch mache und wie ich das Problem lösen kann?
Vielen Dank schon mal im Vorraus
In dem Code wird halt imme ein großes Viereck über die zuvor gezeichneten Parameter drüber gezeichnet da ich unter graphics.py keinen "Anzeigefush" gefunden habe. Wie umgeht man sowas ?




Hier jetzt der Code (ich denke es ist bad Coding):

Code: Alles auswählen

import numpy as np
import pandas as pd
from graphics import *
import random

desired_width = 320
pd.set_option('display.width', desired_width)
np.set_printoptions(linewidth=desired_width)

Zeile = 1
Anzahl_Parameter=20
WINDOWBREITE = 2000
WINDOWLÄNGE = 500
win = GraphWin("Strömungsröhre", WINDOWBREITE, WINDOWLÄNGE)
win.setBackground(color_rgb(0, 0, 0))
foods =[]
abstand=[]
X_Abstandsliste = np.array(np.empty([1, Anzahl_Parameter]))
i=0
population_groeße = (Zeile, Anzahl_Parameter)

while i <= 1000:
    aRectangle = Rectangle(Point(0, 0), Point(WINDOWBREITE, WINDOWLÄNGE))
    aRectangle.setFill(color_rgb(130, 0, 130))
    aRectangle.draw(win)
    win.setBackground(color_rgb(0, 0, 0))


    for jam in range(Anzahl_Parameter):

        foods = np.random.randint(low=0, high=(WINDOWLÄNGE/2), size=population_groeße)
        abstand = np.random.randint(low=0, high=400, size=population_groeße)
        X_Abstandsliste[0,jam] = jam *WINDOWBREITE/Anzahl_Parameter
        print(foods)
        print(abstand)
        print(X_Abstandsliste)

    for food_ind in range(Anzahl_Parameter):

        pt0 = Point((X_Abstandsliste[0][food_ind])+25,(foods[0][food_ind]))
        print("pt0")
        print(pt0)
        pt1 = Point((X_Abstandsliste[0][food_ind-1])+25,(foods[0][food_ind-1]))
        print("pt1")
        print(pt1)
        pt2 = Point((X_Abstandsliste[0][food_ind-1])+25,0)
        print("pt2")
        print(pt2)
        pt3 = Point((X_Abstandsliste[0][food_ind ]) + 25,0 )
        print("pt3")
        print(pt3)
        aLine = Line(pt0, pt1)
        aCircle = Circle(pt0, 10)
        aPolygon = Polygon(pt0, pt1, pt2,pt3)
        aCircle.setFill(color_rgb(255, 0, 0))
        aLine.setFill(color_rgb(255, 0, 0))
        aPolygon.setFill(color_rgb(0, 0, 255))
        aCircle.draw(win)
        if food_ind >0:
            aLine.draw((win))
            aPolygon.draw(win)

    i+=1
    print(i)
    update(1000)
win.getMouse()


Vielen Dank und viele Grüße ins Forum
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Je länger das Programm läuft, desto mehr Polygone und Kreise zeichnest Du, die müssen ja bei jedem Update alle wieder von neuem gezeichnet werden, auch wenn die alle dann von einem großen Rechteck verdeckt werden.
Die Graphikobjekte scheinen eine undraw-Methode zu haben. Du mußt Dir also alle Objekte merken und nach dem Update die undraw-Methode aufrufen.
Was sollen eigentliche die a-Präfixe bei aCircle oder aPolygon?
Variablennamen werden komplett klein geschrieben, Konstanten dagegen komplett gross.
Wenn Zeile immer 1 ist, warum benutzt Du dann überhaupt zweidimensionale Matrizen, statt einfacher Vektoren?
pandas und random werden importiert, aber gar nicht benutzt.
Die Zuweisungen zu foods und abstand an leere Listen werden gar nicht benutzt und können weg. np.empty liefert bereits an np.array, das nochmal aufzurufen ist Quatsch.
Statt der while-Schleife benutze eine for-Schleife.
foods und abstand werden in der ersten for-Schleife ständig initialisiert aber nie benutzt, das gehört also außerhalb der Schleife hin.
Was dann noch in der Schleife steht, macht man besser per np.linspace.
Über einen Index iteriert man nicht, sondern über die Elemente in X_Abstandsliste und foods per zip gemeinsam.

Code: Alles auswählen

import numpy as np
from graphics import *

PARAMETER_ANZAHL = 20
WINDOWBREITE = 2000
WINDOWLÄNGE = 500

win = GraphWin("Strömungsröhre", WINDOWBREITE, WINDOWLÄNGE)
win.setBackground(color_rgb(0, 0, 0))
rectangle = Rectangle(Point(0, 0), Point(WINDOWBREITE, WINDOWLÄNGE))
rectangle.setFill(color_rgb(130, 0, 130))
rectangle.draw(win)
win.setBackground(color_rgb(0, 0, 0))

x_abstaende = np.linspace(0, WINDOWBREITE, PARAMETER_ANZAHL)
for i in range(1000):
    foods = np.random.randint(low=0, high=WINDOWLÄNGE / 2, size=PARAMETER_ANZAHL)
    previous_food = previous_x = None
    graphics_objects = []
    for x, food in zip(x_abstaende, food):
        pt0 = Point((x + 25, food))
        circle = Circle(pt0, 10)
        circle.setFill(color_rgb(255, 0, 0))
        circle.draw(win)
        graphics_objects.append(circle)
        if previous_x is not None:
            pt1 = Point((previous_x + 25, previous_food))
            pt2 = Point((previous_x + 25, 0))
            pt3 = Point((x + 25, 0))
            line = Line(pt0, pt1)
            line.setFill(color_rgb(255, 0, 0))
            line.draw(win)
            graphics_objects.append(line)
            polygon = Polygon(pt0, pt1, pt2, pt3)
            polygon.setFill(color_rgb(0, 0, 255))
            polygon.draw(win)
            graphics_objects.append(polygon)
        previous_x = x
        previous_food = food
    print(i)
    update(1000)
    for g in graphics_objects:
        g.undraw()
win.getMouse()
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Statt ein Polygon aus vielen kleinen Stücken zusammenzusetzen, wäre es besser, alles an einem Stück zu zeichnen:

Code: Alles auswählen

import numpy as np
from graphics import *

PARAMETER_ANZAHL = 20
WINDOWBREITE = 2000
WINDOWLÄNGE = 500

win = GraphWin("Strömungsröhre", WINDOWBREITE, WINDOWLÄNGE)
win.setBackground(color_rgb(0, 0, 0))
rectangle = Rectangle(Point(0, 0), Point(WINDOWBREITE, WINDOWLÄNGE))
rectangle.setFill(color_rgb(130, 0, 130))
rectangle.draw(win)
win.setBackground(color_rgb(0, 0, 0))

x_abstaende = np.linspace(0, WINDOWBREITE, PARAMETER_ANZAHL)
for i in range(1000):
    foods = np.random.randint(low=0, high=WINDOWLÄNGE / 2, size=PARAMETER_ANZAHL)
    points = [Point(x + 25, food) for x, food in zip(x_abstaende, foods)]
    polygon = Polygon([Point(x_abstaende[0] + 25, 0)] + points + [Point(x_abstaende[-1]  + 25, 0)])
    polygon.setFill(color_rgb(0, 0, 255))
    polygon.setOutline("")
    line = Polygon([Point(x_abstaende[0] + 25, 0)] + points + [Point(x_abstaende[-1]  + 25, 0)])
    line.setOutline(color_rgb(255, 0, 0))
    line.setFill("")
    graphics_objects = [polygon, line]
    for point in points:
        circle = Circle(point, 10)
        circle.setFill(color_rgb(255, 0, 0))
        graphics_objects.append(circle)
    print(i)
    for g in graphics_objects:
        g.draw(win)
    update(1000)
    for g in graphics_objects:
        g.undraw()
win.getMouse()
noch etwas schöner:

Code: Alles auswählen

import numpy as np
from graphics import *

PARAMETER_ANZAHL = 20
WINDOWBREITE = 2000
WINDOWLÄNGE = 500


class PolyLine(Polygon):
    def __init__(self, *points):
        Polygon.__init__(self, *points)
        self.config = {
            "arrow": DEFAULT_CONFIG["arrow"],
            "width": DEFAULT_CONFIG["width"],
            "fill": DEFAULT_CONFIG["outline"],
        }
        self.setOutline = self.setFill

    def __repr__(self):
        return "PolyLine%s" % (tuple(p for p in self.points),)

    def _draw(self, canvas, options):
        args = []
        for p in self.points:
            x,y = canvas.toScreen(p.x,p.y)
            args.append(x)
            args.append(y)
        return canvas.create_line(*args, **options)
        
    def setArrow(self, option):
        if not option in ["first","last","both","none"]:
            raise GraphicsError(BAD_OPTION)
        self._reconfig("arrow", option)


win = GraphWin("Strömungsröhre", WINDOWBREITE, WINDOWLÄNGE)
win.setBackground(color_rgb(0, 0, 0))
rectangle = Rectangle(Point(0, 0), Point(WINDOWBREITE, WINDOWLÄNGE))
rectangle.setFill(color_rgb(130, 0, 130))
rectangle.draw(win)
win.setBackground(color_rgb(0, 0, 0))

x_abstaende = np.linspace(0, WINDOWBREITE-50, PARAMETER_ANZAHL)
for i in range(1000):
    foods = np.random.randint(low=0, high=WINDOWLÄNGE / 2, size=PARAMETER_ANZAHL)
    points = [Point(x + 25, food) for x, food in zip(x_abstaende, foods)]
    polygon = Polygon([Point(x_abstaende[0] + 25, 0)] + points + [Point(x_abstaende[-1]  + 25, 0)])
    polygon.setFill(color_rgb(0, 0, 255))
    polygon.setOutline("")
    line = PolyLine(points)
    line.setOutline(color_rgb(255, 0, 0))
    graphics_objects = [polygon, line]
    for point in points:
        circle = Circle(point, 10)
        circle.setFill(color_rgb(255, 0, 0))
        graphics_objects.append(circle)
    print(i)
    for g in graphics_objects:
        g.draw(win)
    update(1000)
    for g in graphics_objects:
        g.undraw()
win.getMouse()
PatBass
User
Beiträge: 3
Registriert: Freitag 31. Juli 2020, 08:47

Wow danke ,
das schnurrt ja wie ein Kätzchen durch.
Vielen Dank für die Programmierhinweise. Sowas hab ich gebraucht um das ganze besser verstehe n zu lernen.
Danke nochmal für die ausführliche und schnelle Antwort.
Viele Grüße
Patrick
Antworten