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
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "f9_oper.h"
6#include "f9_conv.h"
7#include <common/nonstd.h> //rndUint, rndDouble
8#include <string.h>
9
10
11#define FIELDSTRUCT GenoOper_f9
12static ParamEntry geno_f9_paramtab[] =
13{
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, },
17};
18#undef FIELDSTRUCT
19
20
21GenoOper_f9::GenoOper_f9()
22{
23        par.setParamTab(geno_f9_paramtab);
24        par.select(this);
25        par.setDefault();
26        supported_format = '9';
27}
28
29int GenoOper_f9::checkValidity(const char* gene, const char *genoname)
30{
31        if (!gene[0]) return 1; //empty is not valid
32        bool ok = true;
33        size_t i;
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;
36}
37
38///Remove all invalid letters from the genotype
39int GenoOper_f9::validate(char *&gene, const char *genoname)
40{
41        SString validated; //new genotype (everything except turtle_commands_f9 is skipped)
42        for (size_t i = 0; i < strlen(gene); i++)
43                if (strchr(turtle_commands_f9, gene[i])) validated += gene[i];  //validated contains only turtle_commands_f9
44        free(gene);
45        gene = strdup(validated.c_str()); //reallocate
46        return GENOPER_OK;
47}
48
49///Very simple mutation
50int GenoOper_f9::mutate(char *&gene, float &chg, int &method)
51{
52        method = 0;
53        int changes = 0, len = strlen(gene);
54        int symbols = strlen(turtle_commands_f9);
55
56        for (int i = 0; i < len; i++)
57        {
58                if (rndDouble(1) < mut_prob) //normalize prob with the length of the genotype
59                {
60                        char oldgene = gene[i];
61                        gene[i] = turtle_commands_f9[rndUint(symbols)];
62                        if (gene[i] != oldgene) changes++;
63                }
64        }
65
66        if (rndDouble(1) < mut_prob) //add or delete a random char
67        {
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
88        }
89
90        chg = (float)changes / len;
91        return changes > 0 ? GENOPER_OK : GENOPER_OPFAIL; //no changes => OPFAIL so that GenMan will call mutate again
92}
93
94///A simple one-point crossover
95int GenoOper_f9::crossOver(char *&g1, char *&g2, float& chg1, float& chg2)
96{
97        int len1 = strlen(g1), len2 = strlen(g2);
98        int p1 = rndUint(len1);  //random cut point for first genotype
99        int p2 = rndUint(len2);  //random cut point for second genotype
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);
108        return GENOPER_OK;
109}
110
111///Applying some colors and font styles...
112uint32_t GenoOper_f9::style(const char *g, int pos)
113{
114        char ch = g[pos];
115        uint32_t style = GENSTYLE_CS(0, GENSTYLE_INVALID); //default, should be changed below
116        char *ptr = strchr((char*)turtle_commands_f9, ch);
117        if (ptr)
118        {
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);
122        }
123        return style;
124}
Note: See TracBrowser for help on using the repository browser.