Changeset 1228 for cpp/frams/genetics
- Timestamp:
- 04/28/23 23:44:31 (19 months ago)
- Location:
- cpp/frams/genetics/f4
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/f4/f4_general.cpp
r1227 r1228 33 33 } 34 34 35 int scan rec(const char* s, size_t slen, char stopchar)36 { 37 size_t i = 0;35 int scanRecur(const char* s, int slen, char stopchar) 36 { 37 int i = 0; 38 38 //DB( printf(" scan('%s', '%c')\n", s, stopchar); ) 39 39 while (1) 40 40 { 41 if (i >= slen) // ran out the string, should never happen with correct string41 if (i >= slen) // ran out the string, should never happen with a correct string 42 42 return 1; 43 43 if (stopchar == s[i]) // bumped into stopchar … … 47 47 if (s[i] == '(') 48 48 { 49 i += 2 + scan rec(s + i + 1, slen - i - 1, ')');49 i += 2 + scanRecur(s + i + 1, slen - i - 1, ')'); 50 50 continue; 51 51 } 52 52 if (s[i] == '<') 53 53 { 54 i += 2 + scan rec(s + i + 1, slen - i - 1, '>');54 i += 2 + scanRecur(s + i + 1, slen - i - 1, '>'); 55 55 continue; 56 56 } 57 57 if (s[i] == '#') 58 58 { 59 i += 2 + scan rec(s + i + 1, slen - i - 1, '>');59 i += 2 + scanRecur(s + i + 1, slen - i - 1, '>'); 60 60 continue; 61 61 } 62 62 } 63 // s[i] a non-special character63 // s[i] is a non-special character 64 64 i++; 65 65 } 66 return i nt(i);66 return i; 67 67 } 68 68 … … 703 703 f4_Cells::f4_Cells(SString & genome, int nrepair) 704 704 { 705 int res;706 705 repair = nrepair; 707 706 errorcode = GENOPER_OK; … … 715 714 // transform geno from string to nodes 716 715 f4rootnode = new f4_Node(); 717 res = f4_processrec(genome.c_str(), 0, f4rootnode);718 if ( (res < 0) || (1 != f4rootnode->childCount()))716 int res = f4_processRecur(genome.c_str(), 0, f4rootnode); 717 if (res || (f4rootnode->childCount() != 1)) 719 718 { 720 719 errorcode = GENOPER_OPFAIL; … … 833 832 switch (c->type) 834 833 { 835 case CELL_UNDIFF: type = " UNDIFF"; break;834 case CELL_UNDIFF: type = "undiff"; break; 836 835 case CELL_STICK: type = "STICK"; break; 837 836 case CELL_NEURON: type = string("NEURON:") + c->neuclass->name.c_str(); break; … … 1218 1217 { 1219 1218 int n = count(); 1220 // pick a random node ,between 0 and n-11219 // pick a random node between 0 and n-1 1221 1220 return ordNode(rndUint(n)); 1222 1221 } … … 1341 1340 // scan genotype string and build tree 1342 1341 // return >1 for error (errorpos) 1343 int f4_processrec(const char* genot, unsigned pos0, f4_Node *parent) 1344 { 1345 int i, res; 1346 unsigned gpos, oldpos; 1347 f4_Node *node1, *par; 1348 unsigned beginindex; 1342 int f4_processRecur(const char* genot, unsigned pos0, f4_Node *parent) 1343 { 1344 unsigned int gpos; 1345 f4_Node *par; 1349 1346 1350 1347 gpos = pos0; … … 1359 1356 { 1360 1357 // find out genotype start for child 1361 int j = scanrec(genot + gpos + 1,strlen(genot + gpos + 1), '>');1362 1363 node1= new f4_Node("<", par, gpos);1364 par = node 1;1365 res = f4_processrec(genot, gpos + 1, par);1358 int stopchar_offset = scanRecur(genot + gpos + 1, (int)strlen(genot + gpos + 1), '>'); 1359 1360 f4_Node *node = new f4_Node("<", par, gpos); 1361 par = node; 1362 int res = f4_processRecur(genot, gpos + 1, par); 1366 1363 if (res) return res; 1367 if (gpos + j+ 2 < strlen(genot))1368 { 1369 res = f4_process rec(genot, gpos + j+ 2, par);1364 if (gpos + stopchar_offset + 2 < strlen(genot)) 1365 { 1366 res = f4_processRecur(genot, gpos + stopchar_offset + 2, par); 1370 1367 if (res) return res; 1371 1368 } 1372 1369 else // ran out 1373 1370 { 1374 node 1= new f4_Node(">", par, int(strlen(genot)) - 1);1375 par = node 1;1371 node = new f4_Node(">", par, int(strlen(genot)) - 1); 1372 par = node; 1376 1373 } 1377 1374 gpos++; … … 1380 1377 case '>': 1381 1378 { 1382 node1= new f4_Node(">", par, gpos);1383 par = node 1;1379 f4_Node *node = new f4_Node(">", par, gpos); 1380 par = node; 1384 1381 gpos = (unsigned int)strlen(genot); 1385 1382 return 0; // OK … … 1390 1387 ExtValue val; 1391 1388 const char* end = val.parseNumber(genot + gpos + 1, ExtPType::TInt); 1392 if (end == NULL) i = 1; 1393 else i = val.getInt(); 1389 int reps = (end == NULL) ? 1 : val.getInt(); 1394 1390 // find out genotype start for continuation 1395 int j = scanrec(genot + gpos + 1,strlen(genot + gpos + 1), '>');1391 int stopchar_offset = scanRecur(genot + gpos + 1, (int)strlen(genot + gpos + 1), '>'); 1396 1392 // skip number 1397 oldpos = gpos;1393 unsigned int oldpos = gpos; 1398 1394 gpos += end - (genot + gpos); 1399 1395 //gpos++; 1400 1396 //while ((genot[gpos] >= '0') && (genot[gpos] <= '9')) gpos++;node1 = new f4_Node("#", par, oldpos); 1401 node1= new f4_Node("#", par, oldpos);1402 node 1->reps = i;1403 par = node 1;1404 res = f4_processrec(genot, gpos, node1);1397 f4_Node *node = new f4_Node("#", par, oldpos); 1398 node->reps = reps; 1399 par = node; 1400 int res = f4_processRecur(genot, gpos, node); 1405 1401 if (res) return res; 1406 if (oldpos + j+ 2 < strlen(genot))1407 { 1408 res = f4_process rec(genot, oldpos + j + 2, node1);1402 if (oldpos + stopchar_offset + 2 < strlen(genot)) 1403 { 1404 res = f4_processRecur(genot, oldpos + stopchar_offset + 2, node); 1409 1405 if (res) return res; 1410 1406 } 1411 1407 else // ran out 1412 1408 { 1413 node 1= new f4_Node(">", par, int(strlen(genot)) - 1);1409 node = new f4_Node(">", par, int(strlen(genot)) - 1); 1414 1410 } 1415 1411 return 0; // OK … … 1430 1426 return gpos + 1; //error 1431 1427 gpos += 2; //skipping "N:" 1432 beginindex = gpos;1433 char* end = (char*)genot + begin index;1428 unsigned int begin_index = gpos; 1429 char* end = (char*)genot + begin_index; 1434 1430 NeuroClass *neuclass = GenoOperators::parseNeuroClass(end, ModelEnum::SHAPETYPE_BALL_AND_STICK); 1435 1431 if (neuclass == NULL) 1436 1432 return gpos + 1; //error 1437 gpos += end - genot - begin index;1438 string neutype = string(genot + begin index, genot + gpos);1439 node1= new f4_Node(neutype, par, forgenorange);1440 node 1->neuclass = neuclass;1441 par = node 1;1433 gpos += end - genot - begin_index; 1434 string neutype = string(genot + begin_index, genot + gpos); 1435 f4_Node *node = new f4_Node(neutype, par, forgenorange); 1436 node->neuclass = neuclass; 1437 par = node; 1442 1438 // if it continues with a colon that determines a neuron parameter (e.g. N:N:+=: ), then let the switch case for colon handle this 1443 1439 break; … … 1459 1455 return gpos + 1 + 1; //error 1460 1456 } 1461 node1= new f4_Node(":", par, gpos);1462 node 1->prop_symbol = prop_symbol;1463 node 1->prop_increase = prop_dir == '+' ? true : false; // + or -1464 par = node 1;1465 int chars = scanrec(genot + gpos + 1,strlen(genot + gpos + 1), ':');1466 gpos += chars+ 2;1457 f4_Node *node = new f4_Node(":", par, gpos); 1458 node->prop_symbol = prop_symbol; 1459 node->prop_increase = prop_dir == '+' ? true : false; // + or - 1460 par = node; 1461 int stopchar_offset = scanRecur(genot + gpos + 1, (int)strlen(genot + gpos + 1), ':'); 1462 gpos += stopchar_offset + 2; 1467 1463 break; 1468 1464 } … … 1475 1471 return gpos + 1; //error 1476 1472 1477 node1= new f4_Node("[", par, gpos);1478 node 1->conn_from = relfrom;1479 node 1->conn_weight = weight;1480 par = node 1;1481 int j = scanrec(genot + gpos + 1,strlen(genot + gpos + 1), ']');1482 gpos += j+ 2;1473 f4_Node *node = new f4_Node("[", par, gpos); 1474 node->conn_from = relfrom; 1475 node->conn_weight = weight; 1476 par = node; 1477 int stopchar_offset = scanRecur(genot + gpos + 1, (int)strlen(genot + gpos + 1), ']'); 1478 gpos += stopchar_offset + 2; 1483 1479 break; 1484 1480 } … … 1486 1482 { 1487 1483 //printf("any regular character '%c'\n", genot[gpos]); 1488 node1= new f4_Node(genot[gpos], par, gpos);1489 par = node 1;1484 f4_Node *node = new f4_Node(genot[gpos], par, gpos); 1485 par = node; 1490 1486 gpos++; 1491 1487 break; … … 1499 1495 if (par->name != ">") 1500 1496 { 1501 node1= new f4_Node('>', par, int(strlen(genot)) - 1);1502 par = node 1;1497 f4_Node *node = new f4_Node('>', par, int(strlen(genot)) - 1); 1498 par = node; 1503 1499 } 1504 1500 } … … 1526 1522 } 1527 1523 1528 f4_Node* f4_processtree(const char* geno) 1524 /* 1525 f4_Node* f4_processTree(const char* geno) 1529 1526 { 1530 1527 f4_Node *root = new f4_Node(); 1531 int res = f4_process rec(geno, 0, root);1528 int res = f4_processRecur(geno, 0, root); 1532 1529 if (res) return NULL; 1533 1530 //DB( printf("test f4 "); ) … … 1545 1542 return root->child; 1546 1543 } 1544 */ -
cpp/frams/genetics/f4/f4_general.h
r1227 r1228 51 51 * @return 1 if end of string was reached, or position of found character in sequence 52 52 */ 53 int scan rec(const char* s, unsignedint slen, char stopchar);53 int scanRecur(const char* s, int slen, char stopchar); 54 54 55 55 … … 475 475 /** 476 476 * The main function for converting a string of f4 encoding to a tree structure. Prepares 477 * f4_Node root of tree and runs f4_process recfunction for it.477 * f4_Node root of tree and runs f4_processRecur function for it. 478 478 * @param geno the string representing an f4 genotype 479 479 * @return a pointer to the f4_Node object representing the f4 tree root 480 480 */ 481 f4_Node* f4_processtree(const char *geno);481 //f4_Node* f4_processTree(const char *geno); 482 482 483 483 /** … … 485 485 * a tree of f4_Node objects. This method extracts each potentially functional element 486 486 * of a genotype string to a separate f4_Nodes. When the branching character '<' occurs, 487 * f4_process recis deployed for the latest f4_Node element. This method does not487 * f4_processRecur is deployed for the latest f4_Node element. This method does not 488 488 * analyse the genotype semantically, it only checks if the syntax is proper. The only 489 489 * semantic aspect is neuron class name extraction, where the GenoOperators … … 494 494 * @return 0 if processing was successful, otherwise returns the position of an error in the genotype 495 495 */ 496 int f4_process rec(const char *genot, unsigned pos0, f4_Node *parent);496 int f4_processRecur(const char *genot, unsigned pos0, f4_Node *parent); 497 497 498 498 /** -
cpp/frams/genetics/f4/f4_oper.cpp
r1227 r1228 13 13 // TODO getting rid of redundancy (having valid genotypes with a lot of "junk code") in this representation looks like a good idea. 14 14 // 15 // Note: symbols after the last > are ignored, for example /*4*/<X>N:N> N:N[2:-0.5]XXXwhatever but since they are not parsed into the f4_Node tree, they will be lost after any mutation.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 16 // 17 // TODO the behavior of neuron input indexes during mutation seems badly implemented (see also TREAT_BAD_CONNECTIONS_AS_ ERRORS). 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 '['.17 // 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 '['. 18 18 // TODO add simplifying sequences of modifiers (so capital and small letter cancel out, like in f1) - but seems like each single modifier is a separate f4_Node? and perhaps we don't want to use the repair mechanism for this... maybe mutations, when they add/modify/remove a modifier node, should be "cleaning" the tree by removing nodes when they encounter contradictory modifiers on the same subpath? 19 19 // TODO add support for properties of (any class of) neurons - not just sigmoid/force/intertia (':' syntax) for N … … 122 122 // convert geno to tree, then try to validate 20 times 123 123 f4_Node root; 124 if (f4_process rec(geno, 0, &root) || root.childCount() != 1) return GENOPER_OK; // cannot repair124 if (f4_processRecur(geno, 0, &root) || root.childCount() != 1) return GENOPER_OK; // cannot repair 125 125 if (ValidateRec(&root, 20) == GENOPER_REPAIR) // if repaired, make it back to string 126 126 { … … 135 135 { 136 136 f4_Node root; 137 int res = f4_process rec(geno, 0, &root);137 int res = f4_processRecur(geno, 0, &root); 138 138 if (res) return res; // errorpos, >0 139 139 if (root.childCount() != 1) return 1; //earlier: GENOPER_OPFAIL … … 208 208 // The "false" argument in findConnectionNeuronIndexes() below is not suffient, because we also need to access (find) the f4_Node of the other neuron. 209 209 // A similar logic is implemented in F4_ADD_CONN below, but let's not complicate this F4_ADD_DIV mutation anymore. 210 // Adisadvantage is that the node_new_neuron added here which is a neuron that provides output (e.g., a receptor, N, etc.) will not get connected immediately here even when there are already existing neurons wanting inputs (e.g., muscles, N, etc.).210 // The disadvantage is that the node_new_neuron added here which is a neuron that provides output (e.g., a receptor, N, etc.) will not get connected immediately here even when there are already existing neurons wanting inputs (e.g., muscles, N, etc.). 211 211 //bool ok = findConnectionNeuronIndexes(g, ... , false, ..., ...); 212 212 } … … 230 230 231 231 // the probability that a randomly selected node will be a neuron and additionally this neuron will accept inputs is low, 232 // so we disregard randomly picked node_mutated and build a list of all valid candidate nodes here, then select a randomone from them.232 // so we disregard randomly picked node_mutated and build a list of all valid candidate nodes here, then randomly select one from them. 233 233 234 234 vector<f4_Node*> candidate_nodes; //neurons that accept input(s) … … 476 476 // relative input connection to some existing neuron 477 477 nn->conn_from = nn_index - other_index; 478 //nn->conn_from = (int)(4.0f * (rndDouble(1) - 0.5 f)); //in very old times - did not care about neuron input/output preferences478 //nn->conn_from = (int)(4.0f * (rndDouble(1) - 0.5)); //in very old times - did not care about neuron input/output preferences 479 479 480 480 nn->conn_weight = GenoOperators::getMutatedNeuronConnectionWeight(nn->conn_weight); … … 493 493 void Geno_f4::repeatNodeChangeRandom(f4_Node *nn) const 494 494 { 495 if (rndDouble(1) < 0.5 f) nn->reps++; else nn->reps--; // change count495 if (rndDouble(1) < 0.5) nn->reps++; else nn->reps--; // change count 496 496 if (nn->reps < 1) nn->reps = 1; 497 497 if (nn->reps > mut_max_rep) nn->reps = mut_max_rep; … … 547 547 { 548 548 f4_Node *root = new f4_Node; 549 if (f4_process rec(g, 0, root) || root->childCount() != 1)549 if (f4_processRecur(g, 0, root) || root->childCount() != 1) 550 550 { 551 551 delete root; … … 607 607 608 608 // decide number of nodes to mutate 609 n = (int)( 0.5 f+ rndDouble(1) * maxToMut );609 n = (int)( 0.5 + rndDouble(1) * maxToMut ); 610 610 if (n<1) n=1; 611 611 if (n>totNodes) n=totNodes; … … 671 671 672 672 // convert genotype strings into tree structures 673 if (f4_process rec(g1, 0, &root1) || (root1.childCount() != 1)) return GENOPER_OPFAIL;674 if (f4_process rec(g2, 0, &root2) || (root2.childCount() != 1)) return GENOPER_OPFAIL;673 if (f4_processRecur(g1, 0, &root1) || (root1.childCount() != 1)) return GENOPER_OPFAIL; 674 if (f4_processRecur(g2, 0, &root2) || (root2.childCount() != 1)) return GENOPER_OPFAIL; 675 675 676 676 // decide amounts of crossover, 0.25-0.75
Note: See TracChangeset
for help on using the changeset viewer.