Changeset 196 for cpp/frams/genetics/f4/f4_general.cpp
- Timestamp:
- 03/25/14 03:22:37 (11 years ago)
- Location:
- cpp/frams/genetics/f4
- Files:
-
- 1 added
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note: See TracChangeset
for help on using the changeset viewer.