Listen

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
Hakan78
User
Beiträge: 9
Registriert: Mittwoch 14. November 2007, 00:05

Hallo
ich hab ein wenig programmiert und habe einen Algorithmus der verschiedene Höhen von Stützpunkten einer Rutsche in einer Liste speichert.
Diese werden mehrmals mutiert und ich möchte gerne diese mutierten Listen in einer weiteren Liste speichern. Der Code ist folgender:

Code: Alles auswählen

def rekombination(xArray,yArray,pop,generationen):
        population = []
        xArrayTemp = xArray
        yArrayTemp = yArray
        for k in range(generationen):
            for j in range(pop):
                for i in range(len (yArrayTemp)-2):
                    yArrayTemp[i+1] = (yArray[random.randint(0,len(yArray)-1)]+yArray[random.randint(0,len(yArray)-1)])/2
                    if (mutationsbool == True):
                        yArrayTemp[i+1] = mutation(tau,yArrayTemp[i+1])
                if (k == 0):
                    print yArrayTemp
                population.append(yArrayTemp)
                population[j] = yArrayTemp
                if (k == 0):
                    print population[j]
                
            if (Kommaoperator == True):
                print 'hi'
                population.append(yArray)
                print yArray, 'dies ist ein yArray'
            for i in range(len(population)+1):
                if (k==0):
                    print population[i]
            fit = 100
            fittest = 0
            for j in range(len(population)):
                if (fitness(xArray,population[j])<fit):
                    fit = fitness(xArray,population[j])
                    fittest = j
                if (k==0):
                    print fitness(xArray,population[j])        
            yArray = population[fittest]
            #print fitness(xArray,yArray)
        return yArray
Das Problem ist folgendes, sobald die Schleife in welcher mutiert wird durchgelaufen ist, lasse ich mir das Ergebnis noch einmal ausgeben und muss mit erstaunen feststellen, das alle mutierten Listen gleich sind, obwohl in der Zwischenausgabe sie sich deutlich voneinander unterscheiden. Es scheint also nur eine Liste mit append angefügt zu werden ( also bei x facher Mutation 20 Referenzen oder wie man das nennt auf das gleiche Objekt ) so dass nach Ablauf des ganzen ich 20 mal die gleiche Liste habe. Sogar mein Ursprugnsarray yArray welches ich nach yArrayTemp kopiert habe ist auch überschrieben. Ich möchte x verschiedene Listen speichern und nicht immer das selbe. Hier meine print Ausgabe :
[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40]
4.51523640986

