Changeset 1008


Ignore:
Timestamp:
07/14/20 20:20:54 (3 months ago)
Author:
Maciej Komosinski
Message:

Implemented crossing over, handled failed mutations and crossovers, added printing extensive statistics

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/_demos/evol_test.cpp

    r1007 r1008  
    55
    66#include <vector>
     7#include <numeric> //std::accumulate()
    78#include "common/loggers/loggertostdout.h"
    89#include "frams/genetics/preconfigured.h"
     
    2223}
    2324
    24 void evaluate_fitness(Individual &ind, const char *fitness_def)
     25double get_fitness(const Individual &ind, const char *fitness_def)
    2526{
    2627        SString genotype = ind.geno.getGenes();
     
    3233                switch (*p)
    3334                {
     35                case '0':
     36                        break;
     37                case '!': //special symbol for current fitness (used only in printing population stats)
     38                        fitness += ind.fitness;
     39                        break;
    3440                case 'l':
    3541                case 'L':
     
    5965                p++;
    6066        }
    61         ind.fitness = fitness;
     67        return fitness;
     68}
     69
     70void update_fitness(Individual &ind, const char *fitness_def)
     71{
     72        ind.fitness = get_fitness(ind, fitness_def);
     73}
     74
     75void print_stats(const vector<Individual> &population, char criterion)
     76{
     77        vector<double> criterion_values;
     78        char crit[2] = { 0 };
     79        crit[0] = criterion;
     80        for (const Individual& ind : population)
     81                criterion_values.push_back(get_fitness(ind, crit));
     82        printf("%g,%g,%g", *std::min_element(criterion_values.begin(), criterion_values.end()),
     83                std::accumulate(criterion_values.begin(), criterion_values.end(), 0.0) / criterion_values.size(),
     84                *std::max_element(criterion_values.begin(), criterion_values.end()));
    6285}
    6386
     
    7699
    77100
    78 /** A minimalistic steady-state evolutionary algorithm. */
     101// A minimalistic steady-state evolutionary algorithm.
    79102int main(int argc, char *argv[])
    80103{
     
    93116                printf("Too few parameters!\n");
    94117                printf("Command line: <deterministic?_0_or_1> <population_size> <nr_evaluations> <prob_mut> <prob_xover> <genetic_format> <fitness_definition>\n");
    95                 printf("Example: 1 10 50 0.5 0.5 4 NC\n\n\n");
     118                printf("Example: 1 10 50 0.6 0.4 4 NC\n\n");
    96119                printf("Fitness definition is a sequence of capital (+1 weight) and small (-1 weight) letters.\n");
    97120                printf("Each letter corresponds to one fitness criterion, and they are all weighted and added together.\n");
     121                printf("  0      - a constant value of 0 that provides a flat fitness landscape (e.g. for testing biases of genetic operators).\n");
    98122                printf("  l or L - genotype length in characters.\n");
    99123                printf("  p or P - the number of Parts.\n");
     
    103127                //TODO add b - bounding box volume (from Model), s - surface area (from geometry), v - volume (from geometry), h,w,d - three consecutive dimensions (from geometry)
    104128
     129                printf("\nThe output contains 7 columns separated by the TAB character.\n");
     130                printf("The first column is the number of mutated or crossed over and evaluated genotypes.\n");
     131                printf("The remaining columns are triplets of min,avg,max (in the population) of fitness, Parts, Joints, Neurons, Connections, genotype characters.\n");
     132                printf("Finally, the genotypes in the last population are printed with their fitness values.\n");
    105133                return 1;
    106134        }
     
    126154                        return 2;
    127155                }
    128                 evaluate_fitness(ind, fitness_def);
     156                update_fitness(ind, fitness_def);
    129157        }
    130158        for (int i = 0; i < nr_evals; i++)
     
    136164                if (rnd < prob_mut)
    137165                {
    138                         population[selected_negative].geno = genman.mutate(population[selected_positive].geno);
    139                         //TODO handle failed mutation
    140                         evaluate_fitness(population[selected_negative], fitness_def);
     166                        Geno mutant = genman.mutate(population[selected_positive].geno);
     167                        if (mutant.getGenes() == "")
     168                        {
     169                                printf("Failed mutation (%s) of '%s'\n", mutant.getComment().c_str(), population[selected_positive].geno.getGenes().c_str());
     170                        }
     171                        else
     172                        {
     173                                population[selected_negative].geno = mutant;
     174                                update_fitness(population[selected_negative], fitness_def);
     175                        }
    141176                }
    142177                else
    143178                {
    144                         //TODO crossover
     179                        int selected_positive2 = tournament(population, max(2, int(sqrt(population.size()) / 2)));
     180                        Geno xover = genman.crossOver(population[selected_positive].geno, population[selected_positive2].geno);
     181                        if (xover.getGenes() == "")
     182                        {
     183                                printf("Failed crossover (%s) of '%s' and '%s'\n", xover.getComment().c_str(), population[selected_positive].geno.getGenes().c_str(), population[selected_positive2].geno.getGenes().c_str());
     184                        }
     185                        else
     186                        {
     187                                population[selected_negative].geno = xover;
     188                                update_fitness(population[selected_negative], fitness_def);
     189                        }
    145190                }
    146191
    147192                if (i % population.size() == 0 || i == nr_evals - 1)
    148                         printf("Evaluation %d\t...\n", i); //TODO print min,avg,max fitness \t min,avg,max genotype length \t min,avg,max parts \t min,avg,max neurons
     193                {
     194                        printf("Evaluation %d\t", i);
     195                        for (char c : string("!PJNCL"))
     196                        {
     197                                print_stats(population, c);
     198                                printf("\t");
     199                        }
     200                        printf("\n");
     201                }
    149202        }
    150203        for (const Individual& ind : population)
Note: See TracChangeset for help on using the changeset viewer.