Hier werden die Unterschiede zwischen zwei Versionen gezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung | |||
ss19:finaler_code [2019/08/20 22:59] leanderh |
ss19:finaler_code [2019/08/20 23:57] (aktuell) leanderh |
||
---|---|---|---|
Zeile 729: | Zeile 729: | ||
self.alive = False | self.alive = False | ||
</code> | </code> | ||
+ | Kreaturen mit Polynomen haben nun noch die Klasse Polynom. Jedes Polynom hat einige Eigenschaften. | ||
+ | <code> | ||
+ | length=0 #Startlänge des Polynoms | ||
+ | poly=[] #Das Polynom an sich | ||
+ | min_potenz=0 #minimale Startpotenz | ||
+ | max_potenz=0 #maximale Startpotenz | ||
+ | min_koeffizient=0 #min Startkoeffizient | ||
+ | max_koeffizient=0 #max Startkoeffizient | ||
+ | min_output=0 #min Ausgabe | ||
+ | max_output=0 #max Ausgabe | ||
+ | </code> | ||
+ | Darüber hinaus hat jedes Polynom noch eine Liste (poly), in welchem das Polynom an sich gespeichert ist. Wird ein Polynom Initialisiert, so wird es auch direkt erstellt. Dafür werden der Länge des Polynoms entsprechend viele Monome bzw. Listen erstellt. In diesen ist dann jeweils der Koeffizient (a), die Potenz(b) und die Art des Inputs in das Monom (c) gespeichert. Letzteres könnte eine Zahl oder eine Liste sein. Liegt eine Liste vor, so nennen wir das ein Erinnerungspolynom, weil hier die Erinnerung der Kreatur eingesetzt wird. In diesem Fall wird für dieses Erinnerungspolynom als eigenes Polynom in dem Polynom erstellt. Dieses bezeichnen wir auch als Deep Poly und markieren das entsprechend durch die Variable deep_poly. Dadurch wird gekennzeichnet, dass in diesem Polynom keine weiteren Polynome stecken. | ||
+ | <code> | ||
+ | def __init__(self,l,minp,maxp,mink,maxk,mino,maxo,dif_monos,memory_length,deep_poly=False): | ||
+ | self.length=l | ||
+ | self.min_potenz=minp | ||
+ | self.max_potenz=maxp | ||
+ | self.min_koeffizient=mink | ||
+ | self.max_koeffizient=maxk | ||
+ | self.min_output=mino | ||
+ | self.max_output=maxo | ||
+ | self.poly=[] | ||
+ | self.deep_poly=deep_poly #ist das Polynom ein tiefes Polynom, also ein Polynom zur einbindung der Erinnerung | ||
+ | n=0 | ||
+ | while n<self.length: #erstellen des Polynoms | ||
+ | a=random.choice(range(self.min_koeffizient,self.max_koeffizient+1)) | ||
+ | b=random.choice(range(self.min_potenz,self.max_potenz+1)) | ||
+ | c=random.choice(dif_monos) #c legt die Art des Inputs fest mit hier mr=Erinnerung der Schrittweite, ma=Erinnerung der Winkeländerung und mf=Erinnerung der Futterabdeckung | ||
+ | if self.deep_poly==False and c=="m": #Für Erinnerungspolynome | ||
+ | new_poly=polynom(memory_length,0,10,0,10,0,1,["mf","mr","ma"],0,True) #Erinnerungspolynom wird erstellt | ||
+ | self.poly.append([a,b,c,new_poly]) | ||
+ | else: | ||
+ | self.poly.append([a,b,c,[]]) | ||
+ | n+=1 | ||
+ | </code> | ||
+ | Jedes Polynom hat die Möglichkeit, sich zu verändern, dies geschieht durch die Funktion change_poly(). Diese wird immer dann genutzt, wenn eine neue Generation gebildet wird. Hierbei wird zunächst evtl. die Länge des Polynoms geändert. Ist dies der Fall wird, wenn nötig, eine entsprechende Anzahl an Monomen hinzugefügt und das Polynom neu gemischt. | ||
+ | <code> | ||
+ | def change_poly(self,memory_length): #Änderung, also Mutation des Polynoms | ||
+ | n=0 | ||
+ | self.A=[] | ||
+ | if self.length<2: | ||
+ | self.length=random.choice(range(0,2))+self.length | ||
+ | else: | ||
+ | self.length=random.choice(range(-1,2))+self.length | ||
+ | while self.length>len(self.poly): | ||
+ | a=random.choice(range(self.min_koeffizient,self.max_koeffizient+1)) | ||
+ | b=random.choice(range(self.min_potenz,self.max_potenz+1)) | ||
+ | c=random.choice(dif_monos_list) #c legt die Art des Inputs fest mit hier mr=Erinnerung der Schrittweite, ma=Erinnerung der Winkeländerung und mf=Erinnerung der Futterabdeckung | ||
+ | if self.deep_poly==False and c==1: #Für Erinnerungspolynome | ||
+ | new_poly=polynom(memory_length,0,10,0,10,0,1,3,0,True) #Erinnerungspolynom wird erstellt | ||
+ | self.poly.append([a,b,c,new_poly]) | ||
+ | else: | ||
+ | self.poly.append([a,b,c,[]]) | ||
+ | random.shuffle(self.poly) | ||
+ | </code> | ||
+ | Danach wird so lange ein Monom aus der Liste genommen und vom Koeffizienten und der Potenz her leicht verändert und dem neuen Polynom hinzugefügt, bis die angestrebte Länge des Polynoms erreicht ist. dieses neue Polynom wird dann zu Stammpolynom. | ||
+ | <code> | ||
+ | while n<self.length: | ||
+ | mutation=random.choice(range(0,MUTATIONSWAHRSCHEINLICHKEIT_VERHALTEN)) | ||
+ | if mutation==0: | ||
+ | a=random.choice(range(-5,6)) | ||
+ | b=random.choice(range(-9,10)) | ||
+ | aneu=(self.poly[n][0])+0.01*a | ||
+ | bneu=(self.poly[n][1])+0.01*b | ||
+ | self.A.append([aneu,bneu,self.poly[n][2],self.poly[n][3]]) | ||
+ | else: | ||
+ | self.A.append(self.poly[n]) | ||
+ | n+=1 | ||
+ | self.poly=self.A | ||
+ | </code> | ||
+ | Zum Schluss gibt es noch zwei Reaktionsfunktionen, eine für Polynome mit möglichen Unterpolynomen (reaction()) und eine für Polynome definitiv ohne Unterpolynome (Deep_reactio()). \\ | ||
+ | Für reaction() werden die Eingaben Sichtfeld(s) und die Liste der Erinnerungen (Memory) benötigt. Es wird die Liste der Monome durchgegangen. Je nach Wert von c wird entweder s eingesetzt oder es wird eine Deep_reaction() mit der Liste der Erinnerungen ausgelöst. | ||
+ | <code> | ||
+ | def reaction(self,s,memory): #Reaktion der Kreatur auf einen bestimmten Umstand für das normale Polynom | ||
+ | c=0 | ||
+ | for el in self.poly: | ||
+ | if el[0]<0: | ||
+ | a=random.randint(0,10) | ||
+ | else: | ||
+ | a=el[0] | ||
+ | |||
+ | if el[1]<0: | ||
+ | b=random.randint(0,10) | ||
+ | else: | ||
+ | b=el[1] | ||
+ | |||
+ | if el[2]=="s": | ||
+ | x=s | ||
+ | elif el[2]=="m": | ||
+ | x=el[3].deep_reaction(memory) | ||
+ | </code> | ||
+ | Es wird dann der Wert von c an den bei der Initialisierung angegebenen Maximalwert des Outputs angepasst und c ausgegeben. | ||
+ | <code> | ||
+ | c=c+a*x**b | ||
+ | #c=c/len(poly) | ||
+ | while c>self.max_output: | ||
+ | c=self.max_output-(c-self.max_output) | ||
+ | while c<self.min_output: | ||
+ | c=c+(self.min_output-c) | ||
+ | |||
+ | return c | ||
+ | </code> | ||
+ | Die Deep_reaction() läuft ähnlich ab, es werden aber nicht mehr Monome betrachtet als die Erinnerung lang ist. Von dem Wert c hängt es ab, welcher Teil der Erinnerung betrachtet wird: Die Veränderung des Winkels, die Schrittweite oder die Eingabe. | ||
+ | <code> | ||
+ | def deep_reaction(self,l): #Reaktion für erinnerungspolynome | ||
+ | if self.deep_poly: | ||
+ | c=0 | ||
+ | N=min(len(self.poly),len(l)) | ||
+ | n=0 | ||
+ | |||
+ | while n<N: | ||
+ | |||
+ | if self.poly[n][0]<0: | ||
+ | a=random.randint(0,10) | ||
+ | else: | ||
+ | a=self.poly[n][0] | ||
+ | |||
+ | if self.poly[n][1]<0: | ||
+ | b=random.randint(0,10) | ||
+ | else: | ||
+ | b=self.poly[n][1] | ||
+ | |||
+ | if self.poly[n][2]=="mr": | ||
+ | x=l[n][0] | ||
+ | |||
+ | elif self.poly[n][2]=="ma": | ||
+ | x=l[n][1] | ||
+ | |||
+ | elif self.poly[n][2]=="mf": | ||
+ | x=l[n][2] | ||
+ | |||
+ | c=c+a*x**b | ||
+ | n+=1 | ||
+ | #c=c/len(poly) | ||
+ | while c>self.max_output: | ||
+ | c=self.max_output-(c-self.max_output) | ||
+ | while c<self.min_output: | ||
+ | c=c+(self.min_output-c) | ||
+ | |||
+ | return c | ||
+ | |||
+ | else: | ||
+ | return 0 | ||
+ | </code> | ||
+ | Zum Schluss gibt es noch die Funktion show_poly() welche dazu da ist, zum Schluss des map codes, wenn das Polynom der am längsten überlebenden Kreatur betrachtet werden soll, das ganze Polynom mit all seien unterpolynomen zu zeigen. | ||
+ | <code> | ||
+ | def show(self): #zeigt das Polynom als ganzes, mit allen tieferen Polynomen | ||
+ | self.A = [] | ||
+ | for p in self.poly: | ||
+ | if p[2]=="s": | ||
+ | self.A.append(p) | ||
+ | if p[2]=="m": | ||
+ | deep=p[3].poly | ||
+ | self.A.append([p[0],p[1],p[2],deep]) | ||
+ | </code> | ||