Changeset 1000 for cpp/frams/genetics
- Timestamp:
- 07/13/20 13:53:25 (4 years ago)
- Location:
- cpp/frams/genetics/fS
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/fS/fS_conv.h
r958 r1000 19 19 name = "Solid encoding"; 20 20 21 in_format = 'S';22 out_format = '0';21 in_format = "S"; 22 out_format = "0s"; 23 23 mapsupport = 1; 24 24 } -
cpp/frams/genetics/fS/fS_general.cpp
r973 r1000 11 11 #include "frams/neuro/neurolibrary.h" 12 12 #include "../genooperators.h" 13 #include "common/nonstd_math.h" 14 #include "part_distance_estimator.h" 13 15 14 16 int fS_Genotype::precision = 4; 15 17 bool fS_Genotype::TURN_WITH_ROTATION = false; 16 18 19 const 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 }; 17 34 18 35 double fS_stod(const string& str, int start, size_t* size) … … 52 69 } 53 70 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 61 71 void State::rotate(const Pt3D &rotation) 62 72 { 63 rotateVector(v, rotation);73 fS_Utils::rotateVector(v, rotation); 64 74 v.normalize(); 65 75 } … … 111 121 } 112 122 113 Node::Node(Substring &restOfGeno, Node *_parent) 114 { 123 Node::Node(Substring &restOfGeno, Node *_parent, GenotypeParams _genotypeParams) 124 { 125 partDescription = new Substring(restOfGeno); 126 genotypeParams = _genotypeParams; 115 127 parent = _parent; 116 partDescription = new Substring(restOfGeno);117 128 118 129 try … … 289 300 } 290 301 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 else333 {334 // When max radius is much bigger than min radius335 sphereRelativeDistance = 1.0; // Make the spheres adjacent to speed up the computation336 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 = ¢ersParent[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 else398 {399 return COLLISION;400 }401 }402 }403 }404 if (existsAdjacent)405 return ADJACENT;406 else407 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 nullptr414 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 }456 302 457 303 void Node::getState(State *_state) … … 469 315 { 470 316 char mod = it->first; 471 double multiplier = pow( MODIFIER_MULTIPLIER, it->second);317 double multiplier = pow(genotypeParams.modifierMultiplier, it->second); 472 318 if (mod == MODIFIERS[0]) 473 319 state->ing *= multiplier; … … 497 343 for (int i = 0; i < int(branches.size()); i++) 498 344 { 499 children.push_back(new Node(branches[i], this ));345 children.push_back(new Node(branches[i], this, genotypeParams)); 500 346 } 501 347 } … … 581 427 return false; 582 428 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)) 584 430 // When not all radii have different values 585 431 return false; 586 if (partType == Part::Shape::SHAPE_CYLINDER && size. x != size.y)432 if (partType == Part::Shape::SHAPE_CYLINDER && size.y != size.z) 587 433 // If base radii have different values 588 434 return false; … … 619 465 Neuro *neuro = new Neuro(*neurons[i]); 620 466 model.addNeuro(neuro); 621 if (neuro->getClass()->preflocation == 2&& parent != nullptr)467 if (neuro->getClass()->preflocation == NeuroClass::PREFER_JOINT && parent != nullptr) 622 468 { 623 469 neuro->attachToJoint(model.getJoint(model.getJointCount() - 1)); … … 732 578 result += it->first.c_str(); // Add parameter key to string 733 579 result += PARAM_KEY_VALUE_SEPARATOR; 734 string value_text = std::to_string(it->second);735 580 // 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(); 737 582 } 738 583 result += PARAM_END; … … 754 599 } 755 600 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 else764 {765 params[key] = oldValue;766 return false;767 }768 }769 770 601 void Node::getAllNodes(vector<Node *> &allNodes) 771 602 { … … 782 613 } 783 614 784 fS_Genotype::fS_Genotype(const string &geno type)615 fS_Genotype::fS_Genotype(const string &geno) 785 616 { 786 617 try 787 618 { 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); 791 631 validateNeuroInputs(); 792 632 } … … 859 699 { 860 700 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 862 706 startNode->getGeno(geno); 863 707 return geno; -
cpp/frams/genetics/fS/fS_general.h
r969 r1000 16 16 /** @name Values of constants used in encoding */ 17 17 //@{ 18 #define MODE_SEPARATOR ':' 18 19 #define BRANCH_START '(' 19 20 #define BRANCH_END ')' … … 35 36 RIGHT = 1 36 37 }; 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 parts42 * distance between spheres / sphere radius43 * That default value can be changed in certain cases44 * */45 const float SPHERE_RELATIVE_DISTANCE = 0.25;46 /**47 * Used in finding the proper distance between the parts48 * The maximal allowed value for49 * maximal radius of the node / sphere radius50 */51 const int MAX_DIAMETER_QUOTIENT = 30;52 /**53 * The tolerance of the value of distance between parts54 */55 const double SPHERE_DISTANCE_TOLERANCE = 0.99;56 38 57 39 … … 109 91 const vector<string> PARAMS {INGESTION, FRICTION, ROT_X, ROT_Y, ROT_Z, RX, RY, RZ, SIZE, SIZE_X, SIZE_Y, SIZE_Z, 110 92 STIFFNESS}; 93 const vector<string> SIZE_PARAMS {SIZE, SIZE_X, SIZE_Y, SIZE_Z}; 111 94 112 95 /** @name Default values of node parameters*/ 113 static const Part defPart = Model::getDefPart();114 static const Joint defJoint = Model::getDefJoint();115 96 const std::map<Part::Shape, double> volumeMultipliers = { 116 97 {Part::Shape::SHAPE_CUBOID, 8.0}, … … 118 99 {Part::Shape::SHAPE_ELLIPSOID, (4.0 / 3.0) * M_PI}, 119 100 }; 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 102 extern const std::map<string, double> defaultValues; 167 103 168 104 /** @name Number of tries of performing a mutation before GENOPER_FAIL is returned */ … … 318 254 }; 319 255 256 struct GenotypeParams{ 257 double modifierMultiplier; // Every modifier changes the underlying value by this multiplier 258 }; 259 320 260 /** 321 261 * Represents a node in the graph that represents a genotype. … … 334 274 Part *part; /// A part object built from node. Used in building the Model 335 275 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 338 279 vector<Node *> children; /// Vector of all direct children 339 280 std::map<char, int> modifiers; /// Vector of all modifiers … … 432 373 Part::Shape partType; /// The type of the part 433 374 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); 436 378 437 379 ~Node(); … … 463 405 * @return True if the parameter value was change, false otherwise 464 406 */ 465 bool changeSizeParam(string paramKey, bool ensureCircleSection);407 bool mutateSizeParam(string paramKey, bool ensureCircleSection); 466 408 467 409 /** -
cpp/frams/genetics/fS/fS_oper.cpp
r974 r1000 12 12 { 13 13 {"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"}, 33 33 }; 34 34 35 35 #undef FIELDSTRUCT 36 37 38 39 const 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 55 const 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 36 71 37 72 GenoOper_fS::GenoOper_fS() … … 49 84 fS_Genotype genotype(geno); 50 85 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"); 54 89 return errorPosition; 55 90 } … … 57 92 catch (fS_Exception &e) 58 93 { 59 logPrintf("GenoOper_fS", "checkValidity", LOG_ ERROR, e.what());94 logPrintf("GenoOper_fS", "checkValidity", LOG_WARN, e.what()); 60 95 return 1 + e.errorPosition; 61 96 } … … 66 101 int GenoOper_fS::mutate(char *&geno, float &chg, int &method) 67 102 { 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 } 135 178 } 136 179 137 180 int GenoOper_fS::crossOver(char *&g0, char *&g1, float &chg0, float &chg1) 138 181 { 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 } 207 258 return GENOPER_OK; 208 259 } 209 260 210 const char *GenoOper_fS::getSimplest()211 { 212 return " C{x=0.80599;y=0.80599;z=0.80599}";261 const char *GenoOper_fS::getSimplest() 262 { 263 return "1.1:C{x=0.80599;y=0.80599;z=0.80599}"; 213 264 } 214 265 … … 220 271 { 221 272 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 224 274 { 225 275 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 228 277 { 229 278 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 232 280 { 233 281 style = GENSTYLE_RGBS(200, 0, 0, GENSTYLE_NONE); 234 } 235 else if(strchr("()_;[],=", ch)) 282 } else if (strchr("()_;[],=", ch)) 236 283 { 237 284 style = GENSTYLE_CS(0, GENSTYLE_BOLD); // Important char … … 243 290 void GenoOper_fS::rearrangeConnectionsBeforeCrossover(fS_Genotype *geno, Node *sub, int &subStart) 244 291 { 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); 247 294 248 295 if (!subNeurons.empty()) … … 255 302 void GenoOper_fS::rearrangeConnectionsAfterCrossover(fS_Genotype *geno, Node *sub, int subOldStart) 256 303 { 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); 259 306 260 307 // Shift the inputs right … … 281 328 } 282 329 283 bool GenoOper_fS::addPart(fS_Genotype &geno, string availableTypes, bool mutateSize)330 bool GenoOper_fS::addPart(fS_Genotype &geno, const vector <Part::Shape> &availablePartShapes, bool mutateSize) 284 331 { 285 332 geno.getState(); 286 333 Node *node = geno.chooseNode(); 287 char partType = availableTypes[rndUint(availableTypes.length())];334 char partType = SHAPETYPE_TO_GENE.at(availablePartShapes[rndUint(availablePartShapes.size())]); 288 335 289 336 Substring substring(&partType, 0, 1); 290 Node *newNode = new Node(substring, node );337 Node *newNode = new Node(substring, node, node->genotypeParams); 291 338 // 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++) 296 343 newNode->params[rotationParams[i]] = RndGen.Uni(-M_PI / 2, M_PI / 2); 297 } 298 else 344 } else 299 345 { 300 346 string selectedParam = rotationParams[rndUint(3)]; 301 347 newNode->params[selectedParam] = RndGen.Uni(-M_PI / 2, M_PI / 2); 302 348 } 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++) 307 353 newNode->params[rParams[i]] = RndGen.Uni(-M_PI / 2, M_PI / 2); 308 } 309 else 354 } else 310 355 { 311 356 string selectedParam = rParams[rndUint(3)]; … … 329 374 { 330 375 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); 334 379 } 335 380 return true; … … 362 407 } 363 408 364 bool GenoOper_fS::changePartType(fS_Genotype &geno, string availTypes)365 { 366 int avail TypesLength = availTypes.length();409 bool GenoOper_fS::changePartType(fS_Genotype &geno, const vector <Part::Shape> &availablePartShapes) 410 { 411 int availShapesLen = availablePartShapes.size(); 367 412 for (int i = 0; i < mutationTries; i++) 368 413 { 369 414 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]; 377 419 378 420 #ifdef _DEBUG … … 385 427 double relativeVolume = randomNode->calculateVolume() / pow(sizeMultiplier, 3.0); 386 428 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)) 388 430 { 389 431 double radiusQuotient = std::cbrt(volumeMultipliers.at(randomNode->partType) / volumeMultipliers.at(newType)); … … 391 433 randomNode->params[SIZE_Y] = randomNode->getParam(SIZE_Y) * radiusQuotient; 392 434 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) 395 436 { 396 437 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); 398 439 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) 402 442 { 403 443 double newRelativeRadius = cbrt(relativeVolume / volumeMultipliers.at(newType)); … … 405 445 randomNode->params[SIZE_Y] = newRelativeRadius; 406 446 randomNode->params[SIZE_Z] = newRelativeRadius; 407 } 408 else 447 } else 409 448 { 410 449 throw fS_Exception("Invalid part type", 1); … … 422 461 423 462 Node *randomNode = geno.chooseNode(1); // First part does not have joints 424 int jointLen 463 int jointLen = ALL_JOINTS.length(); 425 464 int index = rndUint(jointLen); 426 465 if (ALL_JOINTS[index] == randomNode->joint) … … 441 480 return false; 442 481 // 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; 445 484 if (ensureCircleSection && isRadius) 446 485 { … … 486 525 487 526 // 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()) 489 528 { 490 529 it->second = GenoOperators::mutateCreep('f', it->second, minValues.at(it->first), maxValues.at(it->first), true); 491 530 return true; 492 531 } else 493 return randomNode-> changeSizeParam(it->first, ensureCircleSection);532 return randomNode->mutateSizeParam(it->first, ensureCircleSection); 494 533 } 495 534 } … … 516 555 Node *randomNode = geno.chooseNode(); 517 556 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) 520 559 return false; 521 560 … … 526 565 { 527 566 // 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(); 529 568 vector<int> neuronsWithOutput; 530 569 for (int i = 0; i < int(allNeurons.size()); i++) … … 574 613 bool GenoOper_fS::changeNeuroConnection(fS_Genotype &geno) 575 614 { 576 vector <fS_Neuron*> neurons = geno.getAllNeurons();615 vector < fS_Neuron * > neurons = geno.getAllNeurons(); 577 616 if (neurons.empty()) 578 617 return false; … … 597 636 bool GenoOper_fS::addNeuroConnection(fS_Genotype &geno) 598 637 { 599 vector <fS_Neuron*> neurons = geno.getAllNeurons();638 vector < fS_Neuron * > neurons = geno.getAllNeurons(); 600 639 if (neurons.empty()) 601 640 return false; … … 627 666 bool GenoOper_fS::removeNeuroConnection(fS_Genotype &geno) 628 667 { 629 vector <fS_Neuron*> neurons = geno.getAllNeurons();668 vector < fS_Neuron * > neurons = geno.getAllNeurons(); 630 669 if (neurons.empty()) 631 670 return false; … … 649 688 bool GenoOper_fS::changeNeuroParam(fS_Genotype &geno) 650 689 { 651 vector <fS_Neuron*> neurons = geno.getAllNeurons();690 vector < fS_Neuron * > neurons = geno.getAllNeurons(); 652 691 if (neurons.empty()) 653 692 return false; … … 656 695 return GenoOperators::mutateRandomNeuroClassProperty(neu); 657 696 } 697 698 bool 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 74 74 * @return true if mutation succeeded, false otherwise 75 75 */ 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); 77 77 78 78 /** … … 86 86 * @return true if mutation succeeded, false otherwise 87 87 */ 88 bool changePartType(fS_Genotype &geno, string availableTypes = "ECR");88 bool changePartType(fS_Genotype &geno, const vector<Part::Shape> &availablePartShapes); 89 89 90 90 /**
Note: See TracChangeset
for help on using the changeset viewer.