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

Improved the fS encoding

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/fS/fS_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;
Note: See TracChangeset for help on using the changeset viewer.