Ignore:
Timestamp:
07/13/20 13:53:25 (4 years ago)
Author:
Maciej Komosinski
Message:

Improved the fS encoding

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/fS/fS_oper.cpp

    r974 r1000  
    1212                {
    1313                                {"Genetics: fS",            1, FS_OPCOUNT + 5,},
    14                                 {"fS_mut_add_part",         0, 0, "Add part",                 "f 0 100 10", FIELD(prob[FS_ADD_PART]),             "mutation: probability of adding a part",},
    15                                 {"fS_mut_rem_part",         0, 0, "Remove part",              "f 0 100 10", FIELD(prob[FS_REM_PART]),             "mutation: probability of deleting a part",},
    16                                 {"fS_mut_mod_part",         0, 0, "Modify part",              "f 0 100 10", FIELD(prob[FS_MOD_PART]),             "mutation: probability of changing the part type",},
    17                                 {"fS_mut_change_joint",        0, 0, "Change joint",                "f 0 100 10", FIELD(prob[FS_CHANGE_JOINT]),            "mutation: probability of changing a joint",},
    18                                 {"fS_mut_add_param",        0, 0, "Add param",                "f 0 100 10", FIELD(prob[FS_ADD_PARAM]),            "mutation: probability of adding a parameter",},
    19                                 {"fS_mut_rem_param",        0, 0, "Remove param",             "f 0 100 10", FIELD(prob[FS_REM_PARAM]),            "mutation: probability of removing a parameter",},
    20                                 {"fS_mut_mod_param",        0, 0, "Modify param",             "f 0 100 10", FIELD(prob[FS_MOD_PARAM]),            "mutation: probability of modifying a parameter",},
    21                                 {"fS_mut_mod_mod",          0, 0, "Modify modifier",           "f 0 100 10", FIELD(prob[FS_MOD_MOD]),              "mutation: probability of modifying a modifier",},
    22                                 {"fS_mut_add_neuro",        0, 0, "Add neuron",               "f 0 100 10", FIELD(prob[FS_ADD_NEURO]),            "mutation: probability of adding a neuron",},
    23                                 {"fS_mut_rem_neuro",        0, 0, "Remove neuron",            "f 0 100 10", FIELD(prob[FS_REM_NEURO]),            "mutation: probability of removing a neuron",},
    24                                 {"fS_mut_mod_neuro_conn",        0, 0, "Modify neuron connection",            "f 0 100 10", FIELD(prob[FS_MOD_NEURO_CONNECTION]), "mutation: probability of changing a neuron connection",},
    25                                 {"fS_mut_add_neuro_conn",   0, 0, "Add neuron connection",    "f 0 100 10", FIELD(prob[FS_ADD_NEURO_CONNECTION]), "mutation: probability of adding a neuron connection",},
    26                                 {"fS_mut_rem neuro_conn",   0, 0, "Remove neuron connection", "f 0 100 10", FIELD(prob[FS_REM_NEURO_CONNECTION]), "mutation: probability of removing a neuron connection",},
    27                                 {"fS_mut_mod_neuro_params", 0, 0, "Modify neuron params",     "f 0 100 10", FIELD(prob[FS_MOD_NEURO_PARAMS]),     "mutation: probability of changing a neuron param",},
    28                                 {"fS_circle_section",       0, 0, "Ensure circle section",    "d 0 1 1",    FIELD(ensureCircleSection),           "Ensure that ellipsoids and cylinders have circle cross-section"},
    29                                 {"fS_use_elli",       0, 0, "Use ellipsoids in mutations",    "d 0 1 1",    FIELD(useElli),           "Use ellipsoids in mutations"},
    30                                 {"fS_use_cub",       0, 0, "Use cuboids in mutations",    "d 0 1 1",    FIELD(useCub),           "Use cuboids in mutations"},
    31                                 {"fS_use_cyl",       0, 0, "Use cylinders in mutations",    "d 0 1 1",    FIELD(useCyl),           "Use cylinders in mutations"},
    32                                 {"fS_mut_add_part_strong",       0, 0, "Strong add part mutation",    "d 0 1 1",    FIELD(strongAddPart),           "Add part mutation will produce more parametrized parts"},
     14                                {"fS_mut_add_part",         0, 0, "Add part",                    "f 0 100 10", FIELD(prob[FS_ADD_PART]),             "mutation: probability of adding a part",},
     15                                {"fS_mut_rem_part",         0, 0, "Remove part",                 "f 0 100 10", FIELD(prob[FS_REM_PART]),             "mutation: probability of deleting a part",},
     16                                {"fS_mut_mod_part",         0, 0, "Modify part",                 "f 0 100 10", FIELD(prob[FS_MOD_PART]),             "mutation: probability of changing the part type",},
     17                                {"fS_mut_change_joint",     0, 0, "Change joint",                "f 0 100 10", FIELD(prob[FS_CHANGE_JOINT]),         "mutation: probability of changing a joint",},
     18                                {"fS_mut_add_param",        0, 0, "Add param",                   "f 0 100 10", FIELD(prob[FS_ADD_PARAM]),            "mutation: probability of adding a parameter",},
     19                                {"fS_mut_rem_param",        0, 0, "Remove param",                "f 0 100 10", FIELD(prob[FS_REM_PARAM]),            "mutation: probability of removing a parameter",},
     20                                {"fS_mut_mod_param",        0, 0, "Modify param",                "f 0 100 10", FIELD(prob[FS_MOD_PARAM]),            "mutation: probability of modifying a parameter",},
     21                                {"fS_mut_mod_mod",          0, 0, "Modify modifier",             "f 0 100 10", FIELD(prob[FS_MOD_MOD]),              "mutation: probability of modifying a modifier",},
     22                                {"fS_mut_add_neuro",        0, 0, "Add neuron",                  "f 0 100 10", FIELD(prob[FS_ADD_NEURO]),            "mutation: probability of adding a neuron",},
     23                                {"fS_mut_rem_neuro",        0, 0, "Remove neuron",               "f 0 100 10", FIELD(prob[FS_REM_NEURO]),            "mutation: probability of removing a neuron",},
     24                                {"fS_mut_mod_neuro_conn",   0, 0, "Modify neuron connection",    "f 0 100 10", FIELD(prob[FS_MOD_NEURO_CONNECTION]), "mutation: probability of changing a neuron connection",},
     25                                {"fS_mut_add_neuro_conn",   0, 0, "Add neuron connection",       "f 0 100 10", FIELD(prob[FS_ADD_NEURO_CONNECTION]), "mutation: probability of adding a neuron connection",},
     26                                {"fS_mut_rem neuro_conn",   0, 0, "Remove neuron connection",    "f 0 100 10", FIELD(prob[FS_REM_NEURO_CONNECTION]), "mutation: probability of removing a neuron connection",},
     27                                {"fS_mut_mod_neuro_params", 0, 0, "Modify neuron params",        "f 0 100 10", FIELD(prob[FS_MOD_NEURO_PARAMS]),     "mutation: probability of changing a neuron param",},
     28                                {"fS_circle_section",       0, 0, "Ensure circle section",       "d 0 1 1",    FIELD(ensureCircleSection),           "Ensure that ellipsoids and cylinders have circle cross-section"},
     29                                {"fS_use_elli",             0, 0, "Use ellipsoids in mutations", "d 0 1 1",    FIELD(useElli),                       "Use ellipsoids in mutations"},
     30                                {"fS_use_cub",              0, 0, "Use cuboids in mutations",    "d 0 1 1",    FIELD(useCub),                        "Use cuboids in mutations"},
     31                                {"fS_use_cyl",              0, 0, "Use cylinders in mutations",  "d 0 1 1",    FIELD(useCyl),                        "Use cylinders in mutations"},
     32                                {"fS_mut_add_part_strong",  0, 0, "Strong add part mutation",    "d 0 1 1",    FIELD(strongAddPart),                 "Add part mutation will produce more parametrized parts"},
    3333                };
    3434
    3535#undef FIELDSTRUCT
     36
     37
     38
     39const std::map<string, double> minValues = {
     40                {INGESTION,      0},//Model::getMinPart().ingest},
     41                {FRICTION,       0},//Model::getMinPart().friction},
     42                {STIFFNESS,              0.1},
     43                {ROT_X,          -M_PI},
     44                {ROT_Y,          -M_PI},
     45                {ROT_Z,          -M_PI},
     46                {RX,             -M_PI},
     47                {RY,             -M_PI},
     48                {RZ,             -M_PI},
     49                {SIZE,           0.01},
     50                {SIZE_X,         0},//Model::getMinPart().scale.x},
     51                {SIZE_Y,         0},//Model::getMinPart().scale.y},
     52                {SIZE_Z,         0}//Model::getMinPart().scale.z}
     53};
     54
     55const std::map<string, double> maxValues = {
     56                {INGESTION,      1},//Model::getMaxPart().ingest},
     57                {FRICTION,       1},//Model::getMaxPart().friction},
     58                {STIFFNESS,              0.5},
     59                {ROT_X,          M_PI},
     60                {ROT_Y,          M_PI},
     61                {ROT_Z,          M_PI},
     62                {RX,             M_PI},
     63                {RY,             M_PI},
     64                {RZ,             M_PI},
     65                {SIZE,           100.0},
     66                {SIZE_X,         1},//Model::getMaxPart().scale.x},
     67                {SIZE_Y,         1},//Model::getMaxPart().scale.y},
     68                {SIZE_Z,         1}//Model::getMaxPart().scale.z}
     69};
     70
    3671
    3772GenoOper_fS::GenoOper_fS()
     
    4984                fS_Genotype genotype(geno);
    5085                int errorPosition = genotype.checkValidityOfPartSizes();
    51                 if(errorPosition != 0)
    52                 {
    53                         logPrintf("GenoOper_fS", "checkValidity", LOG_ERROR, "Invalid part size");
     86                if (errorPosition != 0)
     87                {
     88                        logPrintf("GenoOper_fS", "checkValidity", LOG_WARN, "Invalid part size");
    5489                        return errorPosition;
    5590                }
     
    5792        catch (fS_Exception &e)
    5893        {
    59                 logPrintf("GenoOper_fS", "checkValidity", LOG_ERROR, e.what());
     94                logPrintf("GenoOper_fS", "checkValidity", LOG_WARN, e.what());
    6095                return 1 + e.errorPosition;
    6196        }
     
    66101int GenoOper_fS::mutate(char *&geno, float &chg, int &method)
    67102{
    68         fS_Genotype genotype(geno);
    69 
    70         // Calculate available part types
    71         string availableTypes;
    72         if(useElli)
    73                 availableTypes += ELLIPSOID;
    74         if(useCub)
    75                 availableTypes += CUBOID;
    76         if(useCyl)
    77                 availableTypes += CYLINDER;
    78 
    79         // Select a mutation
    80         bool result = false;
    81         method = GenoOperators::roulette(prob, FS_OPCOUNT);
    82         switch (method)
    83         {
    84                 case FS_ADD_PART:
    85                         result = addPart(genotype, availableTypes);
    86                         break;
    87                 case FS_REM_PART:
    88                         result = removePart(genotype);
    89                         break;
    90                 case FS_MOD_PART:
    91                         result = changePartType(genotype, availableTypes);
    92                         break;
    93                 case FS_CHANGE_JOINT:
    94                         result = changeJoint(genotype);
    95                         break;
    96                 case FS_ADD_PARAM:
    97                         result = addParam(genotype);
    98                         break;
    99                 case FS_REM_PARAM:
    100                         result = removeParam(genotype);
    101                         break;
    102                 case FS_MOD_PARAM:
    103                         result = changeParam(genotype);
    104                         break;
    105                 case FS_MOD_MOD:
    106                         result = changeModifier(genotype);
    107                         break;
    108                 case FS_ADD_NEURO:
    109                         result = addNeuro(genotype);
    110                         break;
    111                 case FS_REM_NEURO:
    112                         result = removeNeuro(genotype);
    113                         break;
    114                 case FS_MOD_NEURO_CONNECTION:
    115                         result = changeNeuroConnection(genotype);
    116                         break;
    117                 case FS_ADD_NEURO_CONNECTION:
    118                         result = addNeuroConnection(genotype);
    119                         break;
    120                 case FS_REM_NEURO_CONNECTION:
    121                         result = removeNeuroConnection(genotype);
    122                         break;
    123                 case FS_MOD_NEURO_PARAMS:
    124                         result = changeNeuroParam(genotype);
    125                         break;
    126         }
    127 
    128         if (result)
    129         {
    130                 free(geno);
    131                 geno = strdup(genotype.getGeno().c_str());
    132                 return GENOPER_OK;
    133         }
    134         return GENOPER_OPFAIL;
     103        try
     104        {
     105                fS_Genotype genotype(geno);
     106
     107                // Calculate available part types
     108                vector <Part::Shape> availablePartShapes;
     109                if (useElli)
     110                        availablePartShapes.push_back(Part::Shape::SHAPE_ELLIPSOID);
     111                if (useCub)
     112                        availablePartShapes.push_back(Part::Shape::SHAPE_CUBOID);
     113                if (useCyl)
     114                        availablePartShapes.push_back(Part::Shape::SHAPE_CYLINDER);
     115
     116                // Select a mutation
     117                bool result = false;
     118                method = GenoOperators::roulette(prob, FS_OPCOUNT);
     119                switch (method)
     120                {
     121                        case FS_ADD_PART:
     122                                result = addPart(genotype, availablePartShapes);
     123                                break;
     124                        case FS_REM_PART:
     125                                result = removePart(genotype);
     126                                break;
     127                        case FS_MOD_PART:
     128                                result = changePartType(genotype, availablePartShapes);
     129                                break;
     130                        case FS_CHANGE_JOINT:
     131                                result = changeJoint(genotype);
     132                                break;
     133                        case FS_ADD_PARAM:
     134                                result = addParam(genotype);
     135                                break;
     136                        case FS_REM_PARAM:
     137                                result = removeParam(genotype);
     138                                break;
     139                        case FS_MOD_PARAM:
     140                                result = changeParam(genotype);
     141                                break;
     142                        case FS_MOD_MOD:
     143                                result = changeModifier(genotype);
     144                                break;
     145                        case FS_ADD_NEURO:
     146                                result = addNeuro(genotype);
     147                                break;
     148                        case FS_REM_NEURO:
     149                                result = removeNeuro(genotype);
     150                                break;
     151                        case FS_MOD_NEURO_CONNECTION:
     152                                result = changeNeuroConnection(genotype);
     153                                break;
     154                        case FS_ADD_NEURO_CONNECTION:
     155                                result = addNeuroConnection(genotype);
     156                                break;
     157                        case FS_REM_NEURO_CONNECTION:
     158                                result = removeNeuroConnection(genotype);
     159                                break;
     160                        case FS_MOD_NEURO_PARAMS:
     161                                result = changeNeuroParam(genotype);
     162                                break;
     163                }
     164
     165                if (result)
     166                {
     167                        free(geno);
     168                        geno = strdup(genotype.getGeno().c_str());
     169                        return GENOPER_OK;
     170                }
     171                return GENOPER_OPFAIL;
     172        }
     173        catch (fS_Exception &e)
     174        {
     175                logPrintf("GenoOper_fS", "mutate", LOG_WARN, e.what());
     176                return GENOPER_OPFAIL;
     177        }
    135178}
    136179
    137180int GenoOper_fS::crossOver(char *&g0, char *&g1, float &chg0, float &chg1)
    138181{
    139         assert(PARENT_COUNT == 2); // Cross over works only for 2 parents
    140         fS_Genotype *parents[PARENT_COUNT] = {new fS_Genotype(g0), new fS_Genotype(g1)};
    141 
    142         // Choose random subtrees that have similar size
    143         Node *selected[PARENT_COUNT];
    144         vector<Node*> allNodes0 = parents[0]->getAllNodes();
    145         vector<Node*> allNodes1 = parents[1]->getAllNodes();
    146 
    147         double bestQuotient = DBL_MAX;
    148         for (int i = 0; i < crossOverTries; i++)
    149         {
    150                 Node *tmp0 = allNodes0[rndUint(allNodes0.size())];
    151                 Node *tmp1 = allNodes1[rndUint(allNodes1.size())];
    152                 // Choose this pair if it is the most similar
    153                 double quotient = double(tmp0->getNodeCount()) / double(tmp1->getNodeCount());
    154                 if(quotient < 1.0)
    155                         quotient = 1.0 / quotient;
    156                 if (quotient < bestQuotient)
    157                 {
    158                         bestQuotient = quotient;
    159                         selected[0] = tmp0;
    160                         selected[1] = tmp1;
    161                 }
    162                 if (bestQuotient == 1.0)
    163                         break;
    164         }
    165 
    166         // Compute gene percentages in children
    167         double subtreeSizes[PARENT_COUNT], restSizes[PARENT_COUNT];
    168         for (int i = 0; i < PARENT_COUNT; i++)
    169         {
    170 
    171                 subtreeSizes[i] = selected[i]->getNodeCount();
    172                 restSizes[i] = parents[i]->getNodeCount() - subtreeSizes[i];
    173         }
    174         chg0 = restSizes[0] / (restSizes[0] + subtreeSizes[1]);
    175         chg1 = restSizes[1] / (restSizes[1] + subtreeSizes[0]);
    176 
    177         // Rearrange neurons before crossover
    178         int subOldStart[PARENT_COUNT] {-1, -1};
    179         rearrangeConnectionsBeforeCrossover(parents[0], selected[0], subOldStart[0]);
    180         rearrangeConnectionsBeforeCrossover(parents[1], selected[1], subOldStart[1]);
    181 
    182         // Swap the subtress
    183         for(int i=0; i<PARENT_COUNT; i++)
    184         {
    185                 Node *other = selected[1 - i];
    186                 Node *p = selected[i]->parent;
    187                 if (p != nullptr)
    188                 {
    189                         size_t index = std::distance(p->children.begin(), std::find(p->children.begin(), p->children.end(), selected[i]));
    190                         p->children[index] = other;
    191                 } else
    192                         parents[i]->startNode = other;
    193         }
    194 
    195         // Rearrange neurons after crossover
    196         rearrangeConnectionsAfterCrossover(parents[0], selected[1], subOldStart[0]);
    197         rearrangeConnectionsAfterCrossover(parents[1], selected[0], subOldStart[1]);
    198 
    199         // Clenup, assign children to result strings
    200         free(g0);
    201         free(g1);
    202         g0 = strdup(parents[0]->getGeno().c_str());
    203         g1 = strdup(parents[1]->getGeno().c_str());
    204 
    205         delete parents[0];
    206         delete parents[1];
     182        try
     183        {
     184                assert(PARENT_COUNT == 2); // Cross over works only for 2 parents
     185                fS_Genotype *parents[PARENT_COUNT] = {new fS_Genotype(g0), new fS_Genotype(g1)};
     186
     187                // Choose random subtrees that have similar size
     188                Node *selected[PARENT_COUNT];
     189                vector < Node * > allNodes0 = parents[0]->getAllNodes();
     190                vector < Node * > allNodes1 = parents[1]->getAllNodes();
     191
     192                double bestQuotient = DBL_MAX;
     193                for (int i = 0; i < crossOverTries; i++)
     194                {
     195                        Node *tmp0 = allNodes0[rndUint(allNodes0.size())];
     196                        Node *tmp1 = allNodes1[rndUint(allNodes1.size())];
     197                        // Choose this pair if it is the most similar
     198                        double quotient = double(tmp0->getNodeCount()) / double(tmp1->getNodeCount());
     199                        if (quotient < 1.0)
     200                                quotient = 1.0 / quotient;
     201                        if (quotient < bestQuotient)
     202                        {
     203                                bestQuotient = quotient;
     204                                selected[0] = tmp0;
     205                                selected[1] = tmp1;
     206                        }
     207                        if (bestQuotient == 1.0)
     208                                break;
     209                }
     210
     211                // Compute gene percentages in children
     212                double subtreeSizes[PARENT_COUNT], restSizes[PARENT_COUNT];
     213                for (int i = 0; i < PARENT_COUNT; i++)
     214                {
     215
     216                        subtreeSizes[i] = selected[i]->getNodeCount();
     217                        restSizes[i] = parents[i]->getNodeCount() - subtreeSizes[i];
     218                }
     219                chg0 = restSizes[0] / (restSizes[0] + subtreeSizes[1]);
     220                chg1 = restSizes[1] / (restSizes[1] + subtreeSizes[0]);
     221
     222                // Rearrange neurons before crossover
     223                int subOldStart[PARENT_COUNT] {-1, -1};
     224                rearrangeConnectionsBeforeCrossover(parents[0], selected[0], subOldStart[0]);
     225                rearrangeConnectionsBeforeCrossover(parents[1], selected[1], subOldStart[1]);
     226
     227                // Swap the subtress
     228                for (int i = 0; i < PARENT_COUNT; i++)
     229                {
     230                        Node *other = selected[1 - i];
     231                        Node *p = selected[i]->parent;
     232                        if (p != nullptr)
     233                        {
     234                                size_t index = std::distance(p->children.begin(), std::find(p->children.begin(), p->children.end(), selected[i]));
     235                                p->children[index] = other;
     236                        } else
     237                                parents[i]->startNode = other;
     238                }
     239
     240                // Rearrange neurons after crossover
     241                rearrangeConnectionsAfterCrossover(parents[0], selected[1], subOldStart[0]);
     242                rearrangeConnectionsAfterCrossover(parents[1], selected[0], subOldStart[1]);
     243
     244                // Clenup, assign children to result strings
     245                free(g0);
     246                free(g1);
     247                g0 = strdup(parents[0]->getGeno().c_str());
     248                g1 = strdup(parents[1]->getGeno().c_str());
     249
     250                delete parents[0];
     251                delete parents[1];
     252        }
     253        catch (fS_Exception &e)
     254        {
     255                logPrintf("GenoOper_fS", "crossOver", LOG_WARN, e.what());
     256                return GENOPER_OPFAIL;
     257        }
    207258        return GENOPER_OK;
    208259}
    209260
    210 const char* GenoOper_fS::getSimplest()
    211 {
    212         return "C{x=0.80599;y=0.80599;z=0.80599}";
     261const char *GenoOper_fS::getSimplest()
     262{
     263        return "1.1:C{x=0.80599;y=0.80599;z=0.80599}";
    213264}
    214265
     
    220271        {
    221272                style = GENSTYLE_RGBS(0, 0, 200, GENSTYLE_BOLD);
    222         }
    223         else if(JOINTS.find(ch) != string::npos)        // Joint type
     273        } else if (JOINTS.find(ch) != string::npos)    // Joint type
    224274        {
    225275                style = GENSTYLE_RGBS(0, 200, 200, GENSTYLE_BOLD);
    226         }
    227         else if(MODIFIERS.find(ch) != string::npos) // Modifier
     276        } else if (MODIFIERS.find(ch) != string::npos) // Modifier
    228277        {
    229278                style = GENSTYLE_RGBS(0, 200, 0, GENSTYLE_NONE);
    230         }
    231         else if (isdigit(ch) || strchr(".", ch)) // Numerical value
     279        } else if (isdigit(ch) || strchr(".", ch)) // Numerical value
    232280        {
    233281                style = GENSTYLE_RGBS(200, 0, 0, GENSTYLE_NONE);
    234         }
    235         else if(strchr("()_;[],=", ch))
     282        } else if (strchr("()_;[],=", ch))
    236283        {
    237284                style = GENSTYLE_CS(0, GENSTYLE_BOLD); // Important char
     
    243290void GenoOper_fS::rearrangeConnectionsBeforeCrossover(fS_Genotype *geno, Node *sub, int &subStart)
    244291{
    245         vector<fS_Neuron*> genoNeurons = geno->getAllNeurons();
    246         vector<fS_Neuron*> subNeurons = fS_Genotype::extractNeurons(sub);
     292        vector < fS_Neuron * > genoNeurons = geno->getAllNeurons();
     293        vector < fS_Neuron * > subNeurons = fS_Genotype::extractNeurons(sub);
    247294
    248295        if (!subNeurons.empty())
     
    255302void GenoOper_fS::rearrangeConnectionsAfterCrossover(fS_Genotype *geno, Node *sub, int subOldStart)
    256303{
    257         vector<fS_Neuron*> genoNeurons = geno->getAllNeurons();
    258         vector<fS_Neuron*> subNeurons = fS_Genotype::extractNeurons(sub);
     304        vector < fS_Neuron * > genoNeurons = geno->getAllNeurons();
     305        vector < fS_Neuron * > subNeurons = fS_Genotype::extractNeurons(sub);
    259306
    260307        // Shift the inputs right
     
    281328}
    282329
    283 bool GenoOper_fS::addPart(fS_Genotype &geno, string availableTypes, bool mutateSize)
     330bool GenoOper_fS::addPart(fS_Genotype &geno, const vector <Part::Shape> &availablePartShapes, bool mutateSize)
    284331{
    285332        geno.getState();
    286333        Node *node = geno.chooseNode();
    287         char partType = availableTypes[rndUint(availableTypes.length())];
     334        char partType = SHAPETYPE_TO_GENE.at(availablePartShapes[rndUint(availablePartShapes.size())]);
    288335
    289336        Substring substring(&partType, 0, 1);
    290         Node *newNode = new Node(substring, node);
     337        Node *newNode = new Node(substring, node, node->genotypeParams);
    291338        // Add random rotation
    292         string rotationParams[]{ROT_X, ROT_Y, ROT_Z};
    293         if(strongAddPart)
    294         {
    295                 for(int i=0; i < 3; i++)
     339        string rotationParams[] {ROT_X, ROT_Y, ROT_Z};
     340        if (strongAddPart)
     341        {
     342                for (int i = 0; i < 3; i++)
    296343                        newNode->params[rotationParams[i]] = RndGen.Uni(-M_PI / 2, M_PI / 2);
    297         }
    298         else
     344        } else
    299345        {
    300346                string selectedParam = rotationParams[rndUint(3)];
    301347                newNode->params[selectedParam] = RndGen.Uni(-M_PI / 2, M_PI / 2);
    302348        }
    303         string rParams[]{RX, RY, RZ};
    304         if(strongAddPart)
    305         {
    306                 for(int i=0; i < 3; i++)
     349        string rParams[] {RX, RY, RZ};
     350        if (strongAddPart)
     351        {
     352                for (int i = 0; i < 3; i++)
    307353                        newNode->params[rParams[i]] = RndGen.Uni(-M_PI / 2, M_PI / 2);
    308         }
    309         else
     354        } else
    310355        {
    311356                string selectedParam = rParams[rndUint(3)];
     
    329374        {
    330375                geno.getState();
    331                 newNode->changeSizeParam(SIZE_X, true);
    332                 newNode->changeSizeParam(SIZE_Y, true);
    333                 newNode->changeSizeParam(SIZE_Z, true);
     376                newNode->mutateSizeParam(SIZE_X, true);
     377                newNode->mutateSizeParam(SIZE_Y, true);
     378                newNode->mutateSizeParam(SIZE_Z, true);
    334379        }
    335380        return true;
     
    362407}
    363408
    364 bool GenoOper_fS::changePartType(fS_Genotype &geno, string availTypes)
    365 {
    366         int availTypesLength = availTypes.length();
     409bool GenoOper_fS::changePartType(fS_Genotype &geno, const vector <Part::Shape> &availablePartShapes)
     410{
     411        int availShapesLen = availablePartShapes.size();
    367412        for (int i = 0; i < mutationTries; i++)
    368413        {
    369414                Node *randomNode = geno.chooseNode();
    370                 int index = rndUint(availTypesLength);
    371                 if (availTypes[index] == SHAPETYPE_TO_GENE.at(randomNode->partType))
    372                         index = (index + 1 + rndUint(availTypesLength - 1)) % availTypesLength;
    373                 char newTypeChr = availTypes[index];
    374 
    375                 auto itr = GENE_TO_SHAPETYPE.find(newTypeChr);
    376                 Part::Shape newType = itr->second;
     415                int index = rndUint(availShapesLen);
     416                if (availablePartShapes[index] == randomNode->partType)
     417                        index = (index + 1 + rndUint(availShapesLen - 1)) % availShapesLen;
     418                Part::Shape newType = availablePartShapes[index];
    377419
    378420#ifdef _DEBUG
     
    385427                double relativeVolume = randomNode->calculateVolume() / pow(sizeMultiplier, 3.0);
    386428
    387                 if(!ensureCircleSection || newType == Part::Shape::SHAPE_CUBOID || (randomNode->partType == Part::Shape::SHAPE_ELLIPSOID && newType == Part::Shape::SHAPE_CYLINDER))
     429                if (!ensureCircleSection || newType == Part::Shape::SHAPE_CUBOID || (randomNode->partType == Part::Shape::SHAPE_ELLIPSOID && newType == Part::Shape::SHAPE_CYLINDER))
    388430                {
    389431                        double radiusQuotient = std::cbrt(volumeMultipliers.at(randomNode->partType) / volumeMultipliers.at(newType));
     
    391433                        randomNode->params[SIZE_Y] = randomNode->getParam(SIZE_Y) * radiusQuotient;
    392434                        randomNode->params[SIZE_Z] = randomNode->getParam(SIZE_Z) * radiusQuotient;
    393                 }
    394                 else if(randomNode->partType == Part::Shape::SHAPE_CUBOID && newType == Part::Shape::SHAPE_CYLINDER)
     435                } else if (randomNode->partType == Part::Shape::SHAPE_CUBOID && newType == Part::Shape::SHAPE_CYLINDER)
    395436                {
    396437                        double newRadius = 0.5 * (randomNode->getParam(SIZE_X) + randomNode->getParam(SIZE_Y));
    397                         randomNode->params[SIZE_X] = newRadius;
     438                        randomNode->params[SIZE_X] = 0.5 * relativeVolume / (M_PI * newRadius * newRadius);
    398439                        randomNode->params[SIZE_Y] = newRadius;
    399                         randomNode->params[SIZE_Z] = 0.5 * relativeVolume / (M_PI * newRadius * newRadius);
    400                 }
    401                 else if(newType == Part::Shape::SHAPE_ELLIPSOID)
     440                        randomNode->params[SIZE_Z] = newRadius;
     441                } else if (newType == Part::Shape::SHAPE_ELLIPSOID)
    402442                {
    403443                        double newRelativeRadius = cbrt(relativeVolume / volumeMultipliers.at(newType));
     
    405445                        randomNode->params[SIZE_Y] = newRelativeRadius;
    406446                        randomNode->params[SIZE_Z] = newRelativeRadius;
    407                 }
    408                 else
     447                } else
    409448                {
    410449                        throw fS_Exception("Invalid part type", 1);
     
    422461
    423462        Node *randomNode = geno.chooseNode(1);        // First part does not have joints
    424         int jointLen  = ALL_JOINTS.length();
     463        int jointLen = ALL_JOINTS.length();
    425464        int index = rndUint(jointLen);
    426465        if (ALL_JOINTS[index] == randomNode->joint)
     
    441480                return false;
    442481        // Do not allow invalid changes in part size
    443         bool isRadiusOfBase = key == SIZE_X || key == SIZE_Y;
    444         bool isRadius = isRadiusOfBase || key == SIZE_Z;
     482        bool isRadiusOfBase = key == SIZE_Y || key == SIZE_Z;
     483        bool isRadius = isRadiusOfBase || key == SIZE_X;
    445484        if (ensureCircleSection && isRadius)
    446485        {
     
    486525
    487526                        // Do not allow invalid changes in part size
    488                         if (it->first != SIZE_X && it->first != SIZE_Y && it->first != SIZE_Z)
     527                        if (std::find(SIZE_PARAMS.begin(), SIZE_PARAMS.end(), it->first) == SIZE_PARAMS.end())
    489528                        {
    490529                                it->second = GenoOperators::mutateCreep('f', it->second, minValues.at(it->first), maxValues.at(it->first), true);
    491530                                return true;
    492531                        } else
    493                                 return randomNode->changeSizeParam(it->first, ensureCircleSection);
     532                                return randomNode->mutateSizeParam(it->first, ensureCircleSection);
    494533                }
    495534        }
     
    516555        Node *randomNode = geno.chooseNode();
    517556        fS_Neuron *newNeuron;
    518         NeuroClass *rndclass = GenoOperators::getRandomNeuroClass(Model::SHAPE_SOLIDS);
    519         if(rndclass->preflocation == 2 && randomNode == geno.startNode)
     557        NeuroClass *rndclass = GenoOperators::getRandomNeuroClass(Model::SHAPETYPE_SOLIDS);
     558        if (rndclass->preflocation == NeuroClass::PREFER_JOINT && randomNode == geno.startNode)
    520559                return false;
    521560
     
    526565        {
    527566                // Create as many connections for the neuron as possible (at most prefinputs)
    528                 vector<fS_Neuron*> allNeurons = geno.getAllNeurons();
     567                vector < fS_Neuron * > allNeurons = geno.getAllNeurons();
    529568                vector<int> neuronsWithOutput;
    530569                for (int i = 0; i < int(allNeurons.size()); i++)
     
    574613bool GenoOper_fS::changeNeuroConnection(fS_Genotype &geno)
    575614{
    576         vector<fS_Neuron*> neurons = geno.getAllNeurons();
     615        vector < fS_Neuron * > neurons = geno.getAllNeurons();
    577616        if (neurons.empty())
    578617                return false;
     
    597636bool GenoOper_fS::addNeuroConnection(fS_Genotype &geno)
    598637{
    599         vector<fS_Neuron*> neurons = geno.getAllNeurons();
     638        vector < fS_Neuron * > neurons = geno.getAllNeurons();
    600639        if (neurons.empty())
    601640                return false;
     
    627666bool GenoOper_fS::removeNeuroConnection(fS_Genotype &geno)
    628667{
    629         vector<fS_Neuron*> neurons = geno.getAllNeurons();
     668        vector < fS_Neuron * > neurons = geno.getAllNeurons();
    630669        if (neurons.empty())
    631670                return false;
     
    649688bool GenoOper_fS::changeNeuroParam(fS_Genotype &geno)
    650689{
    651         vector<fS_Neuron*> neurons = geno.getAllNeurons();
     690        vector < fS_Neuron * > neurons = geno.getAllNeurons();
    652691        if (neurons.empty())
    653692                return false;
     
    656695        return GenoOperators::mutateRandomNeuroClassProperty(neu);
    657696}
     697
     698bool Node::mutateSizeParam(string key, bool ensureCircleSection)
     699{
     700        double oldValue = getParam(key);
     701        double volume = calculateVolume();
     702        double valueAtMinVolume, valueAtMaxVolume;
     703        if(key == SIZE)
     704        {
     705                valueAtMinVolume = oldValue * std::cbrt(Model::getMinPart().volume / volume);
     706                valueAtMaxVolume = oldValue * std::cbrt(Model::getMaxPart().volume / volume);
     707        }
     708        else
     709        {
     710                valueAtMinVolume = oldValue * Model::getMinPart().volume / volume;
     711                valueAtMaxVolume = oldValue * Model::getMaxPart().volume / volume;
     712        }
     713
     714        double min = std::max(minValues.at(key), valueAtMinVolume);
     715        double max = std::min(maxValues.at(key), valueAtMaxVolume);
     716
     717        params[key] = GenoOperators::mutateCreep('f', getParam(key), min, max, true);
     718
     719        if (!ensureCircleSection || isPartSizeValid())
     720                return true;
     721        else
     722        {
     723                params[key] = oldValue;
     724                return false;
     725        }
     726}
Note: See TracChangeset for help on using the changeset viewer.