nochmal genetische algorythmen diemal in c++



  • dein code ist zum kotzen 👎



  • nja habt ihr ahnung von genetischen algorithmen? oder soll ich den thread in rechtschreibreform umbenennen?



  • Kannste gerne machen, die Kritik an deinem Code bleibt bestehen. Ich verstehe nicht wie Leute mit so einem Code arbeiten können. Da guckt man drüber und möchte sich sofort die Augen ausstechen. Hau den erstmal ordentlich in den Thread, dann kann man weiter gucken.



  • Der Code ist zwar nicht besonders gut lesbar, aber es fällt sofort auf, dass das swap zwei int vertauscht, du wendest es aber auf ein 5-elementiges Array von int (genes) an. Ist das Absicht, dass nur jeweils das erste Element des genes-Arrays vertauscht wird? Falls ja, würde ich das explizit machen: swap(&...genes[0], ...). Falls nicht, haben wir deinen Fehler.



  • klg71 schrieb:

    nja habt ihr ahnung von genetischen algorithmen? oder soll ich den thread in rechtschreibreform umbenennen?

    Aber du...

    if(sum==Zahl){
                    fitness=abs(sum-Zahl);
                }
    


  • schlorf schrieb:

    klg71 schrieb:

    nja habt ihr ahnung von genetischen algorithmen? oder soll ich den thread in rechtschreibreform umbenennen?

    Aber du...

    if(sum==Zahl){
                    fitness=abs(sum-Zahl);
                }
    

    Wird wohl immer 0 rauskommen 😃 ...



  • ja soll es auch bloß dass passiert nie^^


  • Mod

    Zum Spass mal in C++ umgeschrieben

    #ifndef INOUT_H_INCLUDED
    #define INOUT_H_INCLUDED
    
    #include <cassert>
    #include <iostream>
    #include <functional>
    #include <vector>
    #include <algorithm>
    #include <numeric>
    #include <string>
    #include <sstream>
    #include <iterator>
    
    template<typename T>
    inline T random(T factor) { return factor * std::rand() / ( RAND_MAX + 1 ); }
    
    class Individual
    {
    public:
        explicit Individual(std::size_t num_genes, int num_variants)
        {
            std::generate_n( std::back_inserter( genes ), num_genes, std::tr1::bind( random<int>, num_variants ) );
        }
    
    	friend Individual make_individual(std::size_t num_genes, int num_variants)
        {
            return Individual( num_genes, num_variants );
        }
    
        int get_fitness(int optimum_value) const
        {
            return -std::abs( std::accumulate( genes.begin(), genes.end(), -optimum_value ) );
        }
    
        std::string get_genes() const
        {
            std::ostringstream result;
            std::copy( genes.begin(), genes.end(), std::ostream_iterator<int>( result, " " ) );
            return result.str();
        }
    
        void crossover(Individual& other)
        {
            assert( genes.size() == other.genes.size() );
            using std::swap;
            std::size_t gene = random( genes.size() );
            swap( genes[ gene ], other.genes[ gene ] );
        }
    
        void mutate(int num_variants)
        {
            for ( std::size_t num_mutations = random( genes.size() ) + 1; num_mutations-- != 0; )
                genes[ random( genes.size() ) ] = random( num_variants );
        }
    
    private:
        std::vector<int> genes;
    };
    
    class FitnessCompare : public std::binary_function<Individual,Individual,bool>
    {
    public:
        explicit FitnessCompare(int optimum) : optimum( optimum ) {}
        bool operator()(const Individual& lhs, const Individual& rhs)
        {
            return lhs.get_fitness( optimum ) < rhs.get_fitness( optimum );
        }
    private:
        int optimum;
    };
    class Population
    {
    public:
    	Population(std::size_t num_individuals, std::size_t num_genes, int num_variants)
        {
            std::generate_n( std::back_inserter( individuals ), num_individuals, std::tr1::bind( make_individual, num_genes, num_variants ) );
        }
    
        const Individual& best_individual(int optimum) const
        {
            return *std::max_element( individuals.begin(), individuals.end(), FitnessCompare( optimum ) );
        }
    
        void crossover()
        {
            for ( std::vector<Individual>::iterator individual = individuals.begin(); individual != individuals.end(); ++individual )
                individual->crossover( individuals[ random( individuals.size() ) ] );
        }
    
        void mutate(int num_variants, double prob)
        {
            for ( std::vector<Individual>::iterator individual = individuals.begin(); individual != individuals.end(); ++individual )
                if ( random( 1.0 ) < prob )
                    individual->mutate( num_variants );
        }
    
    private:
        std::vector<Individual> individuals;
    };
    
    #endif // INOUT_H_INCLUDED
    
    #include "inout.h"
    #include <ctime>
    
    int main()
    {
        std::srand( static_cast<unsigned>( std::time( NULL ) ) );
    
        int num_individuals = 0; std::cout << "Anzahl Individuen: "; std::cin >> num_individuals;
        int num_genes = 0;       std::cout << "Anzahl Gene: ";       std::cin >> num_genes;
        int num_variants = 0;    std::cout << "Anzahl Varianten: ";  std::cin >> num_variants;
        int optimum = 0;         std::cout << "Optimum: ";           std::cin >> optimum;
    
        Population population( num_individuals, num_genes, num_variants );
    
        for ( ;; )
        {
            const Individual& best = population.best_individual( optimum );
            int fitness = best.get_fitness( optimum );
            if ( fitness > -num_genes )
            {
                std::cout << "Fitness : " << fitness << '\n'
                          << best.get_genes() << std::endl;
                if ( fitness == 0 )
                    break;
            }
    
            population.crossover();
            population.mutate( num_variants, 0.2 );
        }
    }
    

    Dabei ist mir dann aufgefallen, dass die changeGenes Funktion nicht funktionieren dürfte.
    Ohne Selektion ist das natürlich noch kein genetischer Algorithmus.



  • das heist da muss noch eine auswahlfunktion rein?



  • Die Auswahlwahrscheinlichkeit sollte in Abhängigkeit von ihrer Fitness stehen.
    D.h. je höher die Fitness, desto höher die Wahrscheinlichkeit, ausgewählt zu werden.

    Ich nehme immer das Roulettewheel-Verfahren.
    Das geht aber nur solange gut, wie man von Inzucht weit entfernt ist. Wenn fast alle Elemente gleich sind, macht das keinen Spaß mehr. Insofern ist es manchmal auch besser, ein weniger "perfektes" Genome für Crossover zu nutzen, damit mal etwas "frisches Blut" in die Population kommt.

    Ich logge immer die Durchschnittswerte und Standardabweichungen jedes Gens mit und kann so prüfen, ob sich
    a) der genetische Algorithmus an einzelnen Stellen auf einen bestimmten Wert festlegt ( ist auch eine Aussage )
    b) die Population sich der Inzucht nähert, wogegen man dann etwas unternehmen sollte. ( Paarungen mit einer anderen Population ( sofern vorhanden ), einkreuzen von neuen Genomen, Mutationsrate erhöhen, etc. )


Anmelden zum Antworten