Hier sind die verschieden erzeugten Mutationen
[20, 5, 5, 14, 9, 11, 6, 4, 10, 5, 13, 4, 11, 5, 7, 5, 5, 13, 2, 16, 0]
[20, 12, 6, 16, 14, 4, 5, 9, 10, 10, 7, 13, 14, 9, 14, 8, 17, 14, 15, 19, 0]
[20, 12, 4, 19, 9, 12, 14, 10, 11, 12, 15, 13, 9, 11, 15, 5, 9, 11, 13, 8, 0]
[20, 13, 10, 9, 14, 16, 8, 16, 9, 12, 10, 12, 8, 7, 13, 11, 12, 11, 13, 11, 0]
[20, 13, 8, 10, 14, 11, 8, 8, 10, 11, 10, 8, 11, 12, 4, 11, 10, 14, 13, 14, 0]
[20, 15, 11, 14, 8, 12, 13, 10, 11, 12, 10, 11, 15, 16, 7, 14, 9, 11, 10, 8, 0]
[20, 8, 9, 13, 11, 10, 12, 9, 13, 10, 12, 9, 7, 9, 10, 8, 8, 7, 13, 1, 0]
[20, 13, 7, 8, 0, 7, 10, 9, 8, 8, 4, 8, 9, 1, 5, 12, 6, 10, 8, 7, 0]
[20, 4, 2, 6, 7, 7, 10, 8, 8, 7, 8, 6, 10, 12, 16, 5, 0, 7, 7, 5, 0]
[20, 5, 12, 12, 3, 7, 8, 3, 7, 8, 12, 7, 3, 4, 5, 10, 7, 6, 14, 12, 0]
[20, 13, 7, 3, 12, 8, 7, 14, 11, 6, 7, 7, 7, 20, 17, 12, 11, 15, 15, 17, 0]
[20, 13, 6, 7, 11, 7, 9, 8, 10, 13, 11, 9, 15, 11, 6, 13, 6, 8, 6, 9, 0]
[20, 5, 7, 17, 8, 18, 14, 14, 13, 3, 13, 13, 3, 7, 8, 11, 14, 6, 7, 18, 0]
[20, 12, 10, 8, 14, 5, 13, 9, 9, 12, 8, 7, 12, 9, 2, 12, 9, 10, 13, 18, 0]
[20, 20, 15, 14, 11, 10, 16, 13, 11, 12, 18, 7, 20, 8, 7, 14, 8, 8, 17, 19, 0]
[20, 19, 14, 8, 9, 20, 6, 12, 12, 15, 15, 16, 9, 14, 8, 15, 14, 16, 14, 9, 0]
[20, 11, 8, 19, 8, 17, 13, 10, 6, 9, 6, 13, 15, 14, 4, 8, 7, 11, 14, 9, 0]
[20, 11, 8, 10, 10, 13, 12, 8, 10, 13, 7, 9, 10, 11, 9, 9, 10, 11, 10, 8, 0]
[20, 16, 17, 3, 8, 10, 9, 5, 7, 11, 0, 13, 3, 17, 7, 17, 12, 9, 14, 12, 0]
[20, 9, 10, 14, 9, 8, 11, 12, 3, 8, 15, 13, 7, 12, 12, 8, 11, 9, 11, 14, 0]
[20, 11, 9, 10, 8, 13, 9, 8, 11, 9, 12, 10, 11, 9, 7, 12, 12, 11, 10, 13, 0]
[20, 12, 11, 10, 11, 7, 6, 8, 16, 13, 6, 9, 10, 12, 16, 6, 10, 14, 13, 7, 0]
[20, 10, 10, 9, 10, 12, 6, 10, 7, 9, 9, 11, 12, 14, 7, 11, 9, 12, 11, 10, 0]
[20, 7, 10, 10, 12, 10, 10, 11, 4, 9, 9, 11, 11, 12, 13, 12, 10, 15, 12, 10, 0]
[20, 8, 13, 5, 13, 6, 9, 12, 14, 5, 4, 8, 14, 5, 10, 4, 6, 16, 9, 17, 0]
[20, 13, 8, 14, 13, 18, 9, 9, 11, 10, 11, 13, 11, 12, 7, 13, 15, 10, 17, 9, 0]
[20, 15, 10, 18, 14, 9, 13, 11, 17, 10, 12, 10, 8, 12, 16, 12, 11, 17, 16, 6, 0]
[20, 4, 14, 14, 11, 19, 12, 15, 6, 9, 17, 15, 13, 16, 15, 9, 7, 17, 12, 11, 0]
[20, 16, 14, 9, 12, 8, 10, 17, 13, 12, 12, 14, 15, 18, 8, 15, 11, 9, 12, 16, 0]
[20, 10, 15, 15, 14, 7, 8, 11, 13, 13, 14, 9, 14, 17, 10, 14, 8, 7, 12, 9, 0]
[20, 14, 13, 15, 6, 17, 8, 14, 13, 18, 11, 9, 16, 15, 9, 14, 11, 16, 11, 16, 0]
[20, 18, 9, 13, 17, 13, 12, 10, 7, 8, 16, 10, 12, 12, 15, 16, 14, 14, 13, 10, 0]
[20, 11, 7, 15, 14, 12, 10, 9, 11, 16, 12, 11, 17, 11, 10, 10, 9, 11, 5, 9, 0]
[20, 11, 10, 12, 11, 5, 12, 6, 7, 12, 11, 12, 7, 10, 13, 11, 7, 9, 10, 5, 0]
[20, 16, 15, 11, 9, 7, 5, 7, 7, 16, 12, 8, 7, 7, 13, 13, 11, 10, 8, 13, 0]
[20, 3, 5, 10, 13, 10, 19, 8, 8, 7, 5, 11, 6, 9, 8, 6, 11, 8, 8, 6, 0]
[20, 9, 10, 7, 7, 10, 2, 5, 10, 6, 8, 10, 7, 11, 9, 5, 9, 10, 8, 3, 0]
[20, 7, 5, 0, 9, 7, 8, 4, 8, 6, 8, 9, 8, 8, 7, 9, 9, 8, 5, 4, 0]
[20, 7, 8, 7, 6, 8, 8, 14, 3, 8, 6, 7, 10, 12, 8, 16, 12, 9, 6, 9, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
hi
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0] dies ist ein yArray

Aber nur die letzte wird Ausgegeben und gespeichert:
for i in range(len(population)+1):
if (k==0):
print population
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
[20, 10, 5, 0, 5, 0, 6, 11, 4, 7, 10, 4, 12, 5, 7, 5, 5, 3, 8, 6, 0]
Was muss ich bitte ändern um mir tatsächlich jedesmal ein eigenes Listenobjekt zu erstellen?
Hakan78
User
Beiträge: 9
Registriert: Mittwoch 14. November 2007, 00:05

