Ignore:
Timestamp:
10/01/21 22:52:19 (3 years ago)
Author:
Maciej Komosinski
Message:

Improved f9 mutation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/f9/f9_oper.cpp

    r1005 r1157  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2021  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    77#include <common/nonstd.h> //rndUint, rndDouble
    88#include <string.h>
     9#include <assert.h>
    910
    1011
     
    1314{
    1415        { "Genetics: f9", 1, 1, },
    15         { "f9_mut", 0, 0, "Mutation probability", "f 0 1 0.1", FIELD(mut_prob), "How many genes should be mutated during single mutation (1=all genes, 0.1=ten percent)", },
     16        { "f9_mut", 0, 0, "Mutation probability", "f 0 1 0", FIELD(mut_prob), "How many genes should be mutated during single mutation (1=all genes, 0.1=ten percent, 0=one gene)", },
    1617        { 0, },
    1718};
     
    4748}
    4849
    49 ///Very simple mutation
     50void GenoOper_f9::mutate_replace(char *gene, int i)
     51{
     52        char oldgene = gene[i];
     53        const char *pos = strchr(turtle_commands_f9, oldgene);
     54        if (pos == NULL) //gene not in the set of allowed commands
     55                gene[i] = turtle_commands_f9[rndUint(turtle_commands_f9_count)];
     56        else
     57                gene[i] = turtle_commands_f9[((pos - turtle_commands_f9) + 1 + rndUint(turtle_commands_f9_count - 1)) % turtle_commands_f9_count]; //always change to a different command
     58        //printf("%c %c\n", oldgene, gene[i]);
     59        assert(gene[i] != oldgene);
     60}
     61
     62void GenoOper_f9::mutate_add_or_del(char *& gene, int len, int add_0_del_1)
     63{
     64        string newgeno(gene);
     65        if (add_0_del_1 == 0) //add
     66        {
     67                int p = rndUint(len + 1);  //random location
     68                //printf("before add: %s\n",(const char*)newgeno);
     69                newgeno = newgeno.substr(0, p) + string(turtle_commands_f9 + rndUint(turtle_commands_f9_count), 1) + newgeno.substr(p);
     70                //printf("after add: %s\n",(const char*)newgeno);
     71        }
     72        else //delete
     73        {
     74                int p = rndUint(len);  //random location
     75                //printf("before delete: %s\n",(const char*)newgeno);
     76                newgeno = newgeno.substr(0, p) + newgeno.substr(p + 1);
     77                //printf("after delete: %s\n",(const char*)newgeno);
     78        }
     79        free(gene);
     80        gene = strdup(newgeno.c_str()); //reallocate
     81}
     82
     83///Simple mutation
    5084int GenoOper_f9::mutate(char *&gene, float &chg, int &method)
    5185{
    5286        method = 0;
    5387        int changes = 0, len = strlen(gene);
    54         int symbols = strlen(turtle_commands_f9);
    5588
    56         for (int i = 0; i < len; i++)
    57         {
    58                 if (rndDouble(1) < mut_prob) //normalize prob with the length of the genotype
     89        if (mut_prob > 0)
     90                for (int i = 0; i < len; i++)
    5991                {
    60                         char oldgene = gene[i];
    61                         gene[i] = turtle_commands_f9[rndUint(symbols)];
    62                         if (gene[i] != oldgene) changes++;
     92                        if (rndDouble(1) < mut_prob) //normalize prob with the length of the genotype
     93                        {
     94                                mutate_replace(gene, i);
     95                                changes++;
     96                        }
    6397                }
    64         }
    6598
    6699        if (rndDouble(1) < mut_prob) //add or delete a random char
    67100        {
    68                 SString newgeno(gene);
    69                 if (rndUint(2) == 0) //add
    70                 {
    71                         int symbols = strlen(turtle_commands_f9);
    72                         int p = rndUint(len + 1);  //random location
    73                         //printf("before add: %s\n",(const char*)newgeno);
    74                         newgeno = newgeno.substr(0, p) + SString(turtle_commands_f9 + rndUint(symbols), 1) + newgeno.substr(p);
    75                         //printf("after add: %s\n",(const char*)newgeno);
    76                         changes++;
    77                 }
    78                 else if (len > 1) //delete
    79                 {
    80                         int p = rndUint(len);  //random location
    81                         //printf("before delete: %s\n",(const char*)newgeno);
    82                         newgeno = newgeno.substr(0, p) + newgeno.substr(p + 1);
    83                         //printf("after delete: %s\n",(const char*)newgeno);
    84                         changes++;
    85                 }
    86                 free(gene);
    87                 gene = strdup(newgeno.c_str()); //reallocate
     101                int change_add_or_del = 1 + (len > 1); //either add a new symbol (1), or delete a random symbol (+(len>1))
     102                int add_0_del_1 = rndUint(change_add_or_del);
     103                mutate_add_or_del(gene, len, add_0_del_1);
     104                changes++;
     105        }
     106
     107        if (changes == 0) //if nothing changed so far, then fallback to minimal change: always changes one symbol
     108        {
     109                int change_what = len + 1 + (len > 1); //either replace an existing gene, or add a new symbol (+1), or delete a random symbol (+(len>1))
     110                int change_selected = rndUint(change_what);
     111                if (change_selected < len)
     112                        mutate_replace(gene, change_selected);
     113                else
     114                        mutate_add_or_del(gene, len, change_selected - len);
     115                changes++;
    88116        }
    89117
    90118        chg = (float)changes / len;
    91         return changes > 0 ? GENOPER_OK : GENOPER_OPFAIL; //no changes => OPFAIL so that GenMan will call mutate again
     119        return changes > 0 ? GENOPER_OK : GENOPER_OPFAIL; //no changes? (should never happen) => OPFAIL so that GenMan will call mutate again
    92120}
    93121
Note: See TracChangeset for help on using the changeset viewer.