source: cpp/frams/genetics/fS/fS_general.cpp @ 1000

Last change on this file since 1000 was 1000, checked in by Maciej Komosinski, 4 years ago

Improved the fS encoding

File size: 20.1 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 2019-2020  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include <float.h>
6#include "fS_general.h"
7#include "frams/model/geometry/geometryutils.h"
8#include "frams/genetics/genooperators.h"
9#include "common/Convert.h"
10#include "frams/util/rndutil.h"
11#include "frams/neuro/neurolibrary.h"
12#include "../genooperators.h"
13#include "common/nonstd_math.h"
14#include "part_distance_estimator.h"
15
16int fS_Genotype::precision = 4;
17bool fS_Genotype::TURN_WITH_ROTATION = false;
18
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};
34
35double fS_stod(const string&  str, int start, size_t* size)
36{
37        try
38        {
39                return std::stod(str, size);
40        }
41        catch(const std::invalid_argument& ex)
42        {
43                throw fS_Exception("Invalid numeric value", start);
44        }
45        catch(const std::out_of_range& ex)
46        {
47                throw fS_Exception("Invalid numeric value; out of range", start);
48        }
49}
50
51State::State(State *_state)
52{
53        location = Pt3D(_state->location);
54        v = Pt3D(_state->v);
55        fr = _state->fr;
56        s = _state->s;
57        stif = _state->stif;
58}
59
60State::State(Pt3D _location, Pt3D _v)
61{
62        location = Pt3D(_location);
63        v = Pt3D(_v);
64}
65
66void State::addVector(const double length)
67{
68        location += v * length;
69}
70
71void State::rotate(const Pt3D &rotation)
72{
73       fS_Utils::rotateVector(v, rotation);
74       v.normalize();
75}
76
77
78fS_Neuron::fS_Neuron(const char *str, int start, int length)
79{
80        if (length == 0)
81                return;
82
83        vector<SString> inputStrings;
84        strSplit(SString(str, length), NEURON_INTERNAL_SEPARATOR, false, inputStrings);
85        if (inputStrings.empty())
86                return;
87
88        int inputStart = 0;
89        SString details = "N";
90
91        SString tmp = inputStrings[0];
92        if(tmp.indexOf(':') != -1)
93                tmp = tmp.substr(0, tmp.indexOf(':'));
94
95        if (NeuroLibrary::staticlibrary.findClassIndex(tmp, true) != -1)
96        {
97                inputStart = 1;
98                details = inputStrings[0];
99        }
100        setDetails(details);
101
102        for (int i = inputStart; i < int(inputStrings.size()); i++)
103        {
104                SString keyValue = inputStrings[i];
105                int separatorIndex = keyValue.indexOf(NEURON_I_W_SEPARATOR);
106                const char *buffer = keyValue.c_str();
107                size_t keyLength;
108                double value;
109                if (separatorIndex == -1)
110                {
111                        keyLength = keyValue.length();
112                        value = DEFAULT_NEURO_CONNECTION_WEIGHT;
113                } else
114                {
115                        keyLength = separatorIndex;
116                        size_t valueLength = keyValue.length() - (separatorIndex);
117                        value = fS_stod(buffer + separatorIndex + 1, start, &valueLength);
118                }
119                inputs[fS_stod(buffer, start, &keyLength)] = value;
120        }
121}
122
123Node::Node(Substring &restOfGeno, Node *_parent, GenotypeParams _genotypeParams)
124{
125        partDescription = new Substring(restOfGeno);
126        genotypeParams = _genotypeParams;
127        parent = _parent;
128
129        try
130        {
131                extractModifiers(restOfGeno);
132                extractPartType(restOfGeno);
133                extractNeurons(restOfGeno);
134                extractParams(restOfGeno);
135
136                partDescription->shortenBy(restOfGeno.len);
137                if (restOfGeno.len > 0)
138                        getChildren(restOfGeno);
139        }
140        catch(fS_Exception &e)
141        {
142                cleanUp();
143                throw e;
144        }
145}
146
147Node::~Node()
148{
149        cleanUp();
150}
151
152void Node::cleanUp()
153{
154        delete partDescription;
155        if (state != nullptr)
156                delete state;
157        for (int i = 0; i < int(neurons.size()); i++)
158                delete neurons[i];
159        for (int i = 0; i < int(children.size()); i++)
160                delete children[i];
161}
162
163int Node::getPartPosition(Substring &restOfGenotype)
164{
165        for (int i = 0; i < restOfGenotype.len; i++)
166        {
167                if (GENE_TO_SHAPETYPE.find(restOfGenotype.at(i)) != GENE_TO_SHAPETYPE.end())
168                        return i;
169        }
170        return -1;
171}
172
173void Node::extractModifiers(Substring &restOfGenotype)
174{
175        int partTypePosition = getPartPosition(restOfGenotype);
176        if (partTypePosition == -1)
177                throw fS_Exception("Part type missing", restOfGenotype.start);
178
179        for (int i = 0; i < partTypePosition; i++)
180        {
181                // Extract modifiers and joint
182                char mType = restOfGenotype.at(i);
183                if (JOINTS.find(tolower(mType)) != string::npos)
184                        joint = tolower(mType);
185                else if (MODIFIERS.find(toupper(mType)) != string::npos)
186                        modifiers[toupper(mType)] += isupper(mType) ? 1 : -1;
187                else
188                        throw fS_Exception("Invalid modifier", restOfGenotype.start + i);
189        }
190        restOfGenotype.startFrom(partTypePosition);
191}
192
193void Node::extractPartType(Substring &restOfGenotype)
194{
195        auto itr = GENE_TO_SHAPETYPE.find(restOfGenotype.at(0));
196        if (itr == GENE_TO_SHAPETYPE.end())
197                throw fS_Exception("Invalid part type", restOfGenotype.start);
198
199        partType = itr->second;
200        restOfGenotype.startFrom(1);
201}
202
203vector<int> getSeparatorPositions(const char *str, int len, char separator, char endSign, int &endIndex)
204{
205        endIndex = -1;
206        vector<int> separators {-1};
207        for (int i = 0; i < len; i++)
208        {
209                if (str[i] == separator)
210                        separators.push_back(i);
211                else if (str[i] == endSign)
212                {
213                        endIndex = i;
214                        break;
215                }
216        }
217        separators.push_back(endIndex); // End of string as last separator
218        return separators;
219}
220
221void Node::extractNeurons(Substring &restOfGenotype)
222{
223        if (restOfGenotype.len == 0 || restOfGenotype.at(0) != NEURON_START)
224                return;
225
226        const char *ns = restOfGenotype.c_str() + 1;
227        int neuronsEndIndex;
228        vector<int> separators = getSeparatorPositions(ns, restOfGenotype.len, NEURON_SEPARATOR, NEURON_END, neuronsEndIndex);
229        if(neuronsEndIndex == -1)
230                throw fS_Exception("Lacking neuro end sign", restOfGenotype.start);
231
232        for (int i = 0; i < int(separators.size()) - 1; i++)
233        {
234                int start = separators[i] + 1;
235                int length = separators[i + 1] - start;
236                fS_Neuron *newNeuron = new fS_Neuron(ns + start, restOfGenotype.start + start, length);
237                neurons.push_back(newNeuron);
238        }
239
240        restOfGenotype.startFrom(neuronsEndIndex + 2);
241}
242
243void Node::extractParams(Substring &restOfGenotype)
244{
245        if (restOfGenotype.len == 0 || restOfGenotype.at(0) != PARAM_START)
246                return;
247
248        const char *paramString = restOfGenotype.c_str() + 1;
249
250        // Find the indexes of the parameter separators
251        int paramsEndIndex;
252        vector<int> separators = getSeparatorPositions(paramString, restOfGenotype.len, PARAM_SEPARATOR, PARAM_END, paramsEndIndex);
253        if(paramsEndIndex == -1)
254                throw fS_Exception("Lacking param end sign", restOfGenotype.start);
255        for (int i = 0; i < int(separators.size()) - 1; i++)
256        {
257                int start = separators[i] + 1;
258                int length = separators[i + 1] - start;
259                const char *buffer = paramString + start;
260
261                // Find the index of key-value separator
262                int separatorIndex = -1;
263                for (int i = 0; i < length; i++)
264                {
265                        if (buffer[i] == PARAM_KEY_VALUE_SEPARATOR)
266                        {
267                                separatorIndex = i;
268                                break;
269                        }
270                }
271                if (-1 == separatorIndex)
272                        throw fS_Exception("Parameter separator expected", restOfGenotype.start);
273
274                // Compute the value of parameter and assign it to the key
275                int valueStartIndex = separatorIndex + 1;
276                string key(buffer, separatorIndex);
277                if(std::find(PARAMS.begin(), PARAMS.end(), key) == PARAMS.end())
278                        throw fS_Exception("Invalid parameter key", restOfGenotype.start + start);
279
280                const char *val = buffer + valueStartIndex;
281                size_t len = length - valueStartIndex;
282                double value = fS_stod(val, restOfGenotype.start + start + valueStartIndex, &len);
283                if((key==SIZE_X || key==SIZE_Y || key==SIZE_Z) && value <= 0.0)
284                        throw fS_Exception("Invalid value of radius parameter", restOfGenotype.start + start + valueStartIndex);
285
286                params[key] = value;
287
288        }
289
290        restOfGenotype.startFrom(paramsEndIndex + 2);
291}
292
293double Node::getParam(string key)
294{
295        auto item = params.find(key);
296        if (item != params.end())
297                return item->second;
298        else
299                return defaultValues.at(key);
300}
301
302
303void Node::getState(State *_state)
304{
305        if (state != nullptr)
306                delete state;
307        if (parent == nullptr)
308                state = _state;
309        else
310                state = new State(_state);
311
312
313        // Update state by modifiers
314        for (auto it = modifiers.begin(); it != modifiers.end(); ++it)
315        {
316                char mod = it->first;
317                double multiplier = pow(genotypeParams.modifierMultiplier, it->second);
318                if (mod == MODIFIERS[0])
319                        state->ing *= multiplier;
320                else if (mod == MODIFIERS[1])
321                        state->fr *= multiplier;
322                else if (mod == MODIFIERS[2])
323                        state->s *= multiplier;
324                else if (mod == MODIFIERS[3])
325                        state->stif *= multiplier;
326        }
327
328        if (parent != nullptr)
329        {
330                // Rotate
331                state->rotate(getVectorRotation());
332
333                double distance = getDistance();
334                state->addVector(distance);
335        }
336        for (int i = 0; i < int(children.size()); i++)
337                children[i]->getState(state);
338}
339
340void Node::getChildren(Substring &restOfGenotype)
341{
342        vector<Substring> branches = getBranches(restOfGenotype);
343        for (int i = 0; i < int(branches.size()); i++)
344        {
345                children.push_back(new Node(branches[i], this, genotypeParams));
346        }
347}
348
349vector<Substring> Node::getBranches(Substring &restOfGenotype)
350{
351        vector<Substring> children;
352        if (restOfGenotype.at(0) != BRANCH_START)
353        {
354                children.push_back(restOfGenotype);  // Only one child
355                return children;
356        }
357
358        int depth = 0;
359        int start = 1;
360        char c;
361        const char *str = restOfGenotype.c_str();
362        for (int i = 0; i < restOfGenotype.len; i++)
363        {
364                if (depth < 0)
365                        throw fS_Exception("The number of branch start signs does not equal the number of branch end signs", restOfGenotype.start + i);
366                c = str[i];
367                if (c == BRANCH_START)
368                        depth++;
369                else if ((c == BRANCH_SEPARATOR && depth == 1) || i + 1 == restOfGenotype.len)
370                {
371                        Substring substring(restOfGenotype);
372                        substring.startFrom(start);
373                        substring.len = i - start;
374                        children.push_back(substring);
375                        start = i + 1;
376                } else if (c == BRANCH_END)
377                        depth--;
378        }
379        if (depth != 1)    // T
380                throw fS_Exception("The number of branch start signs does not equal the number of branch end signs", restOfGenotype.start);
381        return children;
382}
383
384Pt3D Node::calculateSize()
385{
386        double sizeMultiplier = getParam(SIZE) * state->s;
387        double sx = getParam(SIZE_X) * sizeMultiplier;
388        double sy = getParam(SIZE_Y) * sizeMultiplier;
389        double sz = getParam(SIZE_Z) * sizeMultiplier;
390        return Pt3D(sx, sy, sz);
391}
392
393double Node::calculateVolume()
394{
395        double result;
396        Pt3D size = calculateSize();
397        double radiiProduct = size.x * size.y * size.z;
398        switch (partType)
399        {
400                case Part::Shape::SHAPE_CUBOID:
401                        result = 8.0 * radiiProduct;
402                        break;
403                case Part::Shape::SHAPE_CYLINDER:
404                        result = 2.0 * M_PI * radiiProduct;
405                        break;
406                case Part::Shape::SHAPE_ELLIPSOID:
407                        result = (4.0 / 3.0) * M_PI * radiiProduct;
408                        break;
409                default:
410                        logMessage("fS", "calculateVolume", LOG_ERROR, "Invalid part type");
411        }
412        return result;
413}
414
415bool Node::isPartSizeValid()
416{
417        Pt3D size = calculateSize();
418        double volume = calculateVolume();
419        Part_MinMaxDef minP = Model::getMinPart();
420        Part_MinMaxDef maxP = Model::getMaxPart();
421
422        if (volume > maxP.volume || minP.volume > volume)
423                return false;
424        if (size.x < minP.scale.x || size.y < minP.scale.y || size.z < minP.scale.z)
425                return false;
426        if (size.x > maxP.scale.x || size.y > maxP.scale.y || size.z > maxP.scale.z)
427                return false;
428
429        if (partType == Part::Shape::SHAPE_ELLIPSOID && fS_Utils::max3(size) != fS_Utils::min3(size))
430                // When not all radii have different values
431                return false;
432        if (partType == Part::Shape::SHAPE_CYLINDER && size.y != size.z)
433                // If base radii have different values
434                return false;
435        return true;
436}
437
438bool Node::hasPartSizeParam()
439{
440        return params.count(SIZE_X) > 0 || params.count(SIZE_Y) > 0 || params.count(SIZE_Z) > 0;
441}
442
443Pt3D Node::getVectorRotation()
444{
445        return Pt3D(getParam(ROT_X), getParam(ROT_Y), getParam(ROT_Z));
446}
447
448Pt3D Node::getRotation()
449{
450        Pt3D rotation = Pt3D(getParam(RX), getParam(RY), getParam(RZ));
451        if(fS_Genotype::TURN_WITH_ROTATION)
452                rotation += getVectorRotation();
453        return rotation;
454}
455
456void Node::buildModel(Model &model, Node *parent)
457{
458        createPart();
459        model.addPart(part);
460        if (parent != nullptr)
461                addJointsToModel(model, parent);
462
463        for (int i = 0; i < int(neurons.size()); i++)
464        {
465                Neuro *neuro = new Neuro(*neurons[i]);
466                model.addNeuro(neuro);
467                if (neuro->getClass()->preflocation == NeuroClass::PREFER_JOINT && parent != nullptr)
468                {
469                        neuro->attachToJoint(model.getJoint(model.getJointCount() - 1));
470                } else
471                        neuro->attachToPart(part);
472        }
473
474        model.checkpoint();
475        part->addMapping(partDescription->toMultiRange());
476
477        for (int i = 0; i < int(children.size()); i++)
478        {
479                Node *child = children[i];
480                child->buildModel(model, this);
481        }
482}
483
484void Node::createPart()
485{
486        part = new Part(partType);
487        part->p = Pt3D(state->location.x,
488                                   state->location.y,
489                                   state->location.z);
490
491        part->friction = getParam(FRICTION) * state->fr;
492        part->ingest = getParam(INGESTION) * state->ing;
493        Pt3D size = calculateSize();
494        part->scale.x = size.x;
495        part->scale.y = size.y;
496        part->scale.z = size.z;
497        part->setRot(getRotation());
498}
499
500void Node::addJointsToModel(Model &model, Node *parent)
501{
502        Joint *j = new Joint();
503        j->stif = getParam(STIFFNESS) * state->stif;
504        j->rotstif = j->stif;
505
506        j->attachToParts(parent->part, part);
507        switch (joint)
508        {
509                case HINGE_X:
510                        j->shape = Joint::Shape::SHAPE_HINGE_X;
511                        break;
512                case HINGE_XY:
513                        j->shape = Joint::Shape::SHAPE_HINGE_XY;
514                        break;
515                default:
516                        j->shape = Joint::Shape::SHAPE_FIXED;
517        }
518        model.addJoint(j);
519        j->addMapping(partDescription->toMultiRange());
520}
521
522
523void Node::getGeno(SString &result)
524{
525        if (joint != DEFAULT_JOINT)
526                result += joint;
527        for (auto it = modifiers.begin(); it != modifiers.end(); ++it)
528        {
529                char mod = it->first;
530                int count = it->second;
531                if(it->second < 0)
532                {
533                        mod = tolower(mod);
534                        count = fabs(count);
535                }
536                result += std::string(count, mod).c_str();
537        }
538        result += SHAPETYPE_TO_GENE.at(partType);
539
540        if (!neurons.empty())
541        {
542                // Add neurons to genotype string
543                result += NEURON_START;
544                for (int i = 0; i < int(neurons.size()); i++)
545                {
546                        fS_Neuron *n = neurons[i];
547                        if (i != 0)
548                                result += NEURON_SEPARATOR;
549
550                        result += n->getDetails();
551                        if (!n->inputs.empty())
552                                result += NEURON_INTERNAL_SEPARATOR;
553
554                        for (auto it = n->inputs.begin(); it != n->inputs.end(); ++it)
555                        {
556                                if (it != n->inputs.begin())
557                                        result += NEURON_INTERNAL_SEPARATOR;
558                                result += SString::valueOf(it->first);
559                                if (it->second != DEFAULT_NEURO_CONNECTION_WEIGHT)
560                                {
561                                        result += NEURON_I_W_SEPARATOR;
562                                        result += SString::valueOf(it->second);
563                                }
564                        }
565                }
566                result += NEURON_END;
567        }
568
569        if (!params.empty())
570        {
571                // Add parameters to genotype string
572                result += PARAM_START;
573                for (auto it = params.begin(); it != params.end(); ++it)
574                {
575                        if (it != params.begin())
576                                result += PARAM_SEPARATOR;
577
578                        result += it->first.c_str();                    // Add parameter key to string
579                        result += PARAM_KEY_VALUE_SEPARATOR;
580                        // Round the value to two decimal places and add to string
581                        result += doubleToString(it->second, fS_Genotype::precision).c_str();
582                }
583                result += PARAM_END;
584        }
585
586        if (children.size() == 1)
587                children[0]->getGeno(result);
588        else if (children.size() > 1)
589        {
590                result += BRANCH_START;
591                for (int i = 0; i < int(children.size()) - 1; i++)
592                {
593                        children[i]->getGeno(result);
594                        result += BRANCH_SEPARATOR;
595                }
596                children.back()->getGeno(result);
597                result += BRANCH_END;
598        }
599}
600
601void Node::getAllNodes(vector<Node *> &allNodes)
602{
603        allNodes.push_back(this);
604        for (int i = 0; i < int(children.size()); i++)
605                children[i]->getAllNodes(allNodes);
606}
607
608int Node::getNodeCount()
609{
610        vector<Node*> allNodes;
611        getAllNodes(allNodes);
612        return allNodes.size();
613}
614
615fS_Genotype::fS_Genotype(const string &geno)
616{
617        try
618        {
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);
631                validateNeuroInputs();
632        }
633        catch (fS_Exception &e)
634        {
635                delete startNode;
636                throw e;
637        }
638}
639
640fS_Genotype::~fS_Genotype()
641{
642        delete startNode;
643}
644
645void fS_Genotype::getState()
646{
647        State *initialState = new State(Pt3D(0), Pt3D(1, 0, 0));
648        startNode->getState(initialState);
649}
650
651void fS_Genotype::buildModel(Model &model)
652{
653        getState();
654        startNode->buildModel(model, nullptr);
655        buildNeuroConnections(model);
656}
657
658
659void fS_Genotype::buildNeuroConnections(Model &model)
660{
661        // All the neurons are already created in the model
662        vector<fS_Neuron*> allNeurons = getAllNeurons();
663        for (int i = 0; i < int(allNeurons.size()); i++)
664        {
665                fS_Neuron *neuron = allNeurons[i];
666                Neuro *modelNeuro = model.getNeuro(i);
667                for (auto it = neuron->inputs.begin(); it != neuron->inputs.end(); ++it)
668                {
669                        Neuro *inputNeuro = model.getNeuro(it->first);
670                        modelNeuro->addInput(inputNeuro, it->second);
671
672                }
673        }
674}
675
676Node *fS_Genotype::getNearestNode(vector<Node *> allNodes, Node *node)
677{
678        Node *result = nullptr;
679        double minDistance = DBL_MAX, distance = DBL_MAX;
680        for (int i = 0; i < int(allNodes.size()); i++)
681        {
682                Node *otherNode = allNodes[i];
683                auto v = node->children;
684                if (otherNode != node &&
685                        find(v.begin(), v.end(), otherNode) == v.end())
686                {   // Not the same node and not a child
687                        distance = node->state->location.distanceTo(otherNode->state->location);
688                        if (distance < minDistance)
689                        {
690                                minDistance = distance;
691                                result = otherNode;
692                        }
693                }
694        }
695        return result;
696}
697
698SString fS_Genotype::getGeno()
699{
700        SString geno;
701        geno.reserve(100);
702
703        geno += doubleToString(startNode->genotypeParams.modifierMultiplier, fS_Genotype::precision).c_str();
704        geno += MODE_SEPARATOR;
705
706        startNode->getGeno(geno);
707        return geno;
708}
709
710vector<fS_Neuron *> fS_Genotype::extractNeurons(Node *node)
711{
712        vector<Node*> allNodes;
713        node->getAllNodes(allNodes);
714
715        vector<fS_Neuron*> allNeurons;
716        for (int i = 0; i < int(allNodes.size()); i++)
717        {
718                for (int j = 0; j < int(allNodes[i]->neurons.size()); j++)
719                {
720                        allNeurons.push_back(allNodes[i]->neurons[j]);
721                }
722        }
723        return allNeurons;
724}
725
726int fS_Genotype::getNeuronIndex(vector<fS_Neuron *> neurons, fS_Neuron *changedNeuron)
727{
728        int neuronIndex = -1;
729        for (int i = 0; i < int(neurons.size()); i++)
730        {
731                if (changedNeuron == neurons[i])
732                {
733                        neuronIndex = i;
734                        break;
735                }
736        }
737        return neuronIndex;
738}
739
740void fS_Genotype::shiftNeuroConnections(vector<fS_Neuron *> &neurons, int start, int end, SHIFT shift)
741{
742        if (start == -1 || end == -1)
743                return;
744        int shiftValue = end - start + 1;
745        if (shift == SHIFT::LEFT)
746                shiftValue *= -1;
747
748        for (int i = 0; i < int(neurons.size()); i++)
749        {
750                fS_Neuron *n = neurons[i];
751                std::map<int, double> newInputs;
752                for (auto it = n->inputs.begin(); it != n->inputs.end(); ++it)
753                {
754                        if (start > it->first)
755                                newInputs[it->first] = it->second;
756                        else if (it->first >= start)
757                        {
758                                if (end >= it->first)
759                                {
760                                        if (shift == SHIFT::RIGHT)
761                                                newInputs[it->first + shiftValue] = it->second;
762                                        // If shift == -1, just delete the input
763                                } else if (it->first > end)
764                                        newInputs[it->first + shiftValue] = it->second;
765                        }
766                }
767                n->inputs = newInputs;
768        }
769}
770
771vector<Node *> fS_Genotype::getAllNodes()
772{
773        vector<Node*> allNodes;
774        startNode->getAllNodes(allNodes);
775        return allNodes;
776}
777
778vector<fS_Neuron *> fS_Genotype::getAllNeurons()
779{
780        return extractNeurons(startNode);
781}
782
783Node *fS_Genotype::chooseNode(int fromIndex)
784{
785        vector<Node*> allNodes = getAllNodes();
786        return allNodes[fromIndex + rndUint(allNodes.size() - fromIndex)];
787}
788
789int fS_Genotype::getNodeCount()
790{
791        return startNode->getNodeCount();
792}
793
794int fS_Genotype::checkValidityOfPartSizes()
795{
796        getState();
797        vector<Node*> nodes = getAllNodes();
798        for (int i = 0; i < int(nodes.size()); i++)
799        {
800                if (!nodes[i]->isPartSizeValid())
801                {
802                        return 1 + nodes[i]->partDescription->start;
803                }
804        }
805        return 0;
806}
807
808
809void fS_Genotype::validateNeuroInputs()
810{
811
812        // Validate neuro input numbers
813        vector<fS_Neuron*> allNeurons = getAllNeurons();
814        int allNeuronsSize = allNeurons.size();
815        for(int i=0; i<allNeuronsSize; i++)
816        {
817                fS_Neuron *n = allNeurons[i];
818                for (auto it = n->inputs.begin(); it != n->inputs.end(); ++it)
819                {
820                        if (it->first < 0 || it->first >= allNeuronsSize)
821                                throw fS_Exception("Invalid neuron input", 0);
822                }
823        }
824}
825
826
827void fS_Genotype::rearrangeNeuronConnections(fS_Neuron *changedNeuron, SHIFT shift)
828{
829        vector<fS_Neuron*> neurons = getAllNeurons();
830        int changedNeuronIndex = getNeuronIndex(neurons, changedNeuron);
831        shiftNeuroConnections(neurons, changedNeuronIndex, changedNeuronIndex, shift);
832}
833
Note: See TracBrowser for help on using the repository browser.