Weasel Program - Errormeldung

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
_whiskeyjack_
User
Beiträge: 3
Registriert: Mittwoch 29. Mai 2013, 20:00

Hallo erstmal :D

ich habe mir überlegt das http://en.wikipedia.org/wiki/Weasel_program in python zu schreiben. Ich bekomme aber eine Fehlermeldung die ich irgendwie nicht erklären kann:

Mein Code (der Fehler ist unten):

Code: Alles auswählen

[code]#Funktionen und Parameter:
import random         

target = list("METHINKS IT IS A WEASEL")             #Zielsequenz wird als Liste initialisiert, um die einzelnen Elemente einfacher
                                                     #veraendern zu koennen
mutation_rate = 0.05                                 #Mutationsrate = 5%
num_progeny = 100                                    #Anzahl der Nachkommen pro Generation
                                   
mutations = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "            #Elemente in die Elemente von parent mutieren koennen, inklusive Leerzeichen

parent = []                                          #(noch) leere Zufaellige Startsequenz
for i in range(len(target)):                         #Die Startsequenz hat die laenge von target (=28)
    parent.append(random.choice(mutations))          #random.choice gibt ein zufaelliges Element einer nicht leeren Sequenz

#Die Funktion "progeny" erzeugt 100 Nachkommen, in denen Elemente von parent mit 5% Mutationsrate zufaellig ausgetauscht werden 
def progeny(parent):
    current_progeny = []                             #Liste aller aktuellen Nachkomme
    for i in range(num_progeny):                     #Erzeugt 100 Nachkommen
        for j in range(23):                          
            if random.random() < mutation_rate:                               
                mutation = random.choice(mutations)     #Erzeugt zufaellige Mutation      
                parent[j] = mutation                    #Fuegt die Mutation in parent ein
                prog = parent
                current_progeny.append(prog)            #Fuegt die mutierte Sequenz in die Liste der aktuellen Nachkommen
            else:
                prog = parent 
                current_progeny.append(prog)            #Fuegt die nicht mutierte Sequenz in die Liste der aktuellen Nachkommen
        return current_progeny


#Die Funktion "fitness" gibt einen Score für den Vergleich von progeny und target, die beste Sequenz wird ausgewaehlt
def fitness(current_progeny, target):
    for i in range(len(current_progeny)):             #Suche jede Sequenz in current_progeny
        optimized_difference = len(target) +1 
        differences = 0
        test_progeny = current_progeny[i]             #setze test_progeny gleich Element i in current_progeny
        for i in range(len(target)):
            if test_progeny[i] != target[i]:          #wenn das Element von test_progeny und target nicht uebereinstimmen, erhoehe differences
                differences += 1
        
            if differences < optimized_difference:
                optimized_difference = differences
                fittest_progeny = progeny            #finde beste Sequenz
        return fittest_progeny
                
            
#Programm:
num_iterations = 0
while target != progeny:                              #Sobald alle 28 Elemente gleich sind sind wird abgebrochen
    num_iterations += 1
    
    prog = progeny(parent)
    parent = fitness(prog, target)
    print ("Sequenz:", parent)
[/code]

Der Error:

Code: Alles auswählen

Sequenz: <function progeny at 0x02952930>
Traceback (most recent call last):
  File "C:\Users\Stefan\Desktop\Python\weasel.py", line 58, in <module>
    parent = fitness(prog, target)
  File "C:\Users\Stefan\Desktop\Python\weasel.py", line 43, in fitness
    if test_progeny[i] != target[i]:
TypeError: 'function' object is not subscriptable
Ich denke da jetzt schon 30 min drüber nach und seh den fehler einfach nicht?!
Danke schonmal für evtl. Hilfe

€: Mal den code gehighlighted (was ein wort^^). Sry wenn der Code etwas lang ist, aber ich habe mal d s ganze programm gespostet, weil ich davon ausgehe später noch ein oder zwei Fragen zu haben :D
BlackJack

