- Timestamp:
- 03/25/14 03:22:37 (11 years ago)
- Location:
- cpp/frams
- Files:
-
- 1 added
- 2 edited
- 6 moved
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/Makefile-GDK-files
r194 r196 4 4 ALL_DIRS={common,frams,frams/canvas,frams/config,frams/errmgr,frams/genetics,frams/genetics/f0,frams/genetics/f1,frams/genetics/f2,frams/genetics/f3,frams/genetics/f4,frams/genetics/f5,frams/genetics/f6,frams/genetics/f7,frams/genetics/f8,frams/genetics/f9,frams/genetics/fF,frams/genetics/fT,frams/model,frams/neuro,frams/neuro/impl,frams/param,frams/test,frams/util,frams/vm/classes,frams/virtfile,frams/_demos,frams/model/geometry,frams/_demos/geometry} 5 5 6 GENMANF4=frams/genetics/f4/oper_f4.o 6 7 GENMANF9=frams/genetics/f9/oper_f9.o 7 8 GENMANFF=frams/genetics/fF/oper_fF.o … … 9 10 10 11 CONVF1=frams/genetics/f1/conv_f1.o 12 CONVF4=frams/genetics/f4/conv_f4.o frams/genetics/f4/f4_general.o 11 13 CONVF9=frams/genetics/f9/conv_f9.o 12 14 CONVFF=frams/genetics/fF/conv_fF.o frams/genetics/fF/fF_genotype.o frams/genetics/fF/fF_chamber3d.o 13 15 14 GENOCONV_GDK_OBJS=frams/genetics/defgenoconv.o $(CONVF1) $(CONVF 9) $(CONVFF)15 GENMAN_GDK_OBJS=$(GENMAN_COMMON_OBJS) $(GENMANF 9) $(GENMANFF) $(GENMANFT)16 GENOCONV_GDK_OBJS=frams/genetics/defgenoconv.o $(CONVF1) $(CONVF4) $(CONVF9) $(CONVFF) 17 GENMAN_GDK_OBJS=$(GENMAN_COMMON_OBJS) $(GENMANF4) $(GENMANF9) $(GENMANFF) $(GENMANFT) 16 18 17 19 GENMAN_COMMON_OBJS=frams/genetics/genman.o frams/param/mutableparam.o frams/param/mutparamlist.o frams/neuro/geneticneuroparam.o frams/neuro/neurolibparam.o frams/vm/classes/genoobj.o frams/model/autoname.o -
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 24 7 25 8 #include "conv_f4.h" 26 #include "framsg.h"27 #include " geno_fx.h" //for GENOPER_OK constant9 #include <common/framsg.h> 10 #include "../oper_fx.h" //for GENOPER_OK constant 28 11 29 12 #ifdef DMALLOC … … 32 15 33 16 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; 17 GenoConv_f40::GenoConv_f40() 18 { 19 name = "Developmental encoding"; 20 in_format = '4'; 21 out_format = '0'; 22 mapsupport = 1; 23 } 24 25 26 SString 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; 56 38 } 57 39 … … 59 41 GenoConv_F41_TestOnly::GenoConv_F41_TestOnly() 60 42 { 61 name = "test-only approximate f4 -> f0converter";62 in_format= '4';63 64 65 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)"; 66 48 } 67 49 … … 69 51 SString GenoConv_F41_TestOnly::convert(SString &in, MultiMap * map) 70 52 { 71 72 73 74 75 76 77 78 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; 79 61 } 80 62 … … 82 64 f4_Model::f4_Model() : Model() 83 65 { 84 66 cells = NULL; 85 67 } 86 68 87 69 f4_Model::~f4_Model() 88 70 { 89 71 if (cells) delete cells; 90 72 } 91 73 92 74 int f4_Model::buildFromF4(SString &geno) 93 75 { 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 for(i=0; i<cells->nc; i++)120 121 122 123 124 125 126 for(i=0; i<cells->nc; i++)127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 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; 142 124 } 143 125 … … 145 127 f4_Cell * f4_Model::getStick(f4_Cell * C) 146 128 { 147 148 149 150 151 for (int i=0; i<cells->nc; i++)152 153 154 155 156 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; 157 139 } 158 140 … … 161 143 int f4_Model::buildModelRec(f4_Cell * C) 162 144 { 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; 296 279 } 297 280 … … 299 282 void f4_Model::toF1Geno(SString &out) 300 283 { 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 24 7 25 8 #ifndef _CONV_F4_H_ 26 9 #define _CONV_F4_H_ 27 10 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> 31 14 #include "f4_general.h" 32 15 33 16 34 17 // The f4->f0 converter 35 class GenoConv_ F40: public GenoConverter18 class GenoConv_f40 : public GenoConverter 36 19 { 37 38 GenoConv_F40();39 20 public: 21 GenoConv_f40(); 22 SString convert(SString &in, MultiMap * map); 40 23 }; 41 24 42 25 43 26 // a test-only f4->f1 converter, approximates only 44 class GenoConv_F41_TestOnly : public GenoConverter27 class GenoConv_F41_TestOnly : public GenoConverter 45 28 { 46 47 48 29 public: 30 GenoConv_F41_TestOnly(); 31 SString convert(SString &in, MultiMap * map); 49 32 }; 50 33 51 34 52 35 // A Model descendant, which support build from an f4 genotype. 53 class f4_Model : public Model36 class f4_Model : public Model 54 37 { 55 56 57 58 59 60 61 62 63 64 65 66 67 68 38 public: 39 f4_Model(); 40 ~f4_Model(); 41 int buildFromF4(SString &geno); 42 void toF1Geno(SString &out); // output to f1 format, approximation 43 private: 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; 69 52 }; 70 53 71 54 72 55 #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 23 7 24 8 #include "f4_general.h" 25 #include "nonstd.h"26 #include "framsg.h"27 #include "model.h"// for min and max attributes28 #include " geno_fx.h" //for GENOPER_ constants9 #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 29 13 #include <stdio.h> 30 #include < math.h>14 #include <common/nonstd_math.h> 31 15 32 16 #ifdef DMALLOC … … 37 21 f4_Props::f4_Props() 38 22 { 39 len= 1.0;40 curv= 0.0;41 mass = 1.0; 42 43 ruch= 0.25; // bio44 assim= 0.25; // bio45 odpor= 0.25; // bio46 ingest= 0.25; // bio47 twist= 0.0;48 energ= 1.0;49 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(); 50 34 } 51 35 52 36 void f4_Props::normalizeBiol4() 53 37 { 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 } 65 50 } 66 51 67 52 void f4_Props::executeModifier(char modif) 68 53 { 69 70 71 72 73 74 75 case 'C': curv += (2.0 - curv) * 0.25; break;76 77 case 'Q': twist += (1.58 - twist) * 0.3; break;78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 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 } 94 79 } 95 80 96 81 void f4_Props::adjust() 97 82 { 98 99 100 83 len = 0.5*len + 0.5*stdProps.len; 84 curv = 0.66 * curv; 85 twist = 0.66 * twist; 101 86 } 102 87 … … 105 90 106 91 void rolling_dec(double * v) { 107 92 *v -= 0.7853; // 0.7853981 45 degrees 108 93 } 109 94 void rolling_inc(double * v) { 110 95 *v += 0.7853; // 0.7853981 45 degrees 111 96 } 112 97 … … 114 99 int scanrec(const char * s, unsigned int slen, char stopchar) 115 100 { 116 117 118 119 120 121 122 123 124 if (i < slen-1) 125 126 if (s[i] == '(') 127 128 i += 2+scanrec(s+i+1, slen-i-1, ')');129 130 131 if (s[i] == '<') 132 133 i += 2+scanrec(s+i+1, slen-i-1, '>');134 135 136 if (s[i] == '#') 137 138 i += 2+scanrec(s+i+1, slen-i-1, '>');139 140 141 142 143 144 145 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; 146 131 } 147 132 148 133 149 134 f4_Cell::f4_Cell(int nname, 150 151 { 152 name= nname;153 type= T_UNDIFF4;154 155 org= NULL;156 genot= NULL;157 gcur= NULL;158 active= 1;159 160 161 162 anglepos= nangle;163 164 165 P= newP;166 rolling= 0;167 xrot= 0;168 zrot= 0;169 170 ctrl= 0;171 state= 0;172 173 force= 0.04;174 sigmo= 2;175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 state= ndad->state;190 191 force= ndad->force;192 sigmo= ndad->sigmo;193 194 195 196 197 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; 198 183 } 199 184 200 185 201 186 f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur, 202 203 { 204 name= nname;205 type= T_UNDIFF4;206 207 org= nO;208 genot= ngeno;209 gcur= ngcur;210 211 212 213 214 215 genoRange.add( ndad->genoRange);216 217 anglepos= nangle;218 219 220 P= newP;221 rolling= 0;222 xrot= 0;223 zrot= 0;224 225 ctrl= 0;226 state= 0;227 228 force= 0.04;229 sigmo= 2;230 231 232 233 234 235 236 237 238 239 240 241 if (T_NEURON4 == ndad->type) 242 243 state= ndad->state;244 245 force= ndad->force;246 sigmo= ndad->sigmo;247 248 249 250 251 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; 252 237 } 253 238 … … 255 240 f4_Cell::~f4_Cell() 256 241 { 257 258 259 260 261 for (i=nolink-1; i>=0; i--)262 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 } 265 250 } 266 251 267 252 268 253 /* return codes: 269 270 271 272 */254 >1 error at pos 255 0 halt development for a cycle 256 -1 development finished OK 257 */ 273 258 int f4_Cell::onestep() 274 259 { 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; 603 592 } 604 593 … … 606 595 int f4_Cell::addlink(f4_Cell * nfrom, double nw, long nt) 607 596 { 608 if (nolink >= MAXINPUTS-1) return -1; // full!609 610 611 597 if (nolink >= MAXINPUTS - 1) return -1; // full! 598 links[nolink] = new f4_CellLink(nfrom, nw, nt); 599 nolink++; 600 return 0; 612 601 } 613 602 … … 615 604 void f4_Cell::adjustRec() 616 605 { 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 } 682 673 } 683 674 … … 686 677 f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, long nt) 687 678 { 688 689 w= nw;690 t= nt;679 from = nfrom; 680 w = nw; 681 t = nt; 691 682 } 692 683 … … 695 686 f4_Cells::f4_Cells(f4_node * genome, int nrepair) 696 687 { 697 698 699 error= 0;700 701 702 703 704 705 706 707 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; 709 700 } 710 701 … … 712 703 f4_Cells::f4_Cells(SString & genome, int nrepair) 713 704 { 714 715 716 error= 0;717 718 719 720 721 722 723 724 725 726 727 if ((res<0) || (1 != f4rootnode->childCount()))728 729 730 731 732 733 734 735 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; 737 728 } 738 729 739 730 f4_Cells::~f4_Cells() 740 731 { 741 742 743 744 745 for (i=nc-1; i>=0; i--)746 747 748 749 750 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; 751 742 } 752 743 … … 754 745 int f4_Cells::onestep() 755 746 { 756 757 758 ret=0;759 for (i=0; i<oldnc; i++) {760 761 762 763 764 765 766 767 768 ret=1;769 770 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; 771 762 } 772 763 … … 774 765 int f4_Cells::simulate() 775 766 { 776 777 778 779 for (i=0; i<nc; i++) C[i]->active = 1;780 781 782 while (onestep());783 784 785 786 787 for(i=0; i<nc; i++)788 789 790 791 792 793 794 795 796 for (i=0; i<nc; i++)797 798 799 800 801 802 803 804 for(i=0; i<nc; i++)805 806 807 for(i=0; i<nc; i++)808 809 810 811 812 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; 813 804 } 814 805 … … 816 807 void f4_Cells::addCell(f4_Cell * newcell) 817 808 { 818 if (nc >= MAX4CELLS-1) {819 820 821 822 823 809 if (nc >= MAX4CELLS - 1) { 810 delete newcell; 811 return; 812 } 813 C[nc] = newcell; 814 nc++; 824 815 } 825 816 … … 827 818 void f4_Cells::setError(int nerrpos) 828 819 { 829 830 820 error = GENOPER_OPFAIL; 821 errorpos = nerrpos; 831 822 } 832 823 833 824 void f4_Cells::setRepairRemove(int nerrpos, f4_node * rem) 834 825 { 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 } 844 836 } 845 837 846 838 int f4_Cells::setRepairInsert(int nerrpos, f4_node * parent, f4_node * insert) 847 839 { 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 } 860 853 } 861 854 862 855 void f4_Cells::repairGeno(f4_node * geno, int whichchild) 863 856 { 864 865 866 if ((NULL==repair_remove) && (NULL==repair_insert)) return;867 868 869 if (1==whichchild) g2 = geno->child;870 871 872 873 874 875 876 877 878 if (1==whichchild) geno->child= g2->child;879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 repair_insert->child= g2;895 896 897 898 899 900 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); 901 894 } 902 895 … … 904 897 void f4_Cells::toF1Geno(SString &out) 905 898 { 906 907 908 909 910 899 if (tmpcel) delete tmpcel; 900 tmpcel = new f4_Cell(-1, NULL, 0, stdProps); 901 out = ""; 902 toF1GenoRec(0, out); 903 delete tmpcel; 911 904 } 912 905 … … 914 907 void f4_Cells::toF1GenoRec(int curc, SString &out) 915 908 { 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 += ")"; 1017 1011 } 1018 1012 … … 1023 1017 f4_node::f4_node() 1024 1018 { 1025 name= '?';1026 1027 child= NULL;1028 1029 pos= -1;1019 name = '?'; 1020 parent = NULL; 1021 child = NULL; 1022 child2 = NULL; 1023 pos = -1; 1030 1024 } 1031 1025 1032 1026 f4_node::f4_node(char nname, f4_node * nparent, int npos) 1033 1027 { 1034 name= nname;1035 1036 child= NULL;1037 1038 pos= npos;1039 1028 name = nname; 1029 parent = nparent; 1030 child = NULL; 1031 child2 = NULL; 1032 pos = npos; 1033 if (parent) parent->addChild(this); 1040 1034 } 1041 1035 1042 1036 f4_node::~f4_node() 1043 1037 { 1044 1045 1046 1047 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; 1048 1042 } 1049 1043 1050 1044 int f4_node::addChild(f4_node * nchi) 1051 1045 { 1052 if (NULL==child) {1053 1054 1055 1056 if (NULL==child2) {1057 1058 1059 1060 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; 1061 1055 } 1062 1056 1063 1057 int f4_node::removeChild(f4_node * nchi) 1064 1058 { 1065 if (nchi==child2) {1066 1067 1068 1069 if (nchi==child) {1070 1071 1072 1073 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; 1074 1068 } 1075 1069 1076 1070 int f4_node::childCount() 1077 1071 { 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 } 1085 1080 } 1086 1081 1087 1082 int f4_node::count() 1088 1083 { 1089 int c=1;1090 if (NULL!=child) c+=child->count();1091 if (NULL!=child2) c+=child2->count();1092 1084 int c = 1; 1085 if (NULL != child) c += child->count(); 1086 if (NULL != child2) c += child2->count(); 1087 return c; 1093 1088 } 1094 1089 1095 1090 f4_node * f4_node::ordNode(int n) 1096 1091 { 1097 1098 1099 1100 1101 1102 if (n<n1) return child->ordNode(n);1103 1104 1105 1106 1107 if (n<n1) return child2->ordNode(n);1108 1109 1110 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; 1111 1106 } 1112 1107 1113 1108 f4_node * f4_node::randomNode() 1114 1109 { 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)); 1120 1113 } 1121 1114 1122 1115 f4_node * f4_node::randomNodeWithSize(int min, int max) 1123 1116 { 1124 1125 1126 1127 1128 1129 for (i=0; i<maxlim; i++) {1130 1131 1132 if ((n>=min) && (n<=max)) return nod;1133 1134 1135 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; 1136 1129 } 1137 1130 1138 1131 void f4_node::sprint(SString & out) 1139 1132 { 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 += ">"; 1182 1180 } 1183 1181 1184 1182 void f4_node::sprintAdj(char *& buf) 1185 1183 { 1186 1187 1188 SString out(strlen(buf)+2000);1189 out="";1190 1191 1192 1193 1194 1195 if (len>1)1196 if ('>' == out[len-1]) { (out.directWrite())[len-1]=0; out.endWrite();};1197 1198 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); 1203 1201 } 1204 1202 1205 1203 f4_node * f4_node::duplicate() 1206 1204 { 1207 1208 1209 1210 copy->child= NULL;1211 1212 if (NULL != child) {1213 copy->child = child->duplicate();1214 copy->child->parent = copy;1215 1216 if (NULL != child2) {1217 1218 1219 1220 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; 1221 1219 } 1222 1220 … … 1224 1222 void f4_node::destroy() 1225 1223 { 1226 1227 1228 1224 // children are destroyed (recursively) through the destructor 1225 if (NULL != child2) delete child2; 1226 if (NULL != child) delete child; 1229 1227 } 1230 1228 … … 1234 1232 int f4_processrec(const char * genot, unsigned pos0, f4_node * parent) 1235 1233 { 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 1385 1385 } 1386 1386 … … 1388 1388 f4_node * f4_processtree(const char * geno) 1389 1389 { 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 23 6 24 7 #ifndef _F4_GENERAL_H_ 25 8 #define _F4_GENERAL_H_ 26 9 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> 31 14 32 15 #ifdef DMALLOC … … 37 20 class f4_Props 38 21 { 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 22 public: 23 // fill with default values 24 f4_Props(); 25 // must sum to 1 26 void normalizeBiol4(); 27 void executeModifier(char modif); 28 void adjust(); 29 30 double 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; 57 40 }; 58 41 … … 85 68 { 86 69 public: 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 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; 159 142 }; 160 143 … … 164 147 { 165 148 public: 166 167 168 169 170 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; 171 154 }; 172 155 … … 176 159 class f4_Cells 177 160 { 178 179 180 181 182 183 184 185 186 187 int geterror() { return error;};188 int geterrorpos() { return errorpos;};189 190 191 192 193 194 195 196 161 public: 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; 197 180 198 181 private: 199 200 201 202 203 204 205 206 207 208 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 209 192 }; 210 193 … … 216 199 { 217 200 public: 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 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. 240 223 private: 241 224 void sprint(SString & out); // print recursively 242 225 }; 243 226 -
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> 29 11 30 12 #include <stdio.h> 31 13 #include <stdlib.h> 32 #include <math.h>14 #include "common/nonstd_math.h" 33 15 #include <string.h> 34 16 … … 36 18 #define FIELDSTRUCT Geno_f4 37 19 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,},20 static 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, }, 50 32 }; 51 33 … … 55 37 Geno_f4::Geno_f4() 56 38 { 57 supported_format='4';58 59 60 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); 72 54 } 73 55 74 56 int Geno_f4::ValidateRec(f4_node * geno, int retrycount) const 75 57 { 76 77 78 79 f4_Cells cells(geno->child, 1);80 81 82 83 84 85 if (cells.geterrorpos() >= 0) return 1+cells.geterrorpos();86 87 88 89 90 91 92 93 94 95 if (retrycount>0)96 res2 = ValidateRec( geno, retrycount-1);97 98 if (res2==GENOPER_OK) return GENOPER_REPAIR;99 100 101 102 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; 103 85 } 104 86 … … 106 88 int Geno_f4::validate(char *& geno) 107 89 { 108 109 110 if (f4_processrec(geno, 0, &root) || root.childCount()!=1) return GENOPER_OK; // cannot repair111 if (ValidateRec( &root, 20 )==GENOPER_REPAIR) // if repaired, make it back to string112 113 geno[0]=0;114 115 116 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; 117 99 } 118 100 … … 120 102 int Geno_f4::checkValidity(const char * geno) 121 103 { 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 119 int 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; 347 331 } 348 332 … … 350 334 void Geno_f4::linkNodeMakeRandom(f4_node * nn) const 351 335 { 352 353 354 355 356 357 prob1 = 1.0f / RAND_MAX * rand();358 359 360 361 362 i = 1 + (int)(3.999f / RAND_MAX * rand());363 364 365 366 367 368 nn->l1 = (int)(4.0f * (1.0f / RAND_MAX * rand()- 0.5f));369 370 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); 372 356 } 373 357 … … 375 359 void Geno_f4::linkNodeChangeRandom(f4_node * nn) const //rewritten by M.K. - should work as before (not tested) 376 360 { 377 378 379 380 double probs[3]={0.1, 0.3, 0.6};381 382 383 384 385 switch (roulette(probs,3))386 387 388 389 390 391 if (prob2 < 0) i=1; else {prob2 -= 0.10f; if (prob2 < 0) i=2;}392 393 394 395 396 397 398 399 400 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 } 402 386 } 403 387 … … 405 389 void Geno_f4::nparNodeMakeRandom(f4_node * nn) const 406 390 { 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 411 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]; 412 396 } 413 397 … … 415 399 void Geno_f4::repeatNodeChangeRandom(f4_node * nn) const 416 400 { 417 418 419 420 421 422 prob1 = 1.0f / RAND_MAX * rand();423 424 425 if (count<1) count=1;426 if (count>REP_MAXCOUNT) count=REP_MAXCOUNT;427 428 } 429 430 431 int Geno_f4::MutateOneValid(f4_node *& g, int &method) const401 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 415 int Geno_f4::MutateOneValid(f4_node *& g, int &method) const 432 416 // mutate one, until a valid genotype is obtained 433 417 { 434 435 436 437 438 439 440 for (i=0; i<20; i++)441 442 443 444 res = MutateOne(gcopy,method);445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 gcopy->child=NULL;463 gcopy->child2=NULL;464 465 466 467 468 469 470 471 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; 472 456 retm1v: 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 461 int 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; 491 479 } 492 480 … … 497 485 // make a number of mutations 498 486 { 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 n = (int)( 0.5f + 1.0f/RAND_MAX * rand()* maxToMut );535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 487 int res, n, i; 488 int totNodes = 0; 489 int maxToMut = 0; 490 491 // convert to tree 492 f4_node * root; 493 root = new f4_node(); 494 res = f4_processrec(g, 0, root); 495 if (res) { 496 // could not convert, fail 497 goto retm; 498 } 499 if (1 != root->childCount()) { 500 res = GENOPER_OPFAIL; 501 goto retm; 502 } 503 504 // check if original is valid 505 res = ValidateRec( root, 20 ); 506 // might have been repaired! 507 if (GENOPER_REPAIR==res) { 508 res = GENOPER_OK; 509 } 510 if (GENOPER_OK != res) { 511 goto retm; 512 } 513 514 // decide number of nodes to mutate 515 // decide maximum number of nodes to mutate: 0.25*nodes, min 2 516 totNodes = root->child->count(); 517 maxToMut = (int)( 0.25f * totNodes); 518 if (maxToMut<2) maxToMut=2; 519 if (maxToMut>totNodes) maxToMut=totNodes; 520 521 // decide number of nodes to mutate 522 n = (int)( 0.5f + rnd01 * maxToMut ); 523 if (n<1) n=1; 524 if (n>totNodes) n=totNodes; 525 // set chg as this percent 526 chg = ((float)n) / ((float)totNodes); 527 for (i=0; i<n; i++) 528 { 529 res = MutateOneValid(root); 530 if (GENOPER_OK != res) 531 { 532 res = GENOPER_OPFAIL; 533 goto retm; 534 } 535 } 536 // OK, convert back to string 537 g[0]=0; 538 root->child->sprintAdj(g); 551 539 retm: 552 553 540 delete root; 541 return res; 554 542 } 555 543 */ … … 558 546 int Geno_f4::CrossOverOne(f4_node * g1, f4_node * g2, float chg) const 559 547 { 560 561 562 563 564 f4_node * n1, * n2, * n1p, *n2p;565 566 567 size = (1-chg) * (float)g1->count();568 smin = (int)(size*0.9f-1);569 smax = (int)(size*1.1f+1);570 571 572 573 574 size = (1-chg) * (float)g2->count();575 smin = (int)(size*0.9f-1);576 smax = (int)(size*1.1f+1);577 578 579 580 581 582 583 584 585 586 587 588 589 590 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; 591 579 } 592 580 593 581 int Geno_f4::crossOver(char *&g1, char *&g2, float &chg1, float &chg2) 594 582 { 595 596 597 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 602 603 604 605 606 607 if (CrossOverOne(copy1, &root2, chg1) != GENOPER_OK) {delete copy1; copy1=NULL;}608 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 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; 616 604 } 617 605 … … 620 608 unsigned long Geno_f4::style(const char *g, int pos) 621 609 { 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 24 7 25 8 #ifndef _GENO_F4_H_ 26 9 #define _GENO_F4_H_ 27 10 11 #include <stdio.h> 28 12 #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> 33 16 34 17 … … 46 29 47 30 48 class Geno_f4 : public Geno_fx31 class Geno_f4 : public GenoOperators 49 32 { 50 33 public: 51 52 53 54 int mutate(char *& g, float & chg,int &method);55 56 char* getSimplest() {return "X";}; 57 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); 58 41 59 60 double prob[F4_COUNT],probadd[F4_ADD_COUNT];42 // mutation probabilities 43 double prob[F4_COUNT], probadd[F4_ADD_COUNT]; 61 44 62 45 protected: 63 /* int MutateMany(char *& g, float & chg); // not used anymore */64 65 int MutateOne(f4_node *& g,int &method) const;66 67 68 69 70 int MutateOneValid(f4_node * &g,int &method) const;71 72 73 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) 74 57 }; 75 58 -
cpp/frams/genetics/gen-config-GDK.h
r194 r196 15 15 //#define USE_GENCONV_f21 16 16 //#define USE_GENCONV_f30 17 //#define USE_GENCONV_f4017 #define USE_GENCONV_f40 18 18 //#define USE_GENCONV_f41_TEST 19 19 //#define USE_GENCONV_f50 … … 25 25 //#define USE_GENMAN_f2 26 26 //#define USE_GENMAN_f3 27 //#define USE_GENMAN_f427 #define USE_GENMAN_f4 28 28 //#define USE_GENMAN_f5 29 29 #define USE_GENMAN_f9
Note: See TracChangeset
for help on using the changeset viewer.