Und nochmal eben der gesamte Code zum ausprobieren :

Code: Alles auswählen

import random
import math

def rutsche(stuetzparam,komma,mut,tau,pop,gener):
    if ( mut == True ) :
        mutationsbool = True
    else:
        mutationsbool = False
    if ( stuetzparam > 0):
        stuetzpunkte = stuetzparam
    else:
        stuetzpunkte = 19
    #stuetzpunkte = 19
    if (komma == True):
        Kommaoperator = True
    else:
        Kommaoperator = False
    tau = tau
    pop = pop
    generationen = gener
    yArray = []
    xArray = []
    hoehe = 20
    breite = 40
    yArray.append(hoehe)
    xArray.append(0)
    for i in range(stuetzpunkte):
        aktuellehoehe = hoehe - hoehe/stuetzpunkte*(i+1)
        yArray.append(aktuellehoehe)
        aktuellebreite = 0 +  (breite/stuetzpunkte)*(i+1)
        xArray.append(aktuellebreite)
    xArray.append(breite)    
    yArray.append(0)
    print yArray
    print xArray

    
    def abstand(x1,x2,y1,y2):
        s = math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
        return s


    def beschleunigung(y1,y2,s):
        a = 9.81*(y1-y2)/s
        return a

    def zeit(v,a,s,y1,y2):
        if y2 == y1:
            t=s/v
        else:
            t=-(v/a)+((math.sqrt(v*v+2*a*s))/a)
        return t

    def geschwindigkeit(v,a,t):
        vneu = v +a*t
        return vneu

    def fitness(xArray,yArray):
        zeitinsec = 0
        v = 0.0
        for i in range(len(xArray)-1):
            s = abstand(xArray[i],xArray[i+1],yArray[i],yArray[i+1])
            #print s
            a = beschleunigung(yArray[i],yArray[i+1],s)
            #print a
            t = zeit(v,a,s,(yArray[i]),(yArray[i+1]))
            #print t
            v = geschwindigkeit(v,a,t)
            zeitinsec = zeitinsec + t
        return zeitinsec

    print fitness(xArray,yArray)
    
    def mutation(tau,y):
        y = y + random.randint(-tau,tau)
        if (y > 20):
            y =20
        return y
    
    def rekombination(xArray,yArray,pop,generationen):
        population = []
        xArrayTemp = xArray
        yArrayTemp = yArray
        for k in range(generationen):
            for j in range(pop):
                for i in range(len (yArrayTemp)-2):
                    yArrayTemp[i+1] = (yArray[random.randint(0,len(yArray)-1)]+yArray[random.randint(0,len(yArray)-1)])/2
                    if (mutationsbool == True):
                        yArrayTemp[i+1] = mutation(tau,yArrayTemp[i+1])
                population.append(yArrayTemp)
                population[j] = yArrayTemp
                if (k == 0):
                    print population[j]
                
            if (Kommaoperator == True):
                print 'hi'
                population.append(yArray)
                print yArray, 'dies ist ein yArray'
            for i in range(len(population)+1):
                if (k==0):
                    print population[i]
            fit = 100
            fittest = 0
            for j in range(len(population)):
                if (fitness(xArray,population[j])<fit):
                    fit = fitness(xArray,population[j])
                    fittest = j
                if (k==0):
                    print fitness(xArray,population[j])        
            yArray = population[fittest]
            #print fitness(xArray,yArray)
        return yArray
    

    yArray
            
         
            
        
        
        
    yArray = rekombination(xArray,yArray,pop,generationen)
    print yArray
    print fitness(xArray,yArray)


rutsche(19,True,True,2,40,40)
BlackJack

