source: cpp/frams/genetics/f9/f9_oper.cpp @ 1005

Last change on this file since 1005 was 1005, checked in by Maciej Komosinski, 4 years ago

Higher conformance with C++17, but gave up after missing M_PI, M_PI_2, strdup() and more; other cosmetic improvements

  • Property svn:eol-style set to native
File size: 3.8 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[974]2// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[120]4
[779]5#include "f9_oper.h"
6#include "f9_conv.h"
[899]7#include <common/nonstd.h> //rndUint, rndDouble
[1005]8#include <string.h>
[120]9
10
11#define FIELDSTRUCT GenoOper_f9
[974]12static ParamEntry geno_f9_paramtab[] =
[120]13{
[168]14        { "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        { 0, },
[120]17};
18#undef FIELDSTRUCT
19
20
21GenoOper_f9::GenoOper_f9()
22{
[974]23        par.setParamTab(geno_f9_paramtab);
[120]24        par.select(this);
25        par.setDefault();
[168]26        supported_format = '9';
[120]27}
28
[513]29int GenoOper_f9::checkValidity(const char* gene, const char *genoname)
[120]30{
31        if (!gene[0]) return 1; //empty is not valid
[168]32        bool ok = true;
[319]33        size_t i;
[168]34        for (i = 0; i < strlen(gene); i++) if (!strchr(turtle_commands_f9, gene[i])) { ok = false; break; }
35        return ok ? GENOPER_OK : i + 1;
[120]36}
37
38///Remove all invalid letters from the genotype
[513]39int GenoOper_f9::validate(char *&gene, const char *genoname)
[120]40{
41        SString validated; //new genotype (everything except turtle_commands_f9 is skipped)
[319]42        for (size_t i = 0; i < strlen(gene); i++)
[168]43                if (strchr(turtle_commands_f9, gene[i])) validated += gene[i];  //validated contains only turtle_commands_f9
[120]44        free(gene);
[348]45        gene = strdup(validated.c_str()); //reallocate
[120]46        return GENOPER_OK;
47}
48
49///Very simple mutation
[168]50int GenoOper_f9::mutate(char *&gene, float &chg, int &method)
[120]51{
[168]52        method = 0;
53        int changes = 0, len = strlen(gene);
54        int symbols = strlen(turtle_commands_f9);
[120]55
[168]56        for (int i = 0; i < len; i++)
[120]57        {
[896]58                if (rndDouble(1) < mut_prob) //normalize prob with the length of the genotype
[120]59                {
[168]60                        char oldgene = gene[i];
[896]61                        gene[i] = turtle_commands_f9[rndUint(symbols)];
[168]62                        if (gene[i] != oldgene) changes++;
[120]63                }
64        }
65
[896]66        if (rndDouble(1) < mut_prob) //add or delete a random char
[120]67        {
68                SString newgeno(gene);
[896]69                if (rndUint(2) == 0) //add
[120]70                {
[168]71                        int symbols = strlen(turtle_commands_f9);
[896]72                        int p = rndUint(len + 1);  //random location
[120]73                        //printf("before add: %s\n",(const char*)newgeno);
[896]74                        newgeno = newgeno.substr(0, p) + SString(turtle_commands_f9 + rndUint(symbols), 1) + newgeno.substr(p);
[120]75                        //printf("after add: %s\n",(const char*)newgeno);
76                        changes++;
[168]77                }
78                else if (len > 1) //delete
[120]79                {
[896]80                        int p = rndUint(len);  //random location
[120]81                        //printf("before delete: %s\n",(const char*)newgeno);
[168]82                        newgeno = newgeno.substr(0, p) + newgeno.substr(p + 1);
[120]83                        //printf("after delete: %s\n",(const char*)newgeno);
84                        changes++;
85                }
86                free(gene);
[348]87                gene = strdup(newgeno.c_str()); //reallocate
[120]88        }
89
[168]90        chg = (float)changes / len;
91        return changes > 0 ? GENOPER_OK : GENOPER_OPFAIL; //no changes => OPFAIL so that GenMan will call mutate again
[120]92}
93
94///A simple one-point crossover
[168]95int GenoOper_f9::crossOver(char *&g1, char *&g2, float& chg1, float& chg2)
[120]96{
[168]97        int len1 = strlen(g1), len2 = strlen(g2);
[896]98        int p1 = rndUint(len1);  //random cut point for first genotype
99        int p2 = rndUint(len2);  //random cut point for second genotype
[168]100        char *child1 = (char*)malloc(p1 + len2 - p2 + 1);
101        char *child2 = (char*)malloc(p2 + len1 - p1 + 1);
102        strncpy(child1, g1, p1);   strcpy(child1 + p1, g2 + p2);
103        strncpy(child2, g2, p2);   strcpy(child2 + p2, g1 + p1);
104        free(g1); g1 = child1;
105        free(g2); g2 = child2;
106        chg1 = (float)p1 / strlen(child1);
107        chg2 = (float)p2 / strlen(child2);
[120]108        return GENOPER_OK;
109}
110
111///Applying some colors and font styles...
[247]112uint32_t GenoOper_f9::style(const char *g, int pos)
[120]113{
[168]114        char ch = g[pos];
[247]115        uint32_t style = GENSTYLE_CS(0, GENSTYLE_INVALID); //default, should be changed below
[168]116        char *ptr = strchr((char*)turtle_commands_f9, ch);
[120]117        if (ptr)
118        {
[168]119                int pos = ptr - turtle_commands_f9;
120                int axis = pos / 2;
121                style = GENSTYLE_RGBS(axis == 0 ? 200 : 0, axis == 1 ? 200 : 0, axis == 2 ? 200 : 0, GENSTYLE_NONE);
[120]122        }
123        return style;
124}
Note: See TracBrowser for help on using the repository browser.