Changeset 760 for cpp/frams/genetics/f4
- Timestamp:
- 03/15/18 22:55:05 (7 years ago)
- Location:
- cpp/frams/genetics/f4
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/f4/conv_f4.cpp
r736 r760 4 4 5 5 // Copyright (C) 1999,2000 Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL 6 // Copyright (C) since 2001 Maciej Komosinski 7 // 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties 6 8 7 9 #include "conv_f4.h" … … 27 29 int res; 28 30 f4_Model * model = new f4_Model(); 29 res = model->buildFromF4(in );31 res = model->buildFromF4(in, using_checkpoints); 30 32 if (GENOPER_OK != res) return SString(); // oops 31 33 if (NULL != map) … … 52 54 int res; 53 55 f4_Model * model = new f4_Model(); 54 res = model->buildFromF4(in );56 res = model->buildFromF4(in, using_checkpoints); 55 57 if (GENOPER_OK != res) return SString(); // oops 56 58 SString out; … … 71 73 } 72 74 73 int f4_Model::buildFromF4(SString &geno )75 int f4_Model::buildFromF4(SString &geno, bool using_checkpoints) 74 76 { 75 77 int i; … … 101 103 cells->C[i]->recProcessedFlag = 0; 102 104 103 open( ); // begin model build105 open(using_checkpoints); // begin model build 104 106 105 107 // process every cell … … 184 186 partidx = addFromString(PartType, tmpLine, &range); 185 187 if (partidx < 0) return -1; 188 this->checkpoint(); 186 189 jj_p1_refno = partidx; 187 190 } … … 200 203 partidx = addFromString(PartType, tmpLine, &range); 201 204 if (partidx < 0) return -2; 205 this->checkpoint(); 202 206 C->p2_refno = partidx; 203 207 … … 220 224 partidx = addFromString(JointType, tmpLine, &range); 221 225 if (partidx < 0) return -13; 226 this->checkpoint(); 222 227 C->joint_refno = partidx; 223 228 } … … 225 230 if (C->type == T_NEURON4) ///<this case was updated by MacKo 226 231 { 227 // new neuron object 228 // it is linked to a part (not a joint!) 229 int p_refno = C->dadlink->p2_refno; 230 if ((p_refno < 0) || (p_refno >= getPartCount())) return -21; 231 // joint_refno is currently not used 232 sprintf(tmpLine, "p=%ld,d=\"N:in=%g,fo=%g,si=%g\"", 233 p_refno, 234 C->inertia, C->force, C->sigmo); 235 partidx = addFromString(NeuronType, tmpLine, &range); 236 if (partidx < 0) return -22; 232 const char * nclass = C->neuclass->name.c_str(); 233 int partno, jointno; 234 if (C->neuclass->getPreferredLocation() == 0) 235 { 236 if (strcmp(nclass, "N") == 0) 237 { 238 partno = C->dadlink->p2_refno; 239 if ((partno < 0) || (partno >= getPartCount())) return -21; 240 else sprintf(tmpLine, "p=%ld,d=\"N:in=%g,fo=%g,si=%g\"", partno, C->inertia, C->force, C->sigmo); 241 } 242 else 243 { 244 sprintf(tmpLine, "d=\"%s\"", nclass); 245 } 246 partidx = addFromString(NeuronType, tmpLine, &range); 247 if (partidx < 0) return -22; 248 this->checkpoint(); 249 C->neuro_refno = partidx; 250 } 251 else if (C->neuclass->getPreferredLocation() == 1) // attached to Part or have no required attachment - also part 252 { 253 partno = C->dadlink->p2_refno; 254 if ((partno < 0) || (partno >= getPartCount())) return -21; 255 if (strcmp(nclass, "N") == 0) 256 { 257 sprintf(tmpLine, "d=\"N:in=%g,fo=%g,si=%g\"", partno, C->inertia, C->force, C->sigmo); 258 } 259 else 260 { 261 sprintf(tmpLine, "p=%ld,d=\"%s\"", partno, nclass); 262 } 263 partidx = addFromString(NeuronType, tmpLine, &range); 264 if (partidx < 0) return -22; 265 this->checkpoint(); 266 C->neuro_refno = partidx; 267 } 268 else // attached to Joint 269 { 270 jointno = C->dadlink->joint_refno; 271 sprintf(tmpLine, "n:j=%d,d=\"%s\"", jointno, nclass); 272 partidx = addFromString(NeuronType, tmpLine, &range); 273 if (partidx < 0) return -32; 274 this->checkpoint(); 275 } 237 276 C->neuro_refno = partidx; 238 277 int n_refno = C->neuro_refno; 239 278 240 if ( C->ctrl)279 if ((strcmp(nclass,"N") == 0) && C->ctrl) 241 280 { 242 281 if (1 == C->ctrl) … … 248 287 sprintf(tmpLine, "%d,%d", partidx, n_refno); 249 288 if (addFromString(NeuronConnectionType, tmpLine, &range) < 0) return -33; 289 this->checkpoint(); 250 290 } 251 291 … … 256 296 257 297 tmpLine[0] = 0; 258 if (1 == C->links[j]->t) sprintf(tmpLine, "p=%d,d=\"*\"", p_refno); 259 if (2 == C->links[j]->t) sprintf(tmpLine, "j=%d,d=\"G\"", C->dadlink->joint_refno); 260 if (3 == C->links[j]->t) sprintf(tmpLine, "p=%d,d=\"T\"", p_refno); 261 if (4 == C->links[j]->t) sprintf(tmpLine, "p=%d,d=\"S\"", p_refno); 298 if (C->links[j]->from == NULL) 299 { 300 const char * nclass = C->links[j]->t.c_str(); 301 char * temp = (char*)C->links[j]->t.c_str(); 302 NeuroClass * sensortest = GenoOperators::parseNeuroClass(temp); 303 //backward compatibility for G*TS 304 if (C->links[j]->t == "*" || C->links[j]->t == "S" || C->links[j]->t == "T") 305 { 306 sprintf(tmpLine, "p=%d,d=\"%s\"", partno, nclass); 307 } 308 else if (C->links[j]->t == "G") 309 { 310 jointno = C->dadlink->joint_refno; 311 sprintf(tmpLine, "j=%d,d=\"%s\"", jointno, nclass); 312 } 313 else if (sensortest->getPreferredLocation() == 0) 314 { 315 sprintf(tmpLine, "d=\"%s\"",nclass); 316 } 317 else if (sensortest->getPreferredLocation() == 1) 318 { 319 sprintf(tmpLine, "p=%d,d=\"%s\"", partno, nclass); 320 } 321 else 322 { 323 jointno = C->dadlink->joint_refno; 324 sprintf(tmpLine, "j=%d,d=\"%s\"", jointno, nclass); 325 } 326 327 } 262 328 int from = -1; 263 329 if (tmpLine[0]) //input from receptor … … 265 331 from = addFromString(NeuronType, tmpLine, &range); 266 332 if (from < 0) return -34; 333 this->checkpoint(); 267 334 } /*could be 'else'...*/ 335 268 336 if (NULL != C->links[j]->from) // input from another neuron 269 337 from = C->links[j]->from->neuro_refno; … … 272 340 sprintf(tmpLine, "%d,%d,%g", n_refno, from, C->links[j]->w); 273 341 if (addFromString(NeuronConnectionType, tmpLine, &range) < 0) return -35; 342 this->checkpoint(); 274 343 } 275 344 } -
cpp/frams/genetics/f4/conv_f4.h
r736 r760 5 5 // Copyright (C) 1999,2000 Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL 6 6 // Copyright (C) since 2001 Maciej Komosinski 7 // 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties 7 8 8 9 #ifndef _CONV_F4_H_ … … 15 16 16 17 17 // The f4->f0 converter 18 /** 19 * Genotype converter from f4 to f0. 20 */ 18 21 class GenoConv_f40 : public GenoConverter 19 22 { 20 23 public: 21 24 GenoConv_f40(); 25 26 /** 27 * Performs conversion from f4 to f0. Creates f4_Model from f4 genotype 28 * and converts the Model to the f0 genotype string. 29 * @param in f4 genotype 30 * @param map mapping from f4 to Model 31 * @param using_checkpoints determines if checkpoints will be available 32 * @return generated f0 genotype 33 */ 22 34 SString convert(SString &in, MultiMap * map, bool using_checkpoints); 23 35 }; 24 36 25 37 26 // a test-only f4->f1 converter, approximates only 38 /** 39 * Genotype converter from f4 to f1. This is only experimental conversion and 40 * returns an approximate f1 genotype. 41 */ 27 42 class GenoConv_F41_TestOnly : public GenoConverter 28 43 { 29 44 public: 45 /** 46 * Initializes converter. 47 */ 30 48 GenoConv_F41_TestOnly(); 49 50 /** 51 * Performs conversion from f4 to f1. Creates f4_Model from f4 genotype 52 * and converts the Model to the f1 genotype string. The final f1 genotype is 53 * an approximation. 54 * @param in f4 genotype 55 * @param map mapping from f4 to Model 56 * @param using_checkpoints determines if checkpoints will be available 57 * @return generated approximate f1 genotype 58 */ 31 59 SString convert(SString &in, MultiMap * map, bool using_checkpoints); 32 60 }; 33 61 34 62 35 // A Model descendant, which support build from an f4 genotype. 63 /** 64 * A Model descendant which supports building from an f4 genotype. 65 */ 36 66 class f4_Model : public Model 37 67 { … … 39 69 f4_Model(); 40 70 ~f4_Model(); 41 int buildFromF4(SString &geno); 71 72 /** 73 * Builds a Model from the f4 genotype string. 74 * @param geno genotype string 75 * @return GENOPER_OK if a Model could be created, error code otherwise 76 */ 77 int buildFromF4(SString &geno, bool using_checkpoints); 78 /** 79 * Outputs a Model in f1 format. It is an approximation of the input f4 genotype. 80 * @param out the reference that stores the conversion result 81 */ 42 82 void toF1Geno(SString &out); // output to f1 format, approximation 43 83 private: -
cpp/frams/genetics/f4/f4_general.cpp
r671 r760 1 1 // This file is a part of Framsticks SDK. http://www.framsticks.com/ 2 // Copyright (C) 1999-201 7Maciej Komosinski and Szymon Ulatowski.2 // Copyright (C) 1999-2018 Maciej Komosinski and Szymon Ulatowski. 3 3 // See LICENSE.txt for details. 4 4 5 5 // Copyright (C) 1999,2000 Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL 6 // 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties 6 7 7 8 #include "f4_general.h" 9 #include "../oper_fx.h" //for GENOPER_ constants 8 10 #include <common/nonstd_stl.h> 9 11 #include <common/log.h> 10 12 #include <frams/model/model.h> // for min and max attributes 11 #include "../oper_fx.h" //for GENOPER_ constants12 #include <stdio.h>13 13 #include <common/nonstd_math.h> 14 14 … … 17 17 #endif 18 18 19 20 f4_Props::f4_Props()21 {22 length = 1.0;23 curvedness = 0.0;24 weight = 1.0;25 friction = 0.4;26 muscle_power = 0.25; // biol27 assimilation = 0.25; // biol28 stamina = 0.25; // biol29 ingestion = 0.25; // biol30 twist = 0.0;31 energy = 1.0;32 normalizeBiol4();33 }34 35 void f4_Props::normalizeBiol4()36 {37 // make them sum to 138 double sum = muscle_power + assimilation + stamina + ingestion;39 if (sum == 0)40 {41 muscle_power = assimilation = stamina = ingestion = 0.25;42 }43 else44 {45 muscle_power /= sum;46 assimilation /= sum;47 stamina /= sum;48 ingestion /= sum;49 }50 }51 52 void f4_Props::executeModifier(char modif)53 {54 switch (modif)55 {56 case 'L': length += (2.5 - length) * 0.3;57 length = min(length, Model::getMaxJoint().d.x); break;58 case 'l': length += (0.3 - length) * 0.3;59 length = max(length, Model::getMinJoint().d.x); break;60 case 'C': curvedness += (2.0 - curvedness) * 0.25; break;61 case 'c': curvedness += (-2.0 - curvedness) * 0.25; break;62 case 'Q': twist += (1.58 - twist) * 0.3; break;63 case 'q': twist += (-1.58 - twist) * 0.3; break;64 case 'A': assimilation += (1 - assimilation) * 0.8; normalizeBiol4(); break;65 case 'a': assimilation -= assimilation * 0.4; normalizeBiol4(); break;66 case 'I': ingestion += (1 - ingestion) * 0.8; normalizeBiol4(); break;67 case 'i': ingestion -= ingestion * 0.4; normalizeBiol4(); break;68 case 'S': stamina += (1 - stamina) * 0.8; normalizeBiol4(); break;69 case 's': stamina -= stamina * 0.4; normalizeBiol4(); break;70 case 'M': muscle_power += (1 - muscle_power) * 0.8; normalizeBiol4(); break;71 case 'm': muscle_power -= muscle_power * 0.4; normalizeBiol4(); break;72 case 'F': friction += (4 - friction) * 0.2; break;73 case 'f': friction -= friction * 0.2; break;74 case 'W': weight += (2.0 - weight) * 0.3; break;75 case 'w': weight += (0.5 - weight) * 0.3; break;76 case 'E': energy += (10.0 - energy) * 0.1; break;77 case 'e': energy -= energy * 0.1; break;78 }79 }80 81 void f4_Props::adjust()82 {83 length = 0.5*length + 0.5*stdProps.length;84 curvedness = 0.66 * curvedness;85 twist = 0.66 * twist;86 }87 88 f4_Props stdProps;89 90 91 19 void rolling_dec(double * v) 92 20 { … … 98 26 *v += 0.7853; // 0.7853981 45 degrees 99 27 } 100 101 28 102 29 int scanrec(const char * s, unsigned int slen, char stopchar) … … 136 63 137 64 f4_Cell::f4_Cell(int nname, 138 f4_Cell * ndad, int nangle, f4_Props newP)65 f4_Cell * ndad, int nangle, GeneProps newP) 139 66 { 140 67 name = nname; … … 145 72 gcur = NULL; 146 73 active = 1; 147 repeat. null();74 repeat.clear(); 148 75 //genoRange.clear(); -- implicit 149 76 … … 187 114 188 115 189 f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur, f4_Cell * ndad, int nangle, f4_Props newP)116 f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur, f4_Cell * ndad, int nangle, GeneProps newP) 190 117 { 191 118 name = nname; … … 196 123 gcur = ngcur; 197 124 active = 1; 198 repeat. null();125 repeat.clear(); 199 126 //genoRange.clear(); -- implicit 200 127 // preserve geno range of parent cell … … 261 188 int f4_Cell::onestep() 262 189 { 263 int i, j, k, relfrom, t;264 double w;265 f4_Cell * tmp;266 f4_Cell * tneu;267 190 if (gcur == NULL) 268 191 { … … 275 198 // currently this is the last one processed 276 199 // the current genotype code is processed 277 genoRange.add(gcur->pos); 278 switch (gcur->name) 279 { 280 case '<': 281 // cell division! 282 //DB( printf(" div! %d\n", name); ) 283 284 // error: sticks cannot divide 285 if (T_STICK4 == type) 286 { 287 // cannot fix 288 org->setError(gcur->pos); 289 return 1; // stop 290 } 291 292 // undiff divides 293 if (T_UNDIFF4 == type) 294 { 295 // commacount is set only when daughter turns into X 296 // daughter cell 297 // adjust new len 298 f4_Props newP = P; 299 newP.adjust(); 300 tmp = new f4_Cell(org, org->nc, genot, gcur->child2, this, commacount, newP); 301 tmp->repeat = repeat; 302 repeat.null(); 303 org->addCell(tmp); 304 } 305 // a neuron divides: create a new, duplicate links 306 if (T_NEURON4 == type) { 307 // daughter cell 308 tmp = new f4_Cell(org, org->nc, genot, gcur->child2, 309 // has the same dadlink 310 this->dadlink, commacount, P); 311 tmp->repeat = repeat; 312 repeat.null(); 313 // it is a neuron from start 314 tmp->type = T_NEURON4; 315 // duplicate links 316 f4_CellLink * ll; 317 for (i = 0; i < nolink; i++) 318 { 319 ll = links[i]; 320 tmp->addlink(ll->from, ll->w, ll->t); 321 } 322 org->addCell(tmp); 323 } 324 // adjustments for this cell 325 gcur = gcur->child; 326 // halt development 327 return 0; 328 329 case '>': 330 // finish 331 // see if there is a repet count 332 if (repeat.top > 0) 333 { // there is a repeat counter 334 if (!repeat.first()->isNull()) 335 { // repeat counter is not null 336 repeat.first()->dec(); 337 if (repeat.first()->count > 0) 200 //genoRange.add(gcur->pos,gcur->pos+gcur->name.length()-1); 201 bool neuclasshandler = false; // if set to true, then there is a set of characters that can be assigned to a neuron class type 202 // old semantics, one-character 203 if (gcur->name.length() == 1) 204 { 205 genoRange.add(gcur->pos, gcur->pos); 206 char name = gcur->name[0]; 207 switch (name) 208 { 209 case '<': 210 { 211 // cell division! 212 //DB( printf(" div! %d\n", name); ) 213 214 // error: sticks cannot divide 215 if (T_STICK4 == type) 216 { 217 // cannot fix 218 org->setError(gcur->pos); 219 return 1; // stop 220 } 221 222 // undiff divides 223 if (T_UNDIFF4 == type) 224 { 225 // commacount is set only when daughter turns into X 226 // daughter cell 227 // adjust new len 228 GeneProps newP = P; 229 newP.propagateAlong(false); 230 f4_Cell * tmp = new f4_Cell(org, org->nc, genot, gcur->child2, this, commacount, newP); 231 tmp->repeat = repeat; 232 repeat.clear(); 233 org->addCell(tmp); 234 } 235 // a neuron divides: create a new, duplicate links 236 if (T_NEURON4 == type) { 237 // daughter cell 238 f4_Cell *tmp = new f4_Cell(org, org->nc, genot, gcur->child2, 239 // has the same dadlink 240 this->dadlink, commacount, P); 241 tmp->repeat = repeat; 242 repeat.clear(); 243 // it is a neuron from start 244 tmp->type = T_NEURON4; 245 // it has the same type as the parent neuron 246 tmp->neuclass = neuclass; 247 // duplicate links 248 f4_CellLink * ll; 249 for (int i = 0; i < nolink; i++) 338 250 { 339 // return to repeat 340 gcur = repeat.first()->node->child; 251 ll = links[i]; 252 tmp->addlink(ll->from, ll->w, ll->t); 253 } 254 org->addCell(tmp); 255 } 256 // adjustments for this cell 257 gcur = gcur->child; 258 // halt development 259 return 0; 260 } 261 case '>': 262 { 263 // finish 264 // see if there is a repet count 265 if (repeat.top > 0) 266 { // there is a repeat counter 267 if (!repeat.first()->isNull()) 268 { // repeat counter is not null 269 repeat.first()->dec(); 270 if (repeat.first()->count > 0) 271 { 272 // return to repeat 273 gcur = repeat.first()->node->child; 274 } 275 else 276 { 277 // continue 278 gcur = repeat.first()->node->child2; 279 repeat.pop(); 280 } 281 break; 341 282 } 342 283 else 343 284 { 344 // continue345 gcur = repeat.first()->node->child2;346 285 repeat.pop(); 347 286 } 287 } 288 else 289 { 290 // error: still undiff 291 if (T_UNDIFF4 == type) 292 { 293 // fix it: insert an 'X' 294 f4_node *insertnode = new f4_node("X", NULL, gcur->pos); 295 if (org->setRepairInsert(gcur->pos, gcur, insertnode)) // not in repair mode, release 296 delete insertnode; 297 return 1; 298 } 299 repeat.clear(); 300 active = 0; // stop 301 // eat up rest 302 gcur = NULL; 303 return 0; 304 } 305 } 306 /* no break */ 307 case '#': 308 { 309 // repetition marker 310 if (repeat.top >= repeat_stack::stackSize) 311 { 312 // repeat pointer stack is full, cannot remember this one. 313 // fix: delete it 314 org->setRepairRemove(gcur->pos, gcur); 315 return 1; // stop 316 } 317 repeat.push(repeat_ptr(gcur, gcur->i1)); 318 gcur = gcur->child; 319 break; 320 } 321 case ',': 322 { 323 commacount++; 324 gcur = gcur->child; 325 break; 326 } 327 case 'r': case 'R': 328 { 329 // error: if neuron 330 if (T_NEURON4 == type) 331 { 332 // fix: delete it 333 org->setRepairRemove(gcur->pos, gcur); 334 return 1; // stop 335 } 336 switch (name) 337 { 338 case 'r': rolling_dec(&rolling); break; 339 case 'R': rolling_inc(&rolling); break; 340 } 341 gcur = gcur->child; 342 break; 343 } 344 case 'l': case 'L': 345 case 'c': case 'C': 346 case 'q': case 'Q': 347 case 'a': case 'A': 348 case 'i': case 'I': 349 case 's': case 'S': 350 case 'm': case 'M': 351 case 'f': case 'F': 352 case 'w': case 'W': 353 case 'e': case 'E': 354 case 'd': case 'D': 355 case 'g': case 'G': 356 case 'b': case 'B': 357 case 'h': case 'H': 358 { 359 // error: if neuron 360 if (T_NEURON4 == type) 361 { 362 // fix: delete it 363 org->setRepairRemove(gcur->pos, gcur); 364 return 1; // stop 365 } 366 P.executeModifier(name); 367 gcur = gcur->child; 368 break; 369 } 370 case 'X': 371 { 372 // turn undiff. cell into a stick 373 // error: already differentiated 374 if (T_UNDIFF4 != type) 375 { 376 // fix: delete this node 377 org->setRepairRemove(gcur->pos, gcur); 378 return 1; // stop 379 } 380 type = T_STICK4; 381 // fix dad commacount and own anglepos 382 if (NULL != dadlink) 383 { 384 dadlink->commacount++; 385 anglepos = dadlink->commacount; 386 } 387 // change of type halts developments, see comment at 'N' 388 gcur = gcur->child; 389 return 0; 390 } 391 case 'N': 392 { 393 // turn undiff. cell into a neuron 394 // error: already differentiated 395 if (T_UNDIFF4 != type) 396 { 397 // fix: delete this node 398 org->setRepairRemove(gcur->pos, gcur); 399 return 1; // stop 400 } 401 // error: if no previous 402 if (NULL == dadlink) 403 { 404 // fix: delete it 405 org->setRepairRemove(gcur->pos, gcur); 406 return 1; // stop 407 } 408 string temp1 = "N"; 409 char *temp = (char*)temp1.c_str(); 410 neuclass = GenoOperators::parseNeuroClass(temp); 411 type = T_NEURON4; 412 // change of type also halts development, to give other 413 // cells a chance for adjustment. Namely, it is important 414 // to wait for other cells to turn N before adding links 415 gcur = gcur->child; 416 return 0; 417 } 418 case '@': 419 case '|': 420 { 421 // neuron rotating / bending 422 int j = 1; 423 if ('@' == name) j = 1; // rot 424 else 425 if ('|' == name) j = 2; // bend 426 427 // if undiff, then this is a new muscle. Thanks to f4_processrec @ and | case we can skip repairing 428 if (T_UNDIFF4 == type) 429 { 430 neuclasshandler = true; 348 431 break; 349 432 } 350 else 351 { 352 repeat.pop(); 353 } 354 } 355 else 356 { 357 // error: still undiff 358 if (T_UNDIFF4 == type) 359 { 360 // fix it: insert an 'X' 361 f4_node * insertnode = new f4_node('X', NULL, gcur->pos); 362 if (org->setRepairInsert(gcur->pos, gcur, insertnode)) // not in repair mode, release 363 delete insertnode; 364 return 1; 365 } 366 repeat.null(); 367 active = 0; // stop 368 // eat up rest 369 gcur = NULL; 370 return 0; 371 } 372 373 case '#': 374 // repetition marker 375 if (repeat.top >= repeat_stack::stackSize) 376 { 377 // repepeat pointer stack is full, cannot remember this one. 433 434 // error: not a neuron (stick) 435 if (T_NEURON4 != type) 436 { 437 // fix: delete it 438 org->setRepairRemove(gcur->pos, gcur); 439 return 1; // stop 440 } 441 // error: already has control 442 if (ctrl != 0) 443 { 444 // fix: delete it 445 org->setRepairRemove(gcur->pos, gcur); 446 return 1; // stop 447 } 448 // make neuron ctrl = 1 or 2 449 ctrl = j; 450 gcur = gcur->child; 451 break; 452 } 453 case '[': 454 { 455 // link to neuron 456 // error: not a neuron 457 if (T_NEURON4 != type) 458 { 459 // fix: delete it 460 org->setRepairRemove(gcur->pos, gcur); 461 return 1; // stop 462 } 463 // input (sensor or %d) 464 int t = gcur->i1; 465 int relfrom = gcur->l1; 466 float w = gcur->f1; 467 f4_Cell *tneu = NULL; 468 if (t > 0) // sensors 469 { 470 char *temp = (char*)gcur->s1.c_str(); 471 NeuroClass *sensortest = GenoOperators::parseNeuroClass(temp); 472 if (sensortest == NULL || sensortest->getPreferredInputs() != 0) 473 { 474 // error: unknown code 475 string buf = "wrong sensor in link '"; 476 buf.append(gcur->s1); 477 buf.append("'"); 478 logMessage("f4_Cell", "onestep", LOG_WARN, buf.c_str()); //TODO ask 479 org->setRepairRemove(gcur->pos, gcur); 480 return 1; 481 } 482 } 483 else { 484 // input from other neuron 485 // find neuron at relative i 486 // find own index 487 int j = 0, k = 0; 488 for (int i = 0; i < org->nc; i++) 489 { 490 if (org->C[i]->type == T_NEURON4) k++; 491 if (org->C[i] == this) { j = k - 1; break; } 492 } 493 // find index of incoming 494 j = j + relfrom; 495 if (j < 0) goto wait_link; 496 if (j >= org->nc) goto wait_link; 497 // find that neuron 498 k = 0; 499 int i; 500 for (i = 0; i < org->nc; i++) 501 { 502 if (org->C[i]->type == T_NEURON4) k++; 503 if (j == (k - 1)) break; 504 } 505 if (i >= org->nc) goto wait_link; 506 tneu = org->C[i]; 507 } 508 // add link 509 // error: could not add link (too many?) 510 if (addlink(tneu, w, gcur->s1)) 511 { 512 // cannot fix 513 org->setError(gcur->pos); 514 return 1; // stop 515 } 516 gcur = gcur->child; 517 break; 518 } 519 wait_link: 520 { 521 // wait for other neurons to develop 522 // if there are others still active 523 active = 0; 524 int j = 0; 525 for (int i = 0; i < org->nc; i++) 526 { 527 if (org->C[i]->active) j++; 528 } 529 if (j > 0) 530 return 0; // there is other active, halt, try again 531 // no more actives, cannot add link, ignore, but treat not as an error 532 gcur = gcur->child; 533 } 534 break; 535 case ':': 536 { 537 // neuron parameter 538 // error: not a neuron 539 if (T_NEURON4 != type) 540 { 541 // fix: delete it 542 org->setRepairRemove(gcur->pos, gcur); 543 return 1; // stop 544 } 545 int j = (int)gcur->l1; 546 switch ((char)gcur->i1) 547 { 548 case '!': 549 if (j) 550 force += (1.0 - force) * 0.2; 551 else 552 force -= force * 0.2; 553 break; 554 case '=': 555 if (j) 556 inertia += (1.0 - inertia) * 0.2; 557 else 558 inertia -= inertia * 0.2; 559 break; 560 case '/': 561 if (j) 562 sigmo *= 1.4; 563 else 564 sigmo /= 1.4; 565 break; 566 default: 567 org->setRepairRemove(gcur->pos, gcur); 568 return 1; // stop 569 } 570 gcur = gcur->child; 571 break; 572 } 573 case ' ': 574 { 575 // space has no effect, should not occur 576 // fix: delete it 577 org->setRepairRemove(gcur->pos, gcur); 578 gcur = gcur->child; 579 break; 580 } 581 default: 582 { 583 // because there are one-character neuron classes, default move control to neuclasshandler 584 neuclasshandler = true; 585 } 586 } 587 } 588 else 589 { 590 // if many characters, then it needs to be parsed below 591 neuclasshandler = true; 592 } 593 594 if (neuclasshandler) 595 { 596 genoRange.add(gcur->pos, gcur->pos + gcur->name.length() + 2 - 1); // +2 for N: 597 if (T_UNDIFF4 != type) 598 { 599 // fix: delete this node 600 org->setRepairRemove(gcur->pos, gcur); 601 return 1; // stop 602 } 603 // error: if no previous 604 if (NULL == dadlink) 605 { 378 606 // fix: delete it 379 607 org->setRepairRemove(gcur->pos, gcur); 380 608 return 1; // stop 381 609 } 382 repeat.push(repeat_ptr(gcur, gcur->i1)); 610 // multiple characters are neuron types. Need to check if exists 611 char *temp = (char*)gcur->name.c_str(); 612 neuclass = GenoOperators::parseNeuroClass(temp); 613 if (neuclass == NULL) 614 { 615 // error: unknown code 616 string buf = "unknown code '"; 617 buf.append(gcur->name); 618 buf.append("'"); 619 logMessage("f4_Cell", "onestep", 2, buf.c_str()); 620 org->setRepairRemove(gcur->pos, gcur); 621 return 1; 622 } 623 type = T_NEURON4; //they belong to neurons 383 624 gcur = gcur->child; 384 break; 385 386 case ',': 387 commacount++; 388 gcur = gcur->child; 389 break; 390 391 case 'r': case 'R': 392 // error: if neuron 393 if (T_NEURON4 == type) 394 { 395 // fix: delete it 396 org->setRepairRemove(gcur->pos, gcur); 397 return 1; // stop 398 } 399 switch (gcur->name) 400 { 401 case 'r': rolling_dec(&rolling); break; 402 case 'R': rolling_inc(&rolling); break; 403 } 404 gcur = gcur->child; 405 break; 406 407 case 'l': case 'L': 408 case 'c': case 'C': 409 case 'q': case 'Q': 410 case 'a': case 'A': 411 case 'i': case 'I': 412 case 's': case 'S': 413 case 'm': case 'M': 414 case 'f': case 'F': 415 case 'w': case 'W': 416 case 'e': case 'E': 417 // error: if neuron 418 if (T_NEURON4 == type) 419 { 420 // fix: delete it 421 org->setRepairRemove(gcur->pos, gcur); 422 return 1; // stop 423 } 424 P.executeModifier(gcur->name); 425 gcur = gcur->child; 426 break; 427 428 case 'X': 429 // turn undiff. cell into a stick 430 // error: already differentiated 431 if (T_UNDIFF4 != type) 432 { 433 // fix: delete this node 434 org->setRepairRemove(gcur->pos, gcur); 435 return 1; // stop 436 } 437 type = T_STICK4; 438 // fix dad commacount and own anglepos 439 if (NULL != dadlink) 440 { 441 dadlink->commacount++; 442 anglepos = dadlink->commacount; 443 } 444 // change of type halts developments, see comment at 'N' 445 gcur = gcur->child; 446 return 0; 447 448 case 'N': 449 // turn undiff. cell into a neuron 450 // error: already differentiated 451 if (T_UNDIFF4 != type) 452 { 453 // fix: delete this node 454 org->setRepairRemove(gcur->pos, gcur); 455 return 1; // stop 456 } 457 // error: if no previous 458 if (NULL == dadlink) 459 { 460 // fix: delete it 461 org->setRepairRemove(gcur->pos, gcur); 462 return 1; // stop 463 } 464 type = T_NEURON4; 465 // change of type also halts development, to give other 466 // cells a chance for adjustment. Namely, it is important 467 // to wait for other cells to turn N before adding links 468 gcur = gcur->child; 469 return 0; 470 471 case '@': 472 case '|': 473 // neuron rotating / bending 474 j = 1; 475 if ('@' == gcur->name) j = 1; // rot 476 if ('|' == gcur->name) j = 2; // bend 477 // error: not a neuron (undiff) 478 if (T_UNDIFF4 == type) 479 { 480 // fix: delete it 481 org->setRepairRemove(gcur->pos, gcur); 482 return 1; // stop 483 } 484 // error: not a neuron (stick) 485 if (T_NEURON4 != type) 486 { 487 // fix: delete it 488 org->setRepairRemove(gcur->pos, gcur); 489 return 1; // stop 490 } 491 // error: already has control 492 if (ctrl != 0) 493 { 494 // fix: delete it 495 org->setRepairRemove(gcur->pos, gcur); 496 return 1; // stop 497 } 498 // make neuron ctrl = 1 or 2 499 ctrl = j; 500 gcur = gcur->child; 501 break; 502 503 case '[': 504 // link to neuron 505 // error: not a neuron 506 if (T_NEURON4 != type) 507 { 508 // fix: delete it 509 org->setRepairRemove(gcur->pos, gcur); 510 return 1; // stop 511 } 512 // input ('*', 'G', 'T', 'S', or %d) 513 t = gcur->i1; 514 relfrom = gcur->l1; 515 w = gcur->f1; 516 if (t > 0) 517 { 518 // * or G 519 tneu = NULL; 520 } 521 else { 522 // input from other neuron 523 // find neuron at relative i 524 // find own index 525 j = 0; k = 0; 526 for (i = 0; i < org->nc; i++) 527 { 528 if (org->C[i]->type == T_NEURON4) k++; 529 if (org->C[i] == this) { j = k - 1; break; } 530 } 531 // find index of incoming 532 j = j + relfrom; 533 if (j < 0) goto wait_link; 534 if (j >= org->nc) goto wait_link; 535 // find that neuron 536 k = 0; 537 for (i = 0; i < org->nc; i++) 538 { 539 if (org->C[i]->type == T_NEURON4) k++; 540 if (j == (k - 1)) break; 541 } 542 if (i >= org->nc) goto wait_link; 543 tneu = org->C[i]; 544 } 545 // add link 546 // error: could not add link (too many?) 547 if (addlink(tneu, w, t)) 548 { 549 // cannot fix 550 org->setError(gcur->pos); 551 return 1; // stop 552 } 553 gcur = gcur->child; 554 break; 555 wait_link: 556 // wait for other neurons to develop 557 // if there are others still active 558 active = 0; 559 j = 0; 560 for (i = 0; i < org->nc; i++) 561 { 562 if (org->C[i]->active) j++; 563 } 564 if (j > 0) 565 return 0; // there is other active, halt, try again 566 // no more actives, cannot add link, ignore, but treat not as an error 567 gcur = gcur->child; 568 break; 569 570 case ':': 571 // neuron parameter 572 // error: not a neuron 573 if (T_NEURON4 != type) 574 { 575 // fix: delete it 576 org->setRepairRemove(gcur->pos, gcur); 577 return 1; // stop 578 } 579 j = (int)gcur->l1; 580 switch ((char)gcur->i1) 581 { 582 case '!': 583 if (j) force += (1.0 - force) * 0.2; 584 else force -= force * 0.2; break; 585 case '=': 586 if (j) inertia += (1.0 - inertia) * 0.2; 587 else inertia -= inertia * 0.2; break; 588 case '/': 589 if (j) sigmo *= 1.4; 590 else sigmo /= 1.4; break; 591 default: 592 org->setRepairRemove(gcur->pos, gcur); 593 return 1; // stop 594 } 595 gcur = gcur->child; 596 break; 597 598 case ' ': 599 // space has no effect, should not occur 600 // fix: delete it 601 org->setRepairRemove(gcur->pos, gcur); 602 gcur = gcur->child; 603 break; 604 605 default: 606 // error: unknown code 607 char buf[40]; 608 sprintf(buf, "unknown code '%c'", gcur->name); 609 logMessage("f4_Cell", "onestep", 2, buf); 610 // fix: delete it 611 org->setRepairRemove(gcur->pos, gcur); 612 return 1; // stop 625 return 0; //stop 613 626 } 614 627 } … … 618 631 619 632 620 int f4_Cell::addlink(f4_Cell * nfrom, double nw, int nt) 621 { 633 int f4_Cell::addlink(f4_Cell * nfrom, double nw, string nt) 634 { 635 // if incoming neuron does not produce output, return error 636 if (nfrom != NULL && nfrom->neuclass->getPreferredOutput() == 0) return -1; 637 if (neuclass->getPreferredInputs() != -1 && nolink >= neuclass->getPreferredInputs()) return -1; 622 638 if (nolink >= MAXINPUTS - 1) return -1; // full! 623 639 links[nolink] = new f4_CellLink(nfrom, nw, nt); … … 664 680 { 665 681 //firstend = dadlink->lastend; 666 f4_Props Pdad = dadlink->P;667 f4_Props Padj = Pdad;668 Padj. adjust();682 GeneProps Pdad = dadlink->P; 683 GeneProps Padj = Pdad; 684 Padj.propagateAlong(false); 669 685 670 686 //rot = Orient_1; … … 700 716 701 717 702 f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, intnt)718 f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, string nt) 703 719 { 704 720 from = nfrom; … … 720 736 tmpcel = NULL; 721 737 f4rootnode = NULL; 722 723 C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, stdProps); 738 C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, GeneProps::standard_values); 724 739 nc = 1; 725 740 } … … 748 763 749 764 // create ancestor cell 750 C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child, NULL, 0, stdProps);765 C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child, NULL, 0, GeneProps::standard_values); 751 766 nc = 1; 752 767 } … … 939 954 { 940 955 if (tmpcel) delete tmpcel; 941 tmpcel = new f4_Cell(-1, NULL, 0, stdProps);956 tmpcel = new f4_Cell(-1, NULL, 0, GeneProps::standard_values); 942 957 out = ""; 943 958 toF1GenoRec(0, out); … … 962 977 963 978 // adjust length, curvedness, etc. 964 tmpcel->P. adjust();979 tmpcel->P.propagateAlong(false); 965 980 while (tmpcel->P.length > thisti->P.length) 966 981 { … … 1015 1030 if (NULL == thneu->links[j]->from) 1016 1031 { 1017 // sensory 1018 if (1 == thneu->links[j]->t) out += "*"; 1019 if (2 == thneu->links[j]->t) out += "G"; 1020 if (3 == thneu->links[j]->t) out += "T"; 1021 if (4 == thneu->links[j]->t) out += "S"; 1032 // sensors 1033 out += thneu->links[j]->t.c_str(); 1022 1034 } 1023 1035 else … … 1073 1085 f4_node::f4_node() 1074 1086 { 1075 name = '?';1087 name = "?"; 1076 1088 parent = NULL; 1077 1089 child = NULL; 1078 1090 child2 = NULL; 1079 1091 pos = -1; 1080 } 1081 1082 f4_node::f4_node(char nname, f4_node * nparent, int npos) 1092 l1 = 0; 1093 i1 = 0; 1094 f1 = 0.0f; 1095 } 1096 1097 f4_node::f4_node(string nname, f4_node *nparent, int npos) 1083 1098 { 1084 1099 name = nname; … … 1088 1103 pos = npos; 1089 1104 if (parent) parent->addChild(this); 1105 l1 = 0; 1106 i1 = 0; 1107 f1 = 0.0f; 1108 } 1109 1110 f4_node::f4_node(char nname, f4_node * nparent, int npos) 1111 { 1112 name = nname; 1113 parent = nparent; 1114 child = NULL; 1115 child2 = NULL; 1116 pos = npos; 1117 if (parent) parent->addChild(this); 1118 l1 = 0; 1119 i1 = 0; 1120 f1 = 0.0f; 1090 1121 } 1091 1122 … … 1194 1225 } 1195 1226 1196 void f4_node::sprint(SString 1197 { 1198 char buf2[20];1227 void f4_node::sprint(SString& out) 1228 { 1229 string buf2 = ""; 1199 1230 // special case: repetition code 1200 if ( '#' == name)1231 if (name == "#") 1201 1232 { 1202 1233 out += "#"; 1203 1234 if (i1 != 1) 1204 1235 { 1205 sprintf( buf2, "%d", i1);1206 out += buf2 ;1236 sprintf((char*)buf2.c_str(), "%d", i1); 1237 out += buf2.c_str(); 1207 1238 } 1208 1239 } 1209 1240 else { 1210 1241 // special case: neuron link 1211 if ( '[' == name)1242 if (name == "[") 1212 1243 { 1213 1244 out += "["; … … 1215 1246 { 1216 1247 // sensor input 1217 if (1 == i1) out += "*"; 1218 if (2 == i1) out += "G"; 1219 if (3 == i1) out += "T"; 1220 if (4 == i1) out += "S"; 1248 out += s1.c_str(); 1221 1249 } 1222 1250 else 1223 1251 { 1224 sprintf(buf2, "%ld", l1); 1225 out += buf2; 1226 } 1227 sprintf(buf2, ":%g]", f1); 1228 out += buf2; 1229 } 1230 else if (':' == name) 1231 { 1232 sprintf(buf2, ":%c%c:", l1 ? '+' : '-', (char)i1); 1233 out += buf2; 1252 sprintf((char*)buf2.c_str(), "%ld", l1); 1253 out += buf2.c_str(); 1254 } 1255 sprintf((char*)buf2.c_str(), ":%g]", f1); 1256 out += buf2.c_str(); 1257 } 1258 else if (name == ":") 1259 { 1260 sprintf((char*)buf2.c_str(), ":%c%c:", l1 ? '+' : '-', (char)i1); 1261 out += buf2.c_str(); 1262 } 1263 else if (name == "@" || name == "|") 1264 { 1265 if (parent->name == "N") 1266 { 1267 buf2 = name; 1268 out += buf2.c_str(); 1269 } 1270 else 1271 { 1272 out += "N:"; 1273 buf2 = name; 1274 out += buf2.c_str(); 1275 } 1234 1276 } 1235 1277 else 1236 1278 { 1237 buf2[0] = name; 1238 buf2[1] = 0; 1239 out += buf2; 1279 char *temp = (char*)name.c_str(); 1280 NeuroClass * nc = GenoOperators::parseNeuroClass(temp); 1281 if (nc != NULL) 1282 { 1283 out += "N:"; 1284 } 1285 buf2 = name; 1286 out += buf2.c_str(); 1240 1287 } 1241 1288 } … … 1301 1348 } 1302 1349 1303 1304 1350 // scan genotype string and build tree 1305 1351 // return >1 for error (errorpos) 1306 1352 int f4_processrec(const char * genot, unsigned pos0, f4_node * parent) 1307 1353 { 1308 int i, j, t, res;1309 char tc1, tc2 ;1354 int i, j, res, t; 1355 char tc1, tc2, tc3; // tc3 is only to ensure that in the end of neuron parameter definition 1310 1356 int relfrom; 1311 1357 double w; 1312 1358 unsigned gpos, oldpos; 1313 1359 f4_node * node1, *par; 1360 unsigned beginindex; 1361 string neutype = ""; 1314 1362 1315 1363 gpos = pos0; … … 1318 1366 while (gpos < strlen(genot)) 1319 1367 { 1320 //DB( printf(" processing '%c' %d %s\n", genot[gpos], gpos, genot); ) 1368 neutype = ""; 1369 // first switch across cell dividers and old semantics 1321 1370 switch (genot[gpos]) 1322 1371 { 1323 1372 case '<': 1324 // cell division! 1325 //DB( printf(" div! %d\n", name); ) 1326 1373 { 1327 1374 // find out genotype start for child 1328 1375 j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), '>'); 1329 1376 1330 node1 = new f4_node( '<', par, gpos);1377 node1 = new f4_node("<", par, gpos); 1331 1378 par = node1; 1332 1379 res = f4_processrec(genot, gpos + 1, par); … … 1339 1386 else // ran out 1340 1387 { 1341 node1 = new f4_node( '>', par, strlen(genot) - 1);1388 node1 = new f4_node(">", par, strlen(genot) - 1); 1342 1389 par = node1; 1343 1390 } 1344 // adjustments1345 1391 gpos++; 1346 1392 return 0; // OK 1347 1393 } 1348 1394 case '>': 1349 node1 = new f4_node('>', par, gpos); 1395 { 1396 node1 = new f4_node(">", par, gpos); 1350 1397 par = node1; 1351 1398 gpos = strlen(genot); 1352 1399 return 0; // OK 1353 1400 } 1354 1401 case '#': 1402 { 1355 1403 // repetition marker, 1 by default 1356 1404 if (sscanf(genot + gpos, "#%d", &i) != 1) i = 1; … … 1361 1409 gpos++; 1362 1410 while ((genot[gpos] >= '0') && (genot[gpos] <= '9')) gpos++; 1363 node1 = new f4_node( '#', par, oldpos);1411 node1 = new f4_node("#", par, oldpos); 1364 1412 node1->i1 = i; 1365 1413 par = node1; … … 1373 1421 else // ran out 1374 1422 { 1375 node1 = new f4_node( '>', par, strlen(genot) - 1);1423 node1 = new f4_node(">", par, strlen(genot) - 1); 1376 1424 } 1377 1425 return 0; // OK 1378 1379 // 'simple' nodes: 1380 case ',': 1426 } 1427 case ' ': 1428 case '\n': 1429 case '\r': 1430 case '\t': 1431 { 1432 // whitespace: ignore 1433 gpos++; 1434 break; 1435 } 1381 1436 case 'l': case 'L': 1382 1437 case 'c': case 'C': 1383 1438 case 'q': case 'Q': 1384 1439 case 'r': case 'R': 1385 case 'X': case 'N': 1386 case '@': case '|': 1440 case 'X': case ',': 1387 1441 case 'a': case 'A': 1388 1442 case 's': case 'S': … … 1392 1446 case 'w': case 'W': 1393 1447 case 'e': case 'E': 1448 { 1394 1449 node1 = new f4_node(genot[gpos], par, gpos); 1395 1450 par = node1; 1396 1451 gpos++; 1397 1452 break; 1398 1453 } 1454 case '@': case '|': 1455 { 1456 // in order to prevent the presence of "free muscles", we need to ensure that a muscle is written as N@/N| or N:@/N:| 1457 if (par != NULL && par->name == "N") 1458 { 1459 node1 = new f4_node(genot[gpos], par, gpos); 1460 par = node1; 1461 gpos++; 1462 } 1463 else 1464 { 1465 return gpos + 1; 1466 } 1467 break; 1468 } 1469 1470 case 'N': 1471 { 1472 // if there is no colon after N, then there is no class definition 1473 if (gpos + 1 >= strlen(genot) || genot[gpos + 1] != ':') 1474 { 1475 node1 = new f4_node(genot[gpos], par, gpos); 1476 par = node1; 1477 gpos++; 1478 break; 1479 } 1480 // if there is a colon determining neuron parameter, then let the switch case colon handle this 1481 else if (sscanf(genot + gpos + 1, ":%c%c%[:]", &tc1, &tc2, &tc3) == 3) 1482 { 1483 node1 = new f4_node(genot[gpos], par, gpos); 1484 par = node1; 1485 gpos++; 1486 break; 1487 } 1488 int forgenorange = gpos; 1489 gpos += 2; //skipping "N:" 1490 beginindex = gpos; 1491 char * end = (char*)genot + beginindex; 1492 GenoOperators::parseNeuroClass(end); 1493 gpos += end - genot - beginindex; 1494 neutype = string(genot + beginindex, genot + gpos); 1495 node1 = new f4_node(neutype, par, forgenorange); 1496 par = node1; 1497 break; 1498 } 1499 case ':': 1500 { 1501 // neuron parameter +! -! += -= +/ or -/ 1502 if (sscanf(genot + gpos, ":%c%c%[:]", &tc1, &tc2, &tc3) != 3) 1503 // error: incorrect format 1504 return gpos + 1 + 1; 1505 if ('+' == tc1) j = 1; 1506 else if ('-' == tc1) j = 0; 1507 else return gpos + 1 + 1; 1508 switch (tc2) 1509 { 1510 case '!': case '=': case '/': break; 1511 default: 1512 return gpos + 1 + 1; 1513 } 1514 node1 = new f4_node(":", par, gpos); 1515 node1->l1 = j; 1516 node1->i1 = (int)tc2; 1517 par = node1; 1518 j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ':'); 1519 gpos += j + 2; 1520 break; 1521 } 1399 1522 case '[': 1400 // link to neuron 1401 // input (%d, '*', 'G', 'T', 'S') 1402 t = -1; 1403 if (sscanf(genot + gpos, "[%ld:%lf]", &relfrom, &w) == 2) t = 0; 1404 else if (sscanf(genot + gpos, "[*:%lf]", &w) == 1) t = 1; 1405 else if (sscanf(genot + gpos, "[G:%lf]", &w) == 1) t = 2; 1406 else if (sscanf(genot + gpos, "[T:%lf]", &w) == 1) t = 3; 1407 else if (sscanf(genot + gpos, "[S:%lf]", &w) == 1) t = 4; 1408 // error: no correct format 1409 if (t < 0) return gpos + 1 + 1; 1410 node1 = new f4_node('[', par, gpos); 1523 { 1524 const char *end = parseConnection(genot + gpos, relfrom, w); 1525 if (end == NULL) 1526 { 1527 end = parseConnectionWithNeuron(genot + gpos, neutype, w); 1528 if (end == NULL) t = -1; 1529 t = 1; 1530 } 1531 else 1532 { 1533 t = 0; 1534 } 1535 node1 = new f4_node("[", par, gpos); 1536 node1->s1 = neutype; 1411 1537 node1->i1 = t; 1412 1538 node1->l1 = relfrom; … … 1416 1542 gpos += j + 2; 1417 1543 break; 1418 1419 case ':': 1420 // neuron parameter +! -! += -= +/ or -/ 1421 if (sscanf(genot + gpos, ":%c%c:", &tc1, &tc2) != 2) 1422 // error: incorrect format 1423 return gpos + 1 + 1; 1424 if ('+' == tc1) j = 1; 1425 else if ('-' == tc1) j = 0; 1426 else return gpos + 1 + 1; 1427 switch (tc2) 1428 { 1429 case '!': case '=': case '/': break; 1430 default: 1431 return gpos + 1 + 1; 1432 } 1433 node1 = new f4_node(':', par, gpos); 1434 node1->l1 = j; 1435 node1->i1 = (int)tc2; 1436 par = node1; 1437 j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ':'); 1438 gpos += j + 2; 1439 break; 1440 1441 case ' ': 1442 case '\n': 1443 case '\t': 1444 // whitespace: ignore 1445 //node1 = new f4_node(' ', par, gpos ); 1446 //par = node1; 1447 gpos++; 1448 break; 1449 1544 } 1450 1545 default: 1546 { 1451 1547 //DB( printf("unknown character '%c' ! \n", genot[gpos]); ) 1452 1548 //add it, build will give the error or repair … … 1456 1552 break; 1457 1553 } 1458 } 1554 } 1555 } 1556 1459 1557 // should end with a '>' 1460 1558 if (par) 1461 1559 { 1462 if ( '>' != par->name)1560 if (par->name != ">") 1463 1561 { 1464 1562 node1 = new f4_node('>', par, strlen(genot) - 1); … … 1467 1565 } 1468 1566 1469 return 0; // OK 1470 } 1471 1567 return 0; 1568 } 1569 1570 const char* parseConnection(const char *fragm, int& relfrom, double &weight) 1571 { 1572 const char *parser = fragm; 1573 if (*parser != '[') return NULL; 1574 parser++; 1575 ExtValue val; 1576 parser = val.parseNumber(parser, ExtPType::TInt); 1577 if (parser == NULL) return NULL; 1578 relfrom = val.getInt(); 1579 if (*parser != ':') return NULL; 1580 parser++; 1581 parser = val.parseNumber(parser, ExtPType::TDouble); 1582 if (parser == NULL) return NULL; 1583 weight = val.getDouble(); 1584 if (*parser != ']') return NULL; 1585 parser++; 1586 return parser; 1587 } 1588 1589 const char* parseConnectionWithNeuron(const char *fragm, string &neutype, double &weight) 1590 { 1591 const char *parser = fragm; 1592 if (*parser != '[') return NULL; 1593 parser++; 1594 char * p = (char*)parser; 1595 if (GenoOperators::parseNeuroClass(p) == NULL) return NULL; 1596 neutype = string(parser, (const char *)p); 1597 parser = p; 1598 if (*parser != ':') return NULL; 1599 parser++; 1600 ExtValue val; 1601 parser = val.parseNumber(parser, ExtPType::TDouble); 1602 if (parser == NULL) return NULL; 1603 weight = val.getDouble(); 1604 if (*parser != ']') return NULL; 1605 parser++; 1606 return parser; 1607 } 1472 1608 1473 1609 f4_node * f4_processtree(const char * geno) -
cpp/frams/genetics/f4/f4_general.h
r671 r760 8 8 #define _F4_GENERAL_H_ 9 9 10 //#include "f4_orientmat.h"11 10 #include <frams/util/3d.h> 12 11 #include <frams/util/sstring.h> 13 12 #include <frams/util/multirange.h> 13 #include <frams/genetics/geneprops.h> 14 14 15 15 #ifdef DMALLOC … … 17 17 #endif 18 18 19 20 class f4_Props 21 { 22 public: 23 // fill with default values 24 f4_Props(); 25 // must sum to 1 26 void normalizeBiol4(); 27 void executeModifier(char modif); 28 void adjust(); 29 30 double length; 31 double curvedness; 32 double weight; 33 double friction; 34 double muscle_power; 35 double assimilation; 36 double stamina; 37 double ingestion; 38 double twist; 39 double energy; 40 }; 41 42 extern f4_Props stdProps; 43 44 45 // rolling (one-time) 19 /** 20 * Performs single rotation angle decrementation on a given value. 21 * @param v pointer to the decremented value 22 */ 46 23 void rolling_dec(double * v); 24 25 /** 26 * Performs single rotation angle incrementation on a given value. 27 * @param v pointer to the incremented value 28 */ 47 29 void rolling_inc(double * v); 48 49 30 50 31 class f4_node; // later … … 53 34 54 35 55 // cell types 56 #define T_UNDIFF4 40 57 #define T_STICK4 41 58 #define T_NEURON4 42 59 36 /** @name Types of f4_Cell's */ 37 //@{ 38 #define T_UNDIFF4 40 ///<undifferentiated cell 39 #define T_STICK4 41 ///<differentiated to stick, cannot divide 40 #define T_NEURON4 42 ///<differentiated to neuron, can divide 41 //@} 42 43 /** 44 * Scans f4 genotype string for a stopping character and returns the position of 45 * this stopping character or 1 if the end of string was reached. This method is used 46 * for closing braces, like ), >, ]. It runs recursively when opening braces 47 * like (, <, # are found. 48 * @param s string with the f4 genotype 49 * @param slen length of a given string 50 * @param stopchar character to be found 51 * @return 1 if end of string was reached, or position of found character in sequence 52 */ 60 53 int scanrec(const char * s, unsigned int slen, char stopchar); 61 54 62 55 63 56 class f4_CellLink; 64 #define MAXINPUTS 100 65 66 // an abstract cell type, extension of part/stick -- for developmental encoding 57 58 /** @name Constraints of f4 genotype structures */ 59 //@{ 60 #define MAXINPUTS 100 ///<maximum number of neuron inputs 61 #define MAX4CELLS 100 ///<maximum number of f4 organism cells 62 //@} 63 64 /** 65 * Abstract cell type - the representation of single component in the developmental 66 * encoding. In the beginning, each f4_Cell is undifferentiated. During the process 67 * of development it can divide or differentiate into a stick or a neuron. If it 68 * differentiates to a neuron, then it preserves the ability to divide, but divided 69 * cells will be the same type as the parent cell. If it is a stick, then it cannot 70 * be divided anymore. 71 * 72 * From f4_Cell array the final Model of a creature is created. 73 */ 67 74 class f4_Cell 68 75 { 69 76 public: 77 /** 78 * Represents the repetition marker. It holds information about the pointer 79 * to the repetition node and the count of repetitions. 80 */ 70 81 class repeat_ptr 71 82 { 72 83 public: 73 84 repeat_ptr() : node(NULL), count(-1) { }; 74 repeat_ptr(f4_node * a, int b) : node(a), count(b) { }; 75 inline void null() { node = NULL; count = -1; }; 85 86 /** 87 * A constructor that takes the pointer to the repetition node and the count of repetitions. 88 * @param a pointer to f4_node for repetition character 89 * @param b the number of repetitions 90 */ 91 repeat_ptr(f4_node *a, int b) : node(a), count(b) { }; 92 93 inline void makeNull() { node = NULL; count = -1; }; 94 76 95 inline bool isNull() const { return ((node == NULL) || (count <= 0)); }; 96 77 97 inline void dec() { count--; }; 78 f4_node * node; // ptr torepetition code79 char count; // 98 f4_node *node; ///<pointer to the repetition code 99 char count; ///<repetition counter 80 100 }; 81 101 82 class repeat_stack // a stack of repet_ptr's 102 /** 103 * Represents the stack of repeat_ptr objects. The objects are 104 * pushed to the stack when '#' repetition symbol appears, and are popped when 105 * the end of the current cell definition, i.e. the '>' character, appears. After the 106 * '>' character, the cell is duplicated as many times as it is defined after the 107 * repetition marker. 108 */ 109 class repeat_stack 83 110 { 84 111 public: 85 repeat_stack() { top = 0; }; 86 inline void null() { top = 0; }; 87 inline void push(repeat_ptr A) { if (top >= stackSize) return; ptr[top] = A; top++; }; 88 inline void pop() { if (top > 0) top--; }; 89 inline repeat_ptr * first() { return &(ptr[top - (top > 0)]); }; 90 static const int stackSize = 4; // max 4 nested levels 91 repeat_ptr ptr[stackSize]; 92 short int top; // top of the stack 112 repeat_stack() { top = 0; } 113 114 inline void clear() { top = 0; } 115 116 /** 117 * Pushes repeat_ptr object onto the stack. If the stack size is exceeded, then no 118 * information is provided. 119 * @param rn repetition node info 120 */ 121 inline void push(repeat_ptr rn) { if (top >= stackSize) return; ptr[top] = rn; top++; } 122 123 inline void pop() { if (top > 0) top--; } 124 125 /** 126 * Gets the current top element. 127 * @return pointer to the element on top of the repeat_stack object 128 */ 129 inline repeat_ptr* first() { return &(ptr[top - (top > 0)]); }; 130 static const int stackSize = 4; ///<max 4 nested levels 131 repeat_ptr ptr[stackSize]; ///<array holding pointers to repeat_ptr 132 short int top; ///<index of the top of the stack 93 133 }; 94 134 135 /** 136 * Creates a new f4_Cell object. 137 * @param nname name of a cell, can be T_UNDIFF4, T_STICK4 or T_NEURON4 138 * @param ndad pointer to the parent of the created cell 139 * @param nangle the amount of commas affecting branch angles 140 * @param newP genotype properties of a given cell 141 */ 95 142 f4_Cell(int nname, 96 f4_Cell * ndad, int nangle, f4_Props newP); 97 f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur, 98 f4_Cell * ndad, int nangle, f4_Props newP); 143 f4_Cell * ndad, int nangle, GeneProps newP); 144 /** 145 * Creates a new f4_Cell object. 146 * @param nO pointer to an organism containing the cell 147 * @param nname name of the cell, can be T_UNDIFF4, T_STICK4 or T_NEURON4 148 * @param ngeno pointer to the root of the genotype tree 149 * @param ngcur pointer to the f4_node representing the current cell in the genotype tree 150 * @param ndad pointer to the parent of the created cell 151 * @param nangle the number of commas affecting branch angles 152 * @param newP genotype properties of a given cell 153 */ 154 f4_Cell(f4_Cells *nO, int nname, f4_node *ngeno, f4_node *ngcur, 155 f4_Cell *ndad, int nangle, GeneProps newP); 156 99 157 ~f4_Cell(); 100 158 159 /** 160 * Performs one step of cell development. This method requires pointer to 161 * f4_Cells object in org attribute. If the current node in genotype tree 162 * represents branching, then the cell divides into two cells, unless the 163 * cell was already differentiated into stick cell. Otherwise the current 164 * differentiation or modification is performed on cell. If current node is 165 * creating a connection between two neuron nodes, and the input node is not 166 * yet developed, then the simulation of current cell halts and waits until 167 * the input node will be developed. The onestep method is ran on each cell 168 * at least once and if one cell requires another to develop, then onestep 169 * should be deployed again on this cell. This method, unlike genotype tree 170 * creation, checks semantics. This means that this function will fail if: 171 * - the stick cell will have divide node, 172 * - the undifferentiated cell will have '>' node (end of cell development), 173 * - the stack of repetition marker '#' will be overflowed, 174 * - the stick modifiers, like rotation, will be applied on neuron cell, 175 * - the differentiated cell will be differentiated again, 176 * - the neuron class inside cell connection definition is not a sensor, 177 * - the connection between neurons could not be established, 178 * - the neuron class is not valid. 179 * 180 * @return 0 if development was successful, 1 if there was an error in genotype tree 181 */ 101 182 int onestep(); // execute one simulation step (till a division) 102 183 103 int addlink(f4_Cell * nfrom, double nw, int nt); 184 /** 185 * Add link between this neuron cell and a given neuron cell. If nfrom object 186 * is not given, than neuron type in nt holds the sensor type. 187 * @param nfrom input neuron cell, or NULL if not given 188 * @param nw weight of connection 189 * @param nt empty string or name of sensor class 190 * @return 0 if link is established, -1 otherwise 191 */ 192 int addlink(f4_Cell * nfrom, double nw, string nt); 193 194 /** 195 * Adjusts properties of stick objects. 196 */ 104 197 void adjustRec(); 105 198 106 int name; // name (number) 107 int type; // type 108 f4_Cell * dadlink; 109 f4_Cells * org; // uplink to organism 110 111 f4_node * genot; // genotype 112 f4_node * gcur; // current genotype execution pointer 113 int active; // whether development is still active 114 repeat_stack repeat; 115 int recProcessedFlag; // used during recursive traverse 116 // remember the genotype codes affecting this cell so far 117 MultiRange genoRange; 118 119 f4_Props P; // properties 120 int anglepos; // number of position within dad's children (,) 121 int childcount; // number of children 122 int commacount; // number of postitions at lastend (>=childcount) 123 double rolling; // rolling angle ('R') (around x) 124 double xrot; 125 double zrot; // horizontal rotation angle due to 126 // branching (around z) 127 //Pt3D firstend; // coord.s of first end (connects to parent) 128 //Pt3D lastend; // last end 129 //f4_OrientMat OM; 130 double mz; // freedom in z 131 int p2_refno; // number of last end part object, used in f0 132 int joint_refno; // number of the joint object, used in f0 133 int neuro_refno; // number of the neuro object, used in f0 134 135 int ctrl; // neuron type 136 double state; 137 double inertia; 138 double force; 139 double sigmo; 140 f4_CellLink* links[MAXINPUTS]; 141 int nolink; 199 int name; ///<name of cell(number) 200 int type; ///<type 201 f4_Cell * dadlink; ///<pointer to cell parent 202 f4_Cells * org; ///<uplink to organism 203 204 f4_node * genot; ///<genotype tree 205 f4_node * gcur; ///<current genotype execution pointer 206 int active; ///<whether development is still active 207 repeat_stack repeat; ///<stack holding repetition nodes and counters 208 int recProcessedFlag; ///<used during recursive traverse 209 MultiRange genoRange; ///<remember the genotype codes affecting this cell so far 210 211 GeneProps P; ///<properties 212 int anglepos; ///<number of position within dad's children (,) 213 int childcount; ///<number of children 214 int commacount; ///<number of postitions at lastend (>=childcount) 215 double rolling; ///<rolling angle ('R') (around x) 216 double xrot; ///<rotation angle around x 217 double zrot; ///<horizontal rotation angle due to branching (around z) 218 219 double mz; ///<freedom in z 220 int p2_refno; ///<number of last end part object, used in f0 221 int joint_refno; ///<number of the joint object, used in f0 222 int neuro_refno; ///<number of the neuro object, used in f0 223 224 int ctrl; ///<neuron type 225 double state; ///<state of neuron 226 double inertia; ///<inertia of neuron 227 double force; ///<force of neuron 228 double sigmo; ///<sigmoid of neuron 229 f4_CellLink* links[MAXINPUTS]; ///<array of neuron links 230 int nolink; ///<number of links 231 NeuroClass * neuclass = NULL; ///<pointer to neuron class 142 232 }; 143 233 144 145 // an input link to a neuron 234 /** 235 * Class representing link between neuron cells. 236 */ 146 237 class f4_CellLink 147 238 { 148 239 public: 149 f4_CellLink(f4_Cell * nfrom, double nw, int nt); 150 f4_Cell * from; 151 // type: 0: input, 1 '*', 2 'G', 3 'T', 4 'S' 152 int t; 153 double w; 240 /** 241 * Constructor for f4_CellLink class. Parameter nfrom can represent input 242 * neuron cell or be NULL, if connection has neuron cell definition inside. 243 * The inside definition must be hold in nt parameter and a neuron class 244 * must represent sensor. 245 * @param nfrom pointer to input neuron cell or NULL 246 * @param nw weight of connection 247 * @param nt name of neuron class or empty string 248 */ 249 f4_CellLink(f4_Cell * nfrom, double nw, string nt); 250 251 f4_Cell * from; ///<pointer to input neuron cell 252 string t; ///<empty if from cell is given, NeuroClass name otherwise 253 double w; ///<weight of connection 154 254 }; 155 255 156 256 157 257 // a collection of cells, like Organism, for developmental encoding 158 #define MAX4CELLS 100 258 /** 259 * Class representing a collection of cells. It is equivalent of organism. 260 */ 159 261 class f4_Cells 160 262 { 161 263 public: 264 265 /** 266 * Constructor taking genotype in a form of a tree. 267 * @param genome genotype tree 268 * @param nrepair 0 if nothing to repair 269 */ 162 270 f4_Cells(f4_node * genome, int nrepair); 271 272 /** 273 * Constructor taking genotype in a form of a string. 274 * @param genome genotype string 275 * @param nrepair 0 if nothing to repair 276 */ 163 277 f4_Cells(SString &genome, int nrepair); 278 279 /** 280 * Destructor removing cells from memory. 281 */ 164 282 ~f4_Cells(); 283 284 /** 285 * Adds new cell to organism. 286 * @param newcell cell to be added 287 */ 165 288 void addCell(f4_Cell * newcell); 166 void toF1Geno(SString &out); // output to f1 format, approximation 167 int onestep(); // simulate all parts for one step 168 int simulate(); // simulate development, return error (0 for ok) 169 // for error reporting / genotype fixing 289 290 /** 291 * Creates approximate genotype in f1 encoding and stores it in a given 292 * parameter. 293 * @param out the string in which approximate f1 genotype will be stored 294 */ 295 void toF1Geno(SString &out); 296 297 /** 298 * Performs single step of organism development. It runs each active cell 299 * in organism. 300 * @return 0 if all cells are developed, or 1 otherwise 301 */ 302 int onestep(); 303 304 /** 305 * Performs full development of organism and returns error code if something 306 * went wrong. 307 * @return 0 if organism developed successfully, error code if something went wrong 308 */ 309 int simulate(); 310 311 /** 312 * Returns error code of last simulation. 313 * @return error code 314 */ 170 315 int geterror() { return error; }; 316 317 /** 318 * Returns position of error in genotype. 319 * @return position of error 320 */ 171 321 int geterrorpos() { return errorpos; }; 322 323 /** 324 * Sets error code GENOPER_OPFAIL for simulation on a given position. 325 * @param nerrpos position of error 326 */ 172 327 void setError(int nerrpos); 328 329 /** 330 * Sets the element of genotype to be repaired by removal. 331 * @param nerrpos position of error in genotype 332 * @param rem the f4_node to be removed from genotype tree in order to repair 333 */ 173 334 void setRepairRemove(int nerrpos, f4_node * rem); 335 336 /** 337 * Sets repairing of genotype by inserting new node to current genotype. 338 * @param nerrpos position of error in genotype 339 * @param parent the parent of new element 340 * @param insert the element to be inserted 341 * @return 0 if repair can be performed, -1 otherwise (the repair flag wasn't set in constructor) 342 */ 174 343 int setRepairInsert(int nerrpos, f4_node * parent, f4_node * insert); 344 345 /** 346 * Repairs genotype according to setRepairRemove or setRepairInsert method. 347 * @param geno pointer to genotype tree 348 * @param whichchild 1 if first child, 2 otherwise 349 */ 175 350 void repairGeno(f4_node * geno, int whichchild); 176 351 177 352 // the cells 178 f4_Cell * C[MAX4CELLS]; 179 int nc; 353 f4_Cell * C[MAX4CELLS]; ///<Array of all cells of organism 354 int nc; ///<Number of cells in organism 180 355 181 356 private: … … 199 374 { 200 375 public: 201 char name; // one-letter 'name' 202 f4_node * parent; // parent link, or NULL 203 f4_node * child; // child, or NULL 204 f4_node * child2; // second child, or NULL 205 int pos; // original position in string 206 int i1; // internal int parameter1 207 int l1; // internal long parameter1 208 double f1; // internal double parameter1 209 376 string name; ///<one-letter 'name', multiple characters for classes 377 f4_node *parent; ///<parent link, or NULL 378 f4_node *child; ///<child, or NULL 379 f4_node *child2; ///<second child, or NULL 380 int pos; ///<original position in string 381 int i1; ///<internal int parameter1 382 int l1; ///<internal long parameter1 383 double f1; ///<internal double parameter1 384 string s1; ///<internal string parameter1 385 386 /** 387 * Default constructor. 388 */ 210 389 f4_node(); 390 391 /** 392 * Multiple-character name constructor. 393 * @param nname string from genotype representing node 394 * @param nparent pointer to parent of node 395 * @param npos position of node substring in genotype string 396 */ 397 f4_node(string nname, f4_node * nparent, int npos); 398 399 /** 400 * One-character name constructor. 401 * @param nname character from genotype representing node 402 * @param nparent pointer to parent of node 403 * @param npos position of node character in genotype string 404 */ 211 405 f4_node(char nname, f4_node * nparent, int npos); 406 407 /** 408 * Desctructor of object. 409 */ 212 410 ~f4_node(); 411 412 /** 413 * Method for adding child to a node. 414 * @param nchi child to be added to node 415 * @return 0 if child could be added, -1 otherwise 416 */ 213 417 int addChild(f4_node * nchi); 418 419 /** 420 * Method for removing child from node. 421 * @param nchi child to be removed from node 422 * @return 0 if child could be removed, -1 otherwise 423 */ 214 424 int removeChild(f4_node * nchi); 215 int childCount(); // return no of children, 0, 1, or 2 216 int count(); // return no of nodes (recursive) 217 f4_node * ordNode(int n); // returns the nth subnode (0-) 218 f4_node * randomNode(); // returns a random subnode 219 f4_node * randomNodeWithSize(int min, int max); // returns a random subnode with given size 220 void sprintAdj(char *& buf); // print recursively 221 f4_node * duplicate(); // create duplicate copy. recursive. 222 void destroy(); // release memory. recursive. 425 426 /** 427 * Returns number of children. 428 * @return 0, 1 or 2 429 */ 430 int childCount(); 431 432 /** 433 * Returns number of nodes coming from this node in a recursive way. 434 * @return number of nodes from this node 435 */ 436 int count(); 437 438 /** 439 * Returns the nth subnode (0-) 440 * @param n index of child to be found 441 * @return pointer to nth subnode or NULL if not found 442 */ 443 f4_node * ordNode(int n); 444 445 /** 446 * Returns a random subnode. 447 * @return random subnode 448 */ 449 f4_node * randomNode(); 450 451 /** 452 * Returns a random subnode with given size. 453 * @param min minimum size 454 * @param max maximum size 455 * @return a random subnode with given size or NULL 456 */ 457 f4_node * randomNodeWithSize(int min, int max); 458 459 /** 460 * Prints recursively tree from a given node. 461 * @param buf variable storing printing result 462 */ 463 void sprintAdj(char *& buf); 464 465 /** 466 * Recursively copies genotype tree from this node. 467 * @return pointer to a tree copy 468 */ 469 f4_node * duplicate(); 470 471 /** 472 * Recursively releases memory from all node children. 473 */ 474 void destroy(); 223 475 private: 224 476 void sprint(SString & out); // print recursively … … 226 478 227 479 // convert f4 geno string to tree structure (internal) 480 481 /** 482 * Main function to perform conversion of f4 geno to tree structure. Prepares 483 * f4_node root of tree and runs f4_processrec function for it. 484 * @param geno string representing f4 genotype 485 * @return pointer to f4_node object representing f4 tree root 486 */ 228 487 f4_node * f4_processtree(const char * geno); 488 489 /** 490 * Scans genotype string from a given position. This recursive method creates 491 * tree of f4_node objects. The method extract each potentially functional element 492 * of genotype string to separate f4_nodes. When branching character '<' occurs, 493 * then f4_processrec is ran for latest f4_node element. This method does not 494 * analyse genotype semantically, it checks only if syntax is proper. The only 495 * semantic aspect is neuron class name extraction, in which the GenoOperators 496 * class is used to parse possible neuron class in genotype. 497 * @param genot the string holding all genotype 498 * @param pos0 the current position of processing in string 499 * @param current parent of analysed branch of genotype 500 * @return 0 if processing was successful or position of error in genotype 501 */ 229 502 int f4_processrec(const char * genot, unsigned pos0, f4_node * parent); 230 503 504 /** 505 * Function parses notation of neuron connection - it takes beginning of connection 506 * definition, extracts relative position of input neurons and weight of connection. 507 * After successful parsing it returns pointer to first character after connection 508 * definition, or NULL if connection definition was not valid - lack of [, :, ] 509 * characters or wrong value of relfrom or weight. 510 * @param fragm the beginning of connection definition, it should be '[' character 511 * @param relfrom the reference to int variable, in which relative position of input neuron will be stored 512 * @param weight the reference to double variable, in which weight of connection will be stored 513 * @return the pointer to first character in string after connection definition 514 */ 515 const char * parseConnection(const char * fragm, int& relfrom, double &weight); 516 517 /** 518 * Function parses notation of neuron connection with neuron definition - it 519 * takes beginning of connection definition, extracts the name of neuron class 520 * that will be the input for current neuron and weight of connection. 521 * After successful parsing it returns pointer to first character after connection 522 * definition, or NULL if connection definition was not valid - lack of [, :, ] 523 * characters, wrong value of weight or invalid neuron class name. 524 * @param fragm the beginning of connection definition, it should be '[' character 525 * @param neutype the reference to string representing input neuron class name. The name of class is validated with GenoOperators::parseNeuroClass 526 * @param weight the reference to double variable, in which weight of connection will be stored 527 * @return the pointer to first character in string after connection definition 528 */ 529 const char * parseConnectionWithNeuron(const char * fragm, string& neutype, double &weight); 231 530 232 531 #endif -
cpp/frams/genetics/f4/oper_f4.cpp
r676 r760 5 5 // Copyright (C) 1999,2000 Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL 6 6 // Copyright (C) since 2001 Maciej Komosinski 7 // 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties 7 8 8 9 #include "oper_f4.h" … … 138 139 #define REP_MAXCOUNT 19 139 140 140 f4_node * n1, *n2, *n3, *n4, *n5;141 142 141 // do the mutation 143 142 // pick a random node 144 n1 = g->child->randomNode(); 143 f4_node *n1 = g->child->randomNode(); 144 vector<NeuroClass*> neulist; 145 145 //DB( printf("%c\n", n1->name); ) 146 int neuronid = -1; 146 147 147 148 switch (roulette(prob, F4_COUNT)) … … 155 156 { 156 157 // add division ('<') 157 n3 = n1->parent;158 f4_node *n3 = n1->parent; 158 159 n3->removeChild(n1); 159 n2 = new f4_node('<', n3, n3->pos);160 f4_node *n2 = new f4_node('<', n3, n3->pos); 160 161 n2->addChild(n1); 161 162 // new cell is stick or neuron 162 163 // "X>" or "N>" 164 f4_node *n5 = NULL; 163 165 double pr = rnd01; 164 166 pr -= 0.5; 165 if (pr < 0) n 3= new f4_node('X', n2, n2->pos);167 if (pr < 0) n5 = new f4_node('X', n2, n2->pos); 166 168 else 167 169 { 168 pr -= 0.5; 169 if (pr < 0) 170 { 171 // if neuron, make muscle and add a link 172 n3 = new f4_node('N', n2, n2->pos); 173 if (randomN(2) == 0) 174 n4 = new f4_node('|', n3, n2->pos); 175 else 176 n4 = new f4_node('@', n3, n2->pos); 177 n5 = new f4_node('[', n4, n2->pos); 178 linkNodeMakeRandom(n5); 179 } 180 } 181 new f4_node('>', n3, n3->pos); 170 // make neuron 171 NeuroClass * rndclass = GenoOperators::getRandomNeuroClass(); 172 if (rndclass == NULL) 173 { 174 n5 = new f4_node('X', n2, n2->pos); 175 } 176 else 177 { 178 f4_node *n4 = new f4_node(rndclass->getName().c_str(), n2, n2->pos); //TODO move this above 179 if (rndclass->getPreferredInputs() != 0) 180 { 181 neuronid = -1; 182 for (int i = 0; i < g->count(); i++) 183 { 184 f4_node * gcur = g->ordNode(i); 185 char * temp = (char*)gcur->name.c_str(); 186 NeuroClass * neuclass = GenoOperators::parseNeuroClass(temp); 187 if (neuclass != NULL) 188 { 189 neulist.push_back(neuclass); 190 } 191 if (g->ordNode(i) == n3) 192 { 193 neuronid = neulist.size()-1; 194 } 195 } 196 if (neuronid == -1) 197 { 198 return GENOPER_OPFAIL; 199 } 200 n5 = new f4_node('[', n4, n2->pos); 201 linkNodeMakeRandom(n5, neuronid, neulist); 202 } 203 else { 204 n5 = n4; 205 } 206 } 207 } 208 new f4_node('>', n5, n5->pos); 182 209 n1->parent = n2; 183 210 // now with 50% chance swap children … … 193 220 { 194 221 // add link 195 n1->parent->removeChild(n1); 196 n2 = new f4_node('[', n1->parent, n1->parent->pos); 197 linkNodeMakeRandom(n2); 198 n2->addChild(n1); 199 n1->parent = n2; 222 f4_node * par = n1->parent; 223 char * temp = (char*)par->name.c_str(); 224 NeuroClass * neuclass = GenoOperators::parseNeuroClass(temp); 225 if (neuclass != NULL) 226 { 227 n1->parent->removeChild(n1); 228 f4_node *n2 = new f4_node('[', n1->parent, n1->parent->pos); 229 n2->addChild(n1); 230 n1->parent = n2; 231 neuronid = -1; 232 for (int i = 0; i < g->count(); i++) 233 { 234 f4_node *gcur = g->ordNode(i); 235 temp = (char*)gcur->name.c_str(); 236 NeuroClass *neuclass = GenoOperators::parseNeuroClass(temp); 237 if (neuclass != NULL) 238 { 239 neulist.push_back(neuclass); 240 } 241 if (gcur == par) 242 { 243 neuronid = neulist.size()-1; 244 } 245 } 246 if (neuronid == -1) 247 { 248 return GENOPER_OPFAIL; 249 } 250 linkNodeMakeRandom(n2, neuronid, neulist); 251 } 200 252 } 201 253 break; … … 204 256 // add neuron modifier 205 257 n1->parent->removeChild(n1); 206 n2 = new f4_node(':', n1->parent, n1->parent->pos);258 f4_node *n2 = new f4_node(':', n1->parent, n1->parent->pos); 207 259 nparNodeMakeRandom(n2); 208 260 n2->addChild(n1); … … 214 266 // add repetition ('#') 215 267 // repeated code (left child) is the original, right child is empty, count is 2 216 n3 = n1->parent;268 f4_node *n3 = n1->parent; 217 269 n3->removeChild(n1); 218 n2 = new f4_node('#', n3, n3->pos);270 f4_node *n2 = new f4_node('#', n3, n3->pos); 219 271 n2->i1 = 2; 220 272 n2->addChild(n1); … … 228 280 // choose a simple node from ADD_SIMPLE_CODES 229 281 n1->parent->removeChild(n1); 230 n2 = new f4_node(ADD_SIMPLE_CODES[randomN(strlen(ADD_SIMPLE_CODES))], n1->parent, n1->parent->pos);282 f4_node *n2 = new f4_node(ADD_SIMPLE_CODES[randomN(strlen(ADD_SIMPLE_CODES))], n1->parent, n1->parent->pos); 231 283 n2->addChild(n1); 232 284 n1->parent = n2; … … 258 310 case 1: // one child 259 311 { 260 n2 = n1->parent;312 f4_node *n2 = n1->parent; 261 313 n2->removeChild(n1); 262 314 if (NULL != n1->child) … … 281 333 { 282 334 // two children 283 n2 = n1->parent;335 f4_node *n2 = n1->parent; 284 336 n2->removeChild(n1); 285 337 // n1 has two children. pick one randomly 50-50, destroy other … … 318 370 while (1) 319 371 { 320 if (strchr(MUT_CHAN_CODES, n1->name )) break;372 if (strchr(MUT_CHAN_CODES, n1->name[0])) break; 321 373 // try a new one 322 374 n1 = g->child->randomNode(); … … 324 376 if (i >= 20) return GENOPER_OPFAIL; 325 377 } 326 switch (n1->name )378 switch (n1->name[0]) 327 379 { 328 380 case '<': 381 { 329 382 // swap children 330 n2 = n1->child; n1->child = n1->child2; n1->child2 = n2; 383 f4_node *n2 = n1->child; n1->child = n1->child2; n1->child2 = n2; 384 } 331 385 break; 332 386 case '[': 333 linkNodeChangeRandom(n1); 387 { 388 neuronid = -1; 389 for (int i = 0; i < g->count(); i++) 390 { 391 f4_node *gcur = g->ordNode(i); 392 char *temp = (char*)gcur->name.c_str(); 393 NeuroClass *neuclass = GenoOperators::parseNeuroClass(temp); 394 if (neuclass != NULL) 395 { 396 neulist.push_back(neuclass); 397 } 398 if (gcur == n1) 399 { 400 neuronid = neulist.size()-1; 401 } 402 } 403 if (neuronid == -1) 404 { 405 return GENOPER_OPFAIL; 406 } 407 linkNodeChangeRandom(n1, neuronid, neulist); 408 } 334 409 break; 410 335 411 case '#': 412 { 336 413 repeatNodeChangeRandom(n1); 414 } 337 415 break; 338 416 } … … 348 426 349 427 // make a random [ node 350 void Geno_f4::linkNodeMakeRandom(f4_node * nn) const 351 { 352 int i; 428 void Geno_f4::linkNodeMakeRandom(f4_node *nn, int neuid, vector<NeuroClass*> neulist) const 429 { 353 430 float prob1; 354 355 i = 0; 431 NeuroClass *nc = NULL; 432 356 433 // 35% chance one of *GTS 357 434 prob1 = rnd01; … … 360 437 { 361 438 // '*', 'G', 'T', or 'S', 1/4 chance each 362 i = 1 + (int)(3.999f * rnd01); 363 } 364 nn->i1 = i; 365 nn->l1 = 0; 366 if (0 == i) 439 nc = GenoOperators::getRandomNeuroClassWithOutputAndNoInputs(); 440 } 441 if (nc != NULL) 442 { 443 nn->i1 = 1; 444 nn->s1 = nc->getName().c_str(); 445 nn->l1 = 0; 446 } 447 else 367 448 { 368 449 // relative input link 369 nn->l1 = (int)(4.0f * (rnd01 - 0.5f)); 450 int id = GenoOperators::getRandomNeuroClassWithOutput(neulist); 451 int relid = neuid - id; 452 nn->l1 = relid; 453 //nn->l1 = (int)(4.0f * (rnd01 - 0.5f)); 370 454 } 371 455 // weight 372 nn->f1 = 10.0f * (rnd01 - 0.5f); 456 nn->f1 = GenoOperators::mutateNeuProperty(nn->f1,NULL,-1); 457 //nn->f1 = 10.0f * (rnd01 - 0.5f); 373 458 } 374 459 375 460 // change a [ node 376 void Geno_f4::linkNodeChangeRandom(f4_node * nn) const //rewritten by M.K. - should work as before (not tested) 377 { 378 int i; 379 float prob2; 380 461 void Geno_f4::linkNodeChangeRandom(f4_node * nn, int neuid, std::vector<NeuroClass*> neulist) const //rewritten by M.K. - should work as before (not tested) 462 { 381 463 double probs[3] = { 0.1, 0.3, 0.6 }; 464 NeuroClass *cl; 382 465 // 10% change type 383 466 // 30% change link … … 387 470 { 388 471 case 0: // change type 389 i = 0; 390 // * G, 10% chance each 391 prob2 = rnd01 - 0.10f; 392 if (prob2 < 0) i = 1; else { prob2 -= 0.10f; if (prob2 < 0) i = 2; } 393 nn->i1 = i; 472 // 80% for link, 20% for random sensor 473 if (rnd01 < 0.2f) 474 { 475 cl = GenoOperators::getRandomNeuroClassWithOutputAndNoInputs(); 476 if (cl != NULL) 477 { 478 nn->i1 = 1; 479 nn->s1 = cl->name.c_str(); 480 nn->l1 = 0; 481 } 482 } 394 483 break; 395 484 case 1: // change link 396 485 if (0 == nn->i1) // relative input link 397 nn->l1 += (int)(2.0f * (rnd01 - 0.5f)); 486 { 487 int id = GenoOperators::getRandomNeuroClassWithOutput(neulist); 488 nn->l1 = neuid - id; 489 } 490 //nn->l1 += (int)(2.0f * (rnd01 - 0.5f)); 398 491 break; 399 492 case 2: // change weight 400 nn->f1 += 1.0f * (rnd01 - 0.5f); 493 nn->f1 = GenoOperators::mutateNeuProperty(nn->f1,NULL,-1); 494 //nn->f1 += 1.0f * (rnd01 - 0.5f); 401 495 break; 402 496 } -
cpp/frams/genetics/f4/oper_f4.h
r674 r760 15 15 #include <frams/param/param.h> 16 16 17 /** @name Codes for general mutation types */ 18 //@{ 19 #define F4_ADD 0 ///<Adding new node 20 #define F4_DEL 1 ///<Deletion of node 21 #define F4_MOD 2 ///<Modification of node 22 #define F4_COUNT 3 ///<Count of mutation types 23 //@} 17 24 18 #define F4_ADD 0 19 #define F4_DEL 1 20 #define F4_MOD 2 21 #define F4_COUNT 3 22 25 /** @name Codes for specific F4_ADD mutation subtypes */ 26 //@{ 23 27 #define F4_ADD_DIV 0 24 28 #define F4_ADD_CONN 1 … … 27 31 #define F4_ADD_SIMP 4 28 32 #define F4_ADD_COUNT 5 29 33 //@} 30 34 31 35 class Geno_f4 : public GenoOperators … … 43 47 44 48 // mutation probabilities 45 double prob[F4_COUNT], probadd[F4_ADD_COUNT]; 49 double prob[F4_COUNT]; ///<reltive probabilities of selecting mutation types in f4 genotype 50 double probadd[F4_ADD_COUNT]; ///<relative probabilities of selecting mutation addition subtypes 46 51 47 SString excluded_modifiers; //not to be used in mutations52 SString excluded_modifiers; ///<Modifiers that are excluded in mutation process 48 53 static const char *all_modifiers; 49 54 50 55 protected: 51 /* int MutateMany(char *& g, float & chg); // not used anymore */ 56 57 /** 58 * Validates a f4 genotype. If the genotype is invalid, the genotype is repaired 59 * and the validation is repeated. Validation is performed as long as repairing 60 * is not effective, or the number of retries exceeded the given limit. 61 * @param geno genotype tree 62 * @param retrycount maximum amount of repair retries 63 * @return GENOOPER_OK if genotype is valid, GENOPER_REPAIR if genotype can be repaired, GENOPER_OPFAIL if genotype can't be repaired 64 */ 52 65 int ValidateRec(f4_node * geno, int retrycount) const; 66 67 /** 68 * Performs mutation of an f4 genotype. The mutation is performed on a random node 69 * from a given tree. The method of mutation is chosen via the roulette selection, 70 * where probabilities of choosing each mutation type are given in the 'prob' 71 * array. Possible mutation types are: 72 * - F4_ADD - adds new element to the genotype by: 73 * - F4_ADD_DIV - replacing randomly selected node with division node '<', setting this node as a child and creating new stick or neuron sibling of the selected cell (the neuron-type sibling will be connected to a random existing neuron), 74 * - F4_ADD_CONN - adding connection for an existing neuron, 75 * - F4_ADD_NEUPAR - adding neuron property to the selected node, if it is a neuron node, 76 * - F4_ADD_REP - adding a repetition node before a randomly selected node (the repetition node has 2 repetitions), 77 * - F4_ADD_SIMP - adding a simple node before a selected node, 78 * - F4_DEL - removes a randomly selected node (the node needs to have a parent and at least one child, otherwise returns GENOPER_OPFAIL), 79 * - F4_MOD - modifies one of simple nodes by: 80 * - '<' - swapping children in division 81 * - '[' - modifying connection of a neuron 82 * - '#' - incrementing or decrementing repetition count 83 * 84 * @param g input genotype; the result of mutation will be stored in this parameter 85 * @param method reference to the variable that will get the selected method of mutation 86 * @return GENOPER_OK if mutation was performed successfully, GENOPER_FAIL otherwise 87 */ 53 88 int MutateOne(f4_node *& g, int &method) const; 54 void linkNodeMakeRandom(f4_node * nn) const; 55 void linkNodeChangeRandom(f4_node * nn) const; 56 void nparNodeMakeRandom(f4_node * nn) const; 57 void repeatNodeChangeRandom(f4_node * nn) const; 89 90 /** 91 * Creates a random connection to an existing neuron or creates an additional 92 * sensor for a neuron. 93 * @param nn neuron class node 94 * @param neuid id of a neuron 95 * @param neulist list of genotype neuron classes 96 */ 97 void linkNodeMakeRandom(f4_node * nn, int neuid, std::vector<NeuroClass*> neulist) const; 98 99 /** 100 * Changes connection to an existing neuron or creates an additional 101 * sensor for neuron. 102 * @param nn neuron connection node 103 * @param neuid id of a neuron 104 * @param neulist list of genotype neuron classes 105 */ 106 void linkNodeChangeRandom(f4_node * nn, int neuid, std::vector<NeuroClass*> neulist) const; 107 108 /** 109 * Introduces a random modification to the neuron node. 110 * @param nn neuron node 111 */ 112 void nparNodeMakeRandom(f4_node *nn) const; 113 114 /** 115 * Increases or decreases the amount of repetitions in the repetition node. 116 * @param nn repetition node 117 */ 118 void repeatNodeChangeRandom(f4_node *nn) const; 119 120 /** 121 * Tries to perform a mutation until success. There is a maximum of 20 tries. Returns GENOPER_OK or GENOPER_OPFAIL. 122 * @param g genotype tree 123 * @param method reference to the variable that will get the selected method of mutation 124 * @return GENOPER_OK if performed successful mutation, GENOPER_FAIL otherwise 125 */ 58 126 int MutateOneValid(f4_node * &g, int &method) const; 127 128 /** 129 * Performs crossover of two creatures. The 'chg' parameter determines approximately what 130 * percentage of the first creature should form the offspring. '1-chg' is the percentage 131 * of the second creature in the offspring. 132 * @param g1 first parent 133 * @param g2 second parent 134 * @param chg percentage of the first parent in offspring (the second parent has the rest) 135 */ 59 136 int CrossOverOne(f4_node *g1, f4_node *g2, float chg) const; 60 // returns GENOPER_OK or GENOPER_OPFAIL61 // chg: fraction of parent1 genes in child (in g1) (parent2 has the rest)62 137 }; 63 138
Note: See TracChangeset
for help on using the changeset viewer.