Wenn Du eine Kopie haben möchtest, musst Du auch eine anlegen. Zum Beispiel mit `neue_liste = list(alte_liste)`` erzeugt eine (flache) Kopie.
Hakan78
User
Beiträge: 9
Registriert: Mittwoch 14. November 2007, 00:05

So das klappt erstmal schonmal ein wenig, wenigstens stirbt mir mein yArray nicht mehr weg ( yArrayTemp = list(yArray) = :D ).
BlackJack

Also ich bekomme bei dem Programm eine Ausnahme:

Code: Alles auswählen

Traceback (most recent call last):
  File "forum.py", line 128, in <module>
    rutsche(19,True,True,2,40,40)
  File "forum.py", line 123, in rutsche
    yArray = rekombination(xArray,yArray,pop,generationen)
  File "forum.py", line 102, in rekombination
    print population[i]
IndexError: list index out of range
Was auch nicht weiter verwundert, wenn man sich die Schleife anschaut.

Zeile 88 ist deutlich länger als 80 Zeichen.

Die Funktion `rutsche()` ist zu lang und unübersichtlich. Ich kann jedenfalls keinen Grund erkennen warum da *alles* drinstecken muss und auch kein Muster wann Du Objekte als Argumente an die inneren Funktionen übergibst und wann einfach auf den umschliessenden Namensraum zugegriffen wird. Das ist sehr verwirrend. Wenn die Funktionen auf Modulebene liegen und Werte die Funktionen nur als Argumente betreten und Rückgabewerte verlassen, ist das Ganze übersichtlicher und man die Funktionen einzeln testen.

Am Anfang der Funktion passiert viel sinnloses. Die Klammern um die Bedingungen bei den ``if``-Abfragen sind überflüssig. Einen Wahrheitswert explizit auf Gleichheit mit `True` oder `False` zu vergleichen ist überflüssg, der Wert *ist* ja bereits `True` oder `False`. Und dann je nachdem ob ein Objekt `True` oder `False` ist explizit `True` oder `False` einem anderen Namen zuzuweisen ist auch *viel* zu kompliziert. Die ersten vier Zeilen der Funktion wären einfach nur ``mutationsbool = mut``. Beide Namen sind ungünstig gewählt. Bei Abkürzungen weiss man oft eine Woche später nicht mehr wofür sie mal standen und muss sich das mühsam wieder erarbeiten. Ein passender Name wäre hier `mutate` oder `mutieren`.

Den Sinn von diesem ganzen neubinden von den Argumentnamen verstehe ich nicht. ``tau = tau``!? Oder auch ``generationen = gener``? Da hätte man das Argument gleich `generationen` nennen können. Nur um Missverständnisse zu vermeiden: Da wird nichts kopiert. Ein und das selbe Objekt bekommt einfach nur noch einen anderen Namen.

Die `range()`-Funktion erzeugt eine Liste mit Zahlen. Wenn man diese Liste nicht wirklich benötigt, sondern einfach nur über die Zahlen iterieren möchte, ist die `xrange()`-Funktion speicherschonender.

In der Schleife ab Zeile 28 sind die beiden Namen `aktuellehoehe` und `aktuellebreite` nicht wirklich nötig. Man muss nicht jedes Zwischenergebnis an Namen binden. Besonders fällt das bei den kurzen Funktionen auf, die einfach nur aus einer kurzen Zuweisung an einen Namen, gefolgt einem ``return`` mit den Namen bestehen.

Wie Rebecca an anderer Stelle schon bemerkte, kann man zusammengehörige Werte auch in Tupeln in einer Liste speichern, anstatt zwei parallele Listen zu verwalten, was fehleranfälliger ist. So eine Liste könnte man zum Beispiel so erstellen:

Code: Alles auswählen

    x_delta = breite / stuetzpunkte
    y_delta = hoehe / stuetzpunkte
    positionen = [(0, hoehe)]
    positionen.extend((x_step * i, hoehe - y_step * i)
                      for i in xrange(1, stuetzpunkte + 1))
    positionen.append((breite, 0))
Damit das so funktioniert wie's wahrscheinlich gedacht ist, sollte man ``from __future__ import division`` als ersten Import in die Datei schreiben. Sonst ist die Division von zwei ganzen Zahlen wieder eine ganze Zahl.

Für `abstand()` kann man den ``**``-Operator für die Quadrierung verwenden.

In `rekombination()` sind dann wieder Zuweisungen die wahrscheinlich nicht das bewirken was Du Dir erhoffst. Der Name `xArrayTemp` wird zudem gar nicht benutzt. Die Funktion ist auch ein bisschen lang für meinen Geschmack.

In der Ausgabeschleife ab Zeile 100 sollte man das ``if`` vor die Schleife ziehen und direkt über die Elemente von `population` iterieren statt den Umweg über einen Index zu gehen.

Code: Alles auswählen

            if k == 0:
                for item in population:
                    print item
In der Schleife ab Zeile 105 kann man den Index `j` auch loswerden.

Das einsame `yArray` in Zeile 116 hat keinen Effekt.

Insgesamt sollte man nicht mit so vielen Indexen herumhantieren sondern lieber neue Listen mittels "list comprehensions" erstellen. Dann erübrigt sich das Problem mit den Kopien wahrscheinlich auch von selbst.
Antworten