- Timestamp:
- 05/08/23 02:10:57 (19 months ago)
- Location:
- cpp/frams/genetics/f4
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/f4/f4_general.cpp
r1237 r1239 19 19 20 20 #define BREAK_WHEN_REP_COUNTER_NULL //see comments where it is used 21 #define EXTRA_STEP_CELL_DEVELOPMENT //see comments where it is used22 21 #define TREAT_BAD_CONNECTIONS_AS_INVALID_GENO //see comments where it is used 23 22 … … 41 40 org = NULL; 42 41 genot = NULL; 43 gcur = NULL; 44 active = true; 42 gcur = old_gcur = NULL; 45 43 repeat.clear(); 46 44 //genoRange.clear(); -- implicit … … 89 87 org = nO; 90 88 genot = ngeno; 91 gcur = ngcur; 92 active = true; 89 gcur = old_gcur = ngcur; 93 90 repeat.clear(); 94 91 //genoRange.clear(); -- implicit … … 268 265 } 269 266 repeat.clear(); 270 active = false; // stop271 267 // eat up rest 272 268 int remaining_nodes = gcur->count() - 1; … … 421 417 { 422 418 // wait for other neurons to develop 423 // if there are others still active 424 425 int active_count = 0; 426 for (int i = 0; i < org->cell_count; i++) 427 if (org->C[i]->active) active_count++; 428 active = false; // next time when we reach wait_conn, we will not count ourselves as active (if we were the last active cell, we got a chance to continue development for one development step only) 429 if (active_count > 0) 430 // there is at least one active (including ourselves), halt, try again 419 420 if (!org->development_stagnation) // other cells are developing, the situation is changing, we may continue waiting... 431 421 return; // error code not set -> halt this development and yield to other cells to develop 422 423 //no cells are developing and we are waiting, but there is no chance other cells will create neurons we are waiting for, so we are forced to move on. 432 424 433 425 #ifdef TREAT_BAD_CONNECTIONS_AS_INVALID_GENO // MacKo 2023-04: there were so many invalid connections accumulating in the genotype (and stopping processing of the chain of gcur->child) that it looks like treating them as errors is better... in 2000's, Framsticks neurons were flexible when it comes to inputs and outputs (for example, when asked, muscles would provide an output too, and neurons that ignored inputs would still accept them when connected) so f4 could create connections pretty randomly, but after 2000's we attempt to respect neurons' getPreferredInputs() and getPreferredOutput() so the network of connections has more constraints. … … 443 435 //so this condition and checking for "#" is a simple way to be kind to some, but not all, bad connections, and not raise errors. Perhaps too kind and we open the door for too many cases with invalid connections. 444 436 //Maybe it would be better to perform this check before addConnection(), seeing that for example we process the last iteration of the repetition counter? But how would we know that the (needed here) input neuron will not be developed later by other dividing cells... 445 active = true; //not sure if needed, but let this cell have the chance to continue for as long as many children in the tree are left 437 446 438 gcur = gcur->child; 439 org->development_stagnation = false; //do not force other potentially waiting cells to hurry and act in this development cycle (which would be the last cycle if development_stagnation stayed true); we just acted and because of this the situation may change, so they can wait until another development_stagnation is detected 447 440 return; // error code not set -> halt this development and yield to other cells to develop 448 441 } … … 541 534 } 542 535 } 543 active = false; // done544 536 } 545 537 … … 650 642 C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, GeneProps::standard_values); 651 643 cell_count = 1; 644 development_stagnation = false; 652 645 } 653 646 … … 670 663 int old_cell_count = cell_count; //cell_count may change in the loop as new cells may be appended because cells may be dividing 671 664 for (int i = 0; i < old_cell_count; i++) 672 { 673 C[i]->oneStep(); //keeps calling independently of C[i]->active 665 C[i]->old_gcur = C[i]->gcur; 666 667 for (int i = 0; i < old_cell_count; i++) 668 { 669 C[i]->oneStep(); 674 670 if (errorcode != GENOPER_OK) 675 { 676 // error 677 C[i]->active = false; // stop 678 return false; 679 } 680 } 681 for (int i = 0; i < cell_count; i++) //we check all cells, including newly created ones 682 if (C[i]->active) 683 return true; //at least one cell is still active. TODO maybe the development should stop NOT because of the "active" field (there is this strange "yielding" state too), but by observing the progress of all cells and continuing the development while (errorcode==GENOPER_OK AND (gcur of at least one cell changed OR cell_count changed)) ? 684 return false; 671 return false; // error -> end development 672 } 673 674 if (cell_count != old_cell_count) //the number of cells changed - something is going on! 675 return true; //so continue development! 676 677 for (int i = 0; i < old_cell_count; i++) 678 if (C[i]->old_gcur != C[i]->gcur) // genotype execution pointer changed - something is going on! 679 return true; //so continue development! 680 681 if (development_stagnation) 682 return false; //the same number of cells, no progress in development in any cell -> stagnation, end development 683 else 684 { 685 development_stagnation = true; //signal (force) f4_Cell's that wait for neural connection development to make a step, because all cells stagnated and waiting cells cannot hope for new neurons to be created 686 return true; 687 } 685 688 } 686 689 … … 690 693 const bool PRINT_CELLS_DEVELOPMENT = false; //print the state of cells 691 694 errorcode = GENOPER_OK; 692 693 for (int i = 0; i < cell_count; i++) C[i]->active = true; 695 development_stagnation = false; //will be detected by oneStep() 694 696 695 697 if (PRINT_CELLS_DEVELOPMENT) f4_Node::print_tree(C[0]->genot, 0); … … 699 701 while (oneStep()) if (PRINT_CELLS_DEVELOPMENT) print_cells("Development step"); 700 702 if (PRINT_CELLS_DEVELOPMENT) print_cells("After last development step"); 701 702 #ifdef EXTRA_STEP_CELL_DEVELOPMENT703 if (errorcode == GENOPER_OK)704 {705 oneStep(); if (PRINT_CELLS_DEVELOPMENT) print_cells("After extra step"); //for these "halted" (yielding) cells (they have active==false) that wait for other cells to develop. Without this step, the last, recently halted one(s) may miss the "retrying" step if all active==true cells became active==false in the last step.706 }707 #endif708 703 709 704 if (errorcode != GENOPER_OK) return errorcode; … … 762 757 default: type = std::to_string(c->type); 763 758 } 764 const char *status = c-> active ? "active" : (c->gcur != NULL ? "yielding" : ""); //yielding = not active but waiting for other cells759 const char *status = c->gcur == c->old_gcur ? (c->gcur != NULL ? "no progress" : "") : (c->gcur != NULL ? "progress" : "finished"); //progress or no progress means the cell is yielding = not finished but decided to halt development and wait for other cells. New cells may be created in case of "no progress" status. 765 760 printf("%2d(%-8s) nr=%d \t type=%-15s \t genot=%s \t gcurrent=%s", i, status, c->nr, type.c_str(), c->genot->name.c_str(), c->gcur ? c->gcur->name.c_str() : "null"); 766 761 if (c->gcur && c->gcur->name == "[") … … 1409 1404 static 1410 1405 #else 1411 thread_local 1406 thread_local 1412 1407 #endif 1413 1408 vector<int> modifs_counts(strlen(all_modifiers_no_comma)); ///<an array with a known constant size storing counters of each modifier symbol from all_modifiers_no_comma, created once to avoid reallocation every time when modifier genes are simplified during parsing. Initialization of required size; it will never be resized. -
cpp/frams/genetics/f4/f4_general.h
r1237 r1239 190 190 f4_Node *genot; ///<genotype tree 191 191 f4_Node *gcur; ///<current genotype execution pointer 192 bool active; ///<determines whether development is still active; even if false, the cell may "yield" - may be halted (but still having its onStep() called) due to neural connections waiting for other cells to potentially develop neurons192 f4_Node *old_gcur; ///<used externally by f4_Cells::oneStep() to track changes of gcur, i.e., to detect progress in cell development 193 193 repeat_stack repeat; ///<stack holding repetition nodes and counters 194 194 int recProcessedFlag; ///<used during recursive traverse … … 329 329 f4_Cell *C[F4_MAX_CELLS]; ///<Array of all cells of an organism 330 330 int cell_count; ///<Number of cells in an organism 331 bool development_stagnation; ///< simulate() and oneStep() use it to force f4_Cell's waiting to develop their neural connections to progress, indicating that all cells have not had progress during the last step 331 332 332 333 private:
Note: See TracChangeset
for help on using the changeset viewer.