- Timestamp:
- 05/02/23 01:36:15 (19 months ago)
- Location:
- cpp/frams/genetics/f4
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/f4/f4_conv.cpp
r1227 r1231 27 27 SString GenoConv_f40::convert(SString &in, MultiMap *map, bool using_checkpoints) 28 28 { 29 int res;30 29 f4_Model *model = new f4_Model(); 31 res = model->buildFromF4(in, using_checkpoints);32 if ( GENOPER_OK != res)30 int res = model->buildFromF4(in, using_checkpoints); 31 if (res != GENOPER_OK) 33 32 { 34 33 delete model; … … 55 54 SString GenoConv_F41_TestOnly::convert(SString &in, MultiMap *map, bool using_checkpoints) 56 55 { 57 int res;58 56 f4_Model *model = new f4_Model(); 59 res = model->buildFromF4(in, using_checkpoints);60 if ( GENOPER_OK != res)57 int res = model->buildFromF4(in, using_checkpoints); 58 if (res != GENOPER_OK) 61 59 { 62 60 delete model; … … 82 80 int f4_Model::buildFromF4(SString &geno, bool using_checkpoints) 83 81 { 84 int i;85 86 82 error = GENOPER_OK; 87 83 errorpos = -1; 88 84 85 // transform geno from string to nodes 86 f4_Node f4rootnode; 87 int res = f4_process(geno.c_str(), &f4rootnode); 88 if (res || (f4rootnode.childCount() != 1)) //consider any error fatal, preventing building a model 89 { 90 error = GENOPER_OPFAIL; 91 errorpos = res; 92 return error; 93 } 94 89 95 // build cells, and simulate 90 96 if (cells) delete cells; 91 cells = new f4_Cells( geno, 0);92 if ( GENOPER_OK != cells->getErrorCode())97 cells = new f4_Cells(f4rootnode.child, false); 98 if (cells->getErrorCode() != GENOPER_OK) 93 99 { 94 100 error = cells->getErrorCode(); … … 99 105 100 106 cells->simulate(); 101 if ( GENOPER_OK != cells->getErrorCode())107 if (cells->getErrorCode() != GENOPER_OK) 102 108 { 103 109 error = cells->getErrorCode(); … … 107 113 108 114 // reset recursive traverse flags 109 for (i = 0; i < cells->cell_count; i++)115 for (int i = 0; i < cells->cell_count; i++) 110 116 cells->C[i]->recProcessedFlag = 0; 111 117 … … 113 119 114 120 // process every cell 115 int res; 116 for (i = 0; i < cells->cell_count; i++) 117 { 118 res = buildModelRec(cells->C[i]); 121 for (int i = 0; i < cells->cell_count; i++) 122 { 123 int res = buildModelRec(cells->C[i]); 119 124 if (res) 120 125 { 121 log Message("f4_Model", "buildFromF4", LOG_ERROR, "Error in building a Model");126 logPrintf("f4_Model", "buildFromF4", LOG_ERROR, "Error %d when building a Model", res); 122 127 error = res; 123 128 break; … … 125 130 } 126 131 127 res = close(); 128 if (0 == res) // invalid 132 int res_close = close(); 133 if (res_close == 0) // invalid 134 { 135 logPrintf("f4_Model", "buildFromF4", LOG_ERROR, "Error %d when closing a Model", res_close); 129 136 error = -10; 137 } 130 138 131 139 return error; -
cpp/frams/genetics/f4/f4_general.cpp
r1230 r1231 640 640 641 641 642 f4_Cells::f4_Cells(f4_Node *genome, int nrepair) 643 { 644 // create ancestor cell 642 f4_Cells::f4_Cells(f4_Node *genome, bool nrepair) 643 { 645 644 repair = nrepair; 646 645 errorcode = GENOPER_OK; … … 650 649 repair_insert = NULL; 651 650 tmpcel = NULL; 652 f4rootnode = NULL; 651 652 // create ancestor cell 653 653 C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, GeneProps::standard_values); 654 654 cell_count = 1; … … 656 656 657 657 658 f4_Cells::f4_Cells(SString & genome, int nrepair)659 {660 repair = nrepair;661 errorcode = GENOPER_OK;662 errorpos = -1;663 repair_remove = NULL;664 repair_parent = NULL;665 repair_insert = NULL;666 tmpcel = NULL;667 f4rootnode = NULL;668 669 // transform geno from string to nodes670 f4rootnode = new f4_Node();671 int _ = 0;672 int res = f4_processRecur(genome.c_str(), _, f4rootnode);673 if (res || (f4rootnode->childCount() != 1))674 {675 errorcode = GENOPER_OPFAIL;676 errorpos = -1;677 }678 679 // create ancestor cell680 C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child, NULL, 0, GeneProps::standard_values);681 cell_count = 1;682 }683 658 684 659 f4_Cells::~f4_Cells() 685 660 { 686 661 // release cells 687 int i;688 662 if (cell_count) 689 663 { 690 for (i = cell_count - 1; i >= 0; i--)664 for (int i = cell_count - 1; i >= 0; i--) 691 665 delete C[i]; 692 666 cell_count = 0; 693 667 } 694 if (f4rootnode)695 delete f4rootnode;696 668 } 697 669 … … 1130 1102 int f4_Node::childCount() 1131 1103 { 1132 if (child != NULL) 1133 { 1134 if (child2 != NULL) return 2; 1135 else return 1; 1136 } 1137 else 1138 { 1139 if (child2 != NULL) return 1; 1140 else return 0; 1141 } 1104 return int(child != NULL) + int(child2 != NULL); //0, 1 or 2 1142 1105 } 1143 1106 … … 1256 1219 len = out.length(); 1257 1220 if (len > 1) 1258 if (out[len - 1] == '>') { (out.directWrite())[len - 1] = 0; out.endWrite(); }; //Macko 2023-04 TODO "can be omitted", but should we remove it as a rule even in generated genotypes? see if I can somehow detect junk characters after top-level '>' ends properly: /*4*/<X>N:N>whatever1221 if (out[len - 1] == '>') { (out.directWrite())[len - 1] = 0; out.endWrite(); }; //Macko 2023-04 "can be omitted", but it is removed as a rule even in generated genotypes :) 1259 1222 // copy back to string 1260 1223 // if new is longer, reallocate buf … … 1305 1268 while (pos_inout < (int)strlen(genot)) 1306 1269 { 1307 1270 //#define PRINT_PARSING_LOCATION 1308 1271 #ifdef PRINT_PARSING_LOCATION 1309 1272 printf("%s\n", genot); … … 1342 1305 case '#': 1343 1306 { 1344 // repetition marker , 1 by default1345 ExtValue val;1346 const char* end = val.parseNumber(genot + pos_inout + 1, ExtPType::TInt);1347 //TODO end==NULL? -> error!1348 int reps = (end == NULL) ? 1 : val.getInt();1307 // repetition marker 1308 ExtValue reps; 1309 const char* end = reps.parseNumber(genot + pos_inout + 1, ExtPType::TInt); 1310 if (end == NULL) 1311 return pos_inout + 1; //error 1349 1312 f4_Node *node = new f4_Node("#", par, pos_inout); 1350 node->reps = reps ;1313 node->reps = reps.getInt(); 1351 1314 // skip number 1352 1315 pos_inout += end - (genot + pos_inout); … … 1455 1418 } 1456 1419 1420 int f4_process(const char *genot, f4_Node *root) 1421 { 1422 int pos = 0; 1423 int res = f4_processRecur(genot, pos, root); 1424 if (res > 0) 1425 return res; //error 1426 else if (genot[pos] == 0) //parsed until the end - OK! 1427 return 0; 1428 else return pos + 1; //junk, unparsed genes after successful parsing, for example /*4*/<X>N:N>whatever or /*4*/<X>X>>> 1429 } 1430 1457 1431 const char* parseConnection(const char *fragm, int& relfrom, double &weight) 1458 1432 { -
cpp/frams/genetics/f4/f4_general.h
r1230 r1231 242 242 * Constructor taking genotype in a form of a tree. 243 243 * @param genome genotype tree 244 * @param nrepair 0 if nothing to repair 245 */ 246 f4_Cells(f4_Node *genome, int nrepair); 247 248 /** 249 * Constructor taking genotype in a form of a string. 250 * @param genome genotype string 251 * @param nrepair 0 if nothing to repair 252 */ 253 f4_Cells(SString &genome, int nrepair); 244 * @param nrepair false if nothing to repair 245 */ 246 f4_Cells(f4_Node *genome, bool nrepair); 254 247 255 248 /** … … 336 329 private: 337 330 // for error reporting / genotype fixing 338 intrepair;331 bool repair; 339 332 int errorcode; 340 333 int errorpos; … … 343 336 f4_Node *repair_insert; 344 337 void toF1GenoRec(int curc, SString &out); 345 f4_Cell *tmpcel; // needed by toF1Geno 346 f4_Node *f4rootnode; // used by constructor 338 f4_Cell *tmpcel; // needed by toF1Geno 347 339 }; 348 340 … … 477 469 * semantic aspect is neuron class name extraction, where the GenoOperators 478 470 * class is used to parse the potential neuron class name. 479 * @param genot the string holding all the genotype 480 * @param pos0 the current position of processing in string 471 * This is an internal function; for regular cases, use f4_process(). 472 * @param genot the string with the entire genotype 473 * @param pos_inout the current position of processing in string (advanced by the function) 481 474 * @param parent current parent of the analysed branch of the genotype 482 475 * @return 0 if processing was successful, otherwise returns the position of an error in the genotype 483 476 */ 484 477 int f4_processRecur(const char *genot, int &pos_inout, f4_Node *parent); 478 479 /** 480 * A wrapper for f4_processRecur(). Creates a tree of f4_Node objects corresponding to 481 * the provided genotype. 482 * @param genot the string with the entire genotype 483 * @param root root of the tree corresponding to the genotype 484 * @return 0 if processing was successful, otherwise returns the position of an error in the genotype 485 */ 486 int f4_process(const char *genot, f4_Node *root); 485 487 486 488 /** -
cpp/frams/genetics/f4/f4_oper.cpp
r1230 r1231 11 11 // may help, but it would be better to improve the source code to make genetic operators neutral in terms of genotype length. Adding such a penalty 12 12 // removes "work in progress" changes in genotypes thus promoting immediate, straightforward improvements while hindering slower, multifaceted progress. 13 // TODO getting rid of redundancy ( having valid genotypes with a lot of "junk code") in this representation looks like a good idea.13 // TODO getting rid of redundancy (valid genotypes with a lot of "junk code") in this representation looks like a good idea; many improvements to this end have already been done in April & May 2023. 14 14 // 15 // Note: symbols after the last > are ignored, for example /*4*/<X>N:N>blablaN:N[2:-0.5]XXXwhatever but since they are not parsed into the f4_Node tree, they will be lost after any mutation.16 15 // 17 16 // TODO the behavior of neuron input indexes during mutation seems badly implemented (see also TREAT_BAD_CONNECTIONS_AS_INVALID_GENO). Are they kept properly maintained when nodes are added and removed? This could be done well because during mutation we operate on the tree structure with cross-references between nodes (so they should not be affected by local changes in the tree), and then convert the tree back to string. Yet, the f4_Node.conn_from is an integer and these fields in nodes do not seem to be maintained on tree node adding/removal... change these integer offsets to references to node objects? But actually, do the offsets that constitute relative connection references concern the f4_Node tree structure (and all these sophisticated calculations of offsets during mutation are useful) or rather they concern the f4_Cells development? verify all situations in f4_Cell::oneStep(), case '['. … … 87 86 } 88 87 89 int Geno_f4::ValidateRec (f4_Node *geno, int retrycount) const88 int Geno_f4::ValidateRecur(f4_Node *geno, int retrycount) const 90 89 { 91 90 // ! the genotype is geno->child (not geno) ! 92 91 // build from it with repair on 93 92 94 f4_Cells cells(geno->child, 1);93 f4_Cells cells(geno->child, true); 95 94 cells.simulate(); //we should simulate?! 96 95 … … 109 108 int res2 = GENOPER_OK; 110 109 if (retrycount > 0) 111 res2 = ValidateRec (geno, retrycount - 1);110 res2 = ValidateRecur(geno, retrycount - 1); 112 111 113 112 if (res2 == GENOPER_OK) return GENOPER_REPAIR; … … 123 122 // convert geno to a tree, then try to validate 124 123 f4_Node root; 125 int _ = 0; 126 if (f4_processRecur(geno, _, &root) || root.childCount() != 1) return GENOPER_OK; // cannot repair 127 124 int res = f4_process(geno, &root); 125 if (res == 0 || root.childCount() != 1) return GENOPER_OK; // either parsing says the genotype is OK or the resulting tree will not be repairable (fatal flaw; root must have exactly one child) - do not attempt repair 126 127 // here we have a genotype with res>0 (for sure has some error) and root.childCount()==1 (still something was parsed into a tree) 128 128 const int VALIDATE_TRIALS = 20; 129 if (ValidateRec(&root, VALIDATE_TRIALS) == GENOPER_REPAIR) // if repaired, make it back to string 129 res = ValidateRecur(&root, VALIDATE_TRIALS); 130 if (res != GENOPER_OPFAIL) // if repaired (GENOPER_REPAIR) or had no errors (GENOPER_OK, e.g. the genotype had some errors that were ignored during tree creation or had junk genes appended at the end, so the tree was OK but the genotype was not), 130 131 { 131 132 geno[0] = 0; 132 root.child->sprintAdj(geno); 133 root.child->sprintAdj(geno); //make it back to string 133 134 } 134 135 return GENOPER_OK; … … 139 140 { 140 141 f4_Node root; 141 int _ = 0; 142 int res = f4_processRecur(geno, _, &root); 142 int res = f4_process(geno, &root); 143 143 if (res) return res; // errorpos, >0 144 if (root.childCount() != 1) return 1; // earlier: GENOPER_OPFAIL145 f4_Cells cells(root.child, 0);144 if (root.childCount() != 1) return 1; // fatal flaw; root must have exactly one child 145 f4_Cells cells(root.child, false); 146 146 cells.simulate(); 147 147 if (cells.getErrorCode() == GENOPER_OPFAIL || cells.getErrorCode() == GENOPER_REPAIR) 148 148 { 149 149 if (cells.getErrorPos() >= 0) return 1 + cells.getErrorPos(); 150 else return 1; //e arlier: GENOPER_OPFAIL;150 else return 1; //error, no known position 151 151 } 152 152 else return GENOPER_OK; … … 525 525 } 526 526 // try to validate it 527 res = ValidateRec (gcopy, 10);527 res = ValidateRecur(gcopy, 10); 528 528 // accept if it is OK, or was repaired 529 529 if (GENOPER_OK == res) … … 552 552 { 553 553 f4_Node *root = new f4_Node; 554 int _ = 0; 555 if (f4_processRecur(g, _, root) || root->childCount() != 1) 554 if (f4_process(g, root) || root->childCount() != 1) 556 555 { 557 556 delete root; … … 677 676 678 677 // convert genotype strings into tree structures 679 int _1 = 0, _2 = 0; 680 if (f4_processRecur(g1, _1, &root1) || (root1.childCount() != 1)) return GENOPER_OPFAIL; 681 if (f4_processRecur(g2, _2, &root2) || (root2.childCount() != 1)) return GENOPER_OPFAIL; 678 if (f4_process(g1, &root1) || (root1.childCount() != 1)) return GENOPER_OPFAIL; 679 if (f4_process(g2, &root2) || (root2.childCount() != 1)) return GENOPER_OPFAIL; 682 680 683 681 // decide amounts of crossover, 0.1-0.9 -
cpp/frams/genetics/f4/f4_oper.h
r1227 r1231 72 72 * @return GENOOPER_OK if genotype is valid, GENOPER_REPAIR if genotype can be repaired, GENOPER_OPFAIL if genotype can't be repaired 73 73 */ 74 int ValidateRec (f4_Node *geno, int retrycount) const;74 int ValidateRecur(f4_Node *geno, int retrycount) const; 75 75 76 76 /**
Note: See TracChangeset
for help on using the changeset viewer.