Changeset 760 for cpp/frams/genetics/f4


Ignore:
Timestamp:
03/15/18 22:55:05 (7 years ago)
Author:
Maciej Komosinski
Message:
  • added support for new API for neuron types and their properties
  • added support for checkpoints
Location:
cpp/frams/genetics/f4
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/f4/conv_f4.cpp

    r736 r760  
    44
    55// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// Copyright (C) since 2001 Maciej Komosinski
     7// 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties
    68
    79#include "conv_f4.h"
     
    2729        int res;
    2830        f4_Model * model = new f4_Model();
    29         res = model->buildFromF4(in);
     31        res = model->buildFromF4(in, using_checkpoints);
    3032        if (GENOPER_OK != res) return SString();  // oops
    3133        if (NULL != map)
     
    5254        int res;
    5355        f4_Model * model = new f4_Model();
    54         res = model->buildFromF4(in);
     56        res = model->buildFromF4(in, using_checkpoints);
    5557        if (GENOPER_OK != res) return SString();  // oops
    5658        SString out;
     
    7173}
    7274
    73 int f4_Model::buildFromF4(SString &geno)
     75int f4_Model::buildFromF4(SString &geno, bool using_checkpoints)
    7476{
    7577        int i;
     
    101103                cells->C[i]->recProcessedFlag = 0;
    102104
    103         open(); // begin model build
     105        open(using_checkpoints); // begin model build
    104106
    105107        // process every cell
     
    184186                        partidx = addFromString(PartType, tmpLine, &range);
    185187                        if (partidx < 0) return -1;
     188                        this->checkpoint();
    186189                        jj_p1_refno = partidx;
    187190                }
     
    200203                partidx = addFromString(PartType, tmpLine, &range);
    201204                if (partidx < 0) return -2;
     205                this->checkpoint();
    202206                C->p2_refno = partidx;
    203207
     
    220224                partidx = addFromString(JointType, tmpLine, &range);
    221225                if (partidx < 0) return -13;
     226                this->checkpoint();
    222227                C->joint_refno = partidx;
    223228        }
     
    225230        if (C->type == T_NEURON4) ///<this case was updated by MacKo
    226231        {
    227                 // new neuron object
    228                 // it is linked to a part (not a joint!)
    229                 int p_refno = C->dadlink->p2_refno;
    230                 if ((p_refno < 0) || (p_refno >= getPartCount())) return -21;
    231                 // joint_refno is currently not used
    232                 sprintf(tmpLine, "p=%ld,d=\"N:in=%g,fo=%g,si=%g\"",
    233                         p_refno,
    234                         C->inertia, C->force, C->sigmo);
    235                 partidx = addFromString(NeuronType, tmpLine, &range);
    236                 if (partidx < 0) return -22;
     232                const char * nclass = C->neuclass->name.c_str();
     233                int partno, jointno;
     234                if (C->neuclass->getPreferredLocation() == 0)
     235                {
     236                        if (strcmp(nclass, "N") == 0)
     237                        {
     238                                partno = C->dadlink->p2_refno;
     239                                if ((partno < 0) || (partno >= getPartCount())) return -21;
     240                                else sprintf(tmpLine, "p=%ld,d=\"N:in=%g,fo=%g,si=%g\"", partno, C->inertia, C->force, C->sigmo);
     241                        }
     242                        else
     243                        {
     244                                sprintf(tmpLine, "d=\"%s\"", nclass);
     245                        }
     246                        partidx = addFromString(NeuronType, tmpLine, &range);
     247                        if (partidx < 0) return -22;
     248                        this->checkpoint();
     249                        C->neuro_refno = partidx;
     250                }
     251                else if (C->neuclass->getPreferredLocation() == 1) // attached to Part or have no required attachment - also part
     252                {
     253                        partno = C->dadlink->p2_refno;
     254                        if ((partno < 0) || (partno >= getPartCount())) return -21;
     255                        if (strcmp(nclass, "N") == 0)
     256                        {
     257                                sprintf(tmpLine, "d=\"N:in=%g,fo=%g,si=%g\"", partno, C->inertia, C->force, C->sigmo);
     258                        }
     259                        else
     260                        {
     261                                sprintf(tmpLine, "p=%ld,d=\"%s\"", partno, nclass);
     262                        }
     263                        partidx = addFromString(NeuronType, tmpLine, &range);
     264                        if (partidx < 0) return -22;
     265                        this->checkpoint();
     266                        C->neuro_refno = partidx;
     267                }
     268                else // attached to Joint
     269                {
     270                        jointno = C->dadlink->joint_refno;
     271                        sprintf(tmpLine, "n:j=%d,d=\"%s\"", jointno, nclass);
     272                        partidx = addFromString(NeuronType, tmpLine, &range);
     273                        if (partidx < 0) return -32;
     274                        this->checkpoint();
     275                }
    237276                C->neuro_refno = partidx;
    238277                int n_refno = C->neuro_refno;
    239278
    240                 if (C->ctrl)
     279                if ((strcmp(nclass,"N") == 0) && C->ctrl)
    241280                {
    242281                        if (1 == C->ctrl)
     
    248287                        sprintf(tmpLine, "%d,%d", partidx, n_refno);
    249288                        if (addFromString(NeuronConnectionType, tmpLine, &range) < 0) return -33;
     289                        this->checkpoint();
    250290                }
    251291
     
    256296
    257297                        tmpLine[0] = 0;
    258                         if (1 == C->links[j]->t) sprintf(tmpLine, "p=%d,d=\"*\"", p_refno);
    259                         if (2 == C->links[j]->t) sprintf(tmpLine, "j=%d,d=\"G\"", C->dadlink->joint_refno);
    260                         if (3 == C->links[j]->t) sprintf(tmpLine, "p=%d,d=\"T\"", p_refno);
    261                         if (4 == C->links[j]->t) sprintf(tmpLine, "p=%d,d=\"S\"", p_refno);
     298                        if (C->links[j]->from == NULL)
     299                        {
     300                                const char * nclass = C->links[j]->t.c_str();
     301                                char * temp = (char*)C->links[j]->t.c_str();
     302                                NeuroClass * sensortest = GenoOperators::parseNeuroClass(temp);
     303                                //backward compatibility for G*TS
     304                                if (C->links[j]->t == "*" || C->links[j]->t == "S" || C->links[j]->t == "T")
     305                                {
     306                                        sprintf(tmpLine, "p=%d,d=\"%s\"", partno, nclass);
     307                                }
     308                                else if (C->links[j]->t == "G")
     309                                {
     310                                        jointno = C->dadlink->joint_refno;
     311                                        sprintf(tmpLine, "j=%d,d=\"%s\"", jointno, nclass);
     312                                }                               
     313                                else if (sensortest->getPreferredLocation() == 0)
     314                                {
     315                                        sprintf(tmpLine, "d=\"%s\"",nclass);
     316                                }
     317                                else if (sensortest->getPreferredLocation() == 1)
     318                                {
     319                                        sprintf(tmpLine, "p=%d,d=\"%s\"", partno, nclass);
     320                                }
     321                                else
     322                                {
     323                                        jointno = C->dadlink->joint_refno;
     324                                        sprintf(tmpLine, "j=%d,d=\"%s\"", jointno, nclass);
     325                                }
     326
     327                        }
    262328                        int from = -1;
    263329                        if (tmpLine[0]) //input from receptor
     
    265331                                from = addFromString(NeuronType, tmpLine, &range);
    266332                                if (from < 0) return -34;
     333                                this->checkpoint();
    267334                        } /*could be 'else'...*/
     335
    268336                        if (NULL != C->links[j]->from) // input from another neuron
    269337                                from = C->links[j]->from->neuro_refno;
     
    272340                                sprintf(tmpLine, "%d,%d,%g", n_refno, from, C->links[j]->w);
    273341                                if (addFromString(NeuronConnectionType, tmpLine, &range) < 0) return -35;
     342                                this->checkpoint();
    274343                        }
    275344                }
  • cpp/frams/genetics/f4/conv_f4.h

    r736 r760  
    55// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
    66// Copyright (C) since 2001 Maciej Komosinski
     7// 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties
    78
    89#ifndef _CONV_F4_H_
     
    1516
    1617
    17 // The f4->f0 converter
     18/**
     19 * Genotype converter from f4 to f0.
     20 */
    1821class GenoConv_f40 : public GenoConverter
    1922{
    2023public:
    2124        GenoConv_f40();
     25
     26        /**
     27         * Performs conversion from f4 to f0. Creates f4_Model from f4 genotype
     28         * and converts the Model to the f0 genotype string.
     29         * @param in f4 genotype
     30         * @param map mapping from f4 to Model
     31         * @param using_checkpoints determines if checkpoints will be available
     32         * @return generated f0 genotype
     33         */
    2234        SString convert(SString &in, MultiMap * map, bool using_checkpoints);
    2335};
    2436
    2537
    26 // a test-only f4->f1 converter, approximates only
     38/**
     39 * Genotype converter from f4 to f1. This is only experimental conversion and
     40 * returns an approximate f1 genotype.
     41 */
    2742class GenoConv_F41_TestOnly : public GenoConverter
    2843{
    2944public:
     45        /**
     46         * Initializes converter.
     47         */
    3048        GenoConv_F41_TestOnly();
     49
     50        /**
     51         * Performs conversion from f4 to f1. Creates f4_Model from f4 genotype
     52         * and converts the Model to the f1 genotype string. The final f1 genotype is
     53         * an approximation.
     54         * @param in f4 genotype
     55         * @param map mapping from f4 to Model
     56         * @param using_checkpoints determines if checkpoints will be available
     57         * @return generated approximate f1 genotype
     58         */
    3159        SString convert(SString &in, MultiMap * map, bool using_checkpoints);
    3260};
    3361
    3462
    35 // A Model descendant, which support build from an f4 genotype.
     63/**
     64 * A Model descendant which supports building from an f4 genotype.
     65 */
    3666class f4_Model : public Model
    3767{
     
    3969        f4_Model();
    4070        ~f4_Model();
    41         int      buildFromF4(SString &geno);
     71
     72        /**
     73         * Builds a Model from the f4 genotype string.
     74         * @param geno genotype string
     75         * @return GENOPER_OK if a Model could be created, error code otherwise
     76         */
     77        int      buildFromF4(SString &geno, bool using_checkpoints);
     78        /**
     79         * Outputs a Model in f1 format. It is an approximation of the input f4 genotype.
     80         * @param out the reference that stores the conversion result
     81         */
    4282        void     toF1Geno(SString &out);       // output to f1 format, approximation
    4383private:
  • cpp/frams/genetics/f4/f4_general.cpp

    r671 r760  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2017  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
    55// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties
    67
    78#include "f4_general.h"
     9#include "../oper_fx.h" //for GENOPER_ constants
    810#include <common/nonstd_stl.h>
    911#include <common/log.h>
    1012#include <frams/model/model.h> // for min and max attributes
    11 #include "../oper_fx.h" //for GENOPER_ constants
    12 #include <stdio.h>
    1313#include <common/nonstd_math.h>
    1414
     
    1717#endif
    1818
    19 
    20 f4_Props::f4_Props()
    21 {
    22         length = 1.0;
    23         curvedness = 0.0;
    24         weight = 1.0;
    25         friction = 0.4;
    26         muscle_power = 0.25; // biol
    27         assimilation = 0.25; // biol
    28         stamina = 0.25; // biol
    29         ingestion = 0.25; // biol
    30         twist = 0.0;
    31         energy = 1.0;
    32         normalizeBiol4();
    33 }
    34 
    35 void f4_Props::normalizeBiol4()
    36 {
    37         // make them sum to 1
    38         double sum = muscle_power + assimilation + stamina + ingestion;
    39         if (sum == 0)
    40         {
    41                 muscle_power = assimilation = stamina = ingestion = 0.25;
    42         }
    43         else
    44         {
    45                 muscle_power /= sum;
    46                 assimilation /= sum;
    47                 stamina /= sum;
    48                 ingestion /= sum;
    49         }
    50 }
    51 
    52 void f4_Props::executeModifier(char modif)
    53 {
    54         switch (modif)
    55         {
    56         case 'L': length += (2.5 - length) * 0.3;
    57                 length = min(length, Model::getMaxJoint().d.x); break;
    58         case 'l': length += (0.3 - length) * 0.3;
    59                 length = max(length, Model::getMinJoint().d.x); break;
    60         case 'C': curvedness += (2.0 - curvedness) * 0.25;  break;
    61         case 'c': curvedness += (-2.0 - curvedness) * 0.25;  break;
    62         case 'Q': twist += (1.58 - twist) * 0.3; break;
    63         case 'q': twist += (-1.58 - twist) * 0.3; break;
    64         case 'A': assimilation += (1 - assimilation) * 0.8; normalizeBiol4(); break;
    65         case 'a': assimilation -= assimilation * 0.4;       normalizeBiol4(); break;
    66         case 'I': ingestion += (1 - ingestion) * 0.8;   normalizeBiol4(); break;
    67         case 'i': ingestion -= ingestion * 0.4;         normalizeBiol4(); break;
    68         case 'S': stamina += (1 - stamina) * 0.8; normalizeBiol4(); break;
    69         case 's': stamina -= stamina * 0.4;       normalizeBiol4(); break;
    70         case 'M': muscle_power += (1 - muscle_power) * 0.8;   normalizeBiol4(); break;
    71         case 'm': muscle_power -= muscle_power * 0.4;         normalizeBiol4(); break;
    72         case 'F': friction += (4 - friction) * 0.2; break;
    73         case 'f': friction -= friction * 0.2;       break;
    74         case 'W': weight += (2.0 - weight) * 0.3;   break;
    75         case 'w': weight += (0.5 - weight) * 0.3;   break;
    76         case 'E': energy += (10.0 - energy) * 0.1; break;
    77         case 'e': energy -= energy * 0.1;          break;
    78         }
    79 }
    80 
    81 void f4_Props::adjust()
    82 {
    83         length = 0.5*length + 0.5*stdProps.length;
    84         curvedness = 0.66 * curvedness;
    85         twist = 0.66 * twist;
    86 }
    87 
    88 f4_Props stdProps;
    89 
    90 
    9119void rolling_dec(double * v)
    9220{
     
    9826        *v += 0.7853;  // 0.7853981  45 degrees
    9927}
    100 
    10128
    10229int scanrec(const char * s, unsigned int slen, char stopchar)
     
    13663
    13764f4_Cell::f4_Cell(int nname,
    138         f4_Cell * ndad, int nangle, f4_Props newP)
     65        f4_Cell * ndad, int nangle, GeneProps newP)
    13966{
    14067        name = nname;
     
    14572        gcur = NULL;
    14673        active = 1;
    147         repeat.null();
     74        repeat.clear();
    14875        //genoRange.clear(); -- implicit
    14976
     
    187114
    188115
    189 f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur, f4_Cell * ndad, int nangle, f4_Props newP)
     116f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur, f4_Cell * ndad, int nangle, GeneProps newP)
    190117{
    191118        name = nname;
     
    196123        gcur = ngcur;
    197124        active = 1;
    198         repeat.null();
     125        repeat.clear();
    199126        //genoRange.clear(); -- implicit
    200127        // preserve geno range of parent cell
     
    261188int f4_Cell::onestep()
    262189{
    263         int i, j, k, relfrom, t;
    264         double w;
    265         f4_Cell * tmp;
    266         f4_Cell * tneu;
    267190        if (gcur == NULL)
    268191        {
     
    275198                // currently this is the last one processed
    276199                // the current genotype code is processed
    277                 genoRange.add(gcur->pos);
    278                 switch (gcur->name)
    279                 {
    280                 case '<':
    281                         // cell division!
    282                         //DB( printf("  div! %d\n", name); )
    283 
    284                         // error: sticks cannot divide
    285                         if (T_STICK4 == type)
    286                         {
    287                                 // cannot fix
    288                                 org->setError(gcur->pos);
    289                                 return 1;  // stop
    290                         }
    291 
    292                         // undiff divides
    293                         if (T_UNDIFF4 == type)
    294                         {
    295                                 // commacount is set only when daughter turns into X
    296                                 // daughter cell
    297                                 // adjust new len
    298                                 f4_Props newP = P;
    299                                 newP.adjust();
    300                                 tmp = new f4_Cell(org, org->nc, genot, gcur->child2, this, commacount, newP);
    301                                 tmp->repeat = repeat;
    302                                 repeat.null();
    303                                 org->addCell(tmp);
    304                         }
    305                         // a neuron divides: create a new, duplicate links
    306                         if (T_NEURON4 == type) {
    307                                 // daughter cell
    308                                 tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
    309                                         // has the same dadlink
    310                                         this->dadlink, commacount, P);
    311                                 tmp->repeat = repeat;
    312                                 repeat.null();
    313                                 // it is a neuron from start
    314                                 tmp->type = T_NEURON4;
    315                                 // duplicate links
    316                                 f4_CellLink * ll;
    317                                 for (i = 0; i < nolink; i++)
    318                                 {
    319                                         ll = links[i];
    320                                         tmp->addlink(ll->from, ll->w, ll->t);
    321                                 }
    322                                 org->addCell(tmp);
    323                         }
    324                         // adjustments for this cell
    325                         gcur = gcur->child;
    326                         // halt development
    327                         return 0;
    328 
    329                 case '>':
    330                         // finish
    331                         // see if there is a repet count
    332                         if (repeat.top > 0)
    333                         { // there is a repeat counter
    334                                 if (!repeat.first()->isNull())
    335                                 { // repeat counter is not null
    336                                         repeat.first()->dec();
    337                                         if (repeat.first()->count > 0)
     200                //genoRange.add(gcur->pos,gcur->pos+gcur->name.length()-1);
     201                bool neuclasshandler = false; // if set to true, then there is a set of characters that can be assigned to a neuron class type
     202                // old semantics, one-character
     203                if (gcur->name.length() == 1)
     204                {
     205                        genoRange.add(gcur->pos, gcur->pos);
     206                        char name = gcur->name[0];
     207                        switch (name)
     208                        {
     209                        case '<':
     210                        {
     211                                // cell division!
     212                                //DB( printf("  div! %d\n", name); )
     213
     214                                // error: sticks cannot divide
     215                                if (T_STICK4 == type)
     216                                {
     217                                        // cannot fix
     218                                        org->setError(gcur->pos);
     219                                        return 1;  // stop
     220                                }
     221
     222                                // undiff divides
     223                                if (T_UNDIFF4 == type)
     224                                {
     225                                        // commacount is set only when daughter turns into X
     226                                        // daughter cell
     227                                        // adjust new len
     228                                        GeneProps newP = P;
     229                                        newP.propagateAlong(false);
     230                                        f4_Cell * tmp = new f4_Cell(org, org->nc, genot, gcur->child2, this, commacount, newP);
     231                                        tmp->repeat = repeat;
     232                                        repeat.clear();
     233                                        org->addCell(tmp);
     234                                }
     235                                // a neuron divides: create a new, duplicate links
     236                                if (T_NEURON4 == type) {
     237                                        // daughter cell
     238                                        f4_Cell *tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
     239                                                // has the same dadlink
     240                                                this->dadlink, commacount, P);
     241                                        tmp->repeat = repeat;
     242                                        repeat.clear();
     243                                        // it is a neuron from start
     244                                        tmp->type = T_NEURON4;
     245                                        // it has the same type as the parent neuron
     246                                        tmp->neuclass = neuclass;
     247                                        // duplicate links
     248                                        f4_CellLink * ll;
     249                                        for (int i = 0; i < nolink; i++)
    338250                                        {
    339                                                 // return to repeat
    340                                                 gcur = repeat.first()->node->child;
     251                                                ll = links[i];
     252                                                tmp->addlink(ll->from, ll->w, ll->t);
     253                                        }
     254                                        org->addCell(tmp);
     255                                }
     256                                // adjustments for this cell
     257                                gcur = gcur->child;
     258                                // halt development
     259                                return 0;
     260                        }
     261                        case '>':
     262                        {
     263                                // finish
     264                                // see if there is a repet count
     265                                if (repeat.top > 0)
     266                                { // there is a repeat counter
     267                                        if (!repeat.first()->isNull())
     268                                        { // repeat counter is not null
     269                                                repeat.first()->dec();
     270                                                if (repeat.first()->count > 0)
     271                                                {
     272                                                        // return to repeat
     273                                                        gcur = repeat.first()->node->child;
     274                                                }
     275                                                else
     276                                                {
     277                                                        // continue
     278                                                        gcur = repeat.first()->node->child2;
     279                                                        repeat.pop();
     280                                                }
     281                                                break;
    341282                                        }
    342283                                        else
    343284                                        {
    344                                                 // continue
    345                                                 gcur = repeat.first()->node->child2;
    346285                                                repeat.pop();
    347286                                        }
     287                                }
     288                                else
     289                                {
     290                                        // error: still undiff
     291                                        if (T_UNDIFF4 == type)
     292                                        {
     293                                                // fix it: insert an 'X'
     294                                                f4_node *insertnode = new f4_node("X", NULL, gcur->pos);
     295                                                if (org->setRepairInsert(gcur->pos, gcur, insertnode)) // not in repair mode, release
     296                                                        delete insertnode;
     297                                                return 1;
     298                                        }
     299                                        repeat.clear();
     300                                        active = 0;  // stop
     301                                        // eat up rest
     302                                        gcur = NULL;
     303                                        return 0;
     304                                }
     305                        }
     306                                /* no break */
     307                        case '#':
     308                        {
     309                                // repetition marker
     310                                if (repeat.top >= repeat_stack::stackSize)
     311                                {
     312                                        // repeat pointer stack is full, cannot remember this one.
     313                                        // fix: delete it
     314                                        org->setRepairRemove(gcur->pos, gcur);
     315                                        return 1;  // stop
     316                                }
     317                                repeat.push(repeat_ptr(gcur, gcur->i1));
     318                                gcur = gcur->child;
     319                                break;
     320                        }
     321                        case ',':
     322                        {
     323                                commacount++;
     324                                gcur = gcur->child;
     325                                break;
     326                        }
     327                        case 'r':  case 'R':
     328                        {
     329                                // error: if neuron
     330                                if (T_NEURON4 == type)
     331                                {
     332                                        // fix: delete it
     333                                        org->setRepairRemove(gcur->pos, gcur);
     334                                        return 1;  // stop
     335                                }
     336                                switch (name)
     337                                {
     338                                case 'r':   rolling_dec(&rolling); break;
     339                                case 'R':   rolling_inc(&rolling); break;
     340                                }
     341                                gcur = gcur->child;
     342                                break;
     343                        }
     344                        case 'l':  case 'L':
     345                        case 'c':  case 'C':
     346                        case 'q':  case 'Q':
     347                        case 'a':  case 'A':
     348                        case 'i':  case 'I':
     349                        case 's':  case 'S':
     350                        case 'm':  case 'M':
     351                        case 'f':  case 'F':
     352                        case 'w':  case 'W':
     353                        case 'e':  case 'E':
     354                        case 'd':  case 'D':
     355                        case 'g':  case 'G':
     356                        case 'b':  case 'B':
     357                        case 'h':  case 'H':
     358                        {
     359                                // error: if neuron
     360                                if (T_NEURON4 == type)
     361                                {
     362                                        // fix: delete it
     363                                        org->setRepairRemove(gcur->pos, gcur);
     364                                        return 1;  // stop
     365                                }
     366                                P.executeModifier(name);
     367                                gcur = gcur->child;
     368                                break;
     369                        }
     370                        case 'X':
     371                        {
     372                                // turn undiff. cell into a stick
     373                                // error: already differentiated
     374                                if (T_UNDIFF4 != type)
     375                                {
     376                                        // fix: delete this node
     377                                        org->setRepairRemove(gcur->pos, gcur);
     378                                        return 1;  // stop
     379                                }
     380                                type = T_STICK4;
     381                                // fix dad commacount and own anglepos
     382                                if (NULL != dadlink)
     383                                {
     384                                        dadlink->commacount++;
     385                                        anglepos = dadlink->commacount;
     386                                }
     387                                // change of type halts developments, see comment at 'N'
     388                                gcur = gcur->child;
     389                                return 0;
     390                        }
     391                        case 'N':
     392                        {
     393                                // turn undiff. cell into a neuron
     394                                // error: already differentiated
     395                                if (T_UNDIFF4 != type)
     396                                {
     397                                        // fix: delete this node
     398                                        org->setRepairRemove(gcur->pos, gcur);
     399                                        return 1;  // stop
     400                                }
     401                                // error: if no previous
     402                                if (NULL == dadlink)
     403                                {
     404                                        // fix: delete it
     405                                        org->setRepairRemove(gcur->pos, gcur);
     406                                        return 1;  // stop
     407                                }
     408                                string temp1 = "N";
     409                                char *temp = (char*)temp1.c_str();
     410                                neuclass = GenoOperators::parseNeuroClass(temp);
     411                                type = T_NEURON4;
     412                                // change of type also halts development, to give other
     413                                // cells a chance for adjustment.  Namely, it is important
     414                                // to wait for other cells to turn N before adding links
     415                                gcur = gcur->child;
     416                                return 0;
     417                        }
     418                        case '@':
     419                        case '|':
     420                        {
     421                                // neuron rotating / bending
     422                                int j = 1;
     423                                if ('@' == name) j = 1; // rot
     424                                else
     425                                        if ('|' == name) j = 2; // bend
     426
     427                                // if undiff, then this is a new muscle. Thanks to f4_processrec @ and | case we can skip repairing
     428                                if (T_UNDIFF4 == type)
     429                                {
     430                                        neuclasshandler = true;
    348431                                        break;
    349432                                }
    350                                 else
    351                                 {
    352                                         repeat.pop();
    353                                 }
    354                         }
    355                         else
    356                         {
    357                                 // error: still undiff
    358                                 if (T_UNDIFF4 == type)
    359                                 {
    360                                         // fix it: insert an 'X'
    361                                         f4_node * insertnode = new f4_node('X', NULL, gcur->pos);
    362                                         if (org->setRepairInsert(gcur->pos, gcur, insertnode)) // not in repair mode, release                                           
    363                                                 delete insertnode;
    364                                         return 1;
    365                                 }
    366                                 repeat.null();
    367                                 active = 0;  // stop
    368                                 // eat up rest
    369                                 gcur = NULL;
    370                                 return 0;
    371                         }
    372 
    373                 case '#':
    374                         // repetition marker
    375                         if (repeat.top >= repeat_stack::stackSize)
    376                         {
    377                                 // repepeat pointer stack is full, cannot remember this one.
     433
     434                                // error: not a neuron (stick)
     435                                if (T_NEURON4 != type)
     436                                {
     437                                        // fix: delete it
     438                                        org->setRepairRemove(gcur->pos, gcur);
     439                                        return 1;  // stop
     440                                }
     441                                // error: already has control
     442                                if (ctrl != 0)
     443                                {
     444                                        // fix: delete it
     445                                        org->setRepairRemove(gcur->pos, gcur);
     446                                        return 1;  // stop
     447                                }
     448                                // make neuron ctrl = 1 or 2
     449                                ctrl = j;
     450                                gcur = gcur->child;
     451                                break;
     452                        }
     453                        case '[':
     454                        {
     455                                // link to neuron
     456                                // error: not a neuron
     457                                if (T_NEURON4 != type)
     458                                {
     459                                        // fix: delete it
     460                                        org->setRepairRemove(gcur->pos, gcur);
     461                                        return 1;  // stop
     462                                }
     463                                // input (sensor or %d)
     464                                int t = gcur->i1;
     465                                int relfrom = gcur->l1;
     466                                float w = gcur->f1;
     467                                f4_Cell *tneu = NULL;
     468                                if (t > 0) // sensors
     469                                {
     470                                        char *temp = (char*)gcur->s1.c_str();
     471                                        NeuroClass *sensortest = GenoOperators::parseNeuroClass(temp);
     472                                        if (sensortest == NULL || sensortest->getPreferredInputs() != 0)
     473                                        {
     474                                                // error: unknown code
     475                                                string buf = "wrong sensor in link '";
     476                                                buf.append(gcur->s1);
     477                                                buf.append("'");
     478                                                logMessage("f4_Cell", "onestep", LOG_WARN, buf.c_str()); //TODO ask
     479                                                org->setRepairRemove(gcur->pos, gcur);
     480                                                return 1;
     481                                        }
     482                                }
     483                                else {
     484                                        // input from other neuron
     485                                        // find neuron at relative i
     486                                        // find own index
     487                                        int j = 0, k = 0;
     488                                        for (int i = 0; i < org->nc; i++)
     489                                        {
     490                                                if (org->C[i]->type == T_NEURON4) k++;
     491                                                if (org->C[i] == this) { j = k - 1; break; }
     492                                        }
     493                                        // find index of incoming
     494                                        j = j + relfrom;
     495                                        if (j < 0) goto wait_link;
     496                                        if (j >= org->nc) goto wait_link;
     497                                        // find that neuron
     498                                        k = 0;
     499                                        int i;
     500                                        for (i = 0; i < org->nc; i++)
     501                                        {
     502                                                if (org->C[i]->type == T_NEURON4) k++;
     503                                                if (j == (k - 1)) break;
     504                                        }
     505                                        if (i >= org->nc) goto wait_link;
     506                                        tneu = org->C[i];
     507                                }
     508                                // add link
     509                                // error: could not add link (too many?)
     510                                if (addlink(tneu, w, gcur->s1))
     511                                {
     512                                        // cannot fix
     513                                        org->setError(gcur->pos);
     514                                        return 1;  // stop
     515                                }
     516                                gcur = gcur->child;
     517                                break;
     518                        }
     519                        wait_link:
     520                        {
     521                                // wait for other neurons to develop
     522                                // if there are others still active
     523                                active = 0;
     524                                int j = 0;
     525                                for (int i = 0; i < org->nc; i++)
     526                                {
     527                                        if (org->C[i]->active) j++;
     528                                }
     529                                if (j > 0)
     530                                        return 0;  // there is other active, halt, try again
     531                                // no more actives, cannot add link, ignore, but treat not as an error
     532                                gcur = gcur->child;
     533                        }
     534                                break;
     535                        case ':':
     536                        {
     537                                // neuron parameter
     538                                // error: not a neuron
     539                                if (T_NEURON4 != type)
     540                                {
     541                                        // fix: delete it
     542                                        org->setRepairRemove(gcur->pos, gcur);
     543                                        return 1;  // stop
     544                                }
     545                                int j = (int)gcur->l1;
     546                                switch ((char)gcur->i1)
     547                                {
     548                                case '!':
     549                                        if (j)
     550                                                force += (1.0 - force) * 0.2;
     551                                        else
     552                                                force -= force * 0.2;
     553                                        break;
     554                                case '=':
     555                                        if (j)
     556                                                inertia += (1.0 - inertia) * 0.2;
     557                                        else
     558                                                inertia -= inertia * 0.2;
     559                                        break;
     560                                case '/':
     561                                        if (j)
     562                                                sigmo *= 1.4;
     563                                        else
     564                                                sigmo /= 1.4;
     565                                        break;
     566                                default:
     567                                        org->setRepairRemove(gcur->pos, gcur);
     568                                        return 1;  // stop
     569                                }
     570                                gcur = gcur->child;
     571                                break;
     572                        }
     573                        case ' ':
     574                        {
     575                                // space has no effect, should not occur
     576                                // fix: delete it
     577                                org->setRepairRemove(gcur->pos, gcur);
     578                                gcur = gcur->child;
     579                                break;
     580                        }
     581                        default:
     582                        {
     583                                // because there are one-character neuron classes, default move control to neuclasshandler
     584                                neuclasshandler = true;
     585                        }
     586                        }
     587                }
     588                else
     589                {
     590                        // if many characters, then it needs to be parsed below
     591                        neuclasshandler = true;
     592                }
     593
     594                if (neuclasshandler)
     595                {
     596                        genoRange.add(gcur->pos, gcur->pos + gcur->name.length() + 2 - 1); // +2 for N:
     597                        if (T_UNDIFF4 != type)
     598                        {
     599                                // fix: delete this node
     600                                org->setRepairRemove(gcur->pos, gcur);
     601                                return 1;  // stop
     602                        }
     603                        // error: if no previous
     604                        if (NULL == dadlink)
     605                        {
    378606                                // fix: delete it
    379607                                org->setRepairRemove(gcur->pos, gcur);
    380608                                return 1;  // stop
    381609                        }
    382                         repeat.push(repeat_ptr(gcur, gcur->i1));
     610                        // multiple characters are neuron types. Need to check if exists
     611                        char *temp = (char*)gcur->name.c_str();
     612                        neuclass = GenoOperators::parseNeuroClass(temp);
     613                        if (neuclass == NULL)
     614                        {
     615                                // error: unknown code
     616                                string buf = "unknown code '";
     617                                buf.append(gcur->name);
     618                                buf.append("'");
     619                                logMessage("f4_Cell", "onestep", 2, buf.c_str());
     620                                org->setRepairRemove(gcur->pos, gcur);
     621                                return 1;
     622                        }
     623                        type = T_NEURON4; //they belong to neurons
    383624                        gcur = gcur->child;
    384                         break;
    385 
    386                 case ',':
    387                         commacount++;
    388                         gcur = gcur->child;
    389                         break;
    390 
    391                 case 'r':  case 'R':
    392                         // error: if neuron
    393                         if (T_NEURON4 == type)
    394                         {
    395                                 // fix: delete it
    396                                 org->setRepairRemove(gcur->pos, gcur);
    397                                 return 1;  // stop
    398                         }
    399                         switch (gcur->name)
    400                         {
    401                         case 'r':   rolling_dec(&rolling); break;
    402                         case 'R':   rolling_inc(&rolling); break;
    403                         }
    404                         gcur = gcur->child;
    405                         break;
    406 
    407                 case 'l':  case 'L':
    408                 case 'c':  case 'C':
    409                 case 'q':  case 'Q':
    410                 case 'a':  case 'A':
    411                 case 'i':  case 'I':
    412                 case 's':  case 'S':
    413                 case 'm':  case 'M':
    414                 case 'f':  case 'F':
    415                 case 'w':  case 'W':
    416                 case 'e':  case 'E':
    417                         // error: if neuron
    418                         if (T_NEURON4 == type)
    419                         {
    420                                 // fix: delete it
    421                                 org->setRepairRemove(gcur->pos, gcur);
    422                                 return 1;  // stop
    423                         }
    424                         P.executeModifier(gcur->name);
    425                         gcur = gcur->child;
    426                         break;
    427 
    428                 case 'X':
    429                         // turn undiff. cell into a stick
    430                         // error: already differentiated
    431                         if (T_UNDIFF4 != type)
    432                         {
    433                                 // fix: delete this node
    434                                 org->setRepairRemove(gcur->pos, gcur);
    435                                 return 1;  // stop
    436                         }
    437                         type = T_STICK4;
    438                         // fix dad commacount and own anglepos
    439                         if (NULL != dadlink)
    440                         {
    441                                 dadlink->commacount++;
    442                                 anglepos = dadlink->commacount;
    443                         }
    444                         // change of type halts developments, see comment at 'N'
    445                         gcur = gcur->child;
    446                         return 0;
    447 
    448                 case 'N':
    449                         // turn undiff. cell into a neuron
    450                         // error: already differentiated
    451                         if (T_UNDIFF4 != type)
    452                         {
    453                                 // fix: delete this node
    454                                 org->setRepairRemove(gcur->pos, gcur);
    455                                 return 1;  // stop
    456                         }
    457                         // error: if no previous
    458                         if (NULL == dadlink)
    459                         {
    460                                 // fix: delete it
    461                                 org->setRepairRemove(gcur->pos, gcur);
    462                                 return 1;  // stop
    463                         }
    464                         type = T_NEURON4;
    465                         // change of type also halts development, to give other
    466                         // cells a chance for adjustment.  Namely, it is important
    467                         // to wait for other cells to turn N before adding links
    468                         gcur = gcur->child;
    469                         return 0;
    470 
    471                 case '@':
    472                 case '|':
    473                         // neuron rotating / bending
    474                         j = 1;
    475                         if ('@' == gcur->name) j = 1; // rot
    476                         if ('|' == gcur->name) j = 2; // bend
    477                         // error: not a neuron (undiff)
    478                         if (T_UNDIFF4 == type)
    479                         {
    480                                 // fix: delete it
    481                                 org->setRepairRemove(gcur->pos, gcur);
    482                                 return 1;  // stop
    483                         }
    484                         // error: not a neuron (stick)
    485                         if (T_NEURON4 != type)
    486                         {
    487                                 // fix: delete it
    488                                 org->setRepairRemove(gcur->pos, gcur);
    489                                 return 1;  // stop
    490                         }
    491                         // error: already has control
    492                         if (ctrl != 0)
    493                         {
    494                                 // fix: delete it
    495                                 org->setRepairRemove(gcur->pos, gcur);
    496                                 return 1;  // stop
    497                         }
    498                         // make neuron ctrl = 1 or 2
    499                         ctrl = j;
    500                         gcur = gcur->child;
    501                         break;
    502 
    503                 case '[':
    504                         // link to neuron
    505                         // error: not a neuron
    506                         if (T_NEURON4 != type)
    507                         {
    508                                 // fix: delete it
    509                                 org->setRepairRemove(gcur->pos, gcur);
    510                                 return 1;  // stop
    511                         }
    512                         // input ('*', 'G', 'T', 'S', or %d)
    513                         t = gcur->i1;
    514                         relfrom = gcur->l1;
    515                         w = gcur->f1;
    516                         if (t > 0)
    517                         {
    518                                 // * or G
    519                                 tneu = NULL;
    520                         }
    521                         else {
    522                                 // input from other neuron
    523                                 // find neuron at relative i
    524                                 // find own index
    525                                 j = 0; k = 0;
    526                                 for (i = 0; i < org->nc; i++)
    527                                 {
    528                                         if (org->C[i]->type == T_NEURON4) k++;
    529                                         if (org->C[i] == this) { j = k - 1; break; }
    530                                 }
    531                                 // find index of incoming
    532                                 j = j + relfrom;
    533                                 if (j < 0) goto wait_link;
    534                                 if (j >= org->nc) goto wait_link;
    535                                 // find that neuron
    536                                 k = 0;
    537                                 for (i = 0; i < org->nc; i++)
    538                                 {
    539                                         if (org->C[i]->type == T_NEURON4) k++;
    540                                         if (j == (k - 1)) break;
    541                                 }
    542                                 if (i >= org->nc) goto wait_link;
    543                                 tneu = org->C[i];
    544                         }
    545                         // add link
    546                         // error: could not add link (too many?)
    547                         if (addlink(tneu, w, t))
    548                         {
    549                                 // cannot fix
    550                                 org->setError(gcur->pos);
    551                                 return 1;  // stop
    552                         }
    553                         gcur = gcur->child;
    554                         break;
    555                 wait_link:
    556                         // wait for other neurons to develop
    557                         // if there are others still active
    558                         active = 0;
    559                         j = 0;
    560                         for (i = 0; i < org->nc; i++)
    561                         {
    562                                 if (org->C[i]->active) j++;
    563                         }
    564                         if (j > 0)
    565                                 return 0;  // there is other active, halt, try again
    566                         // no more actives, cannot add link, ignore, but treat not as an error
    567                         gcur = gcur->child;
    568                         break;
    569 
    570                 case ':':
    571                         // neuron parameter
    572                         // error: not a neuron
    573                         if (T_NEURON4 != type)
    574                         {
    575                                 // fix: delete it
    576                                 org->setRepairRemove(gcur->pos, gcur);
    577                                 return 1;  // stop
    578                         }
    579                         j = (int)gcur->l1;
    580                         switch ((char)gcur->i1)
    581                         {
    582                         case '!':
    583                                 if (j) force += (1.0 - force) * 0.2;
    584                                 else   force -= force * 0.2; break;
    585                         case '=':
    586                                 if (j) inertia += (1.0 - inertia) * 0.2;
    587                                 else   inertia -= inertia * 0.2; break;
    588                         case '/':
    589                                 if (j) sigmo *= 1.4;
    590                                 else   sigmo /= 1.4; break;
    591                         default:
    592                                 org->setRepairRemove(gcur->pos, gcur);
    593                                 return 1;  // stop
    594                         }
    595                         gcur = gcur->child;
    596                         break;
    597 
    598                 case ' ':
    599                         // space has no effect, should not occur
    600                         // fix: delete it
    601                         org->setRepairRemove(gcur->pos, gcur);
    602                         gcur = gcur->child;
    603                         break;
    604 
    605                 default:
    606                         // error: unknown code
    607                         char buf[40];
    608                         sprintf(buf, "unknown code '%c'", gcur->name);
    609                         logMessage("f4_Cell", "onestep", 2, buf);
    610                         // fix: delete it
    611                         org->setRepairRemove(gcur->pos, gcur);
    612                         return 1; // stop
     625                        return 0; //stop
    613626                }
    614627        }
     
    618631
    619632
    620 int f4_Cell::addlink(f4_Cell * nfrom, double nw, int nt)
    621 {
     633int f4_Cell::addlink(f4_Cell * nfrom, double nw, string nt)
     634{
     635        // if incoming neuron does not produce output, return error
     636        if (nfrom != NULL && nfrom->neuclass->getPreferredOutput() == 0) return -1;
     637        if (neuclass->getPreferredInputs() != -1 && nolink >= neuclass->getPreferredInputs()) return -1;
    622638        if (nolink >= MAXINPUTS - 1) return -1; // full!
    623639        links[nolink] = new f4_CellLink(nfrom, nw, nt);
     
    664680                {
    665681                        //firstend = dadlink->lastend;
    666                         f4_Props Pdad = dadlink->P;
    667                         f4_Props Padj = Pdad;
    668                         Padj.adjust();
     682                        GeneProps Pdad = dadlink->P;
     683                        GeneProps Padj = Pdad;
     684                        Padj.propagateAlong(false);
    669685
    670686                        //rot = Orient_1;
     
    700716
    701717
    702 f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, int nt)
     718f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, string nt)
    703719{
    704720        from = nfrom;
     
    720736        tmpcel = NULL;
    721737        f4rootnode = NULL;
    722 
    723         C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, stdProps);
     738        C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, GeneProps::standard_values);
    724739        nc = 1;
    725740}
     
    748763
    749764        // create ancestor cell
    750         C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child, NULL, 0, stdProps);
     765        C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child, NULL, 0, GeneProps::standard_values);
    751766        nc = 1;
    752767}
     
    939954{
    940955        if (tmpcel) delete tmpcel;
    941         tmpcel = new f4_Cell(-1, NULL, 0, stdProps);
     956        tmpcel = new f4_Cell(-1, NULL, 0, GeneProps::standard_values);
    942957        out = "";
    943958        toF1GenoRec(0, out);
     
    962977
    963978        // adjust length, curvedness, etc.
    964         tmpcel->P.adjust();
     979        tmpcel->P.propagateAlong(false);
    965980        while (tmpcel->P.length > thisti->P.length)
    966981        {
     
    10151030                                        if (NULL == thneu->links[j]->from)
    10161031                                        {
    1017                                                 // sensory
    1018                                                 if (1 == thneu->links[j]->t) out += "*";
    1019                                                 if (2 == thneu->links[j]->t) out += "G";
    1020                                                 if (3 == thneu->links[j]->t) out += "T";
    1021                                                 if (4 == thneu->links[j]->t) out += "S";
     1032                                                // sensors
     1033                                                out += thneu->links[j]->t.c_str();
    10221034                                        }
    10231035                                        else
     
    10731085f4_node::f4_node()
    10741086{
    1075         name = '?';
     1087        name = "?";
    10761088        parent = NULL;
    10771089        child = NULL;
    10781090        child2 = NULL;
    10791091        pos = -1;
    1080 }
    1081 
    1082 f4_node::f4_node(char nname, f4_node * nparent, int npos)
     1092        l1 = 0;
     1093        i1 = 0;
     1094        f1 = 0.0f;
     1095}
     1096
     1097f4_node::f4_node(string nname, f4_node *nparent, int npos)
    10831098{
    10841099        name = nname;
     
    10881103        pos = npos;
    10891104        if (parent) parent->addChild(this);
     1105        l1 = 0;
     1106        i1 = 0;
     1107        f1 = 0.0f;
     1108}
     1109
     1110f4_node::f4_node(char nname, f4_node * nparent, int npos)
     1111{
     1112        name = nname;
     1113        parent = nparent;
     1114        child = NULL;
     1115        child2 = NULL;
     1116        pos = npos;
     1117        if (parent) parent->addChild(this);
     1118        l1 = 0;
     1119        i1 = 0;
     1120        f1 = 0.0f;
    10901121}
    10911122
     
    11941225}
    11951226
    1196 void f4_node::sprint(SString & out)
    1197 {
    1198         char buf2[20];
     1227void f4_node::sprint(SString& out)
     1228{
     1229        string buf2 = "";
    11991230        // special case: repetition code
    1200         if ('#' == name)
     1231        if (name == "#")
    12011232        {
    12021233                out += "#";
    12031234                if (i1 != 1)
    12041235                {
    1205                         sprintf(buf2, "%d", i1);
    1206                         out += buf2;
     1236                        sprintf((char*)buf2.c_str(), "%d", i1);
     1237                        out += buf2.c_str();
    12071238                }
    12081239        }
    12091240        else {
    12101241                // special case: neuron link
    1211                 if ('[' == name)
     1242                if (name == "[")
    12121243                {
    12131244                        out += "[";
     
    12151246                        {
    12161247                                // sensor input
    1217                                 if (1 == i1) out += "*";
    1218                                 if (2 == i1) out += "G";
    1219                                 if (3 == i1) out += "T";
    1220                                 if (4 == i1) out += "S";
     1248                                out += s1.c_str();
    12211249                        }
    12221250                        else
    12231251                        {
    1224                                 sprintf(buf2, "%ld", l1);
    1225                                 out += buf2;
    1226                         }
    1227                         sprintf(buf2, ":%g]", f1);
    1228                         out += buf2;
    1229                 }
    1230                 else if (':' == name)
    1231                 {
    1232                         sprintf(buf2, ":%c%c:", l1 ? '+' : '-', (char)i1);
    1233                         out += buf2;
     1252                                sprintf((char*)buf2.c_str(), "%ld", l1);
     1253                                out += buf2.c_str();
     1254                        }
     1255                        sprintf((char*)buf2.c_str(), ":%g]", f1);
     1256                        out += buf2.c_str();
     1257                }
     1258                else if (name == ":")
     1259                {
     1260                        sprintf((char*)buf2.c_str(), ":%c%c:", l1 ? '+' : '-', (char)i1);
     1261                        out += buf2.c_str();
     1262                }
     1263                else if (name == "@" || name == "|")
     1264                {
     1265                        if (parent->name == "N")
     1266                        {
     1267                                buf2 = name;
     1268                                out += buf2.c_str();
     1269                        }
     1270                        else
     1271                        {
     1272                                out += "N:";
     1273                                buf2 = name;
     1274                                out += buf2.c_str();
     1275                        }
    12341276                }
    12351277                else
    12361278                {
    1237                         buf2[0] = name;
    1238                         buf2[1] = 0;
    1239                         out += buf2;
     1279                        char *temp = (char*)name.c_str();
     1280                        NeuroClass * nc = GenoOperators::parseNeuroClass(temp);
     1281                        if (nc != NULL)
     1282                        {
     1283                                out += "N:";
     1284                        }
     1285                        buf2 = name;
     1286                        out += buf2.c_str();
    12401287                }
    12411288        }
     
    13011348}
    13021349
    1303 
    13041350// scan genotype string and build tree
    13051351// return >1 for error (errorpos)
    13061352int f4_processrec(const char * genot, unsigned pos0, f4_node * parent)
    13071353{
    1308         int i, j, t, res;
    1309         char tc1, tc2;
     1354        int i, j, res, t;
     1355        char tc1, tc2, tc3; // tc3 is only to ensure that in the end  of neuron parameter definition
    13101356        int relfrom;
    13111357        double w;
    13121358        unsigned gpos, oldpos;
    13131359        f4_node * node1, *par;
     1360        unsigned beginindex;
     1361        string neutype = "";
    13141362
    13151363        gpos = pos0;
     
    13181366        while (gpos < strlen(genot))
    13191367        {
    1320                 //DB( printf(" processing '%c' %d %s\n", genot[gpos], gpos, genot); )
     1368                neutype = "";
     1369                // first switch across cell dividers and old semantics
    13211370                switch (genot[gpos])
    13221371                {
    13231372                case '<':
    1324                         // cell division!
    1325                         //DB( printf("  div! %d\n", name); )
    1326 
     1373                {
    13271374                        // find out genotype start for child
    13281375                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), '>');
    13291376
    1330                         node1 = new f4_node('<', par, gpos);
     1377                        node1 = new f4_node("<", par, gpos);
    13311378                        par = node1;
    13321379                        res = f4_processrec(genot, gpos + 1, par);
     
    13391386                        else // ran out
    13401387                        {
    1341                                 node1 = new f4_node('>', par, strlen(genot) - 1);
     1388                                node1 = new f4_node(">", par, strlen(genot) - 1);
    13421389                                par = node1;
    13431390                        }
    1344                         // adjustments
    13451391                        gpos++;
    13461392                        return 0;  // OK
    1347 
     1393                }
    13481394                case '>':
    1349                         node1 = new f4_node('>', par, gpos);
     1395                {
     1396                        node1 = new f4_node(">", par, gpos);
    13501397                        par = node1;
    13511398                        gpos = strlen(genot);
    13521399                        return 0;  // OK
    1353 
     1400                }
    13541401                case '#':
     1402                {
    13551403                        // repetition marker, 1 by default
    13561404                        if (sscanf(genot + gpos, "#%d", &i) != 1) i = 1;
     
    13611409                        gpos++;
    13621410                        while ((genot[gpos] >= '0') && (genot[gpos] <= '9')) gpos++;
    1363                         node1 = new f4_node('#', par, oldpos);
     1411                        node1 = new f4_node("#", par, oldpos);
    13641412                        node1->i1 = i;
    13651413                        par = node1;
     
    13731421                        else // ran out
    13741422                        {
    1375                                 node1 = new f4_node('>', par, strlen(genot) - 1);
     1423                                node1 = new f4_node(">", par, strlen(genot) - 1);
    13761424                        }
    13771425                        return 0;  // OK
    1378 
    1379                         // 'simple' nodes:
    1380                 case ',':
     1426                }
     1427                case ' ':
     1428                case '\n':
     1429                case '\r':
     1430                case '\t':
     1431                {
     1432                        // whitespace: ignore
     1433                        gpos++;
     1434                        break;
     1435                }
    13811436                case 'l':  case 'L':
    13821437                case 'c':  case 'C':
    13831438                case 'q':  case 'Q':
    13841439                case 'r':  case 'R':
    1385                 case 'X':  case 'N':
    1386                 case '@':  case '|':
     1440                case 'X':  case ',':
    13871441                case 'a':  case 'A':
    13881442                case 's':  case 'S':
     
    13921446                case 'w':  case 'W':
    13931447                case 'e':  case 'E':
     1448                {
    13941449                        node1 = new f4_node(genot[gpos], par, gpos);
    13951450                        par = node1;
    13961451                        gpos++;
    13971452                        break;
    1398 
     1453                }
     1454                case '@':  case '|':
     1455                {
     1456                        // in order to prevent the presence of "free muscles", we need to ensure that a muscle is written as N@/N| or N:@/N:|
     1457                        if (par != NULL && par->name == "N")
     1458                        {
     1459                                node1 = new f4_node(genot[gpos], par, gpos);
     1460                                par = node1;
     1461                                gpos++;
     1462                        }
     1463                        else
     1464                        {
     1465                                return gpos + 1;
     1466                        }
     1467                        break;
     1468                }
     1469
     1470                case 'N':
     1471                {
     1472                        // if there is no colon after N, then there is no class definition
     1473                        if (gpos + 1 >= strlen(genot) || genot[gpos + 1] != ':')
     1474                        {
     1475                                node1 = new f4_node(genot[gpos], par, gpos);
     1476                                par = node1;
     1477                                gpos++;
     1478                                break;
     1479                        }
     1480                        // if there is a colon determining neuron parameter, then let the switch case colon handle this
     1481                        else if (sscanf(genot + gpos + 1, ":%c%c%[:]", &tc1, &tc2, &tc3) == 3)
     1482                        {
     1483                                node1 = new f4_node(genot[gpos], par, gpos);
     1484                                par = node1;
     1485                                gpos++;
     1486                                break;
     1487                        }
     1488                        int forgenorange = gpos;
     1489                        gpos += 2; //skipping "N:"
     1490                        beginindex = gpos;
     1491                        char * end = (char*)genot + beginindex;
     1492                        GenoOperators::parseNeuroClass(end);
     1493                        gpos += end - genot - beginindex;
     1494                        neutype = string(genot + beginindex, genot + gpos);
     1495                        node1 = new f4_node(neutype, par, forgenorange);
     1496                        par = node1;
     1497                        break;
     1498                }
     1499                case ':':
     1500                {
     1501                        // neuron parameter  +! -! += -= +/ or -/
     1502                        if (sscanf(genot + gpos, ":%c%c%[:]", &tc1, &tc2, &tc3) != 3)
     1503                                // error: incorrect format
     1504                                return gpos + 1 + 1;
     1505                        if ('+' == tc1) j = 1;
     1506                        else if ('-' == tc1) j = 0;
     1507                        else return gpos + 1 + 1;
     1508                        switch (tc2)
     1509                        {
     1510                        case '!':  case '=':  case '/':  break;
     1511                        default:
     1512                                return gpos + 1 + 1;
     1513                        }
     1514                        node1 = new f4_node(":", par, gpos);
     1515                        node1->l1 = j;
     1516                        node1->i1 = (int)tc2;
     1517                        par = node1;
     1518                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ':');
     1519                        gpos += j + 2;
     1520                        break;
     1521                }
    13991522                case '[':
    1400                         // link to neuron
    1401                         // input (%d, '*', 'G', 'T', 'S')
    1402                         t = -1;
    1403                         if (sscanf(genot + gpos, "[%ld:%lf]", &relfrom, &w) == 2) t = 0;
    1404                         else if (sscanf(genot + gpos, "[*:%lf]", &w) == 1) t = 1;
    1405                         else if (sscanf(genot + gpos, "[G:%lf]", &w) == 1) t = 2;
    1406                         else if (sscanf(genot + gpos, "[T:%lf]", &w) == 1) t = 3;
    1407                         else if (sscanf(genot + gpos, "[S:%lf]", &w) == 1) t = 4;
    1408                         // error: no correct format
    1409                         if (t < 0) return gpos + 1 + 1;
    1410                         node1 = new f4_node('[', par, gpos);
     1523                {
     1524                        const char *end = parseConnection(genot + gpos, relfrom, w);
     1525                        if (end == NULL)
     1526                        {
     1527                                end = parseConnectionWithNeuron(genot + gpos, neutype, w);
     1528                                if (end == NULL) t = -1;
     1529                                t = 1;
     1530                        }
     1531                        else
     1532                        {
     1533                                t = 0;
     1534                        }
     1535                        node1 = new f4_node("[", par, gpos);
     1536                        node1->s1 = neutype;
    14111537                        node1->i1 = t;
    14121538                        node1->l1 = relfrom;
     
    14161542                        gpos += j + 2;
    14171543                        break;
    1418 
    1419                 case ':':
    1420                         // neuron parameter  +! -! += -= +/ or -/
    1421                         if (sscanf(genot + gpos, ":%c%c:", &tc1, &tc2) != 2)
    1422                                 // error: incorrect format
    1423                                 return gpos + 1 + 1;
    1424                         if ('+' == tc1) j = 1;
    1425                         else if ('-' == tc1) j = 0;
    1426                         else return gpos + 1 + 1;
    1427                         switch (tc2)
    1428                         {
    1429                         case '!':  case '=':  case '/':  break;
    1430                         default:
    1431                                 return gpos + 1 + 1;
    1432                         }
    1433                         node1 = new f4_node(':', par, gpos);
    1434                         node1->l1 = j;
    1435                         node1->i1 = (int)tc2;
    1436                         par = node1;
    1437                         j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ':');
    1438                         gpos += j + 2;
    1439                         break;
    1440 
    1441                 case ' ':
    1442                 case '\n':
    1443                 case '\t':
    1444                         // whitespace: ignore
    1445                         //node1 = new f4_node(' ', par, gpos );
    1446                         //par = node1;
    1447                         gpos++;
    1448                         break;
    1449 
     1544                }
    14501545                default:
     1546                {
    14511547                        //DB( printf("unknown character '%c' ! \n", genot[gpos]); )
    14521548                        //add it, build will give the error or repair
     
    14561552                        break;
    14571553                }
    1458         }
     1554                }
     1555        }
     1556
    14591557        // should end with a '>'
    14601558        if (par)
    14611559        {
    1462                 if ('>' != par->name)
     1560                if (par->name != ">")
    14631561                {
    14641562                        node1 = new f4_node('>', par, strlen(genot) - 1);
     
    14671565        }
    14681566
    1469         return 0;  // OK
    1470 }
    1471 
     1567        return 0;
     1568}
     1569
     1570const char* parseConnection(const char *fragm, int& relfrom, double &weight)
     1571{
     1572        const char *parser = fragm;
     1573        if (*parser != '[') return NULL;
     1574        parser++;
     1575        ExtValue val;
     1576        parser = val.parseNumber(parser, ExtPType::TInt);
     1577        if (parser == NULL) return NULL;
     1578        relfrom = val.getInt();
     1579        if (*parser != ':') return NULL;
     1580        parser++;
     1581        parser = val.parseNumber(parser, ExtPType::TDouble);
     1582        if (parser == NULL) return NULL;
     1583        weight = val.getDouble();
     1584        if (*parser != ']') return NULL;
     1585        parser++;
     1586        return parser;
     1587}
     1588
     1589const char* parseConnectionWithNeuron(const char *fragm, string &neutype, double &weight)
     1590{
     1591        const char *parser = fragm;
     1592        if (*parser != '[') return NULL;
     1593        parser++;
     1594        char * p = (char*)parser;
     1595        if (GenoOperators::parseNeuroClass(p) == NULL) return NULL;
     1596        neutype = string(parser, (const char *)p);
     1597        parser = p;
     1598        if (*parser != ':') return NULL;
     1599        parser++;
     1600        ExtValue val;
     1601        parser = val.parseNumber(parser, ExtPType::TDouble);
     1602        if (parser == NULL) return NULL;
     1603        weight = val.getDouble();
     1604        if (*parser != ']') return NULL;
     1605        parser++;
     1606        return parser;
     1607}
    14721608
    14731609f4_node * f4_processtree(const char * geno)
  • cpp/frams/genetics/f4/f4_general.h

    r671 r760  
    88#define _F4_GENERAL_H_
    99
    10 //#include "f4_orientmat.h"
    1110#include <frams/util/3d.h>
    1211#include <frams/util/sstring.h>
    1312#include <frams/util/multirange.h>
     13#include <frams/genetics/geneprops.h>
    1414
    1515#ifdef DMALLOC
     
    1717#endif
    1818
    19 
    20 class f4_Props
    21 {
    22 public:
    23         // fill with default values
    24         f4_Props();
    25         // must sum to 1
    26         void normalizeBiol4();
    27         void executeModifier(char modif);
    28         void adjust();
    29 
    30         double length;
    31         double curvedness;
    32         double weight;
    33         double friction;
    34         double muscle_power;
    35         double assimilation;
    36         double stamina;
    37         double ingestion;
    38         double twist;
    39         double energy;
    40 };
    41 
    42 extern f4_Props stdProps;
    43 
    44 
    45 // rolling (one-time)
     19/**
     20 * Performs single rotation angle decrementation on a given value.
     21 * @param v pointer to the decremented value
     22 */
    4623void rolling_dec(double * v);
     24
     25/**
     26 * Performs single rotation angle incrementation on a given value.
     27 * @param v pointer to the incremented value
     28 */
    4729void rolling_inc(double * v);
    48 
    4930
    5031class f4_node;   // later
     
    5334
    5435
    55 // cell types
    56 #define T_UNDIFF4 40
    57 #define T_STICK4  41
    58 #define T_NEURON4 42
    59 
     36/** @name Types of f4_Cell's */
     37//@{
     38#define T_UNDIFF4 40 ///<undifferentiated cell
     39#define T_STICK4  41 ///<differentiated to stick, cannot divide
     40#define T_NEURON4 42 ///<differentiated to neuron, can divide
     41//@}
     42
     43/**
     44 * Scans f4 genotype string for a stopping character and returns the position of
     45 * this stopping character or 1 if the end of string was reached. This method is used
     46 * for closing braces, like ), >, ]. It runs recursively when opening braces
     47 * like (, <, # are found.
     48 * @param s string with the f4 genotype
     49 * @param slen length of a given string
     50 * @param stopchar character to be found
     51 * @return 1 if end of string was reached, or position of found character in sequence
     52 */
    6053int scanrec(const char * s, unsigned int slen, char stopchar);
    6154
    6255
    6356class f4_CellLink;
    64 #define MAXINPUTS 100
    65 
    66 // an abstract cell type, extension of part/stick -- for developmental encoding
     57
     58/** @name Constraints of f4 genotype structures */
     59//@{
     60#define MAXINPUTS 100 ///<maximum number of neuron inputs
     61#define MAX4CELLS 100 ///<maximum number of f4 organism cells
     62//@}
     63
     64/**
     65 * Abstract cell type - the representation of single component in the  developmental
     66 * encoding. In the beginning, each f4_Cell is undifferentiated. During the process
     67 * of development it can divide or differentiate into a stick or a neuron. If it
     68 * differentiates to a neuron, then it preserves the ability to divide, but divided
     69 * cells will be the same type as the parent cell. If it is a stick, then it cannot
     70 * be divided anymore.
     71 *
     72 * From f4_Cell array the final Model of a creature is created.
     73 */
    6774class f4_Cell
    6875{
    6976public:
     77        /**
     78         * Represents the repetition marker. It holds information about the pointer
     79         * to the repetition node and the count of repetitions.
     80         */
    7081        class repeat_ptr
    7182        {
    7283        public:
    7384                repeat_ptr() : node(NULL), count(-1) { };
    74                 repeat_ptr(f4_node * a, int b) : node(a), count(b) { };
    75                 inline void null() { node = NULL; count = -1; };
     85
     86                /**
     87                 * A constructor that takes the pointer to the repetition node and the count of repetitions.
     88                 * @param a pointer to f4_node for repetition character
     89                 * @param b the number of repetitions
     90                 */
     91                repeat_ptr(f4_node *a, int b) : node(a), count(b) { };
     92
     93                inline void makeNull() { node = NULL; count = -1; };
     94
    7695                inline bool isNull() const { return ((node == NULL) || (count <= 0)); };
     96
    7797                inline void dec() { count--; };
    78                 f4_node *  node;  // ptr to repetition code
    79                 char       count; // repetition counter
     98                f4_node    *node; ///<pointer to the repetition code
     99                char       count; ///<repetition counter
    80100        };
    81101
    82         class repeat_stack  // a stack of repet_ptr's
     102        /**
     103         * Represents the stack of repeat_ptr objects. The objects are
     104         * pushed to the stack when '#' repetition symbol appears, and are popped when
     105         * the end of the current cell definition, i.e. the '>' character, appears. After the
     106         * '>' character, the cell is duplicated as many times as it is defined after the
     107         * repetition marker.
     108         */
     109        class repeat_stack
    83110        {
    84111        public:
    85                 repeat_stack() { top = 0; };
    86                 inline void null() { top = 0; };
    87                 inline void push(repeat_ptr A) { if (top >= stackSize) return; ptr[top] = A; top++; };
    88                 inline void pop() { if (top > 0) top--; };
    89                 inline repeat_ptr * first() { return &(ptr[top - (top > 0)]); };
    90                 static const int stackSize = 4;  // max 4 nested levels
    91                 repeat_ptr ptr[stackSize];
    92                 short int top;  // top of the stack
     112                repeat_stack() { top = 0; }
     113
     114                inline void clear() { top = 0; }
     115
     116                /**
     117                 * Pushes repeat_ptr object onto the stack. If the stack size is exceeded, then no
     118                 * information is provided.
     119                 * @param rn repetition node info
     120                 */
     121                inline void push(repeat_ptr rn) { if (top >= stackSize) return; ptr[top] = rn; top++; }
     122
     123                inline void pop() { if (top > 0) top--; }
     124
     125                /**
     126                 * Gets the current top element.
     127                 * @return pointer to the element on top of the repeat_stack object
     128                 */
     129                inline repeat_ptr* first() { return &(ptr[top - (top > 0)]); };
     130                static const int stackSize = 4;  ///<max 4 nested levels
     131                repeat_ptr ptr[stackSize]; ///<array holding pointers to repeat_ptr
     132                short int top;  ///<index of the top of the stack
    93133        };
    94134
     135        /**
     136         * Creates a new f4_Cell object.
     137         * @param nname name of a cell, can be T_UNDIFF4, T_STICK4 or T_NEURON4
     138         * @param ndad pointer to the parent of the created cell
     139         * @param nangle the amount of commas affecting branch angles
     140         * @param newP genotype properties of a given cell
     141         */
    95142        f4_Cell(int nname,
    96                 f4_Cell * ndad, int nangle, f4_Props newP);
    97         f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur,
    98                 f4_Cell * ndad, int nangle, f4_Props newP);
     143                f4_Cell * ndad, int nangle, GeneProps newP);
     144        /**
     145         * Creates a new f4_Cell object.
     146         * @param nO pointer to an organism containing the cell
     147         * @param nname name of the cell, can be T_UNDIFF4, T_STICK4 or T_NEURON4
     148         * @param ngeno pointer to the root of the genotype tree
     149         * @param ngcur pointer to the f4_node representing the current cell in the genotype tree
     150         * @param ndad pointer to the parent of the created cell
     151         * @param nangle the number of commas affecting branch angles
     152         * @param newP genotype properties of a given cell
     153         */
     154        f4_Cell(f4_Cells *nO, int nname, f4_node *ngeno, f4_node *ngcur,
     155                f4_Cell *ndad, int nangle, GeneProps newP);
     156
    99157        ~f4_Cell();
    100158
     159        /**
     160         * Performs one step of cell development. This method requires pointer to
     161         * f4_Cells object in org attribute. If the current node in genotype tree
     162         * represents branching, then the cell divides into two cells, unless the
     163         * cell was already differentiated into stick cell. Otherwise the current
     164         * differentiation or modification is performed on cell. If current node is
     165         * creating a connection between two neuron nodes, and the input node is not
     166         * yet developed, then the simulation of current cell halts and waits until
     167         * the input node will be developed. The onestep method is ran on each cell
     168         * at least once and if one cell requires another to develop, then onestep
     169         * should be deployed again on this cell. This method, unlike genotype tree
     170         * creation, checks semantics. This means that this function will fail if:
     171         *  - the stick cell will have divide node,
     172         *  - the undifferentiated cell will have '>' node (end of cell development),
     173         *  - the stack of repetition marker '#' will be overflowed,
     174         *  - the stick modifiers, like rotation, will be applied on neuron cell,
     175         *  - the differentiated cell will be differentiated again,
     176         *  - the neuron class inside cell connection definition is not a sensor,
     177         *  - the connection between neurons could not be established,
     178         *  - the neuron class is not valid.
     179         *
     180         * @return 0 if development was successful, 1 if there was an error in genotype tree
     181         */
    101182        int onestep();  // execute one simulation step (till a division)
    102183
    103         int   addlink(f4_Cell * nfrom, double nw, int nt);
     184        /**
     185         * Add link between this neuron cell and a given neuron cell. If nfrom object
     186         * is not given, than neuron type in nt holds the sensor type.
     187         * @param nfrom input neuron cell, or NULL if not given
     188         * @param nw weight of connection
     189         * @param nt empty string or name of sensor class
     190         * @return 0 if link is established, -1 otherwise
     191         */
     192        int   addlink(f4_Cell * nfrom, double nw, string nt);
     193
     194        /**
     195         * Adjusts properties of stick objects.
     196         */
    104197        void  adjustRec();
    105198
    106         int        name;     // name (number)
    107         int        type;     // type
    108         f4_Cell *  dadlink;
    109         f4_Cells * org; // uplink to organism
    110 
    111         f4_node *  genot;         // genotype
    112         f4_node *  gcur;        // current genotype execution pointer
    113         int        active;      // whether development is still active
    114         repeat_stack repeat;
    115         int        recProcessedFlag;  // used during recursive traverse
    116         // remember the genotype codes affecting this cell so far
    117         MultiRange genoRange;
    118 
    119         f4_Props     P;             // properties
    120         int          anglepos;      // number of position within dad's children (,)
    121         int          childcount;    // number of children
    122         int          commacount;    // number of postitions at lastend (>=childcount)
    123         double       rolling;       // rolling angle ('R') (around x)
    124         double       xrot;
    125         double       zrot;          // horizontal rotation angle due to
    126         // branching (around z)
    127         //Pt3D         firstend;      // coord.s of first end (connects to parent)
    128         //Pt3D         lastend;       // last end
    129         //f4_OrientMat OM;
    130         double       mz;            // freedom in z
    131         int          p2_refno;   // number of last end part object, used in f0
    132         int          joint_refno;   // number of the joint object, used in f0
    133         int          neuro_refno;   // number of the neuro object, used in f0
    134 
    135         int          ctrl;  // neuron type
    136         double       state;
    137         double       inertia;
    138         double       force;
    139         double       sigmo;
    140         f4_CellLink* links[MAXINPUTS];
    141         int          nolink;
     199        int        name;               ///<name of cell(number)
     200        int        type;               ///<type
     201        f4_Cell *  dadlink;            ///<pointer to cell parent
     202        f4_Cells * org;                ///<uplink to organism
     203
     204        f4_node *  genot;                  ///<genotype tree
     205        f4_node *  gcur;               ///<current genotype execution pointer
     206        int        active;             ///<whether development is still active
     207        repeat_stack repeat;           ///<stack holding repetition nodes and counters
     208        int        recProcessedFlag;   ///<used during recursive traverse
     209        MultiRange genoRange;          ///<remember the genotype codes affecting this cell so far
     210
     211        GeneProps     P;               ///<properties
     212        int          anglepos;         ///<number of position within dad's children (,)
     213        int          childcount;       ///<number of children
     214        int          commacount;       ///<number of postitions at lastend (>=childcount)
     215        double       rolling;          ///<rolling angle ('R') (around x)
     216        double       xrot;                         ///<rotation angle around x
     217        double       zrot;             ///<horizontal rotation angle due to branching (around z)
     218
     219        double       mz;               ///<freedom in z
     220        int          p2_refno;         ///<number of last end part object, used in f0
     221        int          joint_refno;      ///<number of the joint object, used in f0
     222        int          neuro_refno;      ///<number of the neuro object, used in f0
     223
     224        int          ctrl;             ///<neuron type
     225        double       state;            ///<state of neuron
     226        double       inertia;          ///<inertia of neuron
     227        double       force;            ///<force of neuron
     228        double       sigmo;            ///<sigmoid of neuron
     229        f4_CellLink* links[MAXINPUTS]; ///<array of neuron links
     230        int          nolink;           ///<number of links
     231        NeuroClass * neuclass = NULL;  ///<pointer to neuron class
    142232};
    143233
    144 
    145 // an input link to a neuron
     234/**
     235 * Class representing link between neuron cells.
     236 */
    146237class f4_CellLink
    147238{
    148239public:
    149         f4_CellLink(f4_Cell * nfrom, double nw, int nt);
    150         f4_Cell *    from;
    151         // type: 0: input, 1 '*', 2 'G', 3 'T', 4 'S'
    152         int          t;
    153         double       w;
     240        /**
     241         * Constructor for f4_CellLink class. Parameter nfrom can represent input
     242         * neuron cell or be NULL, if connection has neuron cell definition inside.
     243         * The inside definition must be hold in nt parameter and a neuron class
     244         * must represent sensor.
     245         * @param nfrom pointer to input neuron cell or NULL
     246         * @param nw weight of connection
     247         * @param nt name of neuron class or empty string
     248         */
     249        f4_CellLink(f4_Cell * nfrom, double nw, string nt);
     250
     251        f4_Cell *    from; ///<pointer to input neuron cell
     252        string  t;    ///<empty if from cell is given, NeuroClass name otherwise
     253        double       w;    ///<weight of connection
    154254};
    155255
    156256
    157257// a collection of cells, like Organism, for developmental encoding
    158 #define MAX4CELLS 100
     258/**
     259 * Class representing a collection of cells. It is equivalent of organism.
     260 */
    159261class f4_Cells
    160262{
    161263public:
     264
     265        /**
     266         * Constructor taking genotype in a form of a tree.
     267         * @param genome genotype tree
     268         * @param nrepair 0 if nothing to repair
     269         */
    162270        f4_Cells(f4_node * genome, int nrepair);
     271
     272        /**
     273         * Constructor taking genotype in a form of a string.
     274         * @param genome genotype string
     275         * @param nrepair 0 if nothing to repair
     276         */
    163277        f4_Cells(SString &genome, int nrepair);
     278
     279        /**
     280         * Destructor removing cells from memory.
     281         */
    164282        ~f4_Cells();
     283
     284        /**
     285         * Adds new cell to organism.
     286         * @param newcell cell to be added
     287         */
    165288        void addCell(f4_Cell * newcell);
    166         void toF1Geno(SString &out);       // output to f1 format, approximation
    167         int  onestep();       // simulate all parts for one step
    168         int  simulate();      // simulate development, return error (0 for ok)
    169         // for error reporting / genotype fixing
     289
     290        /**
     291         * Creates approximate genotype in f1 encoding and stores it in a given
     292         * parameter.
     293         * @param out the string in which approximate f1 genotype will be stored
     294         */
     295        void toF1Geno(SString &out);
     296
     297        /**
     298         * Performs single step of organism development. It runs each active cell
     299         * in organism.
     300         * @return 0 if all cells are developed, or 1 otherwise
     301         */
     302        int  onestep();
     303
     304        /**
     305         * Performs full development of organism and returns error code if something
     306         * went wrong.
     307         * @return 0 if organism developed successfully, error code if something went wrong
     308         */
     309        int  simulate();
     310
     311        /**
     312         * Returns error code of last simulation.
     313         * @return error code
     314         */
    170315        int  geterror() { return error; };
     316
     317        /**
     318         * Returns position of error in genotype.
     319         * @return position of error
     320         */
    171321        int  geterrorpos() { return errorpos; };
     322
     323        /**
     324         * Sets error code GENOPER_OPFAIL for simulation on a given position.
     325         * @param nerrpos position of error
     326         */
    172327        void setError(int nerrpos);
     328
     329        /**
     330         * Sets the element of genotype to be repaired by removal.
     331         * @param nerrpos position of error in genotype
     332         * @param rem the f4_node to be removed from genotype tree in order to repair
     333         */
    173334        void setRepairRemove(int nerrpos, f4_node * rem);
     335
     336        /**
     337         * Sets repairing of genotype by inserting new node to current genotype.
     338         * @param nerrpos position of error in genotype
     339         * @param parent the parent of new element
     340         * @param insert the element to be inserted
     341         * @return 0 if repair can be performed, -1 otherwise (the repair flag wasn't set in constructor)
     342         */
    174343        int  setRepairInsert(int nerrpos, f4_node * parent, f4_node * insert);
     344
     345        /**
     346         * Repairs genotype according to setRepairRemove or setRepairInsert method.
     347         * @param geno pointer to genotype tree
     348         * @param whichchild 1 if first child, 2 otherwise
     349         */
    175350        void repairGeno(f4_node * geno, int whichchild);
    176351
    177352        // the cells
    178         f4_Cell * C[MAX4CELLS];
    179         int       nc;
     353        f4_Cell * C[MAX4CELLS]; ///<Array of all cells of organism
     354        int       nc;           ///<Number of cells in organism
    180355
    181356private:
     
    199374{
    200375public:
    201         char      name; // one-letter 'name'
    202         f4_node * parent;       // parent link, or NULL
    203         f4_node * child;        // child, or NULL
    204         f4_node * child2;       // second child, or NULL
    205         int       pos;        // original position in string
    206         int       i1;           // internal int  parameter1
    207         int       l1;           // internal long parameter1
    208         double    f1;           // internal double parameter1
    209 
     376        string name; ///<one-letter 'name', multiple characters for classes
     377        f4_node *parent; ///<parent link, or NULL
     378        f4_node *child; ///<child, or NULL
     379        f4_node *child2; ///<second child, or NULL
     380        int         pos; ///<original position in string
     381        int         i1; ///<internal int  parameter1
     382        int         l1; ///<internal long parameter1
     383        double      f1; ///<internal double parameter1
     384        string s1; ///<internal string parameter1
     385
     386        /**
     387         * Default constructor.
     388         */
    210389        f4_node();
     390
     391        /**
     392         * Multiple-character name constructor.
     393         * @param nname string from genotype representing node
     394         * @param nparent pointer to parent of node
     395         * @param npos position of node substring in genotype string
     396         */
     397        f4_node(string nname, f4_node * nparent, int npos);
     398
     399        /**
     400         * One-character name constructor.
     401         * @param nname character from genotype representing node
     402         * @param nparent pointer to parent of node
     403         * @param npos position of node character in genotype string
     404         */
    211405        f4_node(char nname, f4_node * nparent, int npos);
     406
     407        /**
     408         * Desctructor of object.
     409         */
    212410        ~f4_node();
     411
     412        /**
     413         * Method for adding child to a node.
     414         * @param nchi child to be added to node
     415         * @return 0 if child could be added, -1 otherwise
     416         */
    213417        int       addChild(f4_node * nchi);
     418
     419        /**
     420         * Method for removing child from node.
     421         * @param nchi child to be removed from node
     422         * @return 0 if child could be removed, -1 otherwise
     423         */
    214424        int       removeChild(f4_node * nchi);
    215         int       childCount(); // return no of children, 0, 1, or 2
    216         int       count();      // return no of nodes (recursive)
    217         f4_node * ordNode(int n);       // returns the nth subnode (0-)
    218         f4_node * randomNode(); // returns a random subnode
    219         f4_node * randomNodeWithSize(int min, int max); // returns a random subnode with given size
    220         void      sprintAdj(char *& buf);       // print recursively
    221         f4_node * duplicate();         // create duplicate copy. recursive.
    222         void      destroy();    // release memory. recursive.
     425
     426        /**
     427         * Returns number of children.
     428         * @return 0, 1 or 2
     429         */
     430        int       childCount();
     431
     432        /**
     433         * Returns number of nodes coming from this node in a recursive way.
     434         * @return number of nodes from this node
     435         */
     436        int       count();
     437
     438        /**
     439         * Returns the nth subnode (0-)
     440         * @param n index of child to be found
     441         * @return pointer to nth subnode or NULL if not found
     442         */
     443        f4_node * ordNode(int n);
     444
     445        /**
     446         * Returns a random subnode.
     447         * @return random subnode
     448         */
     449        f4_node * randomNode();
     450
     451        /**
     452         * Returns a random subnode with given size.
     453         * @param min minimum size
     454         * @param max maximum size
     455         * @return a random subnode with given size or NULL
     456         */
     457        f4_node * randomNodeWithSize(int min, int max);
     458
     459        /**
     460         * Prints recursively tree from a given node.
     461         * @param buf variable storing printing result
     462         */
     463        void      sprintAdj(char *& buf);
     464
     465        /**
     466         * Recursively copies genotype tree from this node.
     467         * @return pointer to a tree copy
     468         */
     469        f4_node * duplicate();
     470
     471        /**
     472         * Recursively releases memory from all node children.
     473         */
     474        void      destroy();
    223475private:
    224476        void     sprint(SString & out); // print recursively
     
    226478
    227479// convert f4 geno string to tree structure (internal)
     480
     481/**
     482 * Main function to perform conversion of f4 geno to tree structure. Prepares
     483 * f4_node root of tree and runs f4_processrec function for it.
     484 * @param geno string representing f4 genotype
     485 * @return pointer to f4_node object representing f4 tree root
     486 */
    228487f4_node * f4_processtree(const char * geno);
     488
     489/**
     490 * Scans genotype string from a given position. This recursive method creates
     491 * tree of f4_node objects. The method extract each potentially functional element
     492 * of genotype string to separate f4_nodes. When branching character '<' occurs,
     493 * then f4_processrec is ran for latest f4_node element. This method does not
     494 * analyse genotype semantically, it checks only if syntax is proper. The only
     495 * semantic aspect is neuron class name extraction, in which the GenoOperators
     496 * class is used to parse possible neuron class in genotype.
     497 * @param genot the string holding all genotype
     498 * @param pos0 the current position of processing in string
     499 * @param current parent of analysed branch of genotype
     500 * @return 0 if processing was successful or position of error in genotype
     501 */
    229502int f4_processrec(const char * genot, unsigned pos0, f4_node * parent);
    230503
     504/**
     505 * Function parses notation of neuron connection - it takes beginning of connection
     506 * definition, extracts relative position of input neurons and weight of connection.
     507 * After successful parsing it returns pointer to first character after connection
     508 * definition, or NULL if connection definition was not valid - lack of [, :, ]
     509 * characters or wrong value of relfrom or weight.
     510 * @param fragm the beginning of connection definition, it should be '[' character
     511 * @param relfrom the reference to int variable, in which relative position of input neuron will be stored
     512 * @param weight the reference to double variable, in which weight of connection will be stored
     513 * @return the pointer to first character in string after connection definition
     514 */
     515const char * parseConnection(const char * fragm, int& relfrom, double &weight);
     516
     517/**
     518 * Function parses notation of neuron connection with neuron definition - it
     519 * takes beginning of connection definition, extracts the name of neuron class
     520 * that will be the input for current neuron and weight of connection.
     521 * After successful parsing it returns pointer to first character after connection
     522 * definition, or NULL if connection definition was not valid - lack of [, :, ]
     523 * characters, wrong value of weight or invalid neuron class name.
     524 * @param fragm the beginning of connection definition, it should be '[' character
     525 * @param neutype the reference to string representing input neuron class name. The name of class is validated with GenoOperators::parseNeuroClass
     526 * @param weight the reference to double variable, in which weight of connection will be stored
     527 * @return the pointer to first character in string after connection definition
     528 */
     529const char * parseConnectionWithNeuron(const char * fragm, string& neutype, double &weight);
    231530
    232531#endif
  • cpp/frams/genetics/f4/oper_f4.cpp

    r676 r760  
    55// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
    66// Copyright (C) since 2001 Maciej Komosinski
     7// 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties
    78
    89#include "oper_f4.h"
     
    138139#define REP_MAXCOUNT 19
    139140
    140         f4_node * n1, *n2, *n3, *n4, *n5;
    141 
    142141        // do the mutation
    143142        // pick a random node
    144         n1 = g->child->randomNode();
     143        f4_node *n1 = g->child->randomNode();
     144        vector<NeuroClass*> neulist;
    145145        //DB( printf("%c\n", n1->name); )
     146        int neuronid = -1;
    146147
    147148        switch (roulette(prob, F4_COUNT))
     
    155156                {
    156157                        // add division ('<')
    157                         n3 = n1->parent;
     158                        f4_node *n3 = n1->parent;
    158159                        n3->removeChild(n1);
    159                         n2 = new f4_node('<', n3, n3->pos);
     160                        f4_node *n2 = new f4_node('<', n3, n3->pos);
    160161                        n2->addChild(n1);
    161162                        // new cell is stick or neuron
    162163                        // "X>" or "N>"
     164                        f4_node *n5 = NULL;
    163165                        double pr = rnd01;
    164166                        pr -= 0.5;
    165                         if (pr < 0) n3 = new f4_node('X', n2, n2->pos);
     167                        if (pr < 0) n5 = new f4_node('X', n2, n2->pos);
    166168                        else
    167169                        {
    168                                 pr -= 0.5;
    169                                 if (pr < 0)
    170                                 {
    171                                         // if neuron, make muscle and add a link
    172                                         n3 = new f4_node('N', n2, n2->pos);
    173                                         if (randomN(2) == 0)
    174                                                 n4 = new f4_node('|', n3, n2->pos);
    175                                         else
    176                                                 n4 = new f4_node('@', n3, n2->pos);
    177                                         n5 = new f4_node('[', n4, n2->pos);
    178                                         linkNodeMakeRandom(n5);
    179                                 }
    180                         }
    181                         new f4_node('>', n3, n3->pos);
     170                                // make neuron
     171                                NeuroClass * rndclass = GenoOperators::getRandomNeuroClass();
     172                                if (rndclass == NULL)
     173                                {
     174                                        n5 = new f4_node('X', n2, n2->pos);
     175                                }
     176                                else
     177                                {
     178                                        f4_node *n4 = new f4_node(rndclass->getName().c_str(), n2, n2->pos); //TODO move this above
     179                                        if (rndclass->getPreferredInputs() != 0)
     180                                        {
     181                                                neuronid = -1;
     182                                                for (int i = 0; i < g->count(); i++)
     183                                                {
     184                                                        f4_node * gcur = g->ordNode(i);
     185                                                        char * temp = (char*)gcur->name.c_str();
     186                                                        NeuroClass * neuclass = GenoOperators::parseNeuroClass(temp);
     187                                                        if (neuclass != NULL)
     188                                                        {
     189                                                                neulist.push_back(neuclass);
     190                                                        }
     191                                                        if (g->ordNode(i) == n3)
     192                                                        {
     193                                                                neuronid = neulist.size()-1;
     194                                                        }
     195                                                }
     196                                                if (neuronid == -1)
     197                                                {
     198                                                        return GENOPER_OPFAIL;
     199                                                }
     200                                                n5 = new f4_node('[', n4, n2->pos);
     201                                                linkNodeMakeRandom(n5, neuronid, neulist);
     202                                        }
     203                                        else {
     204                                                n5 = n4;
     205                                        }
     206                                }
     207                        }
     208                        new f4_node('>', n5, n5->pos);
    182209                        n1->parent = n2;
    183210                        // now with 50% chance swap children
     
    193220                {
    194221                        // add link
    195                         n1->parent->removeChild(n1);
    196                         n2 = new f4_node('[', n1->parent, n1->parent->pos);
    197                         linkNodeMakeRandom(n2);
    198                         n2->addChild(n1);
    199                         n1->parent = n2;
     222                        f4_node * par = n1->parent;
     223                        char * temp = (char*)par->name.c_str();
     224                        NeuroClass * neuclass = GenoOperators::parseNeuroClass(temp);
     225                        if (neuclass != NULL)
     226                        {
     227                                n1->parent->removeChild(n1);
     228                                f4_node *n2 = new f4_node('[', n1->parent, n1->parent->pos);
     229                                n2->addChild(n1);
     230                                n1->parent = n2;
     231                                neuronid = -1;
     232                                for (int i = 0; i < g->count(); i++)
     233                                {
     234                                        f4_node *gcur = g->ordNode(i);
     235                                        temp = (char*)gcur->name.c_str();
     236                                        NeuroClass *neuclass = GenoOperators::parseNeuroClass(temp);
     237                                        if (neuclass != NULL)
     238                                        {
     239                                                neulist.push_back(neuclass);
     240                                        }
     241                                        if (gcur == par)
     242                                        {
     243                                                neuronid = neulist.size()-1;
     244                                        }
     245                                }
     246                                if (neuronid == -1)
     247                                {
     248                                        return GENOPER_OPFAIL;
     249                                }
     250                                linkNodeMakeRandom(n2, neuronid, neulist);
     251                        }
    200252                }
    201253                        break;
     
    204256                        // add neuron modifier
    205257                        n1->parent->removeChild(n1);
    206                         n2 = new f4_node(':', n1->parent, n1->parent->pos);
     258                        f4_node *n2 = new f4_node(':', n1->parent, n1->parent->pos);
    207259                        nparNodeMakeRandom(n2);
    208260                        n2->addChild(n1);
     
    214266                        // add repetition ('#')
    215267                        // repeated code (left child) is the original, right child is empty, count is 2
    216                         n3 = n1->parent;
     268                        f4_node *n3 = n1->parent;
    217269                        n3->removeChild(n1);
    218                         n2 = new f4_node('#', n3, n3->pos);
     270                        f4_node *n2 = new f4_node('#', n3, n3->pos);
    219271                        n2->i1 = 2;
    220272                        n2->addChild(n1);
     
    228280                        // choose a simple node from ADD_SIMPLE_CODES
    229281                        n1->parent->removeChild(n1);
    230                         n2 = new f4_node(ADD_SIMPLE_CODES[randomN(strlen(ADD_SIMPLE_CODES))], n1->parent, n1->parent->pos);
     282                        f4_node *n2 = new f4_node(ADD_SIMPLE_CODES[randomN(strlen(ADD_SIMPLE_CODES))], n1->parent, n1->parent->pos);
    231283                        n2->addChild(n1);
    232284                        n1->parent = n2;
     
    258310                        case 1:  // one child
    259311                        {
    260                                 n2 = n1->parent;
     312                                f4_node *n2 = n1->parent;
    261313                                n2->removeChild(n1);
    262314                                if (NULL != n1->child)
     
    281333                        {
    282334                                // two children
    283                                 n2 = n1->parent;
     335                                f4_node *n2 = n1->parent;
    284336                                n2->removeChild(n1);
    285337                                // n1 has two children. pick one randomly 50-50, destroy other
     
    318370                while (1)
    319371                {
    320                         if (strchr(MUT_CHAN_CODES, n1->name)) break;
     372                        if (strchr(MUT_CHAN_CODES, n1->name[0])) break;
    321373                        // try a new one
    322374                        n1 = g->child->randomNode();
     
    324376                        if (i >= 20) return GENOPER_OPFAIL;
    325377                }
    326                 switch (n1->name)
     378                switch (n1->name[0])
    327379                {
    328380                case '<':
     381                {
    329382                        // swap children
    330                         n2 = n1->child; n1->child = n1->child2; n1->child2 = n2;
     383                        f4_node *n2 = n1->child; n1->child = n1->child2; n1->child2 = n2;
     384                }
    331385                        break;
    332386                case '[':
    333                         linkNodeChangeRandom(n1);
     387                {
     388                        neuronid = -1;
     389                        for (int i = 0; i < g->count(); i++)
     390                        {
     391                                f4_node *gcur = g->ordNode(i);
     392                                char *temp = (char*)gcur->name.c_str();
     393                                NeuroClass *neuclass = GenoOperators::parseNeuroClass(temp);
     394                                if (neuclass != NULL)
     395                                {
     396                                        neulist.push_back(neuclass);
     397                                }
     398                                if (gcur == n1)
     399                                {
     400                                        neuronid = neulist.size()-1;
     401                                }
     402                        }
     403                        if (neuronid == -1)
     404                        {
     405                                return GENOPER_OPFAIL;
     406                        }
     407                        linkNodeChangeRandom(n1, neuronid, neulist);
     408                }
    334409                        break;
     410
    335411                case '#':
     412                {
    336413                        repeatNodeChangeRandom(n1);
     414                }
    337415                        break;
    338416                }
     
    348426
    349427// make a random [ node
    350 void Geno_f4::linkNodeMakeRandom(f4_node * nn) const
    351 {
    352         int i;
     428void Geno_f4::linkNodeMakeRandom(f4_node *nn, int neuid, vector<NeuroClass*> neulist) const
     429{
    353430        float prob1;
    354 
    355         i = 0;
     431        NeuroClass *nc = NULL;
     432
    356433        // 35% chance one of *GTS
    357434        prob1 = rnd01;
     
    360437        {
    361438                // '*', 'G', 'T', or 'S', 1/4 chance each
    362                 i = 1 + (int)(3.999f * rnd01);
    363         }
    364         nn->i1 = i;
    365         nn->l1 = 0;
    366         if (0 == i)
     439                nc =  GenoOperators::getRandomNeuroClassWithOutputAndNoInputs();
     440        }
     441        if (nc != NULL)
     442        {
     443                nn->i1 = 1;
     444                nn->s1 = nc->getName().c_str();
     445                nn->l1 = 0;
     446        }
     447        else
    367448        {
    368449                // relative input link
    369                 nn->l1 = (int)(4.0f * (rnd01 - 0.5f));
     450                int id = GenoOperators::getRandomNeuroClassWithOutput(neulist);
     451                int relid = neuid - id;
     452                nn->l1 = relid;
     453                //nn->l1 = (int)(4.0f * (rnd01 - 0.5f));
    370454        }
    371455        // weight
    372         nn->f1 = 10.0f * (rnd01 - 0.5f);
     456        nn->f1 = GenoOperators::mutateNeuProperty(nn->f1,NULL,-1);
     457        //nn->f1 = 10.0f * (rnd01 - 0.5f);
    373458}
    374459
    375460// change a [ node
    376 void Geno_f4::linkNodeChangeRandom(f4_node * nn) const      //rewritten by M.K. - should work as before (not tested)
    377 {
    378         int i;
    379         float prob2;
    380 
     461void Geno_f4::linkNodeChangeRandom(f4_node * nn, int neuid, std::vector<NeuroClass*> neulist) const      //rewritten by M.K. - should work as before (not tested)
     462{
    381463        double probs[3] = { 0.1, 0.3, 0.6 };
     464        NeuroClass *cl;
    382465        // 10% change type
    383466        // 30% change link
     
    387470        {
    388471        case 0: // change type
    389                 i = 0;
    390                 // * G, 10% chance each
    391                 prob2 = rnd01 - 0.10f;
    392                 if (prob2 < 0) i = 1; else { prob2 -= 0.10f; if (prob2 < 0) i = 2; }
    393                 nn->i1 = i;
     472                // 80% for link, 20% for random sensor
     473                if (rnd01 < 0.2f)
     474                {
     475                        cl = GenoOperators::getRandomNeuroClassWithOutputAndNoInputs();
     476                        if (cl != NULL)
     477                        {
     478                                nn->i1 = 1;
     479                                nn->s1 = cl->name.c_str();
     480                                nn->l1 = 0;
     481                        }
     482                }
    394483                break;
    395484        case 1: // change link
    396485                if (0 == nn->i1) // relative input link
    397                         nn->l1 += (int)(2.0f * (rnd01 - 0.5f));
     486                {
     487                        int id = GenoOperators::getRandomNeuroClassWithOutput(neulist);
     488                        nn->l1 = neuid - id;
     489                }
     490                        //nn->l1 += (int)(2.0f * (rnd01 - 0.5f));
    398491                break;
    399492        case 2: // change weight
    400                 nn->f1 += 1.0f * (rnd01 - 0.5f);
     493                nn->f1 = GenoOperators::mutateNeuProperty(nn->f1,NULL,-1);
     494                //nn->f1 += 1.0f * (rnd01 - 0.5f);
    401495                break;
    402496        }
  • cpp/frams/genetics/f4/oper_f4.h

    r674 r760  
    1515#include <frams/param/param.h>
    1616
     17/** @name Codes for general mutation types */
     18//@{
     19#define F4_ADD           0 ///<Adding new node
     20#define F4_DEL           1 ///<Deletion of node
     21#define F4_MOD           2 ///<Modification of node
     22#define F4_COUNT         3 ///<Count of mutation types
     23//@}
    1724
    18 #define F4_ADD           0
    19 #define F4_DEL           1
    20 #define F4_MOD           2
    21 #define F4_COUNT         3
    22 
     25/** @name Codes for specific F4_ADD mutation subtypes */
     26//@{
    2327#define F4_ADD_DIV       0
    2428#define F4_ADD_CONN      1
     
    2731#define F4_ADD_SIMP      4
    2832#define F4_ADD_COUNT     5
    29 
     33//@}
    3034
    3135class Geno_f4 : public GenoOperators
     
    4347
    4448        // mutation probabilities
    45         double prob[F4_COUNT], probadd[F4_ADD_COUNT];
     49        double prob[F4_COUNT];            ///<reltive probabilities of selecting mutation types in f4 genotype
     50        double probadd[F4_ADD_COUNT];     ///<relative probabilities of selecting mutation addition subtypes
    4651
    47         SString excluded_modifiers; //not to be used in mutations
     52        SString excluded_modifiers;       ///<Modifiers that are excluded in mutation process
    4853        static const char *all_modifiers;
    4954
    5055protected:
    51         /* int MutateMany(char *& g, float & chg); // not used anymore */
     56
     57        /**
     58         * Validates a f4 genotype. If the genotype is invalid, the genotype is repaired
     59         * and the validation is repeated. Validation is performed as long as repairing
     60         * is not effective, or the number of retries exceeded the given limit.
     61         * @param geno genotype tree
     62         * @param retrycount maximum amount of repair retries
     63         * @return GENOOPER_OK if genotype is valid, GENOPER_REPAIR if genotype can be repaired, GENOPER_OPFAIL if genotype can't be repaired
     64         */
    5265        int  ValidateRec(f4_node * geno, int retrycount) const;
     66
     67        /**
     68         * Performs mutation of an f4 genotype. The mutation is performed on a random node
     69         * from a given tree. The method of mutation is chosen via the roulette selection,
     70         * where probabilities of choosing each mutation type are given in the 'prob'
     71         * array. Possible mutation types are:
     72         *  - F4_ADD - adds new element to the genotype by:
     73         *   - F4_ADD_DIV - replacing randomly selected node with division node '<', setting this node as a child and creating new stick or neuron sibling of the selected cell (the neuron-type sibling will be connected to a random existing neuron),
     74         *   - F4_ADD_CONN - adding connection for an existing neuron,
     75         *   - F4_ADD_NEUPAR - adding neuron property to the selected node, if it is a neuron node,
     76         *   - F4_ADD_REP - adding a repetition node before a randomly selected node (the repetition node has 2 repetitions),
     77         *   - F4_ADD_SIMP - adding a simple node before a selected node,
     78         *  - F4_DEL - removes a randomly selected node (the node needs to have a parent and at least one child, otherwise returns GENOPER_OPFAIL),
     79         *  - F4_MOD - modifies one of simple nodes by:
     80         *   - '<' - swapping children in division
     81         *   - '[' - modifying connection of a neuron
     82         *   - '#' - incrementing or decrementing repetition count
     83         *
     84         * @param g input genotype; the result of mutation will be stored in this parameter
     85         * @param method reference to the variable that will get the selected method of mutation
     86         * @return GENOPER_OK if mutation was performed successfully, GENOPER_FAIL otherwise
     87         */
    5388        int  MutateOne(f4_node *& g, int &method) const;
    54         void linkNodeMakeRandom(f4_node * nn) const;
    55         void linkNodeChangeRandom(f4_node * nn) const;
    56         void nparNodeMakeRandom(f4_node * nn) const;
    57         void repeatNodeChangeRandom(f4_node * nn) const;
     89
     90        /**
     91         * Creates a random connection to an existing neuron or creates an additional
     92         * sensor for a neuron.
     93         * @param nn neuron class node
     94         * @param neuid id of a neuron
     95         * @param neulist list of genotype neuron classes
     96         */
     97        void linkNodeMakeRandom(f4_node * nn, int neuid, std::vector<NeuroClass*> neulist) const;
     98
     99        /**
     100         * Changes connection to an existing neuron or creates an additional
     101         * sensor for neuron.
     102         * @param nn neuron connection node
     103         * @param neuid id of a neuron
     104         * @param neulist list of genotype neuron classes
     105         */
     106        void linkNodeChangeRandom(f4_node * nn, int neuid, std::vector<NeuroClass*> neulist) const;
     107
     108        /**
     109         * Introduces a random modification to the neuron node.
     110         * @param nn neuron node
     111         */
     112        void nparNodeMakeRandom(f4_node *nn) const;
     113
     114        /**
     115         * Increases or decreases the amount of repetitions in the repetition node.
     116         * @param nn repetition node
     117         */
     118        void repeatNodeChangeRandom(f4_node *nn) const;
     119
     120        /**
     121         * Tries to perform a mutation until success. There is a maximum of 20 tries. Returns GENOPER_OK or GENOPER_OPFAIL.
     122         * @param g genotype tree
     123         * @param method reference to the variable that will get the selected method of mutation
     124         * @return GENOPER_OK if performed successful mutation, GENOPER_FAIL otherwise
     125         */
    58126        int  MutateOneValid(f4_node * &g, int &method) const;
     127
     128        /**
     129         * Performs crossover of two creatures. The 'chg' parameter determines approximately what
     130         * percentage of the first creature should form the offspring. '1-chg' is the percentage
     131         * of the second creature in the offspring.
     132         * @param g1 first parent
     133         * @param g2 second parent
     134         * @param chg percentage of the first parent in offspring (the second parent has the rest)
     135         */
    59136        int  CrossOverOne(f4_node *g1, f4_node *g2, float chg) const;
    60         // returns GENOPER_OK or GENOPER_OPFAIL
    61         // chg: fraction of parent1 genes in child (in g1) (parent2 has the rest)
    62137};
    63138
Note: See TracChangeset for help on using the changeset viewer.