Changeset 969


Ignore:
Timestamp:
06/30/20 00:32:56 (4 years ago)
Author:
Maciej Komosinski
Message:

fS: preserved volume during shape-type changes

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

Legend:

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

    r958 r969  
    1010#include "frams/util/rndutil.h"
    1111#include "frams/neuro/neurolibrary.h"
    12 
     12#include "../genooperators.h"
    1313
    1414int fS_Genotype::precision = 4;
    15 
    16 
    17 double round2(double var)
    18 {
    19         double value = (int) (var * 100 + .5);
    20         return (double) value / 100;
    21 }
     15bool fS_Genotype::TURN_WITH_ROTATION = false;
     16
    2217
    2318double fS_stod(const string&  str, int start, size_t* size)
     
    3025        {
    3126                throw fS_Exception("Invalid numeric value", start);
     27        }
     28        catch(const std::out_of_range& ex)
     29        {
     30                throw fS_Exception("Invalid numeric value; out of range", start);
    3231        }
    3332}
     
    3938        fr = _state->fr;
    4039        s = _state->s;
     40        stif = _state->stif;
    4141}
    4242
     
    5555{
    5656        Orient rotmatrix = Orient_1;
    57         rotmatrix.rotate(Pt3D(
    58                         Convert::toRadians(rotation.x),
    59                         Convert::toRadians(rotation.y),
    60                         Convert::toRadians(rotation.z)
    61         ));
     57        rotmatrix.rotate(rotation);
    6258        vector = rotmatrix.transform(vector);
    6359}
     
    115111}
    116112
    117 Node::Node(Substring &restOfGeno, bool _modifierMode, bool _paramMode, bool _cycleMode, Node *_parent)
     113Node::Node(Substring &restOfGeno, Node *_parent)
    118114{
    119115        parent = _parent;
    120         modifierMode = _modifierMode;
    121         paramMode = _paramMode;
    122         cycleMode = _cycleMode;
    123116        partDescription = new Substring(restOfGeno);
    124117
     
    293286                return item->second;
    294287        else
    295                 return defaultParamValues.at(key);
     288                return defaultValues.at(key);
    296289}
    297290
     
    415408}
    416409
    417 double getDistance(Pt3D radiiParent, Pt3D radii, Pt3D vector, Pt3D rotationParent, Pt3D rotation)
    418 {
     410double Node::getDistance()
     411{
     412        Pt3D size = calculateSize();
     413        Pt3D parentSize = parent->calculateSize();      // Here we are sure that parent is not nullptr
    419414        int parentSphereCount, sphereCount;
    420415        double parentSphereRadius, sphereRadius;
    421         Pt3D *centersParent = findSphereCenters(parentSphereCount, parentSphereRadius, radiiParent, rotationParent);
    422         Pt3D *centers = findSphereCenters(sphereCount, sphereRadius, radii, rotation);
     416        Pt3D *centersParent = findSphereCenters(parentSphereCount, parentSphereRadius, parentSize, parent->getRotation());
     417        Pt3D *centers = findSphereCenters(sphereCount, sphereRadius, size, getRotation());
    423418
    424419        double distanceThreshold = sphereRadius + parentSphereRadius;
    425420        double minDistance = 0.0;
    426         double maxDistance = 2 * (max3(radiiParent) + max3(radii));
     421        double maxDistance = 2 * (max3(parentSize) + max3(size));
    427422        double currentDistance = avg(maxDistance, minDistance);
    428423        int result = -1;
     424        int iterationNo = 0;
    429425        while (result != ADJACENT)
    430426        {
    431                 Pt3D currentVector = vector * currentDistance;
     427                iterationNo++;
     428                Pt3D currentVector = state->v * currentDistance;
    432429                result = isCollision(centersParent, centers, parentSphereCount, sphereCount, currentVector, distanceThreshold);
     430
    433431                if (result == DISJOINT)
    434432                {
     
    440438                        currentDistance = avg(maxDistance, currentDistance);
    441439                }
     440
     441                if(maxDistance <= 0 || iterationNo > 1000)
     442                        throw fS_Exception("Computing of distances between parts failed", 0);
    442443                if (currentDistance > maxDistance)
     444                {
    443445                        throw fS_Exception("Internal error; then maximal distance between parts exceeded.", 0);
     446                }
    444447                if (currentDistance < minDistance)
    445448                        throw fS_Exception("Internal error; the minimal distance between parts exceeded.", 0);
     
    449452        delete[] centersParent;
    450453        delete[] centers;
    451         return round2(currentDistance);
    452 }
    453 
    454 void Node::getState(State *_state, const Pt3D &parentSize)
     454        return currentDistance;
     455}
     456
     457void Node::getState(State *_state)
    455458{
    456459        if (state != nullptr)
     
    473476                else if (mod == MODIFIERS[2])
    474477                        state->s *= multiplier;
    475         }
    476 
    477         Pt3D size = calculateSize();
     478                else if (mod == MODIFIERS[3])
     479                        state->stif *= multiplier;
     480        }
     481
    478482        if (parent != nullptr)
    479483        {
     
    481485                state->rotate(getVectorRotation());
    482486
    483                 double distance = getDistance(parentSize, size, state->v, getRotation(), getRotation());
     487                double distance = getDistance();
    484488                state->addVector(distance);
    485489        }
    486490        for (int i = 0; i < int(children.size()); i++)
    487                 children[i]->getState(state, size);
     491                children[i]->getState(state);
    488492}
    489493
     
    493497        for (int i = 0; i < int(branches.size()); i++)
    494498        {
    495                 children.push_back(new Node(branches[i], modifierMode, paramMode, cycleMode, this));
     499                children.push_back(new Node(branches[i], this));
    496500        }
    497501}
     
    593597Pt3D Node::getVectorRotation()
    594598{
    595         double rx = getParam(ROT_X);
    596         double ry = getParam(ROT_Y);
    597         double rz = getParam(ROT_Z);
    598         return Pt3D(rx, ry, rz);
     599        return Pt3D(getParam(ROT_X), getParam(ROT_Y), getParam(ROT_Z));
    599600}
    600601
    601602Pt3D Node::getRotation()
    602603{
    603         double rx = getParam(RX);
    604         double ry = getParam(RY);
    605         double rz = getParam(RZ);
    606         return Pt3D(rx, ry, rz);
     604        Pt3D rotation = Pt3D(getParam(RX), getParam(RY), getParam(RZ));
     605        if(fS_Genotype::TURN_WITH_ROTATION)
     606                rotation += getVectorRotation();
     607        return rotation;
    607608}
    608609
     
    614615                addJointsToModel(model, parent);
    615616
    616 
    617617        for (int i = 0; i < int(neurons.size()); i++)
    618618        {
     
    639639{
    640640        part = new Part(partType);
    641         part->p = Pt3D(round2(state->location.x),
    642                                    round2(state->location.y),
    643                                    round2(state->location.z));
    644 
    645         part->friction = round2(getParam(FRICTION) * state->fr);
    646         part->ingest = round2(getParam(INGESTION) * state->ing);
     641        part->p = Pt3D(state->location.x,
     642                                   state->location.y,
     643                                   state->location.z);
     644
     645        part->friction = getParam(FRICTION) * state->fr;
     646        part->ingest = getParam(INGESTION) * state->ing;
    647647        Pt3D size = calculateSize();
    648         part->scale.x = round2(size.x);
    649         part->scale.y = round2(size.y);
    650         part->scale.z = round2(size.z);
     648        part->scale.x = size.x;
     649        part->scale.y = size.y;
     650        part->scale.z = size.z;
    651651        part->setRot(getRotation());
    652652}
     
    655655{
    656656        Joint *j = new Joint();
     657        j->stif = getParam(STIFFNESS) * state->stif;
     658        j->rotstif = j->stif;
     659
    657660        j->attachToParts(parent->part, part);
    658661        switch (joint)
     
    698701                        if (i != 0)
    699702                                result += NEURON_SEPARATOR;
    700                         if (n->getClassName() != "N")
    701                         {
    702                                 result += n->getDetails();
    703                                 if (!n->inputs.empty())
    704                                         result += NEURON_INTERNAL_SEPARATOR;
    705                         }
     703
     704                        result += n->getDetails();
     705                        if (!n->inputs.empty())
     706                                result += NEURON_INTERNAL_SEPARATOR;
     707
    706708                        for (auto it = n->inputs.begin(); it != n->inputs.end(); ++it)
    707709                        {
     
    714716                                        result += SString::valueOf(it->second);
    715717                                }
    716 
    717718                        }
    718719                }
     
    754755
    755756
    756 bool Node::changeSizeParam(string paramKey, double multiplier, bool ensureCircleSection)
    757 {
    758         double oldValue = getParam(paramKey);
    759         params[paramKey] = oldValue * multiplier;
     757bool 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);
    760761        if (!ensureCircleSection || isPartSizeValid())
    761762                return true;
    762763        else
    763764        {
    764                 params[paramKey] = oldValue;
     765                params[key] = oldValue;
    765766                return false;
    766767        }
     
    786787        {
    787788                string geno = genotype.c_str();
    788                 // M - modifier mode, S - standard mode
    789                 size_t modeSeparatorIndex = geno.find(':');
    790                 if (modeSeparatorIndex == string::npos)
    791                         throw fS_Exception("No mode separator", 0);
    792 
    793                 string modeStr = geno.substr(0, modeSeparatorIndex).c_str();
    794                 bool modifierMode = modeStr.find(MODIFIER_MODE) != string::npos;
    795                 bool paramMode = modeStr.find(PARAM_MODE) != string::npos;
    796                 bool cycleMode = modeStr.find(CYCLE_MODE) != string::npos;
    797 
    798                 int actualGenoStart = modeSeparatorIndex + 1;
    799                 Substring substring(geno.c_str(), actualGenoStart, geno.length() - actualGenoStart);
    800                 startNode = new Node(substring, modifierMode, paramMode, cycleMode, nullptr);
     789                Substring substring(geno.c_str(), 0, geno.length());
     790                startNode = new Node(substring, nullptr);
    801791                validateNeuroInputs();
    802792        }
     
    816806{
    817807        State *initialState = new State(Pt3D(0), Pt3D(1, 0, 0));
    818         startNode->getState(initialState, Pt3D(1.0));
    819 }
    820 
    821 double fS_Genotype::randomParamMultiplier()
    822 {
    823         double multiplier = 1 + fabs(RndGen.GaussStd());
    824         if (multiplier > PARAM_MAX_MULTIPLIER)
    825                 multiplier = PARAM_MAX_MULTIPLIER;
    826         if (rndUint(2) == 0)
    827                 multiplier = 1.0 / multiplier;
    828         return multiplier;
     808        startNode->getState(initialState);
    829809}
    830810
     
    833813        getState();
    834814        startNode->buildModel(model, nullptr);
    835 
    836815        buildNeuroConnections(model);
    837 
    838         // Additional joints
    839         vector<Node*> allNodes = getAllNodes();
    840         for (int i = 0; i < int(allNodes.size()); i++)
    841         {
    842                 Node *node = allNodes[i];
    843                 if (node->params.find(JOINT_DISTANCE) != node->params.end())
    844                 {
    845                         Node *otherNode = getNearestNode(allNodes, node);
    846                         if (otherNode != nullptr)
    847                         {
    848                                 // If other node is close enough, add a joint
    849                                 double distance = node->state->location.distanceTo(otherNode->state->location);
    850                                 if (distance < node->params[JOINT_DISTANCE])
    851                                 {
    852                                         Joint *joint = new Joint();
    853                                         joint->attachToParts(node->part, otherNode->part);
    854 
    855                                         joint->shape = Joint::Shape::SHAPE_FIXED;
    856                                         model.addJoint(joint);
    857                                 }
    858                         }
    859                 }
    860         }
    861816}
    862817
     
    905860        SString geno;
    906861        geno.memoryHint(100);     // Provide a small buffer from the start to improve performance
    907 
    908         if (startNode->modifierMode)
    909                 geno += MODIFIER_MODE;
    910         if (startNode->paramMode)
    911                 geno += PARAM_MODE;
    912         if (startNode->cycleMode)
    913                 geno += CYCLE_MODE;
    914 
    915         geno += ':';
    916862        startNode->getGeno(geno);
    917863        return geno;
     
    1010956                if (!nodes[i]->isPartSizeValid())
    1011957                {
    1012                         return nodes[i]->partDescription->start;
     958                        return 1 + nodes[i]->partDescription->start;
    1013959                }
    1014960        }
  • cpp/frams/genetics/fS/fS_general.h

    r958 r969  
    1414#include "frams/util/multirange.h"
    1515
    16 /** @name Names of genotype modes */
    17 //@{
    18 #define MODIFIER_MODE 'M'
    19 #define PARAM_MODE 'S'
    20 #define CYCLE_MODE 'J'
    21 //@}
    22 
    2316/** @name Values of constants used in encoding */
    2417//@{
    2518#define BRANCH_START '('
    2619#define BRANCH_END ')'
    27 #define BRANCH_SEPARATOR ','
     20#define BRANCH_SEPARATOR '^'
    2821#define PARAM_START '{'
    2922#define PARAM_END '}'
     
    4538/** @name Every modifier changes the underlying value by this multiplier */
    4639const double MODIFIER_MULTIPLIER = 1.1;
    47 /** @name In mutation parameters will be multiplied by at most this value */
    48 const double PARAM_MAX_MULTIPLIER = 1.5;
    49 
    5040/**
    5141 * Used in finding the proper distance between the parts
     
    7060#define INGESTION "i"
    7161#define FRICTION "f"
     62#define STIFFNESS "st"
    7263#define SIZE "s"
    7364#define SIZE_X "x"
     
    8071#define RY "ry"
    8172#define RZ "rz"
    82 #define JOINT_DISTANCE "j"
    8373//@}
    8474/** @name Macros and values used in collision detection */
     
    113103const char DEFAULT_JOINT = 'a';
    114104const string JOINTS = "bc";
     105const string ALL_JOINTS = "abc";
    115106const int JOINT_COUNT = JOINTS.length();
    116 const string MODIFIERS = "IFS";
     107const string MODIFIERS = "IFST";
    117108const char SIZE_MODIFIER = 's';
    118109const vector<string> PARAMS {INGESTION, FRICTION, ROT_X, ROT_Y, ROT_Z, RX, RY, RZ, SIZE, SIZE_X, SIZE_Y, SIZE_Z,
    119                                                           JOINT_DISTANCE};
     110                                                         STIFFNESS};
    120111
    121112/** @name Default values of node parameters*/
    122113static const Part defPart = Model::getDefPart();
    123 const std::map<string, double> defaultParamValues = {
     114static const Joint defJoint = Model::getDefJoint();
     115const std::map<Part::Shape, double> volumeMultipliers = {
     116                {Part::Shape::SHAPE_CUBOID, 8.0},
     117                {Part::Shape::SHAPE_CYLINDER, 2.0 * M_PI},
     118                {Part::Shape::SHAPE_ELLIPSOID, (4.0 / 3.0) * M_PI},
     119};
     120const std::map<string, double> defaultValues = {
    124121                {INGESTION,      defPart.ingest},
    125122                {FRICTION,       defPart.friction},
     123                {STIFFNESS,              defJoint.stif},
    126124                {ROT_X,          0.0},
    127125                {ROT_Y,          0.0},
     
    133131                {SIZE_X,         1.0},
    134132                {SIZE_Y,         1.0},
    135                 {SIZE_Z,         1.0},
    136                 {JOINT_DISTANCE, 1.0}
     133                {SIZE_Z,         1.0}
     134};
     135
     136const 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
     152const 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}
    137166};
    138167
     
    252281        double ing = 1.0;      /// Ingestion multiplier
    253282        double s = 1.0;      /// Size multipliers
     283        double stif = 1.0;      /// Stiffness multipliers
    254284
    255285        State(State *_state); /// Derive the state from parent
     
    301331private:
    302332        Substring *partDescription = nullptr;
    303         bool cycleMode, modifierMode, paramMode; /// Possible modes
    304333        Node *parent;
    305334        Part *part;     /// A part object built from node. Used in building the Model
     
    309338        vector<Node *> children;    /// Vector of all direct children
    310339        std::map<char, int> modifiers;     /// Vector of all modifiers
    311         char joint = DEFAULT_JOINT;           /// Set of all joints
    312340        vector<fS_Neuron *> neurons;    /// Vector of all the neurons
    313341
    314         static double calculateRadiusFromVolume(Part::Shape partType, double volume)
    315         {
    316                 double result;
    317                 switch (partType)
    318                 {
    319                         case Part::Shape::SHAPE_CUBOID:
    320                                 result = std::cbrt(volume / 8.0);
    321                                 break;
    322                         case Part::Shape::SHAPE_CYLINDER:
    323                                 result = std::cbrt(volume / (2.0 * M_PI));
    324                                 break;
    325                         case Part::Shape::SHAPE_ELLIPSOID:
    326                                 result = std::cbrt(volume / ((4.0 / 3.0) * M_PI));
    327                                 break;
    328                         default:
    329                                 logMessage("fS", "calculateVolume", LOG_ERROR, "Invalid part type");
    330                 }
    331                 return result;
    332         }
     342        double getDistance();
    333343
    334344        void cleanUp();
     
    384394         * @param _state state of the parent
    385395         */
    386         void getState(State *_state, const Pt3D &parentSize);
     396        void getState(State *_state);
    387397
    388398        /**
     
    419429
    420430public:
     431        char joint = DEFAULT_JOINT;           /// Set of all joints
    421432        Part::Shape partType;  /// The type of the part
    422433        State *state = nullptr; /// The phenotypic state that inherits from ancestors
    423434
    424         Node(Substring &genotype, bool _modifierMode, bool _paramMode, bool _cycleMode, Node *parent);
     435        Node(Substring &genotype, Node *parent);
    425436
    426437        ~Node();
     
    452463         * @return True if the parameter value was change, false otherwise
    453464         */
    454         bool changeSizeParam(string paramKey, double multiplier, bool ensureCircleSection);
     465        bool changeSizeParam(string paramKey, bool ensureCircleSection);
    455466
    456467        /**
     
    501512
    502513        static int precision;
     514        static bool TURN_WITH_ROTATION;
    503515
    504516        /**
     
    511523
    512524        void getState();
    513 
    514         /**
    515          * Get a random multiplier for parameter mutation
    516          * @return Random parameter multiplier
    517          */
    518         static double randomParamMultiplier();
    519525
    520526        /**
  • cpp/frams/genetics/fS/fS_oper.cpp

    r967 r969  
    1515                                {"fS_mut_rem_part",         0, 0, "Remove part",              "f 0 100 10", FIELD(prob[FS_REM_PART]),             "mutation: probability of deleting a part",},
    1616                                {"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_add_joint",        0, 0, "Add joint",                "f 0 100 10", FIELD(prob[FS_ADD_JOINT]),            "mutation: probability of adding a joint",},
    18                                 {"fS_mut_rem_joint",        0, 0, "Remove joint",             "f 0 100 10", FIELD(prob[FS_REM_JOINT]),            "mutation: probability of removing a joint",},
     17                                {"fS_mut_change_joint",        0, 0, "Change joint",                "f 0 100 10", FIELD(prob[FS_CHANGE_JOINT]),            "mutation: probability of changing a joint",},
    1918                                {"fS_mut_add_param",        0, 0, "Add param",                "f 0 100 10", FIELD(prob[FS_ADD_PARAM]),            "mutation: probability of adding a parameter",},
    2019                                {"fS_mut_rem_param",        0, 0, "Remove param",             "f 0 100 10", FIELD(prob[FS_REM_PARAM]),            "mutation: probability of removing a parameter",},
     
    4140        par.select(this);
    4241        par.setDefault();
    43         supported_format = "S";
     42        supported_format = 'S';
    4443}
    4544
     
    5352                {
    5453                        logPrintf("GenoOper_fS", "checkValidity", LOG_ERROR, "Invalid part size");
    55                         return 1 + errorPosition;
     54                        return errorPosition;
    5655                }
    5756        }
     
    9291                        result = changePartType(genotype, availableTypes);
    9392                        break;
    94                 case FS_ADD_JOINT:
    95                         result = addJoint(genotype);
    96                         break;
    97                 case FS_REM_JOINT:
    98                         result = removeJoint(genotype);
     93                case FS_CHANGE_JOINT:
     94                        result = changeJoint(genotype);
    9995                        break;
    10096                case FS_ADD_PARAM:
     
    214210const char* GenoOper_fS::getSimplest()
    215211{
    216         return "S:C{x=0.80599;y=0.80599;z=0.80599}";
     212        return "C{x=0.80599;y=0.80599;z=0.80599}";
    217213}
    218214
     
    233229                style = GENSTYLE_RGBS(0, 200, 0, GENSTYLE_NONE);
    234230        }
    235         else if (isdigit(ch) || strchr(".=", ch)) // Numerical value
     231        else if (isdigit(ch) || strchr(".", ch)) // Numerical value
    236232        {
    237233                style = GENSTYLE_RGBS(200, 0, 0, GENSTYLE_NONE);
    238234        }
    239         else if(strchr("()_;[],", ch))
     235        else if(strchr("()_;[],=", ch))
    240236        {
    241237                style = GENSTYLE_CS(0, GENSTYLE_BOLD); // Important char
     
    292288
    293289        Substring substring(&partType, 0, 1);
    294         Node *newNode = new Node(substring, node->modifierMode, node->paramMode, node->cycleMode, node);
     290        Node *newNode = new Node(substring, node);
    295291        // Add random rotation
    296292        string rotationParams[]{ROT_X, ROT_Y, ROT_Z};
     
    298294        {
    299295                for(int i=0; i < 3; i++)
    300                         newNode->params[rotationParams[i]] = RndGen.Uni(-90, 90);
     296                        newNode->params[rotationParams[i]] = RndGen.Uni(-M_PI / 2, M_PI / 2);
    301297        }
    302298        else
    303299        {
    304300                string selectedParam = rotationParams[rndUint(3)];
    305                 newNode->params[selectedParam] = RndGen.Uni(-90, 90);
     301                newNode->params[selectedParam] = RndGen.Uni(-M_PI / 2, M_PI / 2);
    306302        }
    307303        string rParams[]{RX, RY, RZ};
     
    309305        {
    310306                for(int i=0; i < 3; i++)
    311                         newNode->params[rParams[i]] = RndGen.Uni(-90, 90);
     307                        newNode->params[rParams[i]] = RndGen.Uni(-M_PI / 2, M_PI / 2);
    312308        }
    313309        else
    314310        {
    315311                string selectedParam = rParams[rndUint(3)];
    316                 newNode->params[selectedParam] = RndGen.Uni(-90, 90);
     312                newNode->params[selectedParam] = RndGen.Uni(-M_PI / 2, M_PI / 2);
    317313        }
    318314        // Assign part size to default value
     
    324320        double relativeVolume = volume / volumeMultiplier;    // Volume without applying modifiers
    325321
    326         double newRadius = Node::calculateRadiusFromVolume(newNode->partType, relativeVolume);
     322        double newRadius = std::cbrt(relativeVolume / volumeMultipliers.at(newNode->partType));
    327323        newNode->params[SIZE_X] = newRadius;
    328324        newNode->params[SIZE_Y] = newRadius;
     
    333329        {
    334330                geno.getState();
    335                 newNode->changeSizeParam(SIZE_X, fS_Genotype::randomParamMultiplier(), true);
    336                 newNode->changeSizeParam(SIZE_Y, fS_Genotype::randomParamMultiplier(), true);
    337                 newNode->changeSizeParam(SIZE_Z, fS_Genotype::randomParamMultiplier(), true);
     331                newNode->changeSizeParam(SIZE_X, true);
     332                newNode->changeSizeParam(SIZE_Y, true);
     333                newNode->changeSizeParam(SIZE_Z, true);
    338334        }
    339335        return true;
     
    374370                int index = rndUint(availTypesLength);
    375371                if (availTypes[index] == SHAPETYPE_TO_GENE.at(randomNode->partType))
    376                         index = (index + 1 + rndUint(availTypesLength)) % availTypesLength;
     372                        index = (index + 1 + rndUint(availTypesLength - 1)) % availTypesLength;
    377373                char newTypeChr = availTypes[index];
    378374
     
    385381#endif
    386382
    387                 if (ensureCircleSection)
    388                 {
    389                         geno.getState();
    390                         if (randomNode->partType == Part::Shape::SHAPE_CUBOID
    391                                 || (randomNode->partType == Part::Shape::SHAPE_CYLINDER && newType == Part::Shape::SHAPE_ELLIPSOID))
    392                         {
    393                                 double sizeMultiplier = randomNode->getParam(SIZE) * randomNode->state->s;
    394                                 double relativeVolume = randomNode->calculateVolume() / pow(sizeMultiplier, 3.0);
    395                                 double newRelativeRadius = Node::calculateRadiusFromVolume(newType, relativeVolume);
    396                                 randomNode->params[SIZE_X] = newRelativeRadius;
    397                                 randomNode->params[SIZE_Y] = newRelativeRadius;
    398                                 randomNode->params[SIZE_Z] = newRelativeRadius;
    399                         }
     383                geno.getState();
     384                double sizeMultiplier = randomNode->getParam(SIZE) * randomNode->state->s;
     385                double relativeVolume = randomNode->calculateVolume() / pow(sizeMultiplier, 3.0);
     386
     387                if(!ensureCircleSection || newType == Part::Shape::SHAPE_CUBOID || (randomNode->partType == Part::Shape::SHAPE_ELLIPSOID && newType == Part::Shape::SHAPE_CYLINDER))
     388                {
     389                        double radiusQuotient = std::cbrt(volumeMultipliers.at(randomNode->partType) / volumeMultipliers.at(newType));
     390                        randomNode->params[SIZE_X] = randomNode->getParam(SIZE_X) * radiusQuotient;
     391                        randomNode->params[SIZE_Y] = randomNode->getParam(SIZE_Y) * radiusQuotient;
     392                        randomNode->params[SIZE_Z] = randomNode->getParam(SIZE_Z) * radiusQuotient;
     393                }
     394                else if(randomNode->partType == Part::Shape::SHAPE_CUBOID && newType == Part::Shape::SHAPE_CYLINDER)
     395                {
     396                        double newRadius = 0.5 * (randomNode->getParam(SIZE_X) + randomNode->getParam(SIZE_Y));
     397                        randomNode->params[SIZE_X] = newRadius;
     398                        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)
     402                {
     403                        double newRelativeRadius = cbrt(relativeVolume / volumeMultipliers.at(newType));
     404                        randomNode->params[SIZE_X] = newRelativeRadius;
     405                        randomNode->params[SIZE_Y] = newRelativeRadius;
     406                        randomNode->params[SIZE_Z] = newRelativeRadius;
     407                }
     408                else
     409                {
     410                        throw fS_Exception("Invalid part type", 1);
    400411                }
    401412                randomNode->partType = newType;
     
    405416}
    406417
    407 bool GenoOper_fS::addJoint(fS_Genotype &geno)
     418bool GenoOper_fS::changeJoint(fS_Genotype &geno)
    408419{
    409420        if (geno.startNode->children.empty())
    410421                return false;
    411422
    412         Node *randomNode;
    413         for (int i = 0; i < mutationTries; i++)
    414         {
    415                 char randomJoint = JOINTS[rndUint(JOINT_COUNT)];
    416                 randomNode = geno.chooseNode(1);        // First part does not have joints
    417                 if (randomNode->joint == DEFAULT_JOINT)
    418                 {
    419                         randomNode->joint = randomJoint;
    420                         return true;
    421                 }
    422         }
    423         return false;
    424 }
    425 
    426 
    427 bool GenoOper_fS::removeJoint(fS_Genotype &geno)
    428 {
    429         // This operator may can lower success rate that others, as it does not work when there is only one node
    430         if (geno.startNode->children.size() < 1) // Only one node; there are no joints
    431                 return false;
    432 
    433         // Choose a node with joints
    434         for (int i = 0; i < mutationTries; i++)
    435         {
    436                 Node *randomNode = geno.chooseNode(1);    // First part does not have joints
    437                 if (randomNode->joint != DEFAULT_JOINT)
    438                 {
    439                         randomNode->joint = DEFAULT_JOINT;
    440                         return true;
    441                 }
    442         }
    443         return false;
     423        Node *randomNode = geno.chooseNode(1);        // First part does not have joints
     424        int jointLen  = ALL_JOINTS.length();
     425        int index = rndUint(jointLen);
     426        if (ALL_JOINTS[index] == randomNode->joint)
     427                index = (index + 1 + rndUint(jointLen - 1)) % jointLen;
     428
     429        randomNode->joint = ALL_JOINTS[index];
     430        return true;
    444431}
    445432
     
    450437        if (paramCount == int(PARAMS.size()))
    451438                return false;
    452         string selectedParam = PARAMS[rndUint(PARAMS.size())];
    453         // Not allow 'j' parameter when the cycle mode is not on
    454         if (selectedParam == JOINT_DISTANCE && !geno.startNode->cycleMode)
    455                 return false;
    456         if (randomNode->params.count(selectedParam) > 0)
     439        string key = PARAMS[rndUint(PARAMS.size())];
     440        if (randomNode->params.count(key) > 0)
    457441                return false;
    458442        // Do not allow invalid changes in part size
    459         bool isRadiusOfBase = selectedParam == SIZE_X || selectedParam == SIZE_Y;
    460         bool isRadius = isRadiusOfBase || selectedParam == SIZE_Z;
     443        bool isRadiusOfBase = key == SIZE_X || key == SIZE_Y;
     444        bool isRadius = isRadiusOfBase || key == SIZE_Z;
    461445        if (ensureCircleSection && isRadius)
    462446        {
     
    467451        }
    468452        // Add modified default value for param
    469         randomNode->params[selectedParam] = defaultParamValues.at(selectedParam);
     453        randomNode->params[key] = mutateCreep('f', defaultValues.at(key), minValues.at(key), maxValues.at(key), true);
    470454        return true;
    471455}
     
    501485                        advance(it, rndUint(paramCount));
    502486
    503                         double multiplier = fS_Genotype::randomParamMultiplier();
    504 
    505 
    506487                        // Do not allow invalid changes in part size
    507488                        if (it->first != SIZE_X && it->first != SIZE_Y && it->first != SIZE_Z)
    508489                        {
    509                                 it->second *= multiplier;
     490                                it->second = GenoOperators::mutateCreep('f', it->second, minValues.at(it->first), maxValues.at(it->first), true);
    510491                                return true;
    511492                        } else
    512                                 return randomNode->changeSizeParam(it->first, multiplier, ensureCircleSection);
     493                                return randomNode->changeSizeParam(it->first, ensureCircleSection);
    513494                }
    514495        }
     
    607588                        advance(it, rndUint(inputCount));
    608589
    609                         it->second = GenoOperators::getMutatedNeuroClassProperty(it->second, selectedNeuron, -1);
     590                        it->second = GenoOperators::getMutatedNeuronConnectionWeight(it->second);
    610591                        return true;
    611592                }
     
    673654
    674655        fS_Neuron *neu = neurons[rndUint(neurons.size())];
    675         SyntParam par = neu->classProperties();
    676 
    677         if (par.getPropCount() > 0)
    678         {
    679                 int i = rndUint(par.getPropCount());
    680                 if (*par.type(i) == 'f')
    681                 {
    682                         double change = GenoOperators::getMutatedNeuroClassProperty(par.getDouble(i), neu, GenoOperators::NEUROCLASS_PROP_OFFSET + i);
    683                         par.setDouble(i, change);
    684                 }
    685                 SString line;
    686                 int tmp = 0;
    687                 par.update(&line);
    688                 SString props;
    689                 line.getNextToken(tmp, props, '\n'); // removal of newline character
    690                 if (props != "")
    691                 {
    692                         SString det = neu->getClass()->name + ": " + props;
    693                         neu->setDetails(det);
    694                         return true;
    695                 }
    696         }
    697 
    698         return false;
    699 }
     656        return GenoOperators::mutateRandomNeuroClassProperty(neu);
     657}
  • cpp/frams/genetics/fS/fS_oper.h

    r958 r969  
    1515#define FS_REM_PART 1
    1616#define FS_MOD_PART 2
    17 #define FS_ADD_JOINT 3
    18 #define FS_REM_JOINT 4
    19 #define FS_ADD_PARAM 5
    20 #define FS_REM_PARAM 6
    21 #define FS_MOD_PARAM 7
    22 #define FS_MOD_MOD 8
    23 #define FS_ADD_NEURO 9
    24 #define FS_REM_NEURO 10
    25 #define FS_MOD_NEURO_CONNECTION 11
    26 #define FS_ADD_NEURO_CONNECTION 12
    27 #define FS_REM_NEURO_CONNECTION 13
    28 #define FS_MOD_NEURO_PARAMS 14
    29 #define FS_OPCOUNT 15
     17#define FS_CHANGE_JOINT 3
     18#define FS_ADD_PARAM 4
     19#define FS_REM_PARAM 5
     20#define FS_MOD_PARAM 6
     21#define FS_MOD_MOD 7
     22#define FS_ADD_NEURO 8
     23#define FS_REM_NEURO 9
     24#define FS_MOD_NEURO_CONNECTION 10
     25#define FS_ADD_NEURO_CONNECTION 11
     26#define FS_REM_NEURO_CONNECTION 12
     27#define FS_MOD_NEURO_PARAMS 13
     28#define FS_OPCOUNT 14
    3029//@}
    3130
     
    9089
    9190        /**
    92          * Performs add joint mutation on genotype
     91         * Changes the type of one joint in genotype
    9392         * @return true if mutation succeeded, false otherwise
    9493         */
    95         bool addJoint(fS_Genotype &geno);
    96 
    97         /**
    98          * Performs remove mutation on genotype
    99          * @return true if mutation succeeded, false otherwise
    100          */
    101         bool removeJoint(fS_Genotype &geno);
     94        bool changeJoint(fS_Genotype &geno);
    10295
    10396        /**
Note: See TracChangeset for help on using the changeset viewer.