@_whiskeyjack_: Das ist doch eigentlich ganz offensichtlich. Schau Dir die erste Zeile Deiner Ausgabe an: Da wird offensichtlich nach dem Text 'Sequenz:' ein Funktionsobjekt ausgegeben. Das ist an den Namen `parent` gebunden. `parent` ist der Rückgabewert der `fitness()`-Funktion. Und in der steht in der vorletzten Zeile ``fittest_progeny = progeny``. Nun ist `progeny` eine Funktion. Und die wird dann zurück gegeben. Das ist sicher nicht so beabsichtigt nehme ich an.

Anmerkungen zum Quelltext: Als erstes sollte mal der ganze Code auf Modulebene der keine Funktionen, Klassen, oder andere Konstanten definiert in einer Funktion verschwinden. Das macht das ganze ein wenig übersichtlicher weil einige Namen sowohl auf Modulebene als auch als lokale Namen in Funktionen existieren.

Was das ganze auch ziemlich unleserlich macht sind die Inline-Kommentare, die den 80-Zeichen-Rahmen locker sprengen und es in vielen Umgebungen sehr schwer machen den Quelltext zu lesen wenn jede zweite Zeile aus einem umgebrochenen halben Kommentar besteht.
_whiskeyjack_
User
Beiträge: 3
Registriert: Mittwoch 29. Mai 2013, 20:00

Ah, danke für die schnelle Hilfe und Tips. Oh man, war klar, dass es sowas offensichtliches ist. Ich habe progeny jetzt mit test_progeny ersetzt und lasse das Programm mal laufen, was aber ne ganze weile dauern könnte. Liegt das vorwiegend an dem "Anfängercode" oder ist Python einfach nicht so fix? Ich habe nämlich nach ~5 min nicht das gefühl, dass sich die sequenz wirklich verbessert.

Das ganze ist nen Projekt für die Uni und man soll alles "ausführlich" kommentieren, deshalb der Exzess an Kommentaren. :mrgreen:
BlackJack

@_whiskeyjack_: Es geht nicht um die Menge an Kommentaren sondern um die Formatierung. Zeilen sollten nicht länger als 80 Zeichen werden, weil es sonst in vielen Umgebungen Probleme gibt den Quelltext vernünftig zu lesen. Damit fallen Kommentare die an Ende von Zeilen gehängt werden nahezu aus. In Python ist es üblich Kommentare über den Quelltext zu schreiben, den sie kommentieren.

Ich habe es mal schnell implementiert und mein Code kommt in einer Zehntelsekunde zum Ergebnis. Das dürfte also auch bei einem sehr langsamen Rechner an Deinem Programm und nicht an Python liegen.

Mein schnell runtergehackter Quelltext:

Code: Alles auswählen

from __future__ import print_function
from random import choice, random
from string import ascii_uppercase

try:
    xrange
except NameError:
    xrange = range

MUTATION_CHANCE = 0.05
GENERATION_SIZE = 100


def main():
    target = list('METHINKS IT IS LIKE A WEASEL')
    gene_pool = ascii_uppercase + ' '
    creature = [choice(gene_pool) for _ in xrange(len(target))]
    while creature != target:
        offspring = (
            [
                (choice(gene_pool) if random() <= MUTATION_CHANCE else c)
                for c in creature
            ]
            for _ in xrange(GENERATION_SIZE)
        )
        creature = max(
            offspring, key=lambda x: sum(a == b for a, b in zip(x, target))
        )
        print(''.join(creature))


if __name__ == '__main__':
    main()
_whiskeyjack_
User
Beiträge: 3
Registriert: Mittwoch 29. Mai 2013, 20:00

Besten Dank, BlackJack!
Ich werde mir deine Version wenn ich Zeit habe mal anschauen, um die nachzuvollziehen. Ich habe jetzt selbst etwas getrickst, indem ich Mutationen die mit der Zielsequenz übereinstimmen festlege und nicht mehr veränderbar lasse. So komme ich nach einigen 100 bis 1000 Iterationen ans Ziel.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@_whiskeyjack_: man sollte, bevor man einfach so mal das Programm startet, testen, ob die Funktionen einzeln das tun, was man erwartet. Ich sehe spontan in Deinem Programm zwei Funktionen, die nicht das tun, was Du erwartest.
Antworten