Changeset 196 for cpp/frams/genetics


Ignore:
Timestamp:
03/25/14 03:22:37 (11 years ago)
Author:
Maciej Komosinski
Message:

Updated f4 sources and made f4 available for GDK demo apps

Location:
cpp/frams/genetics
Files:
1 added
1 edited
6 moved

Legend:

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

    r193 r196  
    1 /**
    2  *  conv_f4.cpp - f4 genotype functions.
    3  *
    4  *  f4genotype - f4 format genotype conversions for Framsticks
    5  *
    6  *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
    7  *  Copyright (C) 2001-2003  Maciej Komosinski
    8  *
    9  *  This library is free software; you can redistribute it and/or
    10  *  modify it under the terms of the GNU Lesser General Public
    11  *  License as published by the Free Software Foundation; either
    12  *  version 2.1 of the License, or (at your option) any later version.
    13  *
    14  *  This library is distributed in the hope that it will be useful,
    15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    17  *  Lesser General Public License for more details.
    18  *
    19  *  You should have received a copy of the GNU Lesser General Public
    20  *  License along with this library; if not, write to the Free Software
    21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    22  *
    23  */
     1// This file is a part of the Framsticks GDK.
     2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
     3// Refer to http://www.framsticks.com/ for further information.
     4
     5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// Copyright (C) since 2001 Maciej Komosinski
    247
    258#include "conv_f4.h"
    26 #include "framsg.h"
    27 #include "geno_fx.h" //for GENOPER_OK constant
     9#include <common/framsg.h>
     10#include "../oper_fx.h" //for GENOPER_OK constant
    2811
    2912#ifdef DMALLOC
     
    3215
    3316
    34 GenoConv_F40::GenoConv_F40()
    35 {
    36   name = "f4 converter";
    37   in_format  = '4';
    38   out_format = '0';
    39   mapsupport = 1;
    40   info = "Developmental encoding";
    41 }
    42 
    43 
    44 SString GenoConv_F40::convert(SString &in, MultiMap * map)
    45 {
    46   int res;
    47   f4_Model * model = new f4_Model();
    48   res = model->buildFromF4(in);
    49   if (GENOPER_OK != res) return SString();  // oops
    50   if (NULL != map)
    51     // generate to-f0 conversion map
    52     model->getCurrentToF0Map(*map);
    53   SString out = model->getF0Geno().getGene();
    54   delete model;
    55   return out;
     17GenoConv_f40::GenoConv_f40()
     18{
     19        name = "Developmental encoding";
     20        in_format = '4';
     21        out_format = '0';
     22        mapsupport = 1;
     23}
     24
     25
     26SString GenoConv_f40::convert(SString &in, MultiMap * map)
     27{
     28        int res;
     29        f4_Model * model = new f4_Model();
     30        res = model->buildFromF4(in);
     31        if (GENOPER_OK != res) return SString();  // oops
     32        if (NULL != map)
     33                // generate to-f0 conversion map
     34                model->getCurrentToF0Map(*map);
     35        SString out = model->getF0Geno().getGene();
     36        delete model;
     37        return out;
    5638}
    5739
     
    5941GenoConv_F41_TestOnly::GenoConv_F41_TestOnly()
    6042{
    61   name = "test-only approximate f4 -> f0 converter";
    62   in_format = '4';
    63   out_format = '1';
    64   mapsupport = 0;
    65   info = "This is for testing.  Do not use in production! (adam)";
     43        name = "test-only approximate f4 -> f1 converter";
     44        in_format = '4';
     45        out_format = '1';
     46        mapsupport = 0;
     47        info = "This is for testing.  Do not use in production! (adam)";
    6648}
    6749
     
    6951SString GenoConv_F41_TestOnly::convert(SString &in, MultiMap * map)
    7052{
    71   int res;
    72   f4_Model * model = new f4_Model();
    73   res = model->buildFromF4(in);
    74   if (GENOPER_OK != res) return SString();  // oops
    75   SString out;
    76   model->toF1Geno(out);
    77   delete model;
    78   return out;
     53        int res;
     54        f4_Model * model = new f4_Model();
     55        res = model->buildFromF4(in);
     56        if (GENOPER_OK != res) return SString();  // oops
     57        SString out;
     58        model->toF1Geno(out);
     59        delete model;
     60        return out;
    7961}
    8062
     
    8264f4_Model::f4_Model() : Model()
    8365{
    84   cells = NULL;
     66        cells = NULL;
    8567}
    8668
    8769f4_Model::~f4_Model()
    8870{
    89   if (cells) delete cells;
     71        if (cells) delete cells;
    9072}
    9173
    9274int f4_Model::buildFromF4(SString &geno)
    9375{
    94   int i;
    95 
    96   error = GENOPER_OK;
    97   errorpos = -1;
    98 
    99   // build cells, and simulate
    100   if (cells) delete cells;
    101   cells = new f4_Cells(geno, 0);
    102   if (GENOPER_OK != cells->geterror())
    103   {
    104     error = cells->geterror();
    105     errorpos = cells->geterrorpos();
    106     //delete cells;
    107     return error;
    108   }
    109 
    110   cells->simulate();
    111   if (GENOPER_OK != cells->geterror())
    112   {
    113     error = cells->geterror();
    114     errorpos = cells->geterrorpos();
    115     return error;
    116   }
    117 
    118   // reset recursive traverse flags
    119   for(i=0; i<cells->nc; i++)
    120     cells->C[i]->recProcessedFlag = 0;
    121 
    122   open(); // begin model build
    123 
    124   // process every cell
    125   int res;
    126   for(i=0; i<cells->nc; i++)
    127   {
    128     res = buildModelRec(cells->C[i]);
    129     if (res)
    130     {
    131       FramMessage("f4_Model", "buildModelRec", "Error in building Model", 2);
    132       error = res;
    133       break;
    134     }
    135   }
    136 
    137   res = close();
    138   if (0 == res) // invalid
    139     error = -10;
    140 
    141   return error;
     76        int i;
     77
     78        error = GENOPER_OK;
     79        errorpos = -1;
     80
     81        // build cells, and simulate
     82        if (cells) delete cells;
     83        cells = new f4_Cells(geno, 0);
     84        if (GENOPER_OK != cells->geterror())
     85        {
     86                error = cells->geterror();
     87                errorpos = cells->geterrorpos();
     88                //delete cells;
     89                return error;
     90        }
     91
     92        cells->simulate();
     93        if (GENOPER_OK != cells->geterror())
     94        {
     95                error = cells->geterror();
     96                errorpos = cells->geterrorpos();
     97                return error;
     98        }
     99
     100        // reset recursive traverse flags
     101        for (i = 0; i < cells->nc; i++)
     102                cells->C[i]->recProcessedFlag = 0;
     103
     104        open(); // begin model build
     105
     106        // process every cell
     107        int res;
     108        for (i = 0; i < cells->nc; i++)
     109        {
     110                res = buildModelRec(cells->C[i]);
     111                if (res)
     112                {
     113                        FramMessage("f4_Model", "buildModelRec", "Error in building Model", 2);
     114                        error = res;
     115                        break;
     116                }
     117        }
     118
     119        res = close();
     120        if (0 == res) // invalid
     121                error = -10;
     122
     123        return error;
    142124}
    143125
     
    145127f4_Cell * f4_Model::getStick(f4_Cell * C)
    146128{
    147   if (T_STICK4 == C->type) return C;
    148   if (NULL != C->dadlink)
    149     return getStick(C->dadlink);
    150   // we have no more dadlinks, find any stick
    151   for (int i=0; i<cells->nc; i++)
    152     if (cells->C[i]->type == T_STICK4)
    153       return cells->C[i];
    154   // none!
    155   FramMessage("f4_Model", "getStick", "Not a single stick", 2);
    156   return NULL;
     129        if (T_STICK4 == C->type) return C;
     130        if (NULL != C->dadlink)
     131                return getStick(C->dadlink);
     132        // we have no more dadlinks, find any stick
     133        for (int i = 0; i < cells->nc; i++)
     134                if (cells->C[i]->type == T_STICK4)
     135                        return cells->C[i];
     136        // none!
     137        FramMessage("f4_Model", "getStick", "Not a single stick", 2);
     138        return NULL;
    157139}
    158140
     
    161143int f4_Model::buildModelRec(f4_Cell * C)
    162144{
    163   int partidx;
    164   int j, res;
    165   MultiRange range;
    166 
    167   if (C->recProcessedFlag)
    168     // already processed
    169     return 0;
    170 
    171   // mark it processed
    172   C->recProcessedFlag = 1;
    173 
    174   // make sure parent is a stick
    175   if (NULL != C->dadlink)
    176     if (C->dadlink->type != T_STICK4)
    177     {
    178       C->dadlink = getStick(C->dadlink);
    179     }
    180 
    181   // make sure its parent is processed first
    182   if (NULL != C->dadlink)
    183   {
    184     res = buildModelRec(C->dadlink);
    185     if (res) return res;
    186   }
    187 
    188   char tmpLine[100];
    189 
    190   range = C->genoRange;
    191   if (C->type == T_STICK4)
    192   {
    193     int jj_p1_refno;  // save for later
    194     // first end is connected to dad, or new
    195     if (C->dadlink == NULL)
    196     {
    197       // new part object for firstend
    198       // coordinates are left to be computed by Model
    199       sprintf(tmpLine, "p:m=1,fr=%g,ing=%g,as=%g",
    200         /*1.0/C->P.mass,*/ C->P.friction, C->P.ingest, C->P.assim
    201         //C->firstend.x, C->firstend.y, C->firstend.z
    202         );
    203       partidx = singleStepBuild(tmpLine, &range );
    204       if (partidx < 0) return -1;
    205       jj_p1_refno = partidx;
    206     } else {
    207       // adjust mass/vol of first endpoint
    208       jj_p1_refno = C->dadlink->p2_refno;
    209       Part * p1 = getPart(jj_p1_refno);
    210       p1->mass += 1.0;
    211 //      p1->volume += 1.0/C->P.mass;
    212     }
    213     // new part object for lastend
    214     sprintf(tmpLine, "p:m=1,fr=%g,ing=%g,as=%g",
    215         //C->lastend.x, C->lastend.y, C->lastend.z
    216         /*"vol=" 1.0/C->P.mass,*/ C->P.friction, C->P.ingest, C->P.assim
    217       );
    218     partidx = singleStepBuild(tmpLine, &range );
    219     if (partidx < 0) return -2;
    220     C->p2_refno = partidx;
    221 
    222     // new joint object
    223     // check that the part references are valid
    224     int jj_p2_refno = C->p2_refno;
    225     if ((jj_p1_refno < 0) || (jj_p1_refno >= getPartCount())) return -11;
    226     if ((jj_p2_refno < 0) || (jj_p2_refno >= getPartCount())) return -12;
    227     sprintf(tmpLine, "j:p1=%ld,p2=%ld,dx=%g,dy=0,dz=0,rx=%g,ry=0,rz=%g"\
    228       ",stam=%g",
    229       jj_p1_refno, jj_p2_refno,
    230       // relative position -- always (len, 0, 0), along the stick
    231       // this is optional!
    232       C->P.len,
    233       // relative rotation
    234       C->xrot, C->zrot,
    235       //C->P.ruch,   // rotstif
    236       C->P.odpor
    237     );
    238     partidx = singleStepBuild(tmpLine, &range );
    239     if (partidx < 0) return -13;
    240     C->joint_refno = partidx;
    241   }
    242 
    243   if (C->type == T_NEURON4) ///<this case was updated by MacKo
    244   {
    245     // new neuron object
    246     // it is linked to a part (not a joint!)
    247     int p_refno = C->dadlink->p2_refno;
    248     if ((p_refno < 0) || (p_refno >= getPartCount())) return -21;
    249     // joint_refno is currently not used
    250     sprintf(tmpLine, "n:p=%ld,d=\"N:in=%g,fo=%g,si=%g\"",
    251       p_refno,
    252       C->inertia, C->force, C->sigmo);
    253     partidx = singleStepBuild(tmpLine, &range );
    254     if (partidx < 0) return -22;
    255     C->neuro_refno = partidx;
    256     int n_refno = C->neuro_refno;
    257 
    258     if (C->ctrl)
    259     {
    260       if (1 == C->ctrl)
    261         sprintf(tmpLine, "n:j=%d,d=\"@:p=%g\"",   C->dadlink->joint_refno, C->P.ruch);
    262       else
    263         sprintf(tmpLine, "n:j=%d,d=\"|:p=%g,r=%g\"",C->dadlink->joint_refno, C->P.ruch, C->mz);
    264       partidx = singleStepBuild(tmpLine, &range );
    265       if (partidx < 0) return -32;
    266       sprintf(tmpLine, "c:%d,%d",partidx,n_refno);
    267       if (singleStepBuild(tmpLine, &range )<0) return -33;
    268     }
    269 
    270     for (j=0; j<C->nolink; j++)
    271     {
    272       if (NULL != C->links[j]->from)
    273         buildModelRec(C->links[j]->from);
    274 
    275       tmpLine[0]=0;
    276       if (1 == C->links[j]->t) sprintf(tmpLine, "n:p=%d,d=\"*\"",p_refno);
    277       if (2 == C->links[j]->t) sprintf(tmpLine, "n:j=%d,d=\"G\"", C->dadlink->joint_refno);
    278       if (3 == C->links[j]->t) sprintf(tmpLine, "n:p=%d,d=\"T\"",p_refno);
    279       if (4 == C->links[j]->t) sprintf(tmpLine, "n:p=%d,d=\"S\"",p_refno);
    280       int from=-1;
    281       if (tmpLine[0]) //input from receptor
    282       {
    283         from=singleStepBuild(tmpLine, &range );
    284         if (from<0) return -34;
    285       } /*could be 'else'...*/
    286       if (NULL != C->links[j]->from) // input from another neuron
    287          from=C->links[j]->from->neuro_refno;
    288       if (from>=0)
    289       {
    290         sprintf(tmpLine, "c:%d,%d,%g", n_refno,from,C->links[j]->w);
    291         if (singleStepBuild(tmpLine, &range ) < 0) return -35;
    292       }
    293     }
    294   }
    295   return 0;
     145        int partidx;
     146        int j, res;
     147        MultiRange range;
     148
     149        if (C->recProcessedFlag)
     150                // already processed
     151                return 0;
     152
     153        // mark it processed
     154        C->recProcessedFlag = 1;
     155
     156        // make sure parent is a stick
     157        if (NULL != C->dadlink)
     158                if (C->dadlink->type != T_STICK4)
     159                {
     160                        C->dadlink = getStick(C->dadlink);
     161                }
     162
     163        // make sure its parent is processed first
     164        if (NULL != C->dadlink)
     165        {
     166                res = buildModelRec(C->dadlink);
     167                if (res) return res;
     168        }
     169
     170        char tmpLine[100];
     171
     172        range = C->genoRange;
     173        if (C->type == T_STICK4)
     174        {
     175                int jj_p1_refno;  // save for later
     176                // first end is connected to dad, or new
     177                if (C->dadlink == NULL)
     178                {
     179                        // new part object for firstend
     180                        // coordinates are left to be computed by Model
     181                        sprintf(tmpLine, "p:m=1,fr=%g,ing=%g,as=%g",
     182                                /*1.0/C->P.mass,*/ C->P.friction, C->P.ingest, C->P.assim
     183                                //C->firstend.x, C->firstend.y, C->firstend.z
     184                                );
     185                        partidx = singleStepBuild(tmpLine, &range);
     186                        if (partidx < 0) return -1;
     187                        jj_p1_refno = partidx;
     188                }
     189                else {
     190                        // adjust mass/vol of first endpoint
     191                        jj_p1_refno = C->dadlink->p2_refno;
     192                        Part * p1 = getPart(jj_p1_refno);
     193                        p1->mass += 1.0;
     194                        //      p1->volume += 1.0/C->P.mass;
     195                }
     196                // new part object for lastend
     197                sprintf(tmpLine, "p:m=1,fr=%g,ing=%g,as=%g",
     198                        //C->lastend.x, C->lastend.y, C->lastend.z
     199                        /*"vol=" 1.0/C->P.mass,*/ C->P.friction, C->P.ingest, C->P.assim
     200                        );
     201                partidx = singleStepBuild(tmpLine, &range);
     202                if (partidx < 0) return -2;
     203                C->p2_refno = partidx;
     204
     205                // new joint object
     206                // check that the part references are valid
     207                int jj_p2_refno = C->p2_refno;
     208                if ((jj_p1_refno < 0) || (jj_p1_refno >= getPartCount())) return -11;
     209                if ((jj_p2_refno < 0) || (jj_p2_refno >= getPartCount())) return -12;
     210                sprintf(tmpLine, "j:p1=%ld,p2=%ld,dx=%g,dy=0,dz=0,rx=%g,ry=0,rz=%g"\
     211                        ",stam=%g",
     212                        jj_p1_refno, jj_p2_refno,
     213                        // relative position -- always (len, 0, 0), along the stick
     214                        // this is optional!
     215                        C->P.len,
     216                        // relative rotation
     217                        C->xrot, C->zrot,
     218                        //C->P.ruch,   // rotstif
     219                        C->P.odpor
     220                        );
     221                partidx = singleStepBuild(tmpLine, &range);
     222                if (partidx < 0) return -13;
     223                C->joint_refno = partidx;
     224        }
     225
     226        if (C->type == T_NEURON4) ///<this case was updated by MacKo
     227        {
     228                // new neuron object
     229                // it is linked to a part (not a joint!)
     230                int p_refno = C->dadlink->p2_refno;
     231                if ((p_refno < 0) || (p_refno >= getPartCount())) return -21;
     232                // joint_refno is currently not used
     233                sprintf(tmpLine, "n:p=%ld,d=\"N:in=%g,fo=%g,si=%g\"",
     234                        p_refno,
     235                        C->inertia, C->force, C->sigmo);
     236                partidx = singleStepBuild(tmpLine, &range);
     237                if (partidx < 0) return -22;
     238                C->neuro_refno = partidx;
     239                int n_refno = C->neuro_refno;
     240
     241                if (C->ctrl)
     242                {
     243                        if (1 == C->ctrl)
     244                                sprintf(tmpLine, "n:j=%d,d=\"@:p=%g\"", C->dadlink->joint_refno, C->P.ruch);
     245                        else
     246                                sprintf(tmpLine, "n:j=%d,d=\"|:p=%g,r=%g\"", C->dadlink->joint_refno, C->P.ruch, C->mz);
     247                        partidx = singleStepBuild(tmpLine, &range);
     248                        if (partidx < 0) return -32;
     249                        sprintf(tmpLine, "c:%d,%d", partidx, n_refno);
     250                        if (singleStepBuild(tmpLine, &range) < 0) return -33;
     251                }
     252
     253                for (j = 0; j < C->nolink; j++)
     254                {
     255                        if (NULL != C->links[j]->from)
     256                                buildModelRec(C->links[j]->from);
     257
     258                        tmpLine[0] = 0;
     259                        if (1 == C->links[j]->t) sprintf(tmpLine, "n:p=%d,d=\"*\"", p_refno);
     260                        if (2 == C->links[j]->t) sprintf(tmpLine, "n:j=%d,d=\"G\"", C->dadlink->joint_refno);
     261                        if (3 == C->links[j]->t) sprintf(tmpLine, "n:p=%d,d=\"T\"", p_refno);
     262                        if (4 == C->links[j]->t) sprintf(tmpLine, "n:p=%d,d=\"S\"", p_refno);
     263                        int from = -1;
     264                        if (tmpLine[0]) //input from receptor
     265                        {
     266                                from = singleStepBuild(tmpLine, &range);
     267                                if (from < 0) return -34;
     268                        } /*could be 'else'...*/
     269                        if (NULL != C->links[j]->from) // input from another neuron
     270                                from = C->links[j]->from->neuro_refno;
     271                        if (from >= 0)
     272                        {
     273                                sprintf(tmpLine, "c:%d,%d,%g", n_refno, from, C->links[j]->w);
     274                                if (singleStepBuild(tmpLine, &range) < 0) return -35;
     275                        }
     276                }
     277        }
     278        return 0;
    296279}
    297280
     
    299282void f4_Model::toF1Geno(SString &out)
    300283{
    301   cells->toF1Geno(out);
    302 }
    303 
    304 
     284        cells->toF1Geno(out);
     285}
  • cpp/frams/genetics/f4/conv_f4.h

    r193 r196  
    1 /**
    2  *  conv_f4.h - f4 conversion functions.
    3  *
    4  *  f4genotype - f4 format genotype conversions for FramSticks
    5  *
    6  *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
    7  *  Copyright (C) 2001-2003  Maciej Komosinski
    8  *
    9  *  This library is free software; you can redistribute it and/or
    10  *  modify it under the terms of the GNU Lesser General Public
    11  *  License as published by the Free Software Foundation; either
    12  *  version 2.1 of the License, or (at your option) any later version.
    13  *
    14  *  This library is distributed in the hope that it will be useful,
    15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    17  *  Lesser General Public License for more details.
    18  *
    19  *  You should have received a copy of the GNU Lesser General Public
    20  *  License along with this library; if not, write to the Free Software
    21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    22  *
    23  */
     1// This file is a part of the Framsticks GDK.
     2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
     3// Refer to http://www.framsticks.com/ for further information.
     4
     5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// Copyright (C) since 2001 Maciej Komosinski
    247
    258#ifndef _CONV_F4_H_
    269#define _CONV_F4_H_
    2710
    28 #include "model.h"
    29 #include "modelparts.h"
    30 #include "genoconv.h"
     11#include <frams/model/model.h>
     12#include <frams/model/modelparts.h>
     13#include <frams/genetics/genoconv.h>
    3114#include "f4_general.h"
    3215
    3316
    3417// The f4->f0 converter
    35 class GenoConv_F40: public GenoConverter
     18class GenoConv_f40 : public GenoConverter
    3619{
    37  public:
    38   GenoConv_F40();
    39   SString convert(SString &in, MultiMap * map);
     20public:
     21        GenoConv_f40();
     22        SString convert(SString &in, MultiMap * map);
    4023};
    4124
    4225
    4326// a test-only f4->f1 converter, approximates only
    44 class GenoConv_F41_TestOnly: public GenoConverter
     27class GenoConv_F41_TestOnly : public GenoConverter
    4528{
    46  public:
    47   GenoConv_F41_TestOnly();
    48   SString convert(SString &in, MultiMap * map);
     29public:
     30        GenoConv_F41_TestOnly();
     31        SString convert(SString &in, MultiMap * map);
    4932};
    5033
    5134
    5235// A Model descendant, which support build from an f4 genotype.
    53 class f4_Model: public Model
     36class f4_Model : public Model
    5437{
    55  public:
    56   f4_Model();
    57   ~f4_Model();
    58   int      buildFromF4(SString &geno);
    59   void     toF1Geno(SString &out);       // output to f1 format, approximation
    60  private:
    61   f4_Cells * cells;
    62   int        buildModelRec(f4_Cell * ndad);
    63   /**
    64   * Get a cell which is a stick, by traversing dadlinks.
    65   */
    66   f4_Cell *  getStick(f4_Cell * C);
    67   int        error;
    68   int        errorpos;
     38public:
     39        f4_Model();
     40        ~f4_Model();
     41        int      buildFromF4(SString &geno);
     42        void     toF1Geno(SString &out);       // output to f1 format, approximation
     43private:
     44        f4_Cells * cells;
     45        int        buildModelRec(f4_Cell * ndad);
     46        /**
     47        * Get a cell which is a stick, by traversing dadlinks.
     48        */
     49        f4_Cell *  getStick(f4_Cell * C);
     50        int        error;
     51        int        errorpos;
    6952};
    7053
    7154
    7255#endif
    73 
  • cpp/frams/genetics/f4/f4_general.cpp

    r193 r196  
    1 /*
    2  *  f4_general.cpp - f4 genotype functions.
    3  *
    4  *  f4genotype - f4 format genotype conversions for FramSticks
    5  *
    6  *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
    7  *
    8  *  This library is free software; you can redistribute it and/or
    9  *  modify it under the terms of the GNU Lesser General Public
    10  *  License as published by the Free Software Foundation; either
    11  *  version 2.1 of the License, or (at your option) any later version.
    12  *
    13  *  This library is distributed in the hope that it will be useful,
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16  *  Lesser General Public License for more details.
    17  *
    18  *  You should have received a copy of the GNU Lesser General Public
    19  *  License along with this library; if not, write to the Free Software
    20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    21  *
    22  */
     1// This file is a part of the Framsticks GDK.
     2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
     3// Refer to http://www.framsticks.com/ for further information.
     4
     5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// Copyright (C) since 2001 Maciej Komosinski
    237
    248#include "f4_general.h"
    25 #include "nonstd.h"
    26 #include "framsg.h"
    27 #include "model.h" // for min and max attributes
    28 #include "geno_fx.h" //for GENOPER_ constants
     9#include <common/nonstd_stl.h>
     10#include <common/framsg.h>
     11#include <frams/model/model.h> // for min and max attributes
     12#include "../oper_fx.h" //for GENOPER_ constants
    2913#include <stdio.h>
    30 #include <math.h>
     14#include <common/nonstd_math.h>
    3115
    3216#ifdef DMALLOC
     
    3721f4_Props::f4_Props()
    3822{
    39   len      = 1.0;
    40   curv    = 0.0;
    41   mass     = 1.0;
    42   friction = 0.4;
    43   ruch    = 0.25; // bio
    44   assim    = 0.25; // bio
    45   odpor    = 0.25; // bio
    46   ingest  = 0.25; // bio
    47   twist    = 0.0;
    48   energ    = 1.0;
    49   normalizeBiol4();
     23        len = 1.0;
     24        curv = 0.0;
     25        mass = 1.0;
     26        friction = 0.4;
     27        ruch = 0.25; // bio
     28        assim = 0.25; // bio
     29        odpor = 0.25; // bio
     30        ingest = 0.25; // bio
     31        twist = 0.0;
     32        energ = 1.0;
     33        normalizeBiol4();
    5034}
    5135
    5236void f4_Props::normalizeBiol4()
    5337{
    54   // must sum to 1
    55   double sum = ruch + assim + odpor + ingest;
    56   if (0 == sum)
    57   {
    58     ruch = assim = odpor = ingest = 0.25;
    59   } else {
    60     ruch   /= sum;
    61     assim  /= sum;
    62     odpor  /= sum;
    63     ingest /= sum;
    64   }
     38        // must sum to 1
     39        double sum = ruch + assim + odpor + ingest;
     40        if (0 == sum)
     41        {
     42                ruch = assim = odpor = ingest = 0.25;
     43        }
     44        else {
     45                ruch /= sum;
     46                assim /= sum;
     47                odpor /= sum;
     48                ingest /= sum;
     49        }
    6550}
    6651
    6752void f4_Props::executeModifier(char modif)
    6853{
    69   switch (modif)
    70   {
    71    case 'L': len += (2.5 - len) * 0.3;
    72              len = min(len, Model::getMaxJoint().d.x); break;
    73    case 'l': len += (0.3 - len) * 0.3;
    74              len = max(len, Model::getMinJoint().d.x); break;
    75    case 'C': curv += ( 2.0 - curv) * 0.25;  break;
    76    case 'c': curv += (-2.0 - curv) * 0.25;  break;
    77    case 'Q': twist += ( 1.58 - twist) * 0.3; break;
    78    case 'q': twist += (-1.58 - twist) * 0.3; break;
    79    case 'A': assim += (1 - assim) * 0.8; normalizeBiol4(); break;
    80    case 'a': assim -= assim * 0.4;       normalizeBiol4(); break;
    81    case 'I': ingest += (1 - ingest) * 0.8;   normalizeBiol4(); break;
    82    case 'i': ingest -= ingest * 0.4;         normalizeBiol4(); break;
    83    case 'S': odpor += (1 - odpor) * 0.8; normalizeBiol4(); break;
    84    case 's': odpor -= odpor * 0.4;       normalizeBiol4(); break;
    85    case 'M': ruch += (1 - ruch) * 0.8;   normalizeBiol4(); break;
    86    case 'm': ruch -= ruch * 0.4;         normalizeBiol4(); break;
    87    case 'F': friction += (4 - friction) * 0.2; break;
    88    case 'f': friction -= friction * 0.2;       break;
    89    case 'W': mass += (2.0 - mass) * 0.3;   break;
    90    case 'w': mass += (0.5 - mass) * 0.3;   break;
    91    case 'E': energ += (10.0 - energ) * 0.1; break;
    92    case 'e': energ -= energ * 0.1;          break;
    93   }
     54        switch (modif)
     55        {
     56        case 'L': len += (2.5 - len) * 0.3;
     57                len = min(len, Model::getMaxJoint().d.x); break;
     58        case 'l': len += (0.3 - len) * 0.3;
     59                len = max(len, Model::getMinJoint().d.x); break;
     60        case 'C': curv += (2.0 - curv) * 0.25;  break;
     61        case 'c': curv += (-2.0 - curv) * 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': assim += (1 - assim) * 0.8; normalizeBiol4(); break;
     65        case 'a': assim -= assim * 0.4;       normalizeBiol4(); break;
     66        case 'I': ingest += (1 - ingest) * 0.8;   normalizeBiol4(); break;
     67        case 'i': ingest -= ingest * 0.4;         normalizeBiol4(); break;
     68        case 'S': odpor += (1 - odpor) * 0.8; normalizeBiol4(); break;
     69        case 's': odpor -= odpor * 0.4;       normalizeBiol4(); break;
     70        case 'M': ruch += (1 - ruch) * 0.8;   normalizeBiol4(); break;
     71        case 'm': ruch -= ruch * 0.4;         normalizeBiol4(); break;
     72        case 'F': friction += (4 - friction) * 0.2; break;
     73        case 'f': friction -= friction * 0.2;       break;
     74        case 'W': mass += (2.0 - mass) * 0.3;   break;
     75        case 'w': mass += (0.5 - mass) * 0.3;   break;
     76        case 'E': energ += (10.0 - energ) * 0.1; break;
     77        case 'e': energ -= energ * 0.1;          break;
     78        }
    9479}
    9580
    9681void f4_Props::adjust()
    9782{
    98   len = 0.5*len + 0.5*stdProps.len;
    99   curv = 0.66 * curv;
    100   twist = 0.66 * twist;
     83        len = 0.5*len + 0.5*stdProps.len;
     84        curv = 0.66 * curv;
     85        twist = 0.66 * twist;
    10186}
    10287
     
    10590
    10691void rolling_dec(double * v) {
    107   *v -= 0.7853;  // 0.7853981  45 degrees
     92        *v -= 0.7853;  // 0.7853981  45 degrees
    10893}
    10994void rolling_inc(double * v) {
    110   *v += 0.7853;  // 0.7853981  45 degrees
     95        *v += 0.7853;  // 0.7853981  45 degrees
    11196}
    11297
     
    11499int scanrec(const char * s, unsigned int slen, char stopchar)
    115100{
    116   unsigned int i = 0;
    117   //DB( printf("    scan('%s', '%c')\n", s, stopchar); )
    118   while (1)
    119   {
    120     if (i >= slen)  // ran out the string, should never happen with correct string
    121       return 1;
    122     if (stopchar == s[i])  // bumped into stopchar
    123       return i;
    124     if (i < slen-1) 
    125     { // s[i] is not the last char
    126       if (s[i] == '(')
    127       {
    128         i += 2+scanrec(s+i+1, slen-i-1, ')');
    129         continue;
    130       }
    131       if (s[i] == '<')
    132       {
    133         i += 2+scanrec(s+i+1, slen-i-1, '>');
    134         continue;
    135       }
    136       if (s[i] == '#')
    137       {
    138         i += 2+scanrec(s+i+1, slen-i-1, '>');
    139         continue;
    140       }
    141     }
    142     // s[i] a non-special character
    143     i++;
    144   }
    145   return i;
     101        unsigned int i = 0;
     102        //DB( printf("    scan('%s', '%c')\n", s, stopchar); )
     103        while (1)
     104        {
     105                if (i >= slen)  // ran out the string, should never happen with correct string
     106                        return 1;
     107                if (stopchar == s[i])  // bumped into stopchar
     108                        return i;
     109                if (i < slen - 1)
     110                { // s[i] is not the last char
     111                        if (s[i] == '(')
     112                        {
     113                                i += 2 + scanrec(s + i + 1, slen - i - 1, ')');
     114                                continue;
     115                        }
     116                        if (s[i] == '<')
     117                        {
     118                                i += 2 + scanrec(s + i + 1, slen - i - 1, '>');
     119                                continue;
     120                        }
     121                        if (s[i] == '#')
     122                        {
     123                                i += 2 + scanrec(s + i + 1, slen - i - 1, '>');
     124                                continue;
     125                        }
     126                }
     127                // s[i] a non-special character
     128                i++;
     129        }
     130        return i;
    146131}
    147132
    148133
    149134f4_Cell::f4_Cell(int nname,
    150     f4_Cell * ndad, int nangle, f4_Props newP)
    151 {
    152   name    = nname;
    153   type    = T_UNDIFF4;
    154   dadlink = ndad;
    155   org    = NULL;
    156   genot  = NULL;
    157   gcur    = NULL;
    158   active = 1;
    159   repeat.null();
    160   //genoRange.clear(); -- implicit
    161 
    162   anglepos  = nangle;
    163   commacount = 0;
    164   childcount = 0;
    165   P          = newP;
    166   rolling    = 0;
    167   xrot      = 0;
    168   zrot      = 0;
    169   //OM = Orient_1;
    170   ctrl    = 0;
    171   state  = 0;
    172   inertia = 0.8;
    173   force  = 0.04;
    174   sigmo  = 2;
    175   nolink = 0;
    176 
    177   // adjust firstend and OM if there is a stick dad
    178   if (ndad != NULL)
    179   {
    180     // make sure it is a stick (and not a stick f4_Cell!)
    181     if (T_STICK4 == ndad->type)
    182     {
    183       //firstend = ndad->lastend;
    184       //OM = ndad->OM;
    185       ndad->childcount++;
    186     }
    187     if (T_NEURON4 == ndad->type)
    188     {
    189       state  = ndad->state;
    190       inertia = ndad->inertia;
    191       force  = ndad->force;
    192       sigmo  = ndad->sigmo;
    193     }
    194   }
    195   // adjust lastend
    196   //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
    197   mz = 1;
     135        f4_Cell * ndad, int nangle, f4_Props newP)
     136{
     137        name = nname;
     138        type = T_UNDIFF4;
     139        dadlink = ndad;
     140        org = NULL;
     141        genot = NULL;
     142        gcur = NULL;
     143        active = 1;
     144        repeat.null();
     145        //genoRange.clear(); -- implicit
     146
     147        anglepos = nangle;
     148        commacount = 0;
     149        childcount = 0;
     150        P = newP;
     151        rolling = 0;
     152        xrot = 0;
     153        zrot = 0;
     154        //OM = Orient_1;
     155        ctrl = 0;
     156        state = 0;
     157        inertia = 0.8;
     158        force = 0.04;
     159        sigmo = 2;
     160        nolink = 0;
     161
     162        // adjust firstend and OM if there is a stick dad
     163        if (ndad != NULL)
     164        {
     165                // make sure it is a stick (and not a stick f4_Cell!)
     166                if (T_STICK4 == ndad->type)
     167                {
     168                        //firstend = ndad->lastend;
     169                        //OM = ndad->OM;
     170                        ndad->childcount++;
     171                }
     172                if (T_NEURON4 == ndad->type)
     173                {
     174                        state = ndad->state;
     175                        inertia = ndad->inertia;
     176                        force = ndad->force;
     177                        sigmo = ndad->sigmo;
     178                }
     179        }
     180        // adjust lastend
     181        //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
     182        mz = 1;
    198183}
    199184
    200185
    201186f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur,
    202     f4_Cell * ndad, int nangle, f4_Props newP)
    203 {
    204   name    = nname;
    205   type    = T_UNDIFF4;
    206   dadlink = ndad;
    207   org    = nO;
    208   genot  = ngeno;
    209   gcur    = ngcur;
    210   active = 1;
    211   repeat.null();
    212   //genoRange.clear(); -- implicit
    213   // preserve geno range of parent cell
    214   if (NULL != ndad)
    215     genoRange.add( ndad->genoRange );
    216 
    217   anglepos  = nangle;
    218   commacount = 0;
    219   childcount = 0;
    220   P          = newP;
    221   rolling    = 0;
    222   xrot      = 0;
    223   zrot      = 0;
    224   //OM = Orient_1;
    225   ctrl    = 0;
    226   state  = 0;
    227   inertia = 0.8;
    228   force  = 0.04;
    229   sigmo  = 2;
    230   nolink = 0;
    231 
    232   // adjust firstend and OM if there is a stick dad
    233   if (ndad != NULL)
    234   {
    235     // make sure it is a stick (and not a stick f4_Cell!)
    236     if (T_STICK4 == ndad->type) {
    237       //firstend = ndad->lastend;
    238       //OM = ndad->OM;
    239       ndad->childcount++;
    240     }
    241     if (T_NEURON4 == ndad->type)
    242     {
    243       state  = ndad->state;
    244       inertia = ndad->inertia;
    245       force  = ndad->force;
    246       sigmo  = ndad->sigmo;
    247     }
    248   }
    249   // adjust lastend
    250   //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
    251   mz = 1;
     187        f4_Cell * ndad, int nangle, f4_Props newP)
     188{
     189        name = nname;
     190        type = T_UNDIFF4;
     191        dadlink = ndad;
     192        org = nO;
     193        genot = ngeno;
     194        gcur = ngcur;
     195        active = 1;
     196        repeat.null();
     197        //genoRange.clear(); -- implicit
     198        // preserve geno range of parent cell
     199        if (NULL != ndad)
     200                genoRange.add(ndad->genoRange);
     201
     202        anglepos = nangle;
     203        commacount = 0;
     204        childcount = 0;
     205        P = newP;
     206        rolling = 0;
     207        xrot = 0;
     208        zrot = 0;
     209        //OM = Orient_1;
     210        ctrl = 0;
     211        state = 0;
     212        inertia = 0.8;
     213        force = 0.04;
     214        sigmo = 2;
     215        nolink = 0;
     216
     217        // adjust firstend and OM if there is a stick dad
     218        if (ndad != NULL)
     219        {
     220                // make sure it is a stick (and not a stick f4_Cell!)
     221                if (T_STICK4 == ndad->type) {
     222                        //firstend = ndad->lastend;
     223                        //OM = ndad->OM;
     224                        ndad->childcount++;
     225                }
     226                if (T_NEURON4 == ndad->type)
     227                {
     228                        state = ndad->state;
     229                        inertia = ndad->inertia;
     230                        force = ndad->force;
     231                        sigmo = ndad->sigmo;
     232                }
     233        }
     234        // adjust lastend
     235        //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
     236        mz = 1;
    252237}
    253238
     
    255240f4_Cell::~f4_Cell()
    256241{
    257   // remove links
    258   if (nolink)
    259   {
    260     int i;
    261     for (i=nolink-1; i>=0; i--)
    262       delete links[i];
    263     nolink=0;
    264   }
     242        // remove links
     243        if (nolink)
     244        {
     245                int i;
     246                for (i = nolink - 1; i >= 0; i--)
     247                        delete links[i];
     248                nolink = 0;
     249        }
    265250}
    266251
    267252
    268253/* return codes:
    269     >1 error at pos
    270      0  halt development for a cycle
    271     -1  development finished OK
    272 */
     254        >1 error at pos
     255        0  halt development for a cycle
     256        -1  development finished OK
     257        */
    273258int f4_Cell::onestep()
    274259{
    275   int i, j, k, relfrom, t;
    276   double w;
    277   f4_Cell * tmp;
    278   f4_Cell * tneu;
    279   if (gcur == NULL)
    280   {
    281     active = 0;
    282     return 0;  // stop
    283   }
    284   while ( NULL != gcur )
    285   {
    286     //DB( printf("  %d (%d) executing '%c' %d\n", name, type, gcur->name, gcur->pos); )
    287     // currently this is the last one processed
    288     // the current genotype code is processed
    289     genoRange.add( gcur->pos );
    290     switch (gcur->name)
    291     {
    292     case '<':
    293       // cell division!
    294       //DB( printf("  div! %d\n", name); )
    295 
    296       // error: sticks cannot divide
    297       if (T_STICK4 == type) {
    298         // cannot fix
    299         org->setError(gcur->pos);
    300         return 1;  // stop
    301       }
    302 
    303       // undiff divides
    304       if (T_UNDIFF4 == type) {
    305         // commacount is set only when daughter turns into X
    306         // daughter cell
    307         // adjust new len
    308         f4_Props newP = P;
    309         newP.adjust();
    310         tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
    311          this,  commacount, newP);
    312         tmp->repeat = repeat;
    313         repeat.null();
    314         org->addCell( tmp );
    315       }
    316       // a neuron divides: create a new, duplicate links
    317       if (T_NEURON4 == type) {
    318         // daughter cell
    319         tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
    320           // has the same dadlink
    321           this->dadlink, commacount, P);
    322         tmp->repeat = repeat;
    323         repeat.null();
    324         // it is a neuron from start
    325         tmp->type = T_NEURON4;
    326         // duplicate links
    327         f4_CellLink * ll;
    328         for (i=0; i<nolink; i++) {
    329           ll = links[i];
    330           tmp->addlink(ll->from, ll->w, ll->t);
    331         }
    332         org->addCell( tmp );
    333       }
    334       // adjustments for this cell
    335       gcur = gcur->child;
    336       // halt development
    337       return 0;
    338 
    339     case '>':
    340       // finish
    341       // see if there is a repet count
    342       if (repeat.top > 0)
    343       { // there is a repeat counter
    344         if (!repeat.first()->isNull())
    345         { // repeat counter is not null
    346           repeat.first()->dec();
    347           if (repeat.first()->count > 0)
    348           {
    349             // return to repeat
    350             gcur = repeat.first()->node->child;
    351           } else {
    352             // continue
    353             gcur = repeat.first()->node->child2;
    354             repeat.pop();
    355           }
    356           break;
    357         } else {
    358           repeat.pop();
    359         }
    360       } else {
    361         // error: still undiff
    362         if (T_UNDIFF4 == type)
    363         {
    364           // fix it: insert an 'X'
    365           f4_node * insertnode = new f4_node('X', NULL, gcur->pos);
    366           if (org->setRepairInsert(gcur->pos, gcur, insertnode))
    367             // not in repair mode, release
    368             delete insertnode;
    369           return 1;
    370         }
    371         repeat.null();
    372         active = 0;  // stop
    373         // eat up rest
    374         gcur = NULL;
    375         return 0;
    376       }
    377 
    378     case '#':
    379       // repetition marker
    380       if (repeat.top >= repeat_stack::stackSize)
    381       {
    382         // repepeat pointer stack is full, cannot remember this one.
    383         // fix: delete it
    384         org->setRepairRemove(gcur->pos, gcur);
    385         return 1;  // stop
    386       }
    387       repeat.push( repeat_ptr(gcur, gcur->i1) );
    388       gcur = gcur->child;
    389       break;
    390 
    391     case ',':
    392       commacount++;
    393       gcur = gcur->child;
    394       break;
    395 
    396     case 'r':  case 'R':
    397       // error: if neuron
    398       if (T_NEURON4 == type) {
    399         // fix: delete it
    400         org->setRepairRemove(gcur->pos, gcur);
    401         return 1;  // stop
    402       }
    403       switch (gcur->name) {
    404        case 'r':   rolling_dec( &rolling ); break;
    405        case 'R':   rolling_inc( &rolling ); break;
    406       }
    407       gcur = gcur->child;
    408       break;
    409 
    410     case 'l':  case 'L':
    411     case 'c':  case 'C':
    412     case 'q':  case 'Q':
    413     case 'a':  case 'A':
    414     case 'i':  case 'I':
    415     case 's':  case 'S':
    416     case 'm':  case 'M':
    417     case 'f':  case 'F':
    418     case 'w':  case 'W':
    419     case 'e':  case 'E':
    420       // error: if neuron
    421       if (T_NEURON4 == type) {
    422         // fix: delete it
    423         org->setRepairRemove(gcur->pos, gcur);
    424         return 1;  // stop
    425       }
    426       P.executeModifier(gcur->name);
    427       gcur = gcur->child;
    428       break;
    429 
    430     case 'X':
    431       // turn undiff. cell into a stick
    432       // error: already differentiated
    433       if (T_UNDIFF4 != type) {
    434         // fix: delete this node
    435         org->setRepairRemove(gcur->pos, gcur);
    436         return 1;  // stop
    437       }
    438       type = T_STICK4;
    439       // fix dad commacount and own anglepos
    440       if (NULL != dadlink) {
    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         // fix: delete this node
    453         org->setRepairRemove(gcur->pos, gcur);
    454         return 1;  // stop
    455       }
    456       // error: if no previous
    457       if (NULL == dadlink) {
    458         // fix: delete it
    459         org->setRepairRemove(gcur->pos, gcur);
    460         return 1;  // stop
    461       }
    462       type = T_NEURON4;
    463       // change of type also halts development, to give other
    464       // cells a chance for adjustment.  Namely, it is important
    465       // to wait for other cells to turn N before adding links
    466       gcur = gcur->child;
    467       return 0;
    468 
    469     case '@':
    470     case '|':
    471       // neuron rotating / bending
    472       j = 1;
    473       if ('@' == gcur->name) j = 1; // rot
    474       if ('|' == gcur->name) j = 2; // bend
    475       // error: not a neuron (undiff)
    476       if (T_UNDIFF4 == type) {
    477         // fix: delete it
    478         org->setRepairRemove(gcur->pos, gcur);
    479         return 1;  // stop
    480       }
    481       // error: not a neuron (stick)
    482       if (T_NEURON4 != type) {
    483         // fix: delete it
    484         org->setRepairRemove(gcur->pos, gcur);
    485         return 1;  // stop
    486       }
    487       // error: already has control
    488       if (ctrl != 0) {
    489         // fix: delete it
    490         org->setRepairRemove(gcur->pos, gcur);
    491         return 1;  // stop
    492       }
    493       // make neuron ctrl = 1 or 2
    494       ctrl = j;
    495       gcur = gcur->child;
    496       break;
    497 
    498     case '[':
    499       // link to neuron
    500       // error: not a neuron
    501       if (T_NEURON4 != type) {
    502         // fix: delete it
    503         org->setRepairRemove(gcur->pos, gcur);
    504         return 1;  // stop
    505       }
    506       // input ('*', 'G', 'T', 'S', or %d)
    507       t       = gcur->i1;
    508       relfrom = gcur->l1;
    509       w       = gcur->f1;
    510       if (t>0) {
    511         // * or G
    512         tneu = NULL;
    513       } else {
    514         // input from other neuron
    515         // find neuron at relative i
    516         // find own index
    517         j = 0; k = 0;
    518         for(i=0; i<org->nc; i++) {
    519           if (org->C[i]->type == T_NEURON4) k++;
    520           if (org->C[i] == this) {j=k-1; break;}
    521         }
    522         // find index of incoming
    523         j = j + relfrom;
    524         if (j<0) goto wait_link;
    525         if (j>=org->nc) goto wait_link;
    526         // find that neuron
    527         k = 0;
    528         for(i=0; i<org->nc; i++) {
    529           if (org->C[i]->type == T_NEURON4) k++;
    530           if (j == (k-1)) break;
    531         }
    532         if (i>=org->nc) goto wait_link;
    533         tneu = org->C[i];
    534       }
    535       // add link
    536       // error: could not add link (too many?)
    537       if (addlink(tneu, w, t)) {
    538         // cannot fix
    539         org->setError(gcur->pos);
    540         return 1;  // stop
    541       }
    542       gcur = gcur->child;
    543       break;
    544     wait_link:
    545       // wait for other neurons to develop
    546       // if there are others still active
    547       active = 0;
    548       j = 0;
    549       for(i=0; i<org->nc; i++) {
    550         if (org->C[i]->active) j++;
    551       }
    552       if (j>0)
    553         return 0;  // there is other active, halt, try again
    554       // no more actives, cannot add link, ignore, but treat not as an error
    555       gcur = gcur->child;
    556       break;
    557 
    558     case ':':
    559       // neuron parameter
    560       // error: not a neuron
    561       if (T_NEURON4 != type) {
    562         // fix: delete it
    563         org->setRepairRemove(gcur->pos, gcur);
    564         return 1;  // stop
    565       }
    566       j = (int)gcur->l1;
    567       switch ((char)gcur->i1) {
    568        case '!':
    569         if (j) force += (1.0 - force) * 0.2;
    570         else   force -= force * 0.2; break;
    571        case '=':
    572         if (j) inertia += (1.0 - inertia) * 0.2;
    573         else   inertia -= inertia * 0.2; break;
    574        case '/':
    575         if (j) sigmo *= 1.4;
    576         else   sigmo /= 1.4; break;
    577        default:
    578          org->setRepairRemove(gcur->pos, gcur);
    579          return 1;  // stop
    580       }
    581       gcur = gcur->child;
    582       break;
    583 
    584     case ' ':
    585       // space has no effect, should not occur
    586       // fix: delete it
    587       org->setRepairRemove(gcur->pos, gcur);
    588       gcur = gcur->child;
    589       break;
    590 
    591     default:
    592       // error: unknown code
    593       char buf[40];
    594       sprintf(buf, "unknown code '%c'", gcur->name);
    595       FramMessage("f4_Cell", "onestep", buf, 2);
    596       // fix: delete it
    597       org->setRepairRemove(gcur->pos, gcur);
    598       return 1; // stop
    599     }
    600   }
    601   active = 0;  // done
    602   return 0;
     260        int i, j, k, relfrom, t;
     261        double w;
     262        f4_Cell * tmp;
     263        f4_Cell * tneu;
     264        if (gcur == NULL)
     265        {
     266                active = 0;
     267                return 0;  // stop
     268        }
     269        while (NULL != gcur)
     270        {
     271                //DB( printf("  %d (%d) executing '%c' %d\n", name, type, gcur->name, gcur->pos); )
     272                // currently this is the last one processed
     273                // the current genotype code is processed
     274                genoRange.add(gcur->pos);
     275                switch (gcur->name)
     276                {
     277                case '<':
     278                        // cell division!
     279                        //DB( printf("  div! %d\n", name); )
     280
     281                        // error: sticks cannot divide
     282                        if (T_STICK4 == type) {
     283                                // cannot fix
     284                                org->setError(gcur->pos);
     285                                return 1;  // stop
     286                        }
     287
     288                        // undiff divides
     289                        if (T_UNDIFF4 == type) {
     290                                // commacount is set only when daughter turns into X
     291                                // daughter cell
     292                                // adjust new len
     293                                f4_Props newP = P;
     294                                newP.adjust();
     295                                tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
     296                                        this, commacount, newP);
     297                                tmp->repeat = repeat;
     298                                repeat.null();
     299                                org->addCell(tmp);
     300                        }
     301                        // a neuron divides: create a new, duplicate links
     302                        if (T_NEURON4 == type) {
     303                                // daughter cell
     304                                tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
     305                                        // has the same dadlink
     306                                        this->dadlink, commacount, P);
     307                                tmp->repeat = repeat;
     308                                repeat.null();
     309                                // it is a neuron from start
     310                                tmp->type = T_NEURON4;
     311                                // duplicate links
     312                                f4_CellLink * ll;
     313                                for (i = 0; i < nolink; i++) {
     314                                        ll = links[i];
     315                                        tmp->addlink(ll->from, ll->w, ll->t);
     316                                }
     317                                org->addCell(tmp);
     318                        }
     319                        // adjustments for this cell
     320                        gcur = gcur->child;
     321                        // halt development
     322                        return 0;
     323
     324                case '>':
     325                        // finish
     326                        // see if there is a repet count
     327                        if (repeat.top > 0)
     328                        { // there is a repeat counter
     329                                if (!repeat.first()->isNull())
     330                                { // repeat counter is not null
     331                                        repeat.first()->dec();
     332                                        if (repeat.first()->count > 0)
     333                                        {
     334                                                // return to repeat
     335                                                gcur = repeat.first()->node->child;
     336                                        }
     337                                        else {
     338                                                // continue
     339                                                gcur = repeat.first()->node->child2;
     340                                                repeat.pop();
     341                                        }
     342                                        break;
     343                                }
     344                                else {
     345                                        repeat.pop();
     346                                }
     347                        }
     348                        else {
     349                                // error: still undiff
     350                                if (T_UNDIFF4 == type)
     351                                {
     352                                        // fix it: insert an 'X'
     353                                        f4_node * insertnode = new f4_node('X', NULL, gcur->pos);
     354                                        if (org->setRepairInsert(gcur->pos, gcur, insertnode))
     355                                                // not in repair mode, release
     356                                                delete insertnode;
     357                                        return 1;
     358                                }
     359                                repeat.null();
     360                                active = 0;  // stop
     361                                // eat up rest
     362                                gcur = NULL;
     363                                return 0;
     364                        }
     365
     366                case '#':
     367                        // repetition marker
     368                        if (repeat.top >= repeat_stack::stackSize)
     369                        {
     370                                // repepeat pointer stack is full, cannot remember this one.
     371                                // fix: delete it
     372                                org->setRepairRemove(gcur->pos, gcur);
     373                                return 1;  // stop
     374                        }
     375                        repeat.push(repeat_ptr(gcur, gcur->i1));
     376                        gcur = gcur->child;
     377                        break;
     378
     379                case ',':
     380                        commacount++;
     381                        gcur = gcur->child;
     382                        break;
     383
     384                case 'r':  case 'R':
     385                        // error: if neuron
     386                        if (T_NEURON4 == type) {
     387                                // fix: delete it
     388                                org->setRepairRemove(gcur->pos, gcur);
     389                                return 1;  // stop
     390                        }
     391                        switch (gcur->name) {
     392                        case 'r':   rolling_dec(&rolling); break;
     393                        case 'R':   rolling_inc(&rolling); break;
     394                        }
     395                        gcur = gcur->child;
     396                        break;
     397
     398                case 'l':  case 'L':
     399                case 'c':  case 'C':
     400                case 'q':  case 'Q':
     401                case 'a':  case 'A':
     402                case 'i':  case 'I':
     403                case 's':  case 'S':
     404                case 'm':  case 'M':
     405                case 'f':  case 'F':
     406                case 'w':  case 'W':
     407                case 'e':  case 'E':
     408                        // error: if neuron
     409                        if (T_NEURON4 == type) {
     410                                // fix: delete it
     411                                org->setRepairRemove(gcur->pos, gcur);
     412                                return 1;  // stop
     413                        }
     414                        P.executeModifier(gcur->name);
     415                        gcur = gcur->child;
     416                        break;
     417
     418                case 'X':
     419                        // turn undiff. cell into a stick
     420                        // error: already differentiated
     421                        if (T_UNDIFF4 != type) {
     422                                // fix: delete this node
     423                                org->setRepairRemove(gcur->pos, gcur);
     424                                return 1;  // stop
     425                        }
     426                        type = T_STICK4;
     427                        // fix dad commacount and own anglepos
     428                        if (NULL != dadlink) {
     429                                dadlink->commacount++;
     430                                anglepos = dadlink->commacount;
     431                        }
     432                        // change of type halts developments, see comment at 'N'
     433                        gcur = gcur->child;
     434                        return 0;
     435
     436                case 'N':
     437                        // turn undiff. cell into a neuron
     438                        // error: already differentiated
     439                        if (T_UNDIFF4 != type) {
     440                                // fix: delete this node
     441                                org->setRepairRemove(gcur->pos, gcur);
     442                                return 1;  // stop
     443                        }
     444                        // error: if no previous
     445                        if (NULL == dadlink) {
     446                                // fix: delete it
     447                                org->setRepairRemove(gcur->pos, gcur);
     448                                return 1;  // stop
     449                        }
     450                        type = T_NEURON4;
     451                        // change of type also halts development, to give other
     452                        // cells a chance for adjustment.  Namely, it is important
     453                        // to wait for other cells to turn N before adding links
     454                        gcur = gcur->child;
     455                        return 0;
     456
     457                case '@':
     458                case '|':
     459                        // neuron rotating / bending
     460                        j = 1;
     461                        if ('@' == gcur->name) j = 1; // rot
     462                        if ('|' == gcur->name) j = 2; // bend
     463                        // error: not a neuron (undiff)
     464                        if (T_UNDIFF4 == type) {
     465                                // fix: delete it
     466                                org->setRepairRemove(gcur->pos, gcur);
     467                                return 1;  // stop
     468                        }
     469                        // error: not a neuron (stick)
     470                        if (T_NEURON4 != type) {
     471                                // fix: delete it
     472                                org->setRepairRemove(gcur->pos, gcur);
     473                                return 1;  // stop
     474                        }
     475                        // error: already has control
     476                        if (ctrl != 0) {
     477                                // fix: delete it
     478                                org->setRepairRemove(gcur->pos, gcur);
     479                                return 1;  // stop
     480                        }
     481                        // make neuron ctrl = 1 or 2
     482                        ctrl = j;
     483                        gcur = gcur->child;
     484                        break;
     485
     486                case '[':
     487                        // link to neuron
     488                        // error: not a neuron
     489                        if (T_NEURON4 != type) {
     490                                // fix: delete it
     491                                org->setRepairRemove(gcur->pos, gcur);
     492                                return 1;  // stop
     493                        }
     494                        // input ('*', 'G', 'T', 'S', or %d)
     495                        t = gcur->i1;
     496                        relfrom = gcur->l1;
     497                        w = gcur->f1;
     498                        if (t > 0) {
     499                                // * or G
     500                                tneu = NULL;
     501                        }
     502                        else {
     503                                // input from other neuron
     504                                // find neuron at relative i
     505                                // find own index
     506                                j = 0; k = 0;
     507                                for (i = 0; i < org->nc; i++) {
     508                                        if (org->C[i]->type == T_NEURON4) k++;
     509                                        if (org->C[i] == this) { j = k - 1; break; }
     510                                }
     511                                // find index of incoming
     512                                j = j + relfrom;
     513                                if (j < 0) goto wait_link;
     514                                if (j >= org->nc) goto wait_link;
     515                                // find that neuron
     516                                k = 0;
     517                                for (i = 0; i < org->nc; i++) {
     518                                        if (org->C[i]->type == T_NEURON4) k++;
     519                                        if (j == (k - 1)) break;
     520                                }
     521                                if (i >= org->nc) goto wait_link;
     522                                tneu = org->C[i];
     523                        }
     524                        // add link
     525                        // error: could not add link (too many?)
     526                        if (addlink(tneu, w, t)) {
     527                                // cannot fix
     528                                org->setError(gcur->pos);
     529                                return 1;  // stop
     530                        }
     531                        gcur = gcur->child;
     532                        break;
     533                wait_link:
     534                        // wait for other neurons to develop
     535                        // if there are others still active
     536                        active = 0;
     537                        j = 0;
     538                        for (i = 0; i<org->nc; i++) {
     539                                if (org->C[i]->active) j++;
     540                        }
     541                        if (j>0)
     542                                return 0;  // there is other active, halt, try again
     543                        // no more actives, cannot add link, ignore, but treat not as an error
     544                        gcur = gcur->child;
     545                        break;
     546
     547                case ':':
     548                        // neuron parameter
     549                        // error: not a neuron
     550                        if (T_NEURON4 != type) {
     551                                // fix: delete it
     552                                org->setRepairRemove(gcur->pos, gcur);
     553                                return 1;  // stop
     554                        }
     555                        j = (int)gcur->l1;
     556                        switch ((char)gcur->i1) {
     557                        case '!':
     558                                if (j) force += (1.0 - force) * 0.2;
     559                                else   force -= force * 0.2; break;
     560                        case '=':
     561                                if (j) inertia += (1.0 - inertia) * 0.2;
     562                                else   inertia -= inertia * 0.2; break;
     563                        case '/':
     564                                if (j) sigmo *= 1.4;
     565                                else   sigmo /= 1.4; break;
     566                        default:
     567                                org->setRepairRemove(gcur->pos, gcur);
     568                                return 1;  // stop
     569                        }
     570                        gcur = gcur->child;
     571                        break;
     572
     573                case ' ':
     574                        // space has no effect, should not occur
     575                        // fix: delete it
     576                        org->setRepairRemove(gcur->pos, gcur);
     577                        gcur = gcur->child;
     578                        break;
     579
     580                default:
     581                        // error: unknown code
     582                        char buf[40];
     583                        sprintf(buf, "unknown code '%c'", gcur->name);
     584                        FramMessage("f4_Cell", "onestep", buf, 2);
     585                        // fix: delete it
     586                        org->setRepairRemove(gcur->pos, gcur);
     587                        return 1; // stop
     588                }
     589        }
     590        active = 0;  // done
     591        return 0;
    603592}
    604593
     
    606595int f4_Cell::addlink(f4_Cell * nfrom, double nw, long nt)
    607596{
    608   if (nolink >= MAXINPUTS-1) return -1; // full!
    609   links[nolink] = new f4_CellLink(nfrom, nw, nt);
    610   nolink++;
    611   return 0;
     597        if (nolink >= MAXINPUTS - 1) return -1; // full!
     598        links[nolink] = new f4_CellLink(nfrom, nw, nt);
     599        nolink++;
     600        return 0;
    612601}
    613602
     
    615604void f4_Cell::adjustRec()
    616605{
    617   //f4_OrientMat rot;
    618   int     i;
    619 
    620   if (recProcessedFlag)
    621     // already processed
    622     return;
    623 
    624   // mark it processed
    625   recProcessedFlag = 1;
    626 
    627   // make sure its parent is processed first
    628   if (NULL != dadlink)
    629     dadlink->adjustRec();
    630 
    631   // count children
    632   childcount = 0;
    633   for(i=0; i<org->nc; i++)
    634   {
    635     if (org->C[i]->dadlink == this)
    636       if (org->C[i]->type == T_STICK4)
    637         childcount++;
    638   }
    639 
    640   if (type == T_STICK4)
    641   {
    642     if (NULL == dadlink)
    643     {
    644       //firstend = Pt3D_0;
    645       // rotation due to rolling
    646       xrot = rolling;
    647       mz = 1;
    648     } else {
    649       //firstend = dadlink->lastend;
    650       f4_Props Pdad = dadlink->P;
    651       f4_Props Padj = Pdad;
    652       Padj.adjust();
    653 
    654       //rot = Orient_1;
    655 
    656       // rotation due to rolling
    657       xrot = rolling +
    658         // rotation due to twist
    659         Pdad.twist;
    660       if (dadlink->commacount <= 1)
    661       {
    662         // rotation due to curvedness
    663         zrot = Padj.curv;
    664       } else {
    665         zrot = Padj.curv +
    666           // GDK uses 3.141 instead of PI!
    667           (anglepos * 1.0/(dadlink->commacount+1) - 0.5) * 3.141 * 2.0;
    668       }
    669 
    670       //rot = rot * f4_OrientMat(yOz, xrot);
    671       //rot = rot * f4_OrientMat(xOy, zrot);
    672       // rotation relative to parent stick
    673       //OM = rot * OM;
    674 
    675       // rotation in world coordinates
    676       //OM =  ((f4_OrientMat)dadlink->OM) * OM;
    677       mz = dadlink->mz / dadlink->childcount;
    678     }
    679     //Pt3D lastoffset = (Orient)OM * (Pt3D(1,0,0)*P.len);
    680     //lastend = firstend + lastoffset;
    681   }
     606        //f4_OrientMat rot;
     607        int     i;
     608
     609        if (recProcessedFlag)
     610                // already processed
     611                return;
     612
     613        // mark it processed
     614        recProcessedFlag = 1;
     615
     616        // make sure its parent is processed first
     617        if (NULL != dadlink)
     618                dadlink->adjustRec();
     619
     620        // count children
     621        childcount = 0;
     622        for (i = 0; i < org->nc; i++)
     623        {
     624                if (org->C[i]->dadlink == this)
     625                        if (org->C[i]->type == T_STICK4)
     626                                childcount++;
     627        }
     628
     629        if (type == T_STICK4)
     630        {
     631                if (NULL == dadlink)
     632                {
     633                        //firstend = Pt3D_0;
     634                        // rotation due to rolling
     635                        xrot = rolling;
     636                        mz = 1;
     637                }
     638                else {
     639                        //firstend = dadlink->lastend;
     640                        f4_Props Pdad = dadlink->P;
     641                        f4_Props Padj = Pdad;
     642                        Padj.adjust();
     643
     644                        //rot = Orient_1;
     645
     646                        // rotation due to rolling
     647                        xrot = rolling +
     648                                // rotation due to twist
     649                                Pdad.twist;
     650                        if (dadlink->commacount <= 1)
     651                        {
     652                                // rotation due to curvedness
     653                                zrot = Padj.curv;
     654                        }
     655                        else {
     656                                zrot = Padj.curv +
     657                                        // GDK uses 3.141 instead of PI!
     658                                        (anglepos * 1.0 / (dadlink->commacount + 1) - 0.5) * 3.141 * 2.0;
     659                        }
     660
     661                        //rot = rot * f4_OrientMat(yOz, xrot);
     662                        //rot = rot * f4_OrientMat(xOy, zrot);
     663                        // rotation relative to parent stick
     664                        //OM = rot * OM;
     665
     666                        // rotation in world coordinates
     667                        //OM =  ((f4_OrientMat)dadlink->OM) * OM;
     668                        mz = dadlink->mz / dadlink->childcount;
     669                }
     670                //Pt3D lastoffset = (Orient)OM * (Pt3D(1,0,0)*P.len);
     671                //lastend = firstend + lastoffset;
     672        }
    682673}
    683674
     
    686677f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, long nt)
    687678{
    688   from = nfrom;
    689   w    = nw;
    690   t    = nt;
     679        from = nfrom;
     680        w = nw;
     681        t = nt;
    691682}
    692683
     
    695686f4_Cells::f4_Cells(f4_node * genome, int nrepair)
    696687{
    697   // create ancestor cell
    698   repair = nrepair;
    699   error = 0;
    700   errorpos = -1;
    701   repair_remove = NULL;
    702   repair_parent = NULL;
    703   repair_insert = NULL;
    704   tmpcel = NULL;
    705   f4rootnode = NULL;
    706 
    707   C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, stdProps);
    708   nc  = 1;
     688        // create ancestor cell
     689        repair = nrepair;
     690        error = 0;
     691        errorpos = -1;
     692        repair_remove = NULL;
     693        repair_parent = NULL;
     694        repair_insert = NULL;
     695        tmpcel = NULL;
     696        f4rootnode = NULL;
     697
     698        C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, stdProps);
     699        nc = 1;
    709700}
    710701
     
    712703f4_Cells::f4_Cells(SString & genome, int nrepair)
    713704{
    714   int res;
    715   repair = nrepair;
    716   error = 0;
    717   errorpos = -1;
    718   repair_remove = NULL;
    719   repair_parent = NULL;
    720   repair_insert = NULL;
    721   tmpcel = NULL;
    722   f4rootnode = NULL;
    723 
    724   // transform geno from string to nodes
    725   f4rootnode = new f4_node();
    726   res = f4_processrec((const char*)genome, (unsigned)0, f4rootnode);
    727   if ((res<0) || (1 != f4rootnode->childCount()))
    728   {
    729     error = GENOPER_OPFAIL;
    730     errorpos = -1;
    731   }
    732 
    733   // create ancestor cell
    734   C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child,
    735     NULL, 0, stdProps);
    736   nc  = 1;
     705        int res;
     706        repair = nrepair;
     707        error = 0;
     708        errorpos = -1;
     709        repair_remove = NULL;
     710        repair_parent = NULL;
     711        repair_insert = NULL;
     712        tmpcel = NULL;
     713        f4rootnode = NULL;
     714
     715        // transform geno from string to nodes
     716        f4rootnode = new f4_node();
     717        res = f4_processrec((const char*)genome, (unsigned)0, f4rootnode);
     718        if ((res < 0) || (1 != f4rootnode->childCount()))
     719        {
     720                error = GENOPER_OPFAIL;
     721                errorpos = -1;
     722        }
     723
     724        // create ancestor cell
     725        C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child,
     726                NULL, 0, stdProps);
     727        nc = 1;
    737728}
    738729
    739730f4_Cells::~f4_Cells()
    740731{
    741   // release cells
    742   int i;
    743   if (nc)
    744   {
    745     for (i=nc-1; i>=0; i--)
    746       delete C[i];
    747     nc = 0;
    748   }
    749   if (f4rootnode)
    750     delete f4rootnode;
     732        // release cells
     733        int i;
     734        if (nc)
     735        {
     736                for (i = nc - 1; i >= 0; i--)
     737                        delete C[i];
     738                nc = 0;
     739        }
     740        if (f4rootnode)
     741                delete f4rootnode;
    751742}
    752743
     
    754745int f4_Cells::onestep()
    755746{
    756   int i, ret, oldnc, ret2;
    757   oldnc = nc;
    758   ret=0;
    759   for (i=0; i<oldnc; i++) {
    760     ret2 = C[i]->onestep();
    761     if (ret2>0) {
    762       // error
    763       C[i]->active = 0;  // stop
    764       return 0;
    765     }
    766     // if still active
    767     if (C[i]->active)
    768       ret=1;
    769   }
    770   return ret;
     747        int i, ret, oldnc, ret2;
     748        oldnc = nc;
     749        ret = 0;
     750        for (i = 0; i<oldnc; i++) {
     751                ret2 = C[i]->onestep();
     752                if (ret2>0) {
     753                        // error
     754                        C[i]->active = 0;  // stop
     755                        return 0;
     756                }
     757                // if still active
     758                if (C[i]->active)
     759                        ret = 1;
     760        }
     761        return ret;
    771762}
    772763
     
    774765int f4_Cells::simulate()
    775766{
    776   int i;
    777   error = GENOPER_OK;
    778 
    779   for (i=0; i<nc; i++)  C[i]->active = 1;
    780 
    781   // execute onestep() in a cycle
    782   while (onestep()) ;
    783 
    784   if (GENOPER_OK != error) return error;
    785 
    786   // fix neuron attachements
    787   for(i=0; i<nc; i++)
    788     if (C[i]->type == T_NEURON4) {
    789       while (T_NEURON4 == C[i]->dadlink->type) {
    790         C[i]->dadlink = C[i]->dadlink->dadlink;
    791       }
    792   }
    793 
    794   // there should be no undiff. cells
    795   // make undifferentiated cells sticks
    796   for (i=0; i<nc ; i++)
    797     if (C[i]->type == T_UNDIFF4) {
    798       C[i]->type = T_STICK4;
    799       //seterror();
    800   }
    801 
    802   // recursive adjust
    803   // reset recursive traverse flags
    804   for(i=0; i<nc; i++)
    805     C[i]->recProcessedFlag = 0;
    806   // process every cell
    807   for(i=0; i<nc; i++)
    808     C[i]->adjustRec();
    809 
    810   //DB( printf("Cell simulation done, %d cells. \n", nc); )
    811 
    812   return error;
     767        int i;
     768        error = GENOPER_OK;
     769
     770        for (i = 0; i < nc; i++)  C[i]->active = 1;
     771
     772        // execute onestep() in a cycle
     773        while (onestep());
     774
     775        if (GENOPER_OK != error) return error;
     776
     777        // fix neuron attachements
     778        for (i = 0; i < nc; i++)
     779                if (C[i]->type == T_NEURON4) {
     780                        while (T_NEURON4 == C[i]->dadlink->type) {
     781                                C[i]->dadlink = C[i]->dadlink->dadlink;
     782                        }
     783                }
     784
     785        // there should be no undiff. cells
     786        // make undifferentiated cells sticks
     787        for (i = 0; i < nc; i++)
     788                if (C[i]->type == T_UNDIFF4) {
     789                        C[i]->type = T_STICK4;
     790                        //seterror();
     791                }
     792
     793        // recursive adjust
     794        // reset recursive traverse flags
     795        for (i = 0; i < nc; i++)
     796                C[i]->recProcessedFlag = 0;
     797        // process every cell
     798        for (i = 0; i < nc; i++)
     799                C[i]->adjustRec();
     800
     801        //DB( printf("Cell simulation done, %d cells. \n", nc); )
     802
     803        return error;
    813804}
    814805
     
    816807void f4_Cells::addCell(f4_Cell * newcell)
    817808{
    818   if (nc >= MAX4CELLS-1) {
    819     delete newcell;
    820     return;
    821   }
    822   C[nc] = newcell;
    823   nc++;
     809        if (nc >= MAX4CELLS - 1) {
     810                delete newcell;
     811                return;
     812        }
     813        C[nc] = newcell;
     814        nc++;
    824815}
    825816
     
    827818void f4_Cells::setError(int nerrpos)
    828819{
    829   error = GENOPER_OPFAIL;
    830   errorpos = nerrpos;
     820        error = GENOPER_OPFAIL;
     821        errorpos = nerrpos;
    831822}
    832823
    833824void f4_Cells::setRepairRemove(int nerrpos, f4_node * rem)
    834825{
    835   if (!repair) {
    836     // not in repair mode, treat as repairable error
    837     error = GENOPER_REPAIR;
    838     errorpos = nerrpos;
    839   } else {
    840     error = GENOPER_REPAIR;
    841     errorpos = nerrpos;
    842     repair_remove = rem;
    843   }
     826        if (!repair) {
     827                // not in repair mode, treat as repairable error
     828                error = GENOPER_REPAIR;
     829                errorpos = nerrpos;
     830        }
     831        else {
     832                error = GENOPER_REPAIR;
     833                errorpos = nerrpos;
     834                repair_remove = rem;
     835        }
    844836}
    845837
    846838int f4_Cells::setRepairInsert(int nerrpos, f4_node * parent, f4_node * insert)
    847839{
    848   if (!repair) {
    849     // not in repair mode, treat as repairable error
    850     error = GENOPER_REPAIR;
    851     errorpos = nerrpos;
    852     return -1;
    853   } else {
    854     error = GENOPER_REPAIR;
    855     errorpos = nerrpos;
    856     repair_parent = parent;
    857     repair_insert = insert;
    858     return 0;
    859   }
     840        if (!repair) {
     841                // not in repair mode, treat as repairable error
     842                error = GENOPER_REPAIR;
     843                errorpos = nerrpos;
     844                return -1;
     845        }
     846        else {
     847                error = GENOPER_REPAIR;
     848                errorpos = nerrpos;
     849                repair_parent = parent;
     850                repair_insert = insert;
     851                return 0;
     852        }
    860853}
    861854
    862855void f4_Cells::repairGeno(f4_node * geno, int whichchild)
    863856{
    864   // assemble repaired geno, if the case
    865   if (!repair) return;
    866   if ((NULL==repair_remove) && (NULL==repair_insert)) return;
    867   // traverse genotype tree, remove / insert node
    868   f4_node * g2;
    869   if (1==whichchild) g2 = geno->child;
    870     else             g2 = geno->child2;
    871   if (NULL == g2)
    872     return;
    873   if (g2 == repair_remove) {
    874     f4_node * oldgeno;
    875     geno->removeChild(g2);
    876     if (g2->child) {
    877       // add g2->child as child to geno
    878       if (1==whichchild) geno->child = g2->child;
    879         else             geno->child2 = g2->child;
    880       g2->child->parent = geno;
    881     }
    882     oldgeno = g2;
    883     oldgeno->child = NULL;
    884     delete oldgeno;
    885     if (NULL == geno->child) return;
    886     // check this new
    887     repairGeno(geno, whichchild);
    888     return;
    889   }
    890   if (g2 == repair_parent) {
    891     geno->removeChild(g2);
    892     geno->addChild(repair_insert);
    893     repair_insert->parent = geno;
    894     repair_insert->child = g2;
    895     repair_insert->child2 = NULL;
    896     g2->parent = repair_insert;
    897   }
    898   // recurse
    899   if (g2->child)  repairGeno(g2, 1);
    900   if (g2->child2) repairGeno(g2, 2);
     857        // assemble repaired geno, if the case
     858        if (!repair) return;
     859        if ((NULL == repair_remove) && (NULL == repair_insert)) return;
     860        // traverse genotype tree, remove / insert node
     861        f4_node * g2;
     862        if (1 == whichchild) g2 = geno->child;
     863        else             g2 = geno->child2;
     864        if (NULL == g2)
     865                return;
     866        if (g2 == repair_remove) {
     867                f4_node * oldgeno;
     868                geno->removeChild(g2);
     869                if (g2->child) {
     870                        // add g2->child as child to geno
     871                        if (1 == whichchild) geno->child = g2->child;
     872                        else             geno->child2 = g2->child;
     873                        g2->child->parent = geno;
     874                }
     875                oldgeno = g2;
     876                oldgeno->child = NULL;
     877                delete oldgeno;
     878                if (NULL == geno->child) return;
     879                // check this new
     880                repairGeno(geno, whichchild);
     881                return;
     882        }
     883        if (g2 == repair_parent) {
     884                geno->removeChild(g2);
     885                geno->addChild(repair_insert);
     886                repair_insert->parent = geno;
     887                repair_insert->child = g2;
     888                repair_insert->child2 = NULL;
     889                g2->parent = repair_insert;
     890        }
     891        // recurse
     892        if (g2->child)  repairGeno(g2, 1);
     893        if (g2->child2) repairGeno(g2, 2);
    901894}
    902895
     
    904897void f4_Cells::toF1Geno(SString &out)
    905898{
    906   if (tmpcel) delete tmpcel;
    907   tmpcel = new f4_Cell(-1, NULL, 0, stdProps);
    908   out = "";
    909   toF1GenoRec(0, out);
    910   delete tmpcel;
     899        if (tmpcel) delete tmpcel;
     900        tmpcel = new f4_Cell(-1, NULL, 0, stdProps);
     901        out = "";
     902        toF1GenoRec(0, out);
     903        delete tmpcel;
    911904}
    912905
     
    914907void f4_Cells::toF1GenoRec(int curc, SString &out)
    915908{
    916   int i, j, ccount;
    917   f4_Cell * thisti;
    918   f4_Cell * thneu;
    919   char buf[200];
    920 
    921   if (curc >= nc) return;
    922 
    923   if (T_STICK4 != C[curc]->type) return;
    924 
    925   thisti = C[curc];
    926   if (NULL != thisti->dadlink) 
    927     *tmpcel = *(thisti->dadlink);
    928 
    929   // adjust length, curvedness, etc.
    930   tmpcel->P.adjust();
    931   while (tmpcel->P.len > thisti->P.len)
    932   {
    933     tmpcel->P.executeModifier('l');
    934     out += "l";
    935   }
    936   while (tmpcel->P.len < thisti->P.len)
    937   {
    938     tmpcel->P.executeModifier('L');
    939     out += "L";
    940   }
    941   while (tmpcel->P.curv > thisti->P.curv)
    942   {
    943     tmpcel->P.executeModifier('c');
    944     out += "c";
    945   }
    946   while (tmpcel->P.curv < thisti->P.curv)
    947   {
    948     tmpcel->P.executeModifier('C');
    949     out += "C";
    950   }
    951   while (thisti->rolling > 0.0f) {
    952     rolling_dec( &(thisti->rolling) );
    953     out += "R";
    954   }
    955   while (thisti->rolling < 0.0f) {
    956     rolling_inc( &(thisti->rolling) );
    957     out += "r";
    958   }
    959 
    960   // output X for this stick
    961   out += "X";
    962 
    963   // neurons attached to it
    964   for (i=0; i<nc; i++)
    965     if (C[i]->type == T_NEURON4) {
    966       if (C[i]->dadlink == thisti) {
    967         thneu = C[i];
    968         out += "[";
    969         // ctrl
    970         if (1 == thneu->ctrl) out += "@";
    971         if (2 == thneu->ctrl) out += "|";
    972         // links
    973         for (j=0; j<thneu->nolink; j++)
    974         {
    975           if (j) out += ",";
    976           if (NULL == thneu->links[j]->from)
    977           {
    978             // sensory
    979             if (1 == thneu->links[j]->t) out += "*";
    980             if (2 == thneu->links[j]->t) out += "G";
    981             if (3 == thneu->links[j]->t) out += "T";
    982             if (4 == thneu->links[j]->t) out += "S";
    983           } else {
    984             sprintf(buf, "%d", thneu->links[j]->from->name - thneu->name);
    985             out += buf;
    986           }
    987           out += ":";
    988           // weight
    989           sprintf(buf, "%g", thneu->links[j]->w );
    990           out += buf;
    991         }
    992         out += "]";
    993     }
    994   }
    995 
    996   // sticks connected to it
    997   if (thisti->commacount>=2)
    998     out += "(";
    999 
    1000   ccount=1;
    1001   for (i=0; i<nc; i++)
    1002    if (C[i]->type == T_STICK4)
    1003     if (C[i]->dadlink == thisti) {
    1004       while (ccount < (C[i])->anglepos) {
    1005         ccount++;
    1006         out += ",";
    1007       }
    1008       toF1GenoRec(i, out);
    1009   }
    1010   while (ccount < thisti->commacount) {
    1011     ccount++;
    1012     out += ",";
    1013   }
    1014 
    1015   if (thisti->commacount >= 2)
    1016     out += ")";
     909        int i, j, ccount;
     910        f4_Cell * thisti;
     911        f4_Cell * thneu;
     912        char buf[200];
     913
     914        if (curc >= nc) return;
     915
     916        if (T_STICK4 != C[curc]->type) return;
     917
     918        thisti = C[curc];
     919        if (NULL != thisti->dadlink)
     920                *tmpcel = *(thisti->dadlink);
     921
     922        // adjust length, curvedness, etc.
     923        tmpcel->P.adjust();
     924        while (tmpcel->P.len > thisti->P.len)
     925        {
     926                tmpcel->P.executeModifier('l');
     927                out += "l";
     928        }
     929        while (tmpcel->P.len < thisti->P.len)
     930        {
     931                tmpcel->P.executeModifier('L');
     932                out += "L";
     933        }
     934        while (tmpcel->P.curv > thisti->P.curv)
     935        {
     936                tmpcel->P.executeModifier('c');
     937                out += "c";
     938        }
     939        while (tmpcel->P.curv < thisti->P.curv)
     940        {
     941                tmpcel->P.executeModifier('C');
     942                out += "C";
     943        }
     944        while (thisti->rolling > 0.0f) {
     945                rolling_dec(&(thisti->rolling));
     946                out += "R";
     947        }
     948        while (thisti->rolling < 0.0f) {
     949                rolling_inc(&(thisti->rolling));
     950                out += "r";
     951        }
     952
     953        // output X for this stick
     954        out += "X";
     955
     956        // neurons attached to it
     957        for (i = 0; i < nc; i++)
     958                if (C[i]->type == T_NEURON4) {
     959                        if (C[i]->dadlink == thisti) {
     960                                thneu = C[i];
     961                                out += "[";
     962                                // ctrl
     963                                if (1 == thneu->ctrl) out += "@";
     964                                if (2 == thneu->ctrl) out += "|";
     965                                // links
     966                                for (j = 0; j < thneu->nolink; j++)
     967                                {
     968                                        if (j) out += ",";
     969                                        if (NULL == thneu->links[j]->from)
     970                                        {
     971                                                // sensory
     972                                                if (1 == thneu->links[j]->t) out += "*";
     973                                                if (2 == thneu->links[j]->t) out += "G";
     974                                                if (3 == thneu->links[j]->t) out += "T";
     975                                                if (4 == thneu->links[j]->t) out += "S";
     976                                        }
     977                                        else {
     978                                                sprintf(buf, "%d", thneu->links[j]->from->name - thneu->name);
     979                                                out += buf;
     980                                        }
     981                                        out += ":";
     982                                        // weight
     983                                        sprintf(buf, "%g", thneu->links[j]->w);
     984                                        out += buf;
     985                                }
     986                                out += "]";
     987                        }
     988                }
     989
     990        // sticks connected to it
     991        if (thisti->commacount >= 2)
     992                out += "(";
     993
     994        ccount = 1;
     995        for (i = 0; i < nc; i++)
     996                if (C[i]->type == T_STICK4)
     997                        if (C[i]->dadlink == thisti) {
     998                                while (ccount < (C[i])->anglepos) {
     999                                        ccount++;
     1000                                        out += ",";
     1001                                }
     1002                                toF1GenoRec(i, out);
     1003                        }
     1004        while (ccount < thisti->commacount) {
     1005                ccount++;
     1006                out += ",";
     1007        }
     1008
     1009        if (thisti->commacount >= 2)
     1010                out += ")";
    10171011}
    10181012
     
    10231017f4_node::f4_node()
    10241018{
    1025   name  = '?';
    1026   parent = NULL;
    1027   child = NULL;
    1028   child2 = NULL;
    1029   pos    = -1;
     1019        name = '?';
     1020        parent = NULL;
     1021        child = NULL;
     1022        child2 = NULL;
     1023        pos = -1;
    10301024}
    10311025
    10321026f4_node::f4_node(char nname, f4_node * nparent, int npos)
    10331027{
    1034   name  = nname;
    1035   parent = nparent;
    1036   child = NULL;
    1037   child2 = NULL;
    1038   pos    = npos;
    1039   if (parent) parent->addChild(this);
     1028        name = nname;
     1029        parent = nparent;
     1030        child = NULL;
     1031        child2 = NULL;
     1032        pos = npos;
     1033        if (parent) parent->addChild(this);
    10401034}
    10411035
    10421036f4_node::~f4_node()
    10431037{
    1044   // (destroy() copied here for efficiency)
    1045   // children are destroyed (recursively) through the destructor
    1046   if (NULL != child2)  delete child2;
    1047   if (NULL != child)   delete child;
     1038        // (destroy() copied here for efficiency)
     1039        // children are destroyed (recursively) through the destructor
     1040        if (NULL != child2)  delete child2;
     1041        if (NULL != child)   delete child;
    10481042}
    10491043
    10501044int f4_node::addChild(f4_node * nchi)
    10511045{
    1052   if (NULL==child) {
    1053     child = nchi;
    1054     return 0;
    1055   }
    1056   if (NULL==child2) {
    1057     child2 = nchi;
    1058     return 0;
    1059   }
    1060   return -1;
     1046        if (NULL == child) {
     1047                child = nchi;
     1048                return 0;
     1049        }
     1050        if (NULL == child2) {
     1051                child2 = nchi;
     1052                return 0;
     1053        }
     1054        return -1;
    10611055}
    10621056
    10631057int f4_node::removeChild(f4_node * nchi)
    10641058{
    1065   if (nchi==child2) {
    1066     child2 = NULL;
    1067     return 0;
    1068   }
    1069   if (nchi==child) {
    1070     child = NULL;
    1071     return 0;
    1072   }
    1073   return -1;
     1059        if (nchi == child2) {
     1060                child2 = NULL;
     1061                return 0;
     1062        }
     1063        if (nchi == child) {
     1064                child = NULL;
     1065                return 0;
     1066        }
     1067        return -1;
    10741068}
    10751069
    10761070int f4_node::childCount()
    10771071{
    1078   if (NULL!=child) {
    1079     if (NULL!=child2) return 2;
    1080                  else return 1;
    1081   } else {
    1082     if (NULL!=child2) return 1;
    1083                  else return 0;
    1084   }
     1072        if (NULL != child) {
     1073                if (NULL != child2) return 2;
     1074                else return 1;
     1075        }
     1076        else {
     1077                if (NULL != child2) return 1;
     1078                else return 0;
     1079        }
    10851080}
    10861081
    10871082int f4_node::count()
    10881083{
    1089   int c=1;
    1090   if (NULL!=child)  c+=child->count();
    1091   if (NULL!=child2) c+=child2->count();
    1092   return c;
     1084        int c = 1;
     1085        if (NULL != child)  c += child->count();
     1086        if (NULL != child2) c += child2->count();
     1087        return c;
    10931088}
    10941089
    10951090f4_node * f4_node::ordNode(int n)
    10961091{
    1097   int n1;
    1098   if (0 == n) return this;
    1099   n--;
    1100   if (NULL != child) {
    1101     n1 = child->count();
    1102     if (n<n1) return child->ordNode(n);
    1103     n -= n1;
    1104   }
    1105   if (NULL != child2) {
    1106     n1 = child2->count();
    1107     if (n<n1) return child2->ordNode(n);
    1108     n -= n1;
    1109   }
    1110   return NULL;
     1092        int n1;
     1093        if (0 == n) return this;
     1094        n--;
     1095        if (NULL != child) {
     1096                n1 = child->count();
     1097                if (n < n1) return child->ordNode(n);
     1098                n -= n1;
     1099        }
     1100        if (NULL != child2) {
     1101                n1 = child2->count();
     1102                if (n < n1) return child2->ordNode(n);
     1103                n -= n1;
     1104        }
     1105        return NULL;
    11111106}
    11121107
    11131108f4_node * f4_node::randomNode()
    11141109{
    1115   int n, i;
    1116   n = count();
    1117   // pick a random node, between 0 and n-1
    1118   i = (int)( ((float)n-0.0001) / RAND_MAX * rand());
    1119   return ordNode(i);
     1110        int n = count();
     1111        // pick a random node, between 0 and n-1
     1112        return ordNode(randomN(n));
    11201113}
    11211114
    11221115f4_node * f4_node::randomNodeWithSize(int min, int max)
    11231116{
    1124   // try random nodes, and accept if size in range
    1125   // limit to maxlim tries
    1126   int i, n, maxlim;
    1127   f4_node * nod = NULL;
    1128   maxlim = count();
    1129   for (i=0; i<maxlim; i++) {
    1130     nod = randomNode();
    1131     n = nod->count();
    1132     if ((n>=min) && (n<=max)) return nod;
    1133   }
    1134   // failed, doesn't matter
    1135   return nod;
     1117        // try random nodes, and accept if size in range
     1118        // limit to maxlim tries
     1119        int i, n, maxlim;
     1120        f4_node * nod = NULL;
     1121        maxlim = count();
     1122        for (i = 0; i < maxlim; i++) {
     1123                nod = randomNode();
     1124                n = nod->count();
     1125                if ((n >= min) && (n <= max)) return nod;
     1126        }
     1127        // failed, doesn't matter
     1128        return nod;
    11361129}
    11371130
    11381131void f4_node::sprint(SString & out)
    11391132{
    1140   char buf2[20];
    1141   // special case: repetition code
    1142   if ('#' == name)
    1143   {
    1144     out += "#";
    1145     if (i1 != 1) {
    1146       sprintf(buf2, "%d", i1);
    1147       out += buf2;
    1148     }
    1149   } else {
    1150   // special case: neuron link
    1151   if ('[' == name) {
    1152     out += "[";
    1153     if (i1>0) {
    1154       // sensor input
    1155       if (1==i1) out += "*";
    1156       if (2==i1) out += "G";
    1157       if (3==i1) out += "T";
    1158       if (4==i1) out += "S";
    1159     } else {
    1160       sprintf(buf2, "%ld", l1);
    1161       out += buf2;
    1162     }
    1163     sprintf(buf2, ":%g]", f1);
    1164     out += buf2;
    1165   } else if (':' == name) {
    1166     sprintf(buf2, ":%c%c:", l1 ? '+' : '-', (char)i1);
    1167     out += buf2;
    1168   } else {
    1169     buf2[0] = name;
    1170     buf2[1] = 0;
    1171     out += buf2;
    1172   }}
    1173   if (NULL != child)     child->sprint(out);
    1174   // if two children, make sure last char is a '>'
    1175   if (2 == childCount())
    1176     if (0 == out[0]) out += ">"; else
    1177       if ('>' != out[out.len()-1]) out += ">";
    1178   if (NULL != child2)    child2->sprint(out);
    1179   // make sure last char is a '>'
    1180   if (0 == out[0]) out += ">"; else
    1181     if ('>' != out[out.len()-1]) out += ">";
     1133        char buf2[20];
     1134        // special case: repetition code
     1135        if ('#' == name)
     1136        {
     1137                out += "#";
     1138                if (i1 != 1) {
     1139                        sprintf(buf2, "%d", i1);
     1140                        out += buf2;
     1141                }
     1142        }
     1143        else {
     1144                // special case: neuron link
     1145                if ('[' == name) {
     1146                        out += "[";
     1147                        if (i1 > 0) {
     1148                                // sensor input
     1149                                if (1 == i1) out += "*";
     1150                                if (2 == i1) out += "G";
     1151                                if (3 == i1) out += "T";
     1152                                if (4 == i1) out += "S";
     1153                        }
     1154                        else {
     1155                                sprintf(buf2, "%ld", l1);
     1156                                out += buf2;
     1157                        }
     1158                        sprintf(buf2, ":%g]", f1);
     1159                        out += buf2;
     1160                }
     1161                else if (':' == name) {
     1162                        sprintf(buf2, ":%c%c:", l1 ? '+' : '-', (char)i1);
     1163                        out += buf2;
     1164                }
     1165                else {
     1166                        buf2[0] = name;
     1167                        buf2[1] = 0;
     1168                        out += buf2;
     1169                }
     1170        }
     1171        if (NULL != child)     child->sprint(out);
     1172        // if two children, make sure last char is a '>'
     1173        if (2 == childCount())
     1174                if (0 == out[0]) out += ">"; else
     1175                        if ('>' != out[out.len() - 1]) out += ">";
     1176        if (NULL != child2)    child2->sprint(out);
     1177        // make sure last char is a '>'
     1178        if (0 == out[0]) out += ">"; else
     1179                if ('>' != out[out.len() - 1]) out += ">";
    11821180}
    11831181
    11841182void f4_node::sprintAdj(char *& buf)
    11851183{
    1186   unsigned int len;
    1187   // build in a SString, with initial size
    1188   SString out(strlen(buf)+2000);
    1189   out="";
    1190 
    1191   sprint(out);
    1192 
    1193   // very last '>' can be omitted
    1194   len = out.len();
    1195   if (len>1)
    1196     if ('>' == out[len-1]) { (out.directWrite())[len-1]=0; out.endWrite();};
    1197   // copy back to string
    1198   // if new is longer, reallocate buf
    1199   if (len+1 > strlen(buf)) {
    1200     buf = (char*) realloc(buf, len+1 );
    1201   }
    1202   strcpy(buf, (const char*) out);
     1184        unsigned int len;
     1185        // build in a SString, with initial size
     1186        SString out(strlen(buf) + 2000);
     1187        out = "";
     1188
     1189        sprint(out);
     1190
     1191        // very last '>' can be omitted
     1192        len = out.len();
     1193        if (len > 1)
     1194                if ('>' == out[len - 1]) { (out.directWrite())[len - 1] = 0; out.endWrite(); };
     1195        // copy back to string
     1196        // if new is longer, reallocate buf
     1197        if (len + 1 > strlen(buf)) {
     1198                buf = (char*)realloc(buf, len + 1);
     1199        }
     1200        strcpy(buf, (const char*)out);
    12031201}
    12041202
    12051203f4_node * f4_node::duplicate()
    12061204{
    1207   f4_node * copy;
    1208   copy = new f4_node(*this);
    1209   copy->parent = NULL;  // set later
    1210   copy->child = NULL;
    1211   copy->child2 = NULL;
    1212   if (NULL != child ) {
    1213     copy->child  = child ->duplicate();
    1214     copy->child ->parent = copy;
    1215   }
    1216   if (NULL != child2 ) {
    1217     copy->child2 = child2->duplicate();
    1218     copy->child2->parent = copy;
    1219   }
    1220   return copy;
     1205        f4_node * copy;
     1206        copy = new f4_node(*this);
     1207        copy->parent = NULL;  // set later
     1208        copy->child = NULL;
     1209        copy->child2 = NULL;
     1210        if (NULL != child) {
     1211                copy->child = child->duplicate();
     1212                copy->child->parent = copy;
     1213        }
     1214        if (NULL != child2) {
     1215                copy->child2 = child2->duplicate();
     1216                copy->child2->parent = copy;
     1217        }
     1218        return copy;
    12211219}
    12221220
     
    12241222void f4_node::destroy()
    12251223{
    1226   // children are destroyed (recursively) through the destructor
    1227   if (NULL != child2)  delete child2;
    1228   if (NULL != child)   delete child;
     1224        // children are destroyed (recursively) through the destructor
     1225        if (NULL != child2)  delete child2;
     1226        if (NULL != child)   delete child;
    12291227}
    12301228
     
    12341232int f4_processrec(const char * genot, unsigned pos0, f4_node * parent)
    12351233{
    1236   int i, j, t, res;
    1237   char tc1, tc2;
    1238   long relfrom;
    1239   double w;
    1240   unsigned gpos, oldpos;
    1241   f4_node * node1, * par;
    1242 
    1243   gpos = pos0;
    1244   par = parent;
    1245   if (gpos >= strlen(genot) ) return 1;
    1246   while (gpos<strlen(genot)) {
    1247     //DB( printf(" processing '%c' %d %s\n", genot[gpos], gpos, genot); )
    1248     switch (genot[gpos]) {
    1249     case '<':
    1250       // cell division!
    1251       //DB( printf("  div! %d\n", name); )
    1252 
    1253       // find out genotype start for child
    1254       j = scanrec(genot+gpos+1, strlen(genot+gpos+1), '>');
    1255 
    1256       node1 = new f4_node('<', par, gpos);
    1257       par = node1;
    1258       res = f4_processrec(genot, gpos+1,   par);
    1259       if (res) return res;
    1260       if (gpos+j+2 < strlen(genot)) {
    1261         res = f4_processrec(genot, gpos+j+2, par);
    1262         if (res) return res;
    1263       } else {  // ran out
    1264         node1 = new f4_node('>', par, strlen(genot)-1 );
    1265         par = node1;
    1266       }
    1267       // adjustments
    1268       gpos++;
    1269       return 0;  // OK
    1270 
    1271     case '>':
    1272       node1 = new f4_node('>', par, gpos );
    1273       par = node1;
    1274       gpos = strlen(genot);
    1275       return 0;  // OK
    1276 
    1277     case '#':
    1278       // repetition marker, 1 by default
    1279       if (sscanf(genot+gpos, "#%d", &i) != 1) i=1;
    1280       // find out genotype start for continuation
    1281       j = scanrec(genot+gpos+1, strlen(genot+gpos+1), '>');
    1282       // skip number
    1283       oldpos = gpos;
    1284       gpos++;
    1285       while ((genot[gpos]>='0') && (genot[gpos]<='9')) gpos++;
    1286       node1 = new f4_node('#', par, oldpos );
    1287       node1->i1 = i;
    1288       par = node1;
    1289       res = f4_processrec(genot, gpos,   node1);
    1290       if (res) return res;
    1291       if (oldpos+j+2 < strlen(genot) ) {
    1292         res = f4_processrec(genot, oldpos+j+2, node1);
    1293         if (res) return res;
    1294       } else {  // ran out
    1295         node1 = new f4_node('>', par, strlen(genot)-1 );
    1296       }
    1297       return 0;  // OK
    1298 
    1299     // 'simple' nodes:
    1300     case ',':
    1301     case 'l':  case 'L':
    1302     case 'c':  case 'C':
    1303     case 'q':  case 'Q':
    1304     case 'r':  case 'R':
    1305     case 'X':  case 'N':
    1306     case '@':  case '|':
    1307     case 'a':  case 'A':
    1308     case 's':  case 'S':
    1309     case 'm':  case 'M':
    1310     case 'i':  case 'I':
    1311     case 'f':  case 'F':
    1312     case 'w':  case 'W':
    1313     case 'e':  case 'E':
    1314       node1 = new f4_node(genot[gpos], par, gpos );
    1315       par = node1;
    1316       gpos++;
    1317       break;
    1318 
    1319     case '[':
    1320       // link to neuron
    1321       // input (%d, '*', 'G', 'T', 'S')
    1322       t = -1;
    1323       if (sscanf(genot+gpos, "[%ld:%lf]", &relfrom, &w) == 2) t=0;
    1324       else if (sscanf(genot+gpos, "[*:%lf]", &w) == 1) t=1;
    1325       else if (sscanf(genot+gpos, "[G:%lf]", &w) == 1) t=2;
    1326       else if (sscanf(genot+gpos, "[T:%lf]", &w) == 1) t=3;
    1327       else if (sscanf(genot+gpos, "[S:%lf]", &w) == 1) t=4;
    1328       // error: no correct format
    1329       if (t<0) return gpos+1+1;
    1330       node1 = new f4_node('[', par, gpos );
    1331       node1->i1 = t;
    1332       node1->l1 = relfrom;
    1333       node1->f1 = w;
    1334       par = node1;
    1335       j = scanrec(genot+gpos+1, strlen(genot+gpos+1), ']');
    1336       gpos += j+2;
    1337       break;
    1338 
    1339     case ':':
    1340       // neuron parameter  +! -! += -= +/ or -/
    1341       if (sscanf(genot+gpos, ":%c%c:", &tc1, &tc2) != 2)
    1342         // error: incorrect format
    1343         return gpos+1+1;
    1344       if ('+' == tc1) j=1;
    1345       else if ('-' == tc1) j=0;
    1346       else return gpos+1+1;
    1347       switch (tc2) {
    1348        case '!':  case '=':  case '/':  break;
    1349        default:
    1350         return gpos+1+1;
    1351       }
    1352       node1 = new f4_node(':', par, gpos );
    1353       node1->l1 = j;
    1354       node1->i1 = (int)tc2;
    1355       par = node1;
    1356       j = scanrec(genot+gpos+1, strlen(genot+gpos+1), ':');
    1357       gpos += j+2;
    1358       break;
    1359 
    1360     case ' ':
    1361     case '\n':
    1362     case '\t':
    1363       // whitespace: ignore
    1364       //node1 = new f4_node(' ', par, gpos );
    1365       //par = node1;
    1366       gpos++;
    1367       break;
    1368 
    1369     default:
    1370       //DB( printf("unknown character '%c' ! \n", genot[gpos]); )
    1371       //add it, build will give the error or repair
    1372       node1 = new f4_node(genot[gpos], par, gpos );
    1373       par = node1;
    1374       gpos++;
    1375       break;
    1376     }
    1377   }
    1378   // should end with a '>'
    1379   if (par)
    1380     if ('>' != par->name) {
    1381       node1 = new f4_node('>', par, strlen(genot)-1 );
    1382       par = node1;
    1383   }
    1384   return 0;  // OK
     1234        int i, j, t, res;
     1235        char tc1, tc2;
     1236        long relfrom;
     1237        double w;
     1238        unsigned gpos, oldpos;
     1239        f4_node * node1, *par;
     1240
     1241        gpos = pos0;
     1242        par = parent;
     1243        if (gpos >= strlen(genot)) return 1;
     1244        while (gpos < strlen(genot)) {
     1245                //DB( printf(" processing '%c' %d %s\n", genot[gpos], gpos, genot); )
     1246                switch (genot[gpos]) {
     1247                case '<':
     1248                        // cell division!
     1249                        //DB( printf("  div! %d\n", name); )
     1250
     1251                        // find out genotype start for child
     1252                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), '>');
     1253
     1254                        node1 = new f4_node('<', par, gpos);
     1255                        par = node1;
     1256                        res = f4_processrec(genot, gpos + 1, par);
     1257                        if (res) return res;
     1258                        if (gpos + j + 2 < strlen(genot)) {
     1259                                res = f4_processrec(genot, gpos + j + 2, par);
     1260                                if (res) return res;
     1261                        }
     1262                        else {  // ran out
     1263                                node1 = new f4_node('>', par, strlen(genot) - 1);
     1264                                par = node1;
     1265                        }
     1266                        // adjustments
     1267                        gpos++;
     1268                        return 0;  // OK
     1269
     1270                case '>':
     1271                        node1 = new f4_node('>', par, gpos);
     1272                        par = node1;
     1273                        gpos = strlen(genot);
     1274                        return 0;  // OK
     1275
     1276                case '#':
     1277                        // repetition marker, 1 by default
     1278                        if (sscanf(genot + gpos, "#%d", &i) != 1) i = 1;
     1279                        // find out genotype start for continuation
     1280                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), '>');
     1281                        // skip number
     1282                        oldpos = gpos;
     1283                        gpos++;
     1284                        while ((genot[gpos] >= '0') && (genot[gpos] <= '9')) gpos++;
     1285                        node1 = new f4_node('#', par, oldpos);
     1286                        node1->i1 = i;
     1287                        par = node1;
     1288                        res = f4_processrec(genot, gpos, node1);
     1289                        if (res) return res;
     1290                        if (oldpos + j + 2 < strlen(genot)) {
     1291                                res = f4_processrec(genot, oldpos + j + 2, node1);
     1292                                if (res) return res;
     1293                        }
     1294                        else {  // ran out
     1295                                node1 = new f4_node('>', par, strlen(genot) - 1);
     1296                        }
     1297                        return 0;  // OK
     1298
     1299                        // 'simple' nodes:
     1300                case ',':
     1301                case 'l':  case 'L':
     1302                case 'c':  case 'C':
     1303                case 'q':  case 'Q':
     1304                case 'r':  case 'R':
     1305                case 'X':  case 'N':
     1306                case '@':  case '|':
     1307                case 'a':  case 'A':
     1308                case 's':  case 'S':
     1309                case 'm':  case 'M':
     1310                case 'i':  case 'I':
     1311                case 'f':  case 'F':
     1312                case 'w':  case 'W':
     1313                case 'e':  case 'E':
     1314                        node1 = new f4_node(genot[gpos], par, gpos);
     1315                        par = node1;
     1316                        gpos++;
     1317                        break;
     1318
     1319                case '[':
     1320                        // link to neuron
     1321                        // input (%d, '*', 'G', 'T', 'S')
     1322                        t = -1;
     1323                        if (sscanf(genot + gpos, "[%ld:%lf]", &relfrom, &w) == 2) t = 0;
     1324                        else if (sscanf(genot + gpos, "[*:%lf]", &w) == 1) t = 1;
     1325                        else if (sscanf(genot + gpos, "[G:%lf]", &w) == 1) t = 2;
     1326                        else if (sscanf(genot + gpos, "[T:%lf]", &w) == 1) t = 3;
     1327                        else if (sscanf(genot + gpos, "[S:%lf]", &w) == 1) t = 4;
     1328                        // error: no correct format
     1329                        if (t < 0) return gpos + 1 + 1;
     1330                        node1 = new f4_node('[', par, gpos);
     1331                        node1->i1 = t;
     1332                        node1->l1 = relfrom;
     1333                        node1->f1 = w;
     1334                        par = node1;
     1335                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ']');
     1336                        gpos += j + 2;
     1337                        break;
     1338
     1339                case ':':
     1340                        // neuron parameter  +! -! += -= +/ or -/
     1341                        if (sscanf(genot + gpos, ":%c%c:", &tc1, &tc2) != 2)
     1342                                // error: incorrect format
     1343                                return gpos + 1 + 1;
     1344                        if ('+' == tc1) j = 1;
     1345                        else if ('-' == tc1) j = 0;
     1346                        else return gpos + 1 + 1;
     1347                        switch (tc2) {
     1348                        case '!':  case '=':  case '/':  break;
     1349                        default:
     1350                                return gpos + 1 + 1;
     1351                        }
     1352                        node1 = new f4_node(':', par, gpos);
     1353                        node1->l1 = j;
     1354                        node1->i1 = (int)tc2;
     1355                        par = node1;
     1356                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ':');
     1357                        gpos += j + 2;
     1358                        break;
     1359
     1360                case ' ':
     1361                case '\n':
     1362                case '\t':
     1363                        // whitespace: ignore
     1364                        //node1 = new f4_node(' ', par, gpos );
     1365                        //par = node1;
     1366                        gpos++;
     1367                        break;
     1368
     1369                default:
     1370                        //DB( printf("unknown character '%c' ! \n", genot[gpos]); )
     1371                        //add it, build will give the error or repair
     1372                        node1 = new f4_node(genot[gpos], par, gpos);
     1373                        par = node1;
     1374                        gpos++;
     1375                        break;
     1376                }
     1377        }
     1378        // should end with a '>'
     1379        if (par)
     1380                if ('>' != par->name) {
     1381                        node1 = new f4_node('>', par, strlen(genot) - 1);
     1382                        par = node1;
     1383                }
     1384        return 0;  // OK
    13851385}
    13861386
     
    13881388f4_node * f4_processtree(const char * geno)
    13891389{
    1390   f4_node * root;
    1391   int res;
    1392   root = new f4_node();
    1393   res = f4_processrec(geno, 0, root);
    1394   if (res) return NULL;
    1395   //DB( printf("test f4  "); )
    1396   DB(
    1397     if (root->child) {
    1398       char * buf = (char*) malloc( 300 );
    1399       DB( printf("(%d) ", root->child->count() ); )
    1400       buf[0]=0;
    1401       root->child->sprintAdj(buf);
    1402       DB( printf("%s\n", buf); )
    1403       free(buf);
    1404     }
    1405   )
    1406   return root->child;
    1407 }
    1408 
     1390        f4_node * root;
     1391        int res;
     1392        root = new f4_node();
     1393        res = f4_processrec(geno, 0, root);
     1394        if (res) return NULL;
     1395        //DB( printf("test f4  "); )
     1396        DB(
     1397                if (root->child) {
     1398                        char * buf = (char*)malloc(300);
     1399                        DB(printf("(%d) ", root->child->count());)
     1400                                buf[0] = 0;
     1401                        root->child->sprintAdj(buf);
     1402                        DB(printf("%s\n", buf);)
     1403                                free(buf);
     1404                }
     1405        )
     1406                return root->child;
     1407}
  • cpp/frams/genetics/f4/f4_general.h

    r193 r196  
    1 /*
    2  *  f4_general.h - f4 genotype functions.
    3  *
    4  *  f4genotype - f4 format genotype conversions for FramSticks
    5  *
    6  *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
    7  *
    8  *  This library is free software; you can redistribute it and/or
    9  *  modify it under the terms of the GNU Lesser General Public
    10  *  License as published by the Free Software Foundation; either
    11  *  version 2.1 of the License, or (at your option) any later version.
    12  *
    13  *  This library is distributed in the hope that it will be useful,
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16  *  Lesser General Public License for more details.
    17  *
    18  *  You should have received a copy of the GNU Lesser General Public
    19  *  License along with this library; if not, write to the Free Software
    20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    21  *
    22  */
     1// This file is a part of the Framsticks GDK.
     2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
     3// Refer to http://www.framsticks.com/ for further information.
     4
     5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
    236
    247#ifndef _F4_GENERAL_H_
    258#define _F4_GENERAL_H_
    269
    27 #include "f4_orientmat.h"
    28 #include "3d.h"
    29 #include "sstring.h"
    30 #include "multirange.h"
     10//#include "f4_orientmat.h"
     11#include <frams/util/3d.h>
     12#include <frams/util/sstring.h>
     13#include <frams/util/multirange.h>
    3114
    3215#ifdef DMALLOC
     
    3720class f4_Props
    3821{
    39  public:
    40   // fill with default values
    41   f4_Props();
    42   // must sum to 1
    43   void normalizeBiol4();
    44   void executeModifier(char modif);
    45   void adjust();
    46 
    47   double len;      // length (dlug)
    48   double curv;     // curvedness (skr)
    49   double mass;
    50   double friction;
    51   double ruch;
    52   double assim;
    53   double odpor;
    54   double ingest;  // ingestion (wchl)
    55   double twist;
    56   double energ;
     22public:
     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 len;      // length (dlug)
     31        double curv;     // curvedness (skr)
     32        double mass;
     33        double friction;
     34        double ruch;
     35        double assim;
     36        double odpor;
     37        double ingest;  // ingestion (wchl)
     38        double twist;
     39        double energ;
    5740};
    5841
     
    8568{
    8669public:
    87   class repeat_ptr
    88   {
    89    public:
    90     repeat_ptr() : node(NULL), count(-1) { };
    91     repeat_ptr(f4_node * a, int b) : node(a), count(b) { };
    92     inline void null() { node = NULL; count = -1; };
    93     inline bool isNull() const { return ((node == NULL) || (count <= 0)); };
    94     inline void dec() { count--; };
    95     f4_node *  node;  // ptr to repetition code
    96     char       count; // repetition counter
    97   };
    98 
    99   class repeat_stack  // a stack of repet_ptr's
    100   {
    101    public:
    102     repeat_stack() { top=0; };
    103     inline void null() { top=0; };
    104     inline void push(repeat_ptr A) { if (top>=stackSize) return; ptr[top]=A; top++; };
    105     inline void pop() { if (top>0) top--; };
    106     inline repeat_ptr * first() { return &(ptr[top-(top>0)]); };
    107     static const int stackSize = 4;  // max 4 nested levels
    108     repeat_ptr ptr[stackSize];
    109     short int top;  // top of the stack
    110   };
    111 
    112   f4_Cell(int nname,
    113     f4_Cell * ndad, int nangle, f4_Props newP);
    114   f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur,
    115     f4_Cell * ndad, int nangle, f4_Props newP);
    116   ~f4_Cell();
    117 
    118   int onestep();        // execute one simulation step (till a division)
    119 
    120   int   addlink(f4_Cell * nfrom, double nw, long nt);
    121   void  adjustRec();
    122 
    123   int        name;     // name (number)
    124   int        type;     // type
    125   f4_Cell *  dadlink;
    126   f4_Cells * org;       // uplink to organism
    127 
    128   f4_node *  genot;       // genotype
    129   f4_node *  gcur;        // current genotype execution pointer
    130   int        active;      // whether development is still active
    131   repeat_stack repeat;
    132   int        recProcessedFlag;  // used during recursive traverse
    133   // remember the genotype codes affecting this cell so far
    134   MultiRange genoRange;
    135 
    136   f4_Props     P;             // properties
    137   int          anglepos;      // number of position within dad's children (,)
    138   int          childcount;    // number of children
    139   int          commacount;    // number of postitions at lastend (>=childcount)
    140   double       rolling;       // rolling angle ('R') (around x)
    141   double       xrot;
    142   double       zrot;          // horizontal rotation angle due to
    143                               // branching (around z)
    144   //Pt3D         firstend;      // coord.s of first end (connects to parent)
    145   //Pt3D         lastend;       // last end
    146   //f4_OrientMat OM;
    147   double       mz;            // freedom in z
    148   long         p2_refno;   // number of last end part object, used in f0
    149   long         joint_refno;   // number of the joint object, used in f0
    150   long         neuro_refno;   // number of the neuro object, used in f0
    151 
    152   long         ctrl;  // neuron type
    153   double       state;
    154   double       inertia;
    155   double       force;
    156   double       sigmo;
    157   f4_CellLink* links[MAXINPUTS];
    158   int          nolink;
     70        class repeat_ptr
     71        {
     72        public:
     73                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; };
     76                inline bool isNull() const { return ((node == NULL) || (count <= 0)); };
     77                inline void dec() { count--; };
     78                f4_node *  node;  // ptr to repetition code
     79                char       count; // repetition counter
     80        };
     81
     82        class repeat_stack  // a stack of repet_ptr's
     83        {
     84        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
     93        };
     94
     95        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);
     99        ~f4_Cell();
     100
     101        int onestep();  // execute one simulation step (till a division)
     102
     103        int   addlink(f4_Cell * nfrom, double nw, long nt);
     104        void  adjustRec();
     105
     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        long         p2_refno;   // number of last end part object, used in f0
     132        long         joint_refno;   // number of the joint object, used in f0
     133        long         neuro_refno;   // number of the neuro object, used in f0
     134
     135        long         ctrl;  // neuron type
     136        double       state;
     137        double       inertia;
     138        double       force;
     139        double       sigmo;
     140        f4_CellLink* links[MAXINPUTS];
     141        int          nolink;
    159142};
    160143
     
    164147{
    165148public:
    166                f4_CellLink(f4_Cell * nfrom, double nw, long nt);
    167   f4_Cell *    from;
    168   // type: 0: input, 1 '*', 2 'G', 3 'T', 4 'S'
    169   long         t;
    170   double       w;
     149        f4_CellLink(f4_Cell * nfrom, double nw, long nt);
     150        f4_Cell *    from;
     151        // type: 0: input, 1 '*', 2 'G', 3 'T', 4 'S'
     152        long         t;
     153        double       w;
    171154};
    172155
     
    176159class f4_Cells
    177160{
    178  public:
    179   f4_Cells(f4_node * genome, int nrepair);
    180   f4_Cells(SString &genome, int nrepair);
    181   ~f4_Cells();
    182   void addCell(f4_Cell * newcell);
    183   void toF1Geno(SString &out);       // output to f1 format, approximation
    184   int  onestep();       // simulate all parts for one step
    185   int  simulate();      // simulate development, return error (0 for ok)
    186   // for error reporting / genotype fixing
    187   int  geterror() { return error;};
    188   int  geterrorpos() { return errorpos;};
    189   void setError(int nerrpos);
    190   void setRepairRemove(int nerrpos, f4_node * rem);
    191   int  setRepairInsert(int nerrpos, f4_node * parent, f4_node * insert);
    192   void repairGeno(f4_node * geno, int whichchild);
    193 
    194   // the cells
    195   f4_Cell * C[MAX4CELLS];
    196   int       nc;
     161public:
     162        f4_Cells(f4_node * genome, int nrepair);
     163        f4_Cells(SString &genome, int nrepair);
     164        ~f4_Cells();
     165        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
     170        int  geterror() { return error; };
     171        int  geterrorpos() { return errorpos; };
     172        void setError(int nerrpos);
     173        void setRepairRemove(int nerrpos, f4_node * rem);
     174        int  setRepairInsert(int nerrpos, f4_node * parent, f4_node * insert);
     175        void repairGeno(f4_node * geno, int whichchild);
     176
     177        // the cells
     178        f4_Cell * C[MAX4CELLS];
     179        int       nc;
    197180
    198181private:
    199   // for error reporting / genotype fixing
    200   int repair;
    201   int error;
    202   int errorpos;
    203   f4_node * repair_remove;
    204   f4_node * repair_parent;
    205   f4_node * repair_insert;
    206   void toF1GenoRec(int curc, SString &out);
    207   f4_Cell * tmpcel;             // needed by toF1Geno
    208   f4_node * f4rootnode;          // used by constructor
     182        // for error reporting / genotype fixing
     183        int repair;
     184        int error;
     185        int errorpos;
     186        f4_node * repair_remove;
     187        f4_node * repair_parent;
     188        f4_node * repair_insert;
     189        void toF1GenoRec(int curc, SString &out);
     190        f4_Cell * tmpcel;               // needed by toF1Geno
     191        f4_node * f4rootnode;          // used by constructor
    209192};
    210193
     
    216199{
    217200public:
    218   char      name;       // one-letter 'name'
    219   f4_node * parent;     // parent link, or NULL
    220   f4_node * child;      // child, or NULL
    221   f4_node * child2;     // second child, or NULL
    222   int       pos;        // original position in string
    223   int       i1;         // internal int  parameter1
    224   long      l1;         // internal long parameter1
    225   double    f1;         // internal double parameter1
    226 
    227             f4_node();
    228             f4_node(char nname, f4_node * nparent, int npos);
    229             ~f4_node();
    230   int       addChild(f4_node * nchi);
    231   int       removeChild(f4_node * nchi);
    232   int       childCount();       // return no of children, 0, 1, or 2
    233   int       count();    // return no of nodes (recursive)
    234   f4_node * ordNode(int n);     // returns the nth subnode (0-)
    235   f4_node * randomNode();       // returns a random subnode
    236   f4_node * randomNodeWithSize(int min, int max);       // returns a random subnode with given size
    237   void      sprintAdj(char *& buf);     // print recursively
    238   f4_node * duplicate();         // create duplicate copy. recursive.
    239   void      destroy();  // release memory. recursive.
     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        long      l1;           // internal long parameter1
     208        double    f1;           // internal double parameter1
     209
     210        f4_node();
     211        f4_node(char nname, f4_node * nparent, int npos);
     212        ~f4_node();
     213        int       addChild(f4_node * nchi);
     214        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.
    240223private:
    241   void     sprint(SString & out);       // print recursively
     224        void     sprint(SString & out); // print recursively
    242225};
    243226
  • cpp/frams/genetics/f4/oper_f4.cpp

    r193 r196  
    1 /*
    2  *  geno_f4.cpp - f4 genetic operators.
    3  *
    4  *  f4genotype - f4 format genotype conversions for FramSticks
    5  *
    6  *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
    7  *  Copyright (C) 2001-2004  Maciej Komosinski
    8  *
    9  *  This library is free software; you can redistribute it and/or
    10  *  modify it under the terms of the GNU Lesser General Public
    11  *  License as published by the Free Software Foundation; either
    12  *  version 2.1 of the License, or (at your option) any later version.
    13  *
    14  *  This library is distributed in the hope that it will be useful,
    15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    17  *  Lesser General Public License for more details.
    18  *
    19  *  You should have received a copy of the GNU Lesser General Public
    20  *  License along with this library; if not, write to the Free Software
    21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    22  *
    23  */
    24 
    25 #include "geno_f4.h"
    26 #include "nonstd.h"
    27 #include "sstring.h"
    28 #include "framsg.h"
     1// This file is a part of the Framsticks GDK.
     2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
     3// Refer to http://www.framsticks.com/ for further information.
     4
     5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// Copyright (C) since 2001 Maciej Komosinski
     7
     8#include "oper_f4.h"
     9#include <frams/util/sstring.h>
     10#include <common/framsg.h>
    2911
    3012#include <stdio.h>
    3113#include <stdlib.h>
    32 #include <math.h>
     14#include "common/nonstd_math.h"
    3315#include <string.h>
    3416
     
    3618#define FIELDSTRUCT Geno_f4
    3719
    38 static ParamEntry GENO4param_tab[]=
    39 {
    40  {"Genetics: f4",1,F4_COUNT+F4_ADD_COUNT,},
    41  {"f4_mut_add", 0, 0, "Add node", "f 0 100 50", FIELD(prob[F4_ADD]),"mutation: probability of adding a node", },
    42  {"f4_mut_add_div", 0, 0, "- add division", "f 0 100 20", FIELD(probadd[F4_ADD_DIV]),"add node mutation: probability of adding a division", },
    43  {"f4_mut_add_conn", 0, 0, "- add connection", "f 0 100 15", FIELD(probadd[F4_ADD_CONN]),"add node mutation: probability of adding a neural connection", },
    44  {"f4_mut_add_neupar", 0, 0, "- add neuron property", "f 0 100 5", FIELD(probadd[F4_ADD_NEUPAR]),"add node mutation: probability of adding a neuron property/modifier", },
    45  {"f4_mut_add_rep", 0, 0, "- add repetition", "f 0 100 10",FIELD(probadd[F4_ADD_REP]),"add node mutation: probability of adding a repetition", },
    46  {"f4_mut_add_simp", 0, 0, "- add simple node", "f 0 100 50",FIELD(probadd[F4_ADD_SIMP]),"add node mutation: probability of adding a random, simple gene", },
    47  {"f4_mut_del", 0, 0, "Delete node", "f 0 100 20", FIELD(prob[F4_DEL]),"mutation: probability of deleting a node", },
    48  {"f4_mut_mod", 0, 0, "Modify node", "f 0 100 30", FIELD(prob[F4_MOD]),"mutation: probability of changing a node", },
    49  {0,},
     20static ParamEntry GENO4param_tab[] =
     21{
     22        { "Genetics: f4", 1, F4_COUNT + F4_ADD_COUNT, },
     23        { "f4_mut_add", 0, 0, "Add node", "f 0 100 50", FIELD(prob[F4_ADD]), "mutation: probability of adding a node", },
     24        { "f4_mut_add_div", 0, 0, "- add division", "f 0 100 20", FIELD(probadd[F4_ADD_DIV]), "add node mutation: probability of adding a division", },
     25        { "f4_mut_add_conn", 0, 0, "- add connection", "f 0 100 15", FIELD(probadd[F4_ADD_CONN]), "add node mutation: probability of adding a neural connection", },
     26        { "f4_mut_add_neupar", 0, 0, "- add neuron property", "f 0 100 5", FIELD(probadd[F4_ADD_NEUPAR]), "add node mutation: probability of adding a neuron property/modifier", },
     27        { "f4_mut_add_rep", 0, 0, "- add repetition", "f 0 100 10", FIELD(probadd[F4_ADD_REP]), "add node mutation: probability of adding a repetition", },
     28        { "f4_mut_add_simp", 0, 0, "- add simple node", "f 0 100 50", FIELD(probadd[F4_ADD_SIMP]), "add node mutation: probability of adding a random, simple gene", },
     29        { "f4_mut_del", 0, 0, "Delete node", "f 0 100 20", FIELD(prob[F4_DEL]), "mutation: probability of deleting a node", },
     30        { "f4_mut_mod", 0, 0, "Modify node", "f 0 100 30", FIELD(prob[F4_MOD]), "mutation: probability of changing a node", },
     31        { 0, },
    5032};
    5133
     
    5537Geno_f4::Geno_f4()
    5638{
    57    supported_format='4';
    58    par.setParamTab(GENO4param_tab);
    59    par.select(this);
    60    par.setDefault();
    61 
    62    mutation_method_names=new char*[F4_COUNT+F4_ADD_COUNT-1];
    63    int index=0;
    64    mutation_method_names[index++]="added division";
    65    mutation_method_names[index++]="added neural connection";
    66    mutation_method_names[index++]="added neuron property";
    67    mutation_method_names[index++]="added repetition gene";
    68    mutation_method_names[index++]="added a simple node";
    69    mutation_method_names[index++]="deleted a node";
    70    mutation_method_names[index++]="modified a node";
    71    if (index!=F4_COUNT+F4_ADD_COUNT-1) FramMessage("Geno_f4","Constructor","Mutation names init error",3);
     39        supported_format = '4';
     40        par.setParamTab(GENO4param_tab);
     41        par.select(this);
     42        par.setDefault();
     43
     44        mutation_method_names = new char*[F4_COUNT + F4_ADD_COUNT - 1];
     45        int index = 0;
     46        mutation_method_names[index++] = "added division";
     47        mutation_method_names[index++] = "added neural connection";
     48        mutation_method_names[index++] = "added neuron property";
     49        mutation_method_names[index++] = "added repetition gene";
     50        mutation_method_names[index++] = "added a simple node";
     51        mutation_method_names[index++] = "deleted a node";
     52        mutation_method_names[index++] = "modified a node";
     53        if (index != F4_COUNT + F4_ADD_COUNT - 1) FramMessage("Geno_f4", "Constructor", "Mutation names init error", 3);
    7254}
    7355
    7456int Geno_f4::ValidateRec(f4_node * geno, int retrycount) const
    7557{
    76   // ! the genotype is geno->child (not geno) !
    77   // build from it with repair on
    78 
    79   f4_Cells cells( geno->child, 1);
    80   cells.simulate();  //we should simulate?!
    81 
    82   // errors not fixed:
    83   if (GENOPER_OPFAIL == cells.geterror())
    84   {
    85     if (cells.geterrorpos() >= 0) return 1+cells.geterrorpos();
    86     return GENOPER_OPFAIL;
    87   }
    88   // errors can be fixed
    89   if (GENOPER_REPAIR == cells.geterror())
    90   {
    91     cells.repairGeno(geno, 1);
    92     // note: geno might have been fixed
    93     // check again
    94     int res2 = GENOPER_OK;
    95     if (retrycount>0)
    96       res2 = ValidateRec( geno, retrycount-1 );
    97 
    98     if (res2==GENOPER_OK) return GENOPER_REPAIR;
    99     return res2;
    100   }
    101   // no errors:
    102   return GENOPER_OK;
     58        // ! the genotype is geno->child (not geno) !
     59        // build from it with repair on
     60
     61        f4_Cells cells(geno->child, 1);
     62        cells.simulate();  //we should simulate?!
     63
     64        // errors not fixed:
     65        if (GENOPER_OPFAIL == cells.geterror())
     66        {
     67                if (cells.geterrorpos() >= 0) return 1 + cells.geterrorpos();
     68                return GENOPER_OPFAIL;
     69        }
     70        // errors can be fixed
     71        if (GENOPER_REPAIR == cells.geterror())
     72        {
     73                cells.repairGeno(geno, 1);
     74                // note: geno might have been fixed
     75                // check again
     76                int res2 = GENOPER_OK;
     77                if (retrycount > 0)
     78                        res2 = ValidateRec(geno, retrycount - 1);
     79
     80                if (res2 == GENOPER_OK) return GENOPER_REPAIR;
     81                return res2;
     82        }
     83        // no errors:
     84        return GENOPER_OK;
    10385}
    10486
     
    10688int Geno_f4::validate(char *& geno)
    10789{
    108   // convert geno to tree, then try to validate 20 times
    109   f4_node root;
    110   if (f4_processrec(geno, 0, &root) || root.childCount()!=1) return GENOPER_OK; // cannot repair
    111   if (ValidateRec( &root, 20 )==GENOPER_REPAIR) // if repaired, make it back to string
    112   {
    113     geno[0]=0;
    114     root.child->sprintAdj(geno);
    115   }
    116   return GENOPER_OK;
     90        // convert geno to tree, then try to validate 20 times
     91        f4_node root;
     92        if (f4_processrec(geno, 0, &root) || root.childCount() != 1) return GENOPER_OK; // cannot repair
     93        if (ValidateRec(&root, 20) == GENOPER_REPAIR) // if repaired, make it back to string
     94        {
     95                geno[0] = 0;
     96                root.child->sprintAdj(geno);
     97        }
     98        return GENOPER_OK;
    11799}
    118100
     
    120102int Geno_f4::checkValidity(const char * geno)
    121103{
    122   f4_node root;
    123   int res = f4_processrec(geno, 0, &root);
    124   if (res) return res;  // errorpos, >0
    125   if (root.childCount()!=1) return 1; //earlier: GENOPER_OPFAIL
    126   f4_Cells cells( root.child, 0);
    127   cells.simulate();
    128   if (cells.geterror()==GENOPER_OPFAIL || cells.geterror()==GENOPER_REPAIR)
    129   {
    130     if (cells.geterrorpos() >= 0) return 1+cells.geterrorpos();
    131       else return 1; //earlier: GENOPER_OPFAIL;
    132   } else return GENOPER_OK;
    133 }
    134 
    135 
    136 int Geno_f4::MutateOne(f4_node *& g,int &method) const
    137 {
    138   // ! the genotype is g->child (not g) !
    139 
    140   // codes that can be changed (apart being added/deleted)
    141   #define MUT_CHAN_CODES "<[#"
    142   #define ADD_SIMPLE_CODES ",XlLcCrRaAiIsSmMfFwWeEN@|"
    143   #define REP_MAXCOUNT 19
    144 
    145   f4_node * n1, * n2, * n3, * n4, * n5;
    146   int i, j;
    147 
    148   // do the mutation
    149   // pick a random node
    150   n1 = g->child->randomNode();
    151   //DB( printf("%c\n", n1->name); )
    152 
    153   switch(roulette(prob,F4_COUNT))
    154   {
    155     case F4_ADD:
    156     {
    157       // add a node
    158       switch(method=roulette(probadd,F4_ADD_COUNT))
    159       {
    160         case F4_ADD_DIV:
    161         {
    162           // add division ('<')
    163           n3 = n1->parent;
    164           n3->removeChild(n1);
    165           n2 = new f4_node('<', n3, n3->pos );
    166           n2->addChild(n1);
    167           // new cell is stick or neuron
    168           // "X>" or "N>"
    169           double pr = rnd01;
    170           pr -= 0.5;
    171           if (pr<0) n3 = new f4_node('X', n2, n2->pos);
    172           else
    173           {
    174             pr -= 0.5;
    175             if (pr<0)
    176             {
    177               // if neuron, make muscle and add a link
    178               n3 = new f4_node('N', n2, n2->pos);
    179               if (randomN(2) == 0)
    180                 n4 = new f4_node('|', n3, n2->pos);
    181               else
    182                 n4 = new f4_node('@', n3, n2->pos);
    183               n5 = new f4_node('[', n4, n2->pos);
    184               linkNodeMakeRandom(n5);
    185             }
    186           }
    187           new f4_node('>', n3, n3->pos);
    188           n1->parent = n2;
    189           // now with 50% chance swap children
    190           if (randomN(2) == 0)
    191           {
    192             n3 = n2->child;
    193             n2->child = n2->child2;
    194             n2->child2 = n3;
    195           }
    196         }
    197         break;
    198         case F4_ADD_CONN:
    199         {
    200           // add link
    201           n1->parent->removeChild(n1);
    202           n2 = new f4_node('[', n1->parent, n1->parent->pos);
    203           linkNodeMakeRandom(n2);
    204           n2->addChild(n1);
    205           n1->parent = n2;
    206         }
    207         break;
    208         case F4_ADD_NEUPAR:
    209         {
    210           // add neuron modifier
    211           n1->parent->removeChild(n1);
    212           n2 = new f4_node(':', n1->parent, n1->parent->pos);
    213           nparNodeMakeRandom(n2);
    214           n2->addChild(n1);
    215           n1->parent = n2;
    216         }
    217         break;
    218         case F4_ADD_REP:
    219         {
    220           // add repetition ('#')
    221           // repeated code (left child) is the original, right child is empty, count is 2
    222           n3 = n1->parent;
    223           n3->removeChild(n1);
    224           n2 = new f4_node('#', n3, n3->pos );
    225           n2->i1 = 2;
    226           n2->addChild(n1);
    227           new f4_node('>', n2, n2->pos);
    228           n1->parent = n2;
    229         }
    230         break;
    231         case F4_ADD_SIMP:
    232         {
    233           // add simple node
    234           // choose a simple node from ADD_SIMPLE_CODES
    235           n1->parent->removeChild(n1);
    236           n2 = new f4_node(ADD_SIMPLE_CODES[randomN(strlen(ADD_SIMPLE_CODES))], n1->parent, n1->parent->pos );
    237           n2->addChild(n1);
    238           n1->parent = n2;
    239         }
    240         break;
    241       }
    242     }
    243     break;
    244 
    245     case F4_DEL:
    246     {
    247       method=F4_ADD_COUNT-1+F4_DEL;
    248       // delete a node
    249       // must pick a node with parent, and at least one child
    250       // already picked a node, but repeat may be needed
    251       for (i=0; i<10; i++) {
    252         if ((NULL != n1->parent) && (g != n1->parent))
    253           if (NULL != n1->child)
    254             break;
    255         // try a new one
    256         n1 = g->child->randomNode();
    257       }
    258       if ((NULL != n1->parent) && (g != n1->parent))
    259       {
    260         switch (n1->childCount())
    261         {
    262          case 0: break;
    263          case 1:  // one child
    264          {
    265             n2 = n1->parent;
    266             n2->removeChild(n1);
    267             if (NULL != n1->child) {
    268               n1->child->parent = n2;
    269               n2->addChild(n1->child);
    270               n1->child = NULL;
    271             }
    272             if (NULL != n1->child2) {
    273               n1->child2->parent = n2;
    274               n2->addChild(n1->child2);
    275               n1->child2 = NULL;
    276             }
    277             // destroy n1
    278             n1->parent=NULL;
    279             delete n1;
    280          }
    281          break;
    282 
    283          case 2:  // two children
    284          {
    285             // two children
    286             n2 = n1->parent;
    287             n2->removeChild(n1);
    288             // n1 has two children. pick one randomly 50-50, destroy other
    289             if (randomN(2) == 0)
    290             {
    291               n1->child->parent = n2;
    292               n2->addChild(n1->child);
    293               n1->child = NULL;
    294               n1->child2->parent = NULL;
    295             } else
    296             {
    297               n1->child2->parent = n2;
    298               n2->addChild(n1->child2);
    299               n1->child2 = NULL;
    300               n1->child->parent = NULL;
    301             }
    302             // destroy n1
    303             n1->parent=NULL;
    304             delete n1;
    305          }
    306          break;
    307         }
    308       } else return GENOPER_OPFAIL;
    309     }
    310     break;
    311     case F4_MOD:
    312     {
    313       method=F4_ADD_COUNT-1+F4_MOD;
    314       // change a node
    315       // the only nodes that are modifiable are MUT_CHAN_CODES
    316       // try to get a modifiable node
    317       // already picked a node, but repeat may be needed
    318       i=0;
    319       while (1)
    320       {
    321         if (strchr(MUT_CHAN_CODES, n1->name)) break;
    322         // try a new one
    323         n1 = g->child->randomNode();
    324         i++;
    325         if (i>=20) return GENOPER_OPFAIL;
    326       }
    327       switch (n1->name) {
    328         case '<':
    329           // swap children
    330           n2 = n1->child; n1->child = n1->child2; n1->child2 = n2;
    331           break;
    332         case '[':
    333           linkNodeChangeRandom(n1);
    334           break;
    335         case '#':
    336           repeatNodeChangeRandom(n1);
    337           break;
    338       }
    339     }
    340     break;
    341 
    342     default: //no mutations allowed?
    343     return GENOPER_OPFAIL;
    344   }
    345 
    346   return GENOPER_OK;
     104        f4_node root;
     105        int res = f4_processrec(geno, 0, &root);
     106        if (res) return res;  // errorpos, >0
     107        if (root.childCount() != 1) return 1; //earlier: GENOPER_OPFAIL
     108        f4_Cells cells(root.child, 0);
     109        cells.simulate();
     110        if (cells.geterror() == GENOPER_OPFAIL || cells.geterror() == GENOPER_REPAIR)
     111        {
     112                if (cells.geterrorpos() >= 0) return 1 + cells.geterrorpos();
     113                else return 1; //earlier: GENOPER_OPFAIL;
     114        }
     115        else return GENOPER_OK;
     116}
     117
     118
     119int Geno_f4::MutateOne(f4_node *& g, int &method) const
     120{
     121        // ! the genotype is g->child (not g) !
     122
     123        // codes that can be changed (apart being added/deleted)
     124#define MUT_CHAN_CODES "<[#"
     125#define ADD_SIMPLE_CODES ",XlLcCrRaAiIsSmMfFwWeEN@|"
     126#define REP_MAXCOUNT 19
     127
     128        f4_node * n1, *n2, *n3, *n4, *n5;
     129
     130        // do the mutation
     131        // pick a random node
     132        n1 = g->child->randomNode();
     133        //DB( printf("%c\n", n1->name); )
     134
     135        switch (roulette(prob, F4_COUNT))
     136        {
     137        case F4_ADD:
     138        {
     139                // add a node
     140                switch (method = roulette(probadd, F4_ADD_COUNT))
     141                {
     142                case F4_ADD_DIV:
     143                {
     144                        // add division ('<')
     145                        n3 = n1->parent;
     146                        n3->removeChild(n1);
     147                        n2 = new f4_node('<', n3, n3->pos);
     148                        n2->addChild(n1);
     149                        // new cell is stick or neuron
     150                        // "X>" or "N>"
     151                        double pr = rnd01;
     152                        pr -= 0.5;
     153                        if (pr < 0) n3 = new f4_node('X', n2, n2->pos);
     154                        else
     155                        {
     156                                pr -= 0.5;
     157                                if (pr < 0)
     158                                {
     159                                        // if neuron, make muscle and add a link
     160                                        n3 = new f4_node('N', n2, n2->pos);
     161                                        if (randomN(2) == 0)
     162                                                n4 = new f4_node('|', n3, n2->pos);
     163                                        else
     164                                                n4 = new f4_node('@', n3, n2->pos);
     165                                        n5 = new f4_node('[', n4, n2->pos);
     166                                        linkNodeMakeRandom(n5);
     167                                }
     168                        }
     169                        new f4_node('>', n3, n3->pos);
     170                        n1->parent = n2;
     171                        // now with 50% chance swap children
     172                        if (randomN(2) == 0)
     173                        {
     174                                n3 = n2->child;
     175                                n2->child = n2->child2;
     176                                n2->child2 = n3;
     177                        }
     178                }
     179                        break;
     180                case F4_ADD_CONN:
     181                {
     182                        // add link
     183                        n1->parent->removeChild(n1);
     184                        n2 = new f4_node('[', n1->parent, n1->parent->pos);
     185                        linkNodeMakeRandom(n2);
     186                        n2->addChild(n1);
     187                        n1->parent = n2;
     188                }
     189                        break;
     190                case F4_ADD_NEUPAR:
     191                {
     192                        // add neuron modifier
     193                        n1->parent->removeChild(n1);
     194                        n2 = new f4_node(':', n1->parent, n1->parent->pos);
     195                        nparNodeMakeRandom(n2);
     196                        n2->addChild(n1);
     197                        n1->parent = n2;
     198                }
     199                        break;
     200                case F4_ADD_REP:
     201                {
     202                        // add repetition ('#')
     203                        // repeated code (left child) is the original, right child is empty, count is 2
     204                        n3 = n1->parent;
     205                        n3->removeChild(n1);
     206                        n2 = new f4_node('#', n3, n3->pos);
     207                        n2->i1 = 2;
     208                        n2->addChild(n1);
     209                        new f4_node('>', n2, n2->pos);
     210                        n1->parent = n2;
     211                }
     212                        break;
     213                case F4_ADD_SIMP:
     214                {
     215                        // add simple node
     216                        // choose a simple node from ADD_SIMPLE_CODES
     217                        n1->parent->removeChild(n1);
     218                        n2 = new f4_node(ADD_SIMPLE_CODES[randomN(strlen(ADD_SIMPLE_CODES))], n1->parent, n1->parent->pos);
     219                        n2->addChild(n1);
     220                        n1->parent = n2;
     221                }
     222                        break;
     223                }
     224        }
     225                break;
     226
     227        case F4_DEL:
     228        {
     229                method = F4_ADD_COUNT - 1 + F4_DEL;
     230                // delete a node
     231                // must pick a node with parent, and at least one child
     232                // already picked a node, but repeat may be needed
     233                for (int i = 0; i < 10; i++) {
     234                        if ((NULL != n1->parent) && (g != n1->parent))
     235                                if (NULL != n1->child)
     236                                        break;
     237                        // try a new one
     238                        n1 = g->child->randomNode();
     239                }
     240                if ((NULL != n1->parent) && (g != n1->parent))
     241                {
     242                        switch (n1->childCount())
     243                        {
     244                        case 0: break;
     245                        case 1:  // one child
     246                        {
     247                                n2 = n1->parent;
     248                                n2->removeChild(n1);
     249                                if (NULL != n1->child) {
     250                                        n1->child->parent = n2;
     251                                        n2->addChild(n1->child);
     252                                        n1->child = NULL;
     253                                }
     254                                if (NULL != n1->child2) {
     255                                        n1->child2->parent = n2;
     256                                        n2->addChild(n1->child2);
     257                                        n1->child2 = NULL;
     258                                }
     259                                // destroy n1
     260                                n1->parent = NULL;
     261                                delete n1;
     262                        }
     263                                break;
     264
     265                        case 2:  // two children
     266                        {
     267                                // two children
     268                                n2 = n1->parent;
     269                                n2->removeChild(n1);
     270                                // n1 has two children. pick one randomly 50-50, destroy other
     271                                if (randomN(2) == 0)
     272                                {
     273                                        n1->child->parent = n2;
     274                                        n2->addChild(n1->child);
     275                                        n1->child = NULL;
     276                                        n1->child2->parent = NULL;
     277                                }
     278                                else
     279                                {
     280                                        n1->child2->parent = n2;
     281                                        n2->addChild(n1->child2);
     282                                        n1->child2 = NULL;
     283                                        n1->child->parent = NULL;
     284                                }
     285                                // destroy n1
     286                                n1->parent = NULL;
     287                                delete n1;
     288                        }
     289                                break;
     290                        }
     291                }
     292                else return GENOPER_OPFAIL;
     293        }
     294                break;
     295        case F4_MOD:
     296        {
     297                method = F4_ADD_COUNT - 1 + F4_MOD;
     298                // change a node
     299                // the only nodes that are modifiable are MUT_CHAN_CODES
     300                // try to get a modifiable node
     301                // already picked a node, but repeat may be needed
     302                int i = 0;
     303                while (1)
     304                {
     305                        if (strchr(MUT_CHAN_CODES, n1->name)) break;
     306                        // try a new one
     307                        n1 = g->child->randomNode();
     308                        i++;
     309                        if (i >= 20) return GENOPER_OPFAIL;
     310                }
     311                switch (n1->name) {
     312                case '<':
     313                        // swap children
     314                        n2 = n1->child; n1->child = n1->child2; n1->child2 = n2;
     315                        break;
     316                case '[':
     317                        linkNodeChangeRandom(n1);
     318                        break;
     319                case '#':
     320                        repeatNodeChangeRandom(n1);
     321                        break;
     322                }
     323        }
     324                break;
     325
     326        default: //no mutations allowed?
     327                return GENOPER_OPFAIL;
     328        }
     329
     330        return GENOPER_OK;
    347331}
    348332
     
    350334void Geno_f4::linkNodeMakeRandom(f4_node * nn) const
    351335{
    352   int i;
    353   float prob1;
    354 
    355   i = 0;
    356   // 35% chance one of *GTS
    357   prob1 = 1.0f / RAND_MAX * rand();
    358   prob1 -= 0.35f;
    359   if (prob1 < 0)
    360   {
    361     // '*', 'G', 'T', or 'S', 1/4 chance each
    362     i = 1 + (int)(3.999f / RAND_MAX * rand());
    363   }
    364   nn->i1 = i;
    365   nn->l1 = 0;
    366   if (0 == i) {
    367      // relative input link
    368      nn->l1 = (int)(4.0f * (1.0f /  RAND_MAX * rand() - 0.5f));
    369   }
    370   // weight
    371   nn->f1 = 10.0f * (1.0f / RAND_MAX * rand() - 0.5f);
     336        int i;
     337        float prob1;
     338
     339        i = 0;
     340        // 35% chance one of *GTS
     341        prob1 = rnd01;
     342        prob1 -= 0.35f;
     343        if (prob1 < 0)
     344        {
     345                // '*', 'G', 'T', or 'S', 1/4 chance each
     346                i = 1 + (int)(3.999f * rnd01);
     347        }
     348        nn->i1 = i;
     349        nn->l1 = 0;
     350        if (0 == i) {
     351                // relative input link
     352                nn->l1 = (int)(4.0f * (rnd01 - 0.5f));
     353        }
     354        // weight
     355        nn->f1 = 10.0f * (rnd01 - 0.5f);
    372356}
    373357
     
    375359void Geno_f4::linkNodeChangeRandom(f4_node * nn) const      //rewritten by M.K. - should work as before (not tested)
    376360{
    377   int i;
    378   float prob2;
    379 
    380   double probs[3]={0.1, 0.3, 0.6};
    381   // 10% change type
    382   // 30% change link
    383   // 60% change weight
    384 
    385   switch (roulette(probs,3))
    386   {
    387      case 0: // change type
    388           i = 0;
    389           // * G, 10% chance each
    390           prob2 = rnd01 - 0.10f;
    391           if (prob2 < 0) i=1; else {prob2 -= 0.10f; if (prob2 < 0) i=2;}
    392           nn->i1 = i;
    393           break;
    394      case 1: // change link
    395           if (0 == nn->i1) // relative input link
    396              nn->l1 += (int)(2.0f * (rnd01 - 0.5f));
    397           break;
    398      case 2: // change weight
    399           nn->f1 += 1.0f * (rnd01 - 0.5f);
    400           break;
    401   }
     361        int i;
     362        float prob2;
     363
     364        double probs[3] = { 0.1, 0.3, 0.6 };
     365        // 10% change type
     366        // 30% change link
     367        // 60% change weight
     368
     369        switch (roulette(probs, 3))
     370        {
     371        case 0: // change type
     372                i = 0;
     373                // * G, 10% chance each
     374                prob2 = rnd01 - 0.10f;
     375                if (prob2 < 0) i = 1; else { prob2 -= 0.10f; if (prob2 < 0) i = 2; }
     376                nn->i1 = i;
     377                break;
     378        case 1: // change link
     379                if (0 == nn->i1) // relative input link
     380                        nn->l1 += (int)(2.0f * (rnd01 - 0.5f));
     381                break;
     382        case 2: // change weight
     383                nn->f1 += 1.0f * (rnd01 - 0.5f);
     384                break;
     385        }
    402386}
    403387
     
    405389void Geno_f4::nparNodeMakeRandom(f4_node * nn) const
    406390{
    407   int sign = (int)( 2.0f / RAND_MAX * rand() );
    408   int param = (int)( 3.0f / RAND_MAX * rand() );
    409   if (param>2) param=2;
    410   nn->l1 = sign;
    411   nn->i1 = "!=/"[param];
     391        int sign = (int)(2.0f * rnd01);
     392        int param = (int)(3.0f * rnd01);
     393        if (param > 2) param = 2;
     394        nn->l1 = sign;
     395        nn->i1 = "!=/"[param];
    412396}
    413397
     
    415399void Geno_f4::repeatNodeChangeRandom(f4_node * nn) const
    416400{
    417   int count;
    418   float prob1;
    419 
    420   // change count
    421   count = nn->i1;
    422   prob1 = 1.0f / RAND_MAX * rand();
    423   if (prob1 < 0.5f) count++;
    424                else count--;
    425   if (count<1) count=1;
    426   if (count>REP_MAXCOUNT) count=REP_MAXCOUNT;
    427   nn->i1 = count;
    428 }
    429 
    430 
    431 int Geno_f4::MutateOneValid(f4_node *& g,int &method) const
     401        int count;
     402        float prob1;
     403
     404        // change count
     405        count = nn->i1;
     406        prob1 = rnd01;
     407        if (prob1 < 0.5f) count++;
     408        else count--;
     409        if (count<1) count = 1;
     410        if (count>REP_MAXCOUNT) count = REP_MAXCOUNT;
     411        nn->i1 = count;
     412}
     413
     414
     415int Geno_f4::MutateOneValid(f4_node *& g, int &method) const
    432416// mutate one, until a valid genotype is obtained
    433417{
    434   // ! the genotype is g->child (not g) !
    435   int i, res;
    436   f4_node * gcopy = NULL;
    437   // try this max 20 times:
    438   //   copy, mutate, then validate
    439 
    440   for (i=0; i<20; i++)
    441   {
    442     gcopy = g->duplicate();
    443 
    444     res = MutateOne(gcopy,method);
    445 
    446     if (GENOPER_OK != res)
    447     {
    448       // mutation failed, try again
    449       delete gcopy;
    450       continue;  // for
    451     }
    452     // try to validate it
    453     res = ValidateRec(gcopy, 10);
    454     // accept if it is OK, or was repaired
    455     if (GENOPER_OK == res)
    456      //(GENOPER_REPAIR == res)
    457     {
    458       // destroy the original one
    459       g->destroy();
    460       // make it the new one
    461       *g = *gcopy;
    462       gcopy->child=NULL;
    463       gcopy->child2=NULL;
    464       delete gcopy;
    465       res = GENOPER_OK;
    466       goto retm1v;
    467     }
    468     delete gcopy;
    469   }
    470   // attempts failed
    471   res = GENOPER_OPFAIL;
     418        // ! the genotype is g->child (not g) !
     419        int i, res;
     420        f4_node * gcopy = NULL;
     421        // try this max 20 times:
     422        //   copy, mutate, then validate
     423
     424        for (i = 0; i < 20; i++)
     425        {
     426                gcopy = g->duplicate();
     427
     428                res = MutateOne(gcopy, method);
     429
     430                if (GENOPER_OK != res)
     431                {
     432                        // mutation failed, try again
     433                        delete gcopy;
     434                        continue;  // for
     435                }
     436                // try to validate it
     437                res = ValidateRec(gcopy, 10);
     438                // accept if it is OK, or was repaired
     439                if (GENOPER_OK == res)
     440                        //(GENOPER_REPAIR == res)
     441                {
     442                        // destroy the original one
     443                        g->destroy();
     444                        // make it the new one
     445                        *g = *gcopy;
     446                        gcopy->child = NULL;
     447                        gcopy->child2 = NULL;
     448                        delete gcopy;
     449                        res = GENOPER_OK;
     450                        goto retm1v;
     451                }
     452                delete gcopy;
     453        }
     454        // attempts failed
     455        res = GENOPER_OPFAIL;
    472456retm1v:
    473   return res;
    474 }
    475 
    476 
    477 int Geno_f4::mutate(char *& g, float & chg,int &method)
    478 {
    479   f4_node *root=new f4_node;
    480   if (f4_processrec(g, 0, root) || root->childCount()!=1)
    481      {delete root; return GENOPER_OPFAIL;} // could not convert or bad: fail
    482   // mutate one node, set chg as this percent
    483   chg = 1.0/float(root->child->count());
    484   if (MutateOneValid(root,method)!=GENOPER_OK)
    485      {delete root; return GENOPER_OPFAIL;}
    486   // OK, convert back to string
    487   g[0]=0;
    488   root->child->sprintAdj(g);
    489   delete root;
    490   return GENOPER_OK;
     457        return res;
     458}
     459
     460
     461int Geno_f4::mutate(char *& g, float & chg, int &method)
     462{
     463        f4_node *root = new f4_node;
     464        if (f4_processrec(g, 0, root) || root->childCount() != 1)
     465        {
     466                delete root; return GENOPER_OPFAIL;
     467        } // could not convert or bad: fail
     468        // mutate one node, set chg as this percent
     469        chg = 1.0 / float(root->child->count());
     470        if (MutateOneValid(root, method) != GENOPER_OK)
     471        {
     472                delete root; return GENOPER_OPFAIL;
     473        }
     474        // OK, convert back to string
     475        g[0] = 0;
     476        root->child->sprintAdj(g);
     477        delete root;
     478        return GENOPER_OK;
    491479}
    492480
     
    497485// make a number of mutations
    498486{
    499   int res, n, i;
    500   int totNodes = 0;
    501   int maxToMut = 0;
    502 
    503   // convert to tree
    504   f4_node * root;
    505   root = new f4_node();
    506   res = f4_processrec(g, 0, root);
    507   if (res) {
    508     // could not convert, fail
    509     goto retm;
    510   }
    511   if (1 != root->childCount()) {
    512     res = GENOPER_OPFAIL;
    513     goto retm;
    514   }
    515 
    516   // check if original is valid
    517   res = ValidateRec( root, 20 );
    518   // might have been repaired!
    519   if (GENOPER_REPAIR==res) {
    520     res = GENOPER_OK;
    521   }
    522   if (GENOPER_OK != res) {
    523     goto retm;
    524   }
    525 
    526   // decide number of nodes to mutate
    527   // decide maximum number of nodes to mutate: 0.25*nodes, min 2
    528   totNodes = root->child->count();
    529   maxToMut = (int)( 0.25f * totNodes);
    530   if (maxToMut<2) maxToMut=2;
    531   if (maxToMut>totNodes) maxToMut=totNodes;
    532 
    533   // decide number of nodes to mutate
    534   n = (int)( 0.5f + 1.0f/RAND_MAX * rand() * maxToMut );
    535   if (n<1) n=1;
    536   if (n>totNodes) n=totNodes;
    537   // set chg as this percent
    538   chg = ((float)n) / ((float)totNodes);
    539   for (i=0; i<n; i++)
    540   {
    541     res = MutateOneValid(root);
    542     if (GENOPER_OK != res)
    543     {
    544       res = GENOPER_OPFAIL;
    545       goto retm;
    546     }
    547   }
    548   // OK, convert back to string
    549   g[0]=0;
    550   root->child->sprintAdj(g);
     487int res, n, i;
     488int totNodes = 0;
     489int maxToMut = 0;
     490
     491// convert to tree
     492f4_node * root;
     493root = new f4_node();
     494res = f4_processrec(g, 0, root);
     495if (res) {
     496// could not convert, fail
     497goto retm;
     498}
     499if (1 != root->childCount()) {
     500res = GENOPER_OPFAIL;
     501goto retm;
     502}
     503
     504// check if original is valid
     505res = ValidateRec( root, 20 );
     506// might have been repaired!
     507if (GENOPER_REPAIR==res) {
     508res = GENOPER_OK;
     509}
     510if (GENOPER_OK != res) {
     511goto retm;
     512}
     513
     514// decide number of nodes to mutate
     515// decide maximum number of nodes to mutate: 0.25*nodes, min 2
     516totNodes = root->child->count();
     517maxToMut = (int)( 0.25f * totNodes);
     518if (maxToMut<2) maxToMut=2;
     519if (maxToMut>totNodes) maxToMut=totNodes;
     520
     521// decide number of nodes to mutate
     522n = (int)( 0.5f + rnd01 * maxToMut );
     523if (n<1) n=1;
     524if (n>totNodes) n=totNodes;
     525// set chg as this percent
     526chg = ((float)n) / ((float)totNodes);
     527for (i=0; i<n; i++)
     528{
     529res = MutateOneValid(root);
     530if (GENOPER_OK != res)
     531{
     532res = GENOPER_OPFAIL;
     533goto retm;
     534}
     535}
     536// OK, convert back to string
     537g[0]=0;
     538root->child->sprintAdj(g);
    551539retm:
    552   delete root;
    553   return res;
     540delete root;
     541return res;
    554542}
    555543*/
     
    558546int Geno_f4::CrossOverOne(f4_node * g1, f4_node * g2, float chg) const
    559547{
    560   // ! the genotypes are g1->child and g2->child (not g1 g2) !
    561   // single offspring in g1
    562   int smin, smax;
    563   float size;
    564   f4_node * n1, * n2, * n1p, * n2p;
    565 
    566   // determine desired size
    567   size = (1-chg) * (float)g1->count();
    568   smin = (int)(size*0.9f-1);
    569   smax = (int)(size*1.1f+1);
    570   // get a random node with desired size
    571   n1 = g1->child->randomNodeWithSize(smin, smax);
    572 
    573   // determine desired size
    574   size = (1-chg) * (float)g2->count();
    575   smin = (int)(size*0.9f-1);
    576   smax = (int)(size*1.1f+1);
    577   // get a random node with desired size
    578   n2 = g2->child->randomNodeWithSize(smin, smax);
    579 
    580   // exchange the two nodes:
    581   n1p = n1->parent;
    582   n2p = n2->parent;
    583   n1p->removeChild(n1);
    584   n1p->addChild(n2);
    585   n2p->removeChild(n2);
    586   n2p->addChild(n1);
    587   n1->parent = n2p;
    588   n2->parent = n1p;
    589 
    590   return GENOPER_OK;
     548        // ! the genotypes are g1->child and g2->child (not g1 g2) !
     549        // single offspring in g1
     550        int smin, smax;
     551        float size;
     552        f4_node * n1, *n2, *n1p, *n2p;
     553
     554        // determine desired size
     555        size = (1 - chg) * (float)g1->count();
     556        smin = (int)(size*0.9f - 1);
     557        smax = (int)(size*1.1f + 1);
     558        // get a random node with desired size
     559        n1 = g1->child->randomNodeWithSize(smin, smax);
     560
     561        // determine desired size
     562        size = (1 - chg) * (float)g2->count();
     563        smin = (int)(size*0.9f - 1);
     564        smax = (int)(size*1.1f + 1);
     565        // get a random node with desired size
     566        n2 = g2->child->randomNodeWithSize(smin, smax);
     567
     568        // exchange the two nodes:
     569        n1p = n1->parent;
     570        n2p = n2->parent;
     571        n1p->removeChild(n1);
     572        n1p->addChild(n2);
     573        n2p->removeChild(n2);
     574        n2p->addChild(n1);
     575        n1->parent = n2p;
     576        n2->parent = n1p;
     577
     578        return GENOPER_OK;
    591579}
    592580
    593581int Geno_f4::crossOver(char *&g1, char *&g2, float &chg1, float &chg2)
    594582{
    595   f4_node root1, root2, *copy1, *copy2;
    596 
    597   // convert genotype strings into tree structures
    598   if (f4_processrec(g1,0,&root1) || (root1.childCount()!=1)) return GENOPER_OPFAIL;
    599   if (f4_processrec(g2,0,&root2) || (root2.childCount()!=1)) return GENOPER_OPFAIL;
    600 
    601   // decide amounts of crossover, 0.25-0.75
    602   // adam: seems 0.1-0.9 -- MacKo
    603   chg1 = 0.1f + 0.8f*rnd01;
    604   chg2 = 0.1f + 0.8f*rnd01;
    605 
    606   copy1 = root1.duplicate();
    607   if (CrossOverOne(copy1, &root2, chg1) != GENOPER_OK) {delete copy1; copy1=NULL;}
    608   copy2 = root2.duplicate();
    609   if (CrossOverOne(copy2, &root1, chg2) != GENOPER_OK) {delete copy2; copy2=NULL;}
    610 
    611   g1[0]=0;
    612   g2[0]=0;
    613   if (copy1) {copy1->child->sprintAdj(g1); delete copy1;}
    614   if (copy2) {copy2->child->sprintAdj(g2); delete copy2;}
    615   if (g1[0] || g2[0]) return GENOPER_OK; else return GENOPER_OPFAIL;
     583        f4_node root1, root2, *copy1, *copy2;
     584
     585        // convert genotype strings into tree structures
     586        if (f4_processrec(g1, 0, &root1) || (root1.childCount() != 1)) return GENOPER_OPFAIL;
     587        if (f4_processrec(g2, 0, &root2) || (root2.childCount() != 1)) return GENOPER_OPFAIL;
     588
     589        // decide amounts of crossover, 0.25-0.75
     590        // adam: seems 0.1-0.9 -- MacKo
     591        chg1 = 0.1f + 0.8f*rnd01;
     592        chg2 = 0.1f + 0.8f*rnd01;
     593
     594        copy1 = root1.duplicate();
     595        if (CrossOverOne(copy1, &root2, chg1) != GENOPER_OK) { delete copy1; copy1 = NULL; }
     596        copy2 = root2.duplicate();
     597        if (CrossOverOne(copy2, &root1, chg2) != GENOPER_OK) { delete copy2; copy2 = NULL; }
     598
     599        g1[0] = 0;
     600        g2[0] = 0;
     601        if (copy1) { copy1->child->sprintAdj(g1); delete copy1; }
     602        if (copy2) { copy2->child->sprintAdj(g2); delete copy2; }
     603        if (g1[0] || g2[0]) return GENOPER_OK; else return GENOPER_OPFAIL;
    616604}
    617605
     
    620608unsigned long Geno_f4::style(const char *g, int pos)
    621609{
    622   char ch = g[pos];
    623   // style categories
    624   #define STYL4CAT_MODIFIC "LlRrCcQqAaIiSsMmFfWwEe,"
    625   #define STYL4CAT_NEUMOD "[]|@*GTS:+-/!="
    626   #define STYL4CAT_DIGIT "0123456789."
    627   #define STYL4CAT_REST "XN<># "
    628   if (!strchr(STYL4CAT_MODIFIC STYL4CAT_NEUMOD STYL4CAT_DIGIT STYL4CAT_REST, ch))
    629     return GENSTYLE_CS(0,GENSTYLE_INVALID);
    630   unsigned long style=GENSTYLE_CS(0,GENSTYLE_STRIKEOUT); //default, should be changed below
    631   if (strchr("X ", ch))              style=GENSTYLE_CS(0,GENSTYLE_NONE);
    632   if (strchr("N", ch))               style=GENSTYLE_RGBS(0,200,0,GENSTYLE_NONE); 
    633   if (strchr("<", ch))               style=GENSTYLE_RGBS(0,0,200,GENSTYLE_BOLD); 
    634   if (strchr(">", ch))               style=GENSTYLE_RGBS(0,0,100,GENSTYLE_NONE); 
    635   if (strchr(STYL4CAT_DIGIT, ch))     style=GENSTYLE_RGBS(100,100,100,GENSTYLE_NONE);
    636   if (strchr(STYL4CAT_MODIFIC, ch))   style=GENSTYLE_RGBS(100,100,100,GENSTYLE_NONE);
    637   if (strchr(STYL4CAT_NEUMOD, ch))    style=GENSTYLE_RGBS(0,150,0,GENSTYLE_NONE);
    638   return style;
    639 }
    640 
    641 
     610        char ch = g[pos];
     611        // style categories
     612#define STYL4CAT_MODIFIC "LlRrCcQqAaIiSsMmFfWwEe,"
     613#define STYL4CAT_NEUMOD "[]|@*GTS:+-/!="
     614#define STYL4CAT_DIGIT "0123456789."
     615#define STYL4CAT_REST "XN<># "
     616        if (!strchr(STYL4CAT_MODIFIC STYL4CAT_NEUMOD STYL4CAT_DIGIT STYL4CAT_REST, ch))
     617                return GENSTYLE_CS(0, GENSTYLE_INVALID);
     618        unsigned long style = GENSTYLE_CS(0, GENSTYLE_STRIKEOUT); //default, should be changed below
     619        if (strchr("X ", ch))              style = GENSTYLE_CS(0, GENSTYLE_NONE);
     620        if (strchr("N", ch))               style = GENSTYLE_RGBS(0, 200, 0, GENSTYLE_NONE);
     621        if (strchr("<", ch))               style = GENSTYLE_RGBS(0, 0, 200, GENSTYLE_BOLD);
     622        if (strchr(">", ch))               style = GENSTYLE_RGBS(0, 0, 100, GENSTYLE_NONE);
     623        if (strchr(STYL4CAT_DIGIT, ch))     style = GENSTYLE_RGBS(100, 100, 100, GENSTYLE_NONE);
     624        if (strchr(STYL4CAT_MODIFIC, ch))   style = GENSTYLE_RGBS(100, 100, 100, GENSTYLE_NONE);
     625        if (strchr(STYL4CAT_NEUMOD, ch))    style = GENSTYLE_RGBS(0, 150, 0, GENSTYLE_NONE);
     626        return style;
     627}
  • cpp/frams/genetics/f4/oper_f4.h

    r193 r196  
    1 /*
    2  *  geno_f4.h - f4 genetic operators.
    3  *
    4  *  f4genotype - f4 format genotype conversions for FramSticks
    5  *
    6  *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
    7  *  Copyright (C) 2001-2004  Maciej Komosinski
    8  *
    9  *  This library is free software; you can redistribute it and/or
    10  *  modify it under the terms of the GNU Lesser General Public
    11  *  License as published by the Free Software Foundation; either
    12  *  version 2.1 of the License, or (at your option) any later version.
    13  *
    14  *  This library is distributed in the hope that it will be useful,
    15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    17  *  Lesser General Public License for more details.
    18  *
    19  *  You should have received a copy of the GNU Lesser General Public
    20  *  License along with this library; if not, write to the Free Software
    21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    22  *
    23  */
     1// This file is a part of the Framsticks GDK.
     2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
     3// Refer to http://www.framsticks.com/ for further information.
     4
     5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// Copyright (C) since 2001 Maciej Komosinski
    247
    258#ifndef _GENO_F4_H_
    269#define _GENO_F4_H_
    2710
     11#include <stdio.h>
    2812#include "f4_general.h"
    29 #include "nonstd.h"
    30 #include <stdio.h>
    31 #include "geno_fx.h"
    32 #include "param.h"
     13#include "common/nonstd.h"
     14#include "../oper_fx.h"
     15#include <frams/param/param.h>
    3316
    3417
     
    4629
    4730
    48 class Geno_f4: public Geno_fx
     31class Geno_f4 : public GenoOperators
    4932{
    5033public:
    51   Geno_f4();
    52   int validate(char *&);
    53   int checkValidity(const char *);
    54   int mutate(char *& g, float & chg,int &method);
    55   int crossOver(char *&g1, char *&g2, float& chg1, float& chg2);
    56   char* getSimplest() {return "X";};
    57   unsigned long style(const char *g, int pos);
     34        Geno_f4();
     35        int validate(char *&);
     36        int checkValidity(const char *);
     37        int mutate(char *& g, float & chg, int &method);
     38        int crossOver(char *&g1, char *&g2, float& chg1, float& chg2);
     39        const char* getSimplest() { return "X"; }
     40        unsigned long style(const char *g, int pos);
    5841
    59   // mutation probabilities
    60   double prob[F4_COUNT],probadd[F4_ADD_COUNT];
     42        // mutation probabilities
     43        double prob[F4_COUNT], probadd[F4_ADD_COUNT];
    6144
    6245protected:
    63   /* int MutateMany(char *& g, float & chg); // not used any more */
    64   int  ValidateRec(f4_node * geno, int retrycount) const;
    65   int  MutateOne(f4_node *& g,int &method) const;
    66   void linkNodeMakeRandom(f4_node * nn) const;
    67   void linkNodeChangeRandom(f4_node * nn) const;
    68   void nparNodeMakeRandom(f4_node * nn) const;
    69   void repeatNodeChangeRandom(f4_node * nn) const;
    70   int  MutateOneValid(f4_node * &g,int &method) const;
    71   int  CrossOverOne(f4_node *g1, f4_node *g2, float chg) const;
    72     // returns GENOPER_OK or GENOPER_OPFAIL
    73     // chg: fraction of parent1 genes in child (in g1) (parent2 has the rest)
     46        /* int MutateMany(char *& g, float & chg); // not used anymore */
     47        int  ValidateRec(f4_node * geno, int retrycount) const;
     48        int  MutateOne(f4_node *& g, int &method) const;
     49        void linkNodeMakeRandom(f4_node * nn) const;
     50        void linkNodeChangeRandom(f4_node * nn) const;
     51        void nparNodeMakeRandom(f4_node * nn) const;
     52        void repeatNodeChangeRandom(f4_node * nn) const;
     53        int  MutateOneValid(f4_node * &g, int &method) const;
     54        int  CrossOverOne(f4_node *g1, f4_node *g2, float chg) const;
     55        // returns GENOPER_OK or GENOPER_OPFAIL
     56        // chg: fraction of parent1 genes in child (in g1) (parent2 has the rest)
    7457};
    7558
  • cpp/frams/genetics/gen-config-GDK.h

    r194 r196  
    1515//#define USE_GENCONV_f21
    1616//#define USE_GENCONV_f30
    17 //#define USE_GENCONV_f40
     17#define USE_GENCONV_f40
    1818//#define USE_GENCONV_f41_TEST
    1919//#define USE_GENCONV_f50
     
    2525//#define USE_GENMAN_f2
    2626//#define USE_GENMAN_f3
    27 //#define USE_GENMAN_f4
     27#define USE_GENMAN_f4
    2828//#define USE_GENMAN_f5
    2929#define USE_GENMAN_f9
Note: See TracChangeset for help on using the changeset viewer.