Changeset 760 for cpp/frams/genetics/f4/f4_general.cpp
- Timestamp:
- 03/15/18 22:55:05 (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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)
Note: See TracChangeset
for help on using the changeset viewer.