Changeset 1000 for cpp/frams/genetics


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

Improved the fS encoding

Location:
cpp/frams/genetics/fS
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/fS/fS_conv.h

    r958 r1000  
    1919                name = "Solid encoding";
    2020
    21                 in_format = 'S';
    22                 out_format = '0';
     21                in_format = "S";
     22                out_format = "0s";
    2323                mapsupport = 1;
    2424        }
  • cpp/frams/genetics/fS/fS_general.cpp

    r973 r1000  
    1111#include "frams/neuro/neurolibrary.h"
    1212#include "../genooperators.h"
     13#include "common/nonstd_math.h"
     14#include "part_distance_estimator.h"
    1315
    1416int fS_Genotype::precision = 4;
    1517bool fS_Genotype::TURN_WITH_ROTATION = false;
    1618
     19const std::map<string, double> defaultValues = {
     20                {INGESTION,      0.5},//Model::getDefPart().ingest },
     21                {FRICTION,       0.5},//Model::getDefPart().friction},
     22                {STIFFNESS,              0.5},//Model::getDefJoint().stif},
     23                {ROT_X,          0.0},
     24                {ROT_Y,          0.0},
     25                {ROT_Z,          0.0},
     26                {RX,             0.0},
     27                {RY,             0.0},
     28                {RZ,             0.0},
     29                {SIZE,           1.0},
     30                {SIZE_X,         0.5},//Model::getDefPart().scale.x},
     31                {SIZE_Y,         0.5},//Model::getDefPart().scale.y},
     32                {SIZE_Z,         0.5}//Model::getDefPart().scale.z}
     33};
    1734
    1835double fS_stod(const string&  str, int start, size_t* size)
     
    5269}
    5370
    54 void rotateVector(Pt3D &vector, const Pt3D &rotation)
    55 {
    56         Orient rotmatrix = Orient_1;
    57         rotmatrix.rotate(rotation);
    58         vector = rotmatrix.transform(vector);
    59 }
    60 
    6171void State::rotate(const Pt3D &rotation)
    6272{
    63        rotateVector(v, rotation);
     73       fS_Utils::rotateVector(v, rotation);
    6474       v.normalize();
    6575}
     
    111121}
    112122
    113 Node::Node(Substring &restOfGeno, Node *_parent)
    114 {
     123Node::Node(Substring &restOfGeno, Node *_parent, GenotypeParams _genotypeParams)
     124{
     125        partDescription = new Substring(restOfGeno);
     126        genotypeParams = _genotypeParams;
    115127        parent = _parent;
    116         partDescription = new Substring(restOfGeno);
    117128
    118129        try
     
    289300}
    290301
    291 double avg(double a, double b)
    292 {
    293         return 0.5 * (a + b);
    294 }
    295 
    296 double min3(Pt3D p)
    297 {
    298         double tmp = p.x;
    299         if (p.y < tmp)
    300                 tmp = p.y;
    301         if (p.z < tmp)
    302                 tmp = p.z;
    303         return tmp;
    304 }
    305 
    306 double max3(Pt3D p)
    307 {
    308         double tmp = p.x;
    309         if (p.y > tmp)
    310                 tmp = p.y;
    311         if (p.z > tmp)
    312                 tmp = p.z;
    313         return tmp;
    314 }
    315 
    316 double getSphereCoordinate(double dimension, double sphereDiameter, double index, int count)
    317 {
    318         if (count == 1)
    319                 return 0;
    320         return (dimension - sphereDiameter) * (index / (count - 1) - 0.5);
    321 }
    322 
    323 Pt3D *findSphereCenters(int &sphereCount, double &sphereRadius, Pt3D radii, Pt3D rotations)
    324 {
    325         double sphereRelativeDistance = SPHERE_RELATIVE_DISTANCE;
    326         double minRadius = min3(radii);
    327         if(minRadius <= 0)
    328             throw fS_Exception("Invalid part size", 0);
    329         double maxRadius = max3(radii);
    330         if (MAX_DIAMETER_QUOTIENT > maxRadius / minRadius)
    331                 sphereRadius = minRadius;
    332         else
    333         {
    334                 // When max radius is much bigger than min radius
    335                 sphereRelativeDistance = 1.0;   // Make the spheres adjacent to speed up the computation
    336                 sphereRadius = maxRadius / MAX_DIAMETER_QUOTIENT;
    337         }
    338         double sphereDiameter = 2 * sphereRadius;
    339 
    340         double *diameters = new double[3] {2 * radii.x, 2 * radii.y, 2 * radii.z};
    341         int counts[3];
    342         for (int i = 0; i < 3; i++)
    343         {
    344                 counts[i] = 1;
    345                 if (diameters[i] > sphereDiameter)
    346                         counts[i] += ceil((diameters[i] - sphereDiameter) / sphereDiameter / sphereRelativeDistance);
    347         }
    348 
    349         sphereCount = counts[0] * counts[1] * counts[2];
    350         double x, y, z;
    351         int totalCount = 0;
    352         Pt3D *centers = new Pt3D[sphereCount];
    353         for (double xi = 0; xi < counts[0]; xi++)
    354         {
    355                 x = getSphereCoordinate(diameters[0], sphereDiameter, xi, counts[0]);
    356                 for (double yi = 0; yi < counts[1]; yi++)
    357                 {
    358                         y = getSphereCoordinate(diameters[1], sphereDiameter, yi, counts[1]);
    359                         for (double zi = 0; zi < counts[2]; zi++)
    360                         {
    361                                 z = getSphereCoordinate(diameters[2], sphereDiameter, zi, counts[2]);
    362                                 centers[totalCount] = Pt3D(x, y, z);
    363                                 rotateVector(centers[totalCount], rotations);
    364                                 totalCount++;
    365                         }
    366                 }
    367         }
    368         delete[] diameters;
    369         return centers;
    370 }
    371 
    372 int isCollision(Pt3D *centersParent, Pt3D *centers, int parentSphereCount, int sphereCount, Pt3D &vector,
    373                                 double distanceThreshold)
    374 {
    375         double upperThreshold = distanceThreshold;
    376         double lowerThreshold = SPHERE_DISTANCE_TOLERANCE * distanceThreshold;
    377         double distance;
    378         double dx, dy, dz;
    379         bool existsAdjacent = false;
    380         Pt3D *tmpPoint;
    381         for (int sc = 0; sc < sphereCount; sc++)
    382         {
    383                 Pt3D shiftedSphere = Pt3D(centers[sc]);
    384                 shiftedSphere += vector;
    385                 for (int psc = 0; psc < parentSphereCount; psc++)
    386                 {
    387                         tmpPoint = &centersParent[psc];
    388                         dx = shiftedSphere.x - tmpPoint->x;
    389                         dy = shiftedSphere.y - tmpPoint->y;
    390                         dz = shiftedSphere.z - tmpPoint->z;
    391                         distance = sqrt(dx * dx + dy * dy + dz * dz);
    392 
    393                         if (distance <= upperThreshold)
    394                         {
    395                                 if (distance >= lowerThreshold)
    396                                         existsAdjacent = true;
    397                                 else
    398                                 {
    399                                         return COLLISION;
    400                                 }
    401                         }
    402                 }
    403         }
    404         if (existsAdjacent)
    405                 return ADJACENT;
    406         else
    407                 return DISJOINT;
    408 }
    409 
    410 double Node::getDistance()
    411 {
    412         Pt3D size = calculateSize();
    413         Pt3D parentSize = parent->calculateSize();      // Here we are sure that parent is not nullptr
    414         int parentSphereCount, sphereCount;
    415         double parentSphereRadius, sphereRadius;
    416         Pt3D *centersParent = findSphereCenters(parentSphereCount, parentSphereRadius, parentSize, parent->getRotation());
    417         Pt3D *centers = findSphereCenters(sphereCount, sphereRadius, size, getRotation());
    418 
    419         double distanceThreshold = sphereRadius + parentSphereRadius;
    420         double minDistance = 0.0;
    421         double maxDistance = 2 * (max3(parentSize) + max3(size));
    422         double currentDistance = avg(maxDistance, minDistance);
    423         int result = -1;
    424         int iterationNo = 0;
    425         while (result != ADJACENT)
    426         {
    427                 iterationNo++;
    428                 Pt3D currentVector = state->v * currentDistance;
    429                 result = isCollision(centersParent, centers, parentSphereCount, sphereCount, currentVector, distanceThreshold);
    430 
    431                 if (result == DISJOINT)
    432                 {
    433                         maxDistance = currentDistance;
    434                         currentDistance = avg(currentDistance, minDistance);
    435                 } else if (result == COLLISION)
    436                 {
    437                         minDistance = currentDistance;
    438                         currentDistance = avg(maxDistance, currentDistance);
    439                 }
    440 
    441                 if(maxDistance <= 0 || iterationNo > 1000)
    442                         throw fS_Exception("Computing of distances between parts failed", 0);
    443                 if (currentDistance > maxDistance)
    444                 {
    445                         throw fS_Exception("Internal error; then maximal distance between parts exceeded.", 0);
    446                 }
    447                 if (currentDistance < minDistance)
    448                         throw fS_Exception("Internal error; the minimal distance between parts exceeded.", 0);
    449 
    450         }
    451 
    452         delete[] centersParent;
    453         delete[] centers;
    454         return currentDistance;
    455 }
    456302
    457303void Node::getState(State *_state)
     
    469315        {
    470316                char mod = it->first;
    471                 double multiplier = pow(MODIFIER_MULTIPLIER, it->second);
     317                double multiplier = pow(genotypeParams.modifierMultiplier, it->second);
    472318                if (mod == MODIFIERS[0])
    473319                        state->ing *= multiplier;
     
    497343        for (int i = 0; i < int(branches.size()); i++)
    498344        {
    499                 children.push_back(new Node(branches[i], this));
     345                children.push_back(new Node(branches[i], this, genotypeParams));
    500346        }
    501347}
     
    581427                return false;
    582428
    583         if (partType == Part::Shape::SHAPE_ELLIPSOID && max3(size) != min3(size))
     429        if (partType == Part::Shape::SHAPE_ELLIPSOID && fS_Utils::max3(size) != fS_Utils::min3(size))
    584430                // When not all radii have different values
    585431                return false;
    586         if (partType == Part::Shape::SHAPE_CYLINDER && size.x != size.y)
     432        if (partType == Part::Shape::SHAPE_CYLINDER && size.y != size.z)
    587433                // If base radii have different values
    588434                return false;
     
    619465                Neuro *neuro = new Neuro(*neurons[i]);
    620466                model.addNeuro(neuro);
    621                 if (neuro->getClass()->preflocation == 2 && parent != nullptr)
     467                if (neuro->getClass()->preflocation == NeuroClass::PREFER_JOINT && parent != nullptr)
    622468                {
    623469                        neuro->attachToJoint(model.getJoint(model.getJointCount() - 1));
     
    732578                        result += it->first.c_str();                    // Add parameter key to string
    733579                        result += PARAM_KEY_VALUE_SEPARATOR;
    734                         string value_text = std::to_string(it->second);
    735580                        // Round the value to two decimal places and add to string
    736                         result += value_text.substr(0, value_text.find(".") + fS_Genotype::precision).c_str();
     581                        result += doubleToString(it->second, fS_Genotype::precision).c_str();
    737582                }
    738583                result += PARAM_END;
     
    754599}
    755600
    756 
    757 bool Node::changeSizeParam(string key, bool ensureCircleSection)
    758 {
    759         double oldValue = getParam(key);
    760         params[key] = GenoOperators::mutateCreep('f', params[key], minValues.at(key), maxValues.at(key), true);
    761         if (!ensureCircleSection || isPartSizeValid())
    762                 return true;
    763         else
    764         {
    765                 params[key] = oldValue;
    766                 return false;
    767         }
    768 }
    769 
    770601void Node::getAllNodes(vector<Node *> &allNodes)
    771602{
     
    782613}
    783614
    784 fS_Genotype::fS_Genotype(const string &genotype)
     615fS_Genotype::fS_Genotype(const string &geno)
    785616{
    786617        try
    787618        {
    788                 string geno = genotype.c_str();
    789                 Substring substring(geno.c_str(), 0, geno.length());
    790                 startNode = new Node(substring, nullptr);
     619                GenotypeParams genotypeParams;
     620                genotypeParams.modifierMultiplier = 1.1;
     621
     622                size_t modeSeparatorIndex = geno.find(MODE_SEPARATOR);
     623                if (modeSeparatorIndex == string::npos)
     624                        throw fS_Exception("Genotype parameters missing", 0);
     625
     626                genotypeParams.modifierMultiplier = fS_stod(geno, 0, &modeSeparatorIndex);
     627
     628                int genoStart = modeSeparatorIndex + 1;
     629                Substring substring(geno.c_str(), genoStart, geno.length() - genoStart);
     630                startNode = new Node(substring, nullptr, genotypeParams);
    791631                validateNeuroInputs();
    792632        }
     
    859699{
    860700        SString geno;
    861         geno.reserve(100);     // Provide a small buffer from the start to improve performance
     701        geno.reserve(100);
     702
     703        geno += doubleToString(startNode->genotypeParams.modifierMultiplier, fS_Genotype::precision).c_str();
     704        geno += MODE_SEPARATOR;
     705
    862706        startNode->getGeno(geno);
    863707        return geno;
  • cpp/frams/genetics/fS/fS_general.h

    r969 r1000  
    1616/** @name Values of constants used in encoding */
    1717//@{
     18#define MODE_SEPARATOR ':'
    1819#define BRANCH_START '('
    1920#define BRANCH_END ')'
     
    3536        RIGHT = 1
    3637};
    37 
    38 /** @name Every modifier changes the underlying value by this multiplier */
    39 const double MODIFIER_MULTIPLIER = 1.1;
    40 /**
    41  * Used in finding the proper distance between the parts
    42  * distance between spheres / sphere radius
    43  * That default value can be changed in certain cases
    44  * */
    45 const float SPHERE_RELATIVE_DISTANCE = 0.25;
    46 /**
    47  * Used in finding the proper distance between the parts
    48  * The maximal allowed value for
    49  * maximal radius of the node / sphere radius
    50  */
    51 const int MAX_DIAMETER_QUOTIENT = 30;
    52 /**
    53  * The tolerance of the value of distance between parts
    54  */
    55 const double SPHERE_DISTANCE_TOLERANCE = 0.99;
    5638
    5739
     
    10991const vector<string> PARAMS {INGESTION, FRICTION, ROT_X, ROT_Y, ROT_Z, RX, RY, RZ, SIZE, SIZE_X, SIZE_Y, SIZE_Z,
    11092                                                         STIFFNESS};
     93const vector<string> SIZE_PARAMS {SIZE, SIZE_X, SIZE_Y, SIZE_Z};
    11194
    11295/** @name Default values of node parameters*/
    113 static const Part defPart = Model::getDefPart();
    114 static const Joint defJoint = Model::getDefJoint();
    11596const std::map<Part::Shape, double> volumeMultipliers = {
    11697                {Part::Shape::SHAPE_CUBOID, 8.0},
     
    11899                {Part::Shape::SHAPE_ELLIPSOID, (4.0 / 3.0) * M_PI},
    119100};
    120 const std::map<string, double> defaultValues = {
    121                 {INGESTION,      defPart.ingest},
    122                 {FRICTION,       defPart.friction},
    123                 {STIFFNESS,              defJoint.stif},
    124                 {ROT_X,          0.0},
    125                 {ROT_Y,          0.0},
    126                 {ROT_Z,          0.0},
    127                 {RX,             0.0},
    128                 {RY,             0.0},
    129                 {RZ,             0.0},
    130                 {SIZE,           1.0},
    131                 {SIZE_X,         1.0},
    132                 {SIZE_Y,         1.0},
    133                 {SIZE_Z,         1.0}
    134 };
    135 
    136 const std::map<string, double> minValues = {
    137                 {INGESTION,      0},
    138                 {FRICTION,       0},
    139                 {STIFFNESS,      0.0},
    140                 {ROT_X,          -M_PI},
    141                 {ROT_Y,          -M_PI},
    142                 {ROT_Z,          -M_PI},
    143                 {RX,             -M_PI},
    144                 {RY,             -M_PI},
    145                 {RZ,             -M_PI},
    146                 {SIZE,           0.01},
    147                 {SIZE_X,         0.01},
    148                 {SIZE_Y,         0.01},
    149                 {SIZE_Z,         0.01}
    150 };
    151 
    152 const std::map<string, double> maxValues = {
    153                 {INGESTION,      1.0},
    154                 {FRICTION,       1.0},
    155                 {STIFFNESS,      0.0},
    156                 {ROT_X,          M_PI},
    157                 {ROT_Y,          M_PI},
    158                 {ROT_Z,          M_PI},
    159                 {RX,             M_PI},
    160                 {RY,             M_PI},
    161                 {RZ,             M_PI},
    162                 {SIZE,           100.0},
    163                 {SIZE_X,         100.0},
    164                 {SIZE_Y,         100.0},
    165                 {SIZE_Z,         100.0}
    166 };
     101
     102extern const std::map<string, double> defaultValues;
    167103
    168104/** @name Number of tries of performing a mutation before GENOPER_FAIL is returned */
     
    318254};
    319255
     256struct GenotypeParams{
     257        double modifierMultiplier;      // Every modifier changes the underlying value by this multiplier
     258};
     259
    320260/**
    321261 * Represents a node in the graph that represents a genotype.
     
    334274        Part *part;     /// A part object built from node. Used in building the Model
    335275        int partCodeLen; /// The length of substring that directly describes the corresponding part
    336 
    337         std::map<string, double> params; /// The map of all the node params
     276        GenotypeParams genotypeParams;
     277
     278
    338279        vector<Node *> children;    /// Vector of all direct children
    339280        std::map<char, int> modifiers;     /// Vector of all modifiers
     
    432373        Part::Shape partType;  /// The type of the part
    433374        State *state = nullptr; /// The phenotypic state that inherits from ancestors
    434 
    435         Node(Substring &genotype, Node *parent);
     375        std::map<string, double> params; /// The map of all the node params
     376
     377        Node(Substring &genotype, Node *parent, GenotypeParams genotypeParams);
    436378
    437379        ~Node();
     
    463405         * @return True if the parameter value was change, false otherwise
    464406         */
    465         bool changeSizeParam(string paramKey,  bool ensureCircleSection);
     407        bool mutateSizeParam(string paramKey,  bool ensureCircleSection);
    466408
    467409        /**
  • 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}
  • cpp/frams/genetics/fS/fS_oper.h

    r969 r1000  
    7474         * @return true if mutation succeeded, false otherwise
    7575         */
    76         bool addPart(fS_Genotype &geno, string availableTypes = "ECR", bool mutateSize = true);
     76        bool addPart(fS_Genotype &geno, const vector<Part::Shape> &availablePartShapes, bool mutateSize = true);
    7777
    7878        /**
     
    8686         * @return true if mutation succeeded, false otherwise
    8787         */
    88         bool changePartType(fS_Genotype &geno, string availableTypes = "ECR");
     88        bool changePartType(fS_Genotype &geno, const vector<Part::Shape> &availablePartShapes);
    8989
    9090        /**
Note: See TracChangeset for help on using the changeset viewer.