Ignore:
Timestamp:
04/28/23 23:44:31 (13 months ago)
Author:
Maciej Komosinski
Message:

Fixed a bug where an f4_Node tree that resulted from an f4 genotype that was not properly/completely parsed due to some error would still be used to try growing an organism

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/f4/f4_oper.cpp

    r1227 r1228  
    1313// TODO getting rid of redundancy (having valid genotypes with a lot of "junk code") in this representation looks like a good idea.
    1414//
    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.
    1616//
    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 '['.
    1818// 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?
    1919// TODO add support for properties of (any class of) neurons - not just sigmoid/force/intertia (':' syntax) for N
     
    122122        // convert geno to tree, then try to validate 20 times
    123123        f4_Node root;
    124         if (f4_processrec(geno, 0, &root) || root.childCount() != 1) return GENOPER_OK; // cannot repair
     124        if (f4_processRecur(geno, 0, &root) || root.childCount() != 1) return GENOPER_OK; // cannot repair
    125125        if (ValidateRec(&root, 20) == GENOPER_REPAIR) // if repaired, make it back to string
    126126        {
     
    135135{
    136136        f4_Node root;
    137         int res = f4_processrec(geno, 0, &root);
     137        int res = f4_processRecur(geno, 0, &root);
    138138        if (res) return res;  // errorpos, >0
    139139        if (root.childCount() != 1) return 1; //earlier: GENOPER_OPFAIL
     
    208208                                                        // The "false" argument in findConnectionNeuronIndexes() below is not suffient, because we also need to access (find) the f4_Node of the other neuron.
    209209                                                        // A similar logic is implemented in F4_ADD_CONN below, but let's not complicate this F4_ADD_DIV mutation anymore.
    210                                                         // A 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.).
     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.).
    211211                                                        //bool ok = findConnectionNeuronIndexes(g, ... , false, ..., ...);
    212212                                                }
     
    230230
    231231                        // 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 random one 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.
    233233
    234234                        vector<f4_Node*> candidate_nodes; //neurons that accept input(s)
     
    476476        // relative input connection to some existing neuron
    477477        nn->conn_from = nn_index - other_index;
    478         //nn->conn_from = (int)(4.0f * (rndDouble(1) - 0.5f)); //in very old times - did not care about neuron input/output preferences
     478        //nn->conn_from = (int)(4.0f * (rndDouble(1) - 0.5)); //in very old times - did not care about neuron input/output preferences
    479479
    480480        nn->conn_weight = GenoOperators::getMutatedNeuronConnectionWeight(nn->conn_weight);
     
    493493void Geno_f4::repeatNodeChangeRandom(f4_Node *nn) const
    494494{
    495         if (rndDouble(1) < 0.5f) nn->reps++; else nn->reps--; // change count
     495        if (rndDouble(1) < 0.5) nn->reps++; else nn->reps--; // change count
    496496        if (nn->reps < 1) nn->reps = 1;
    497497        if (nn->reps > mut_max_rep) nn->reps = mut_max_rep;
     
    547547{
    548548        f4_Node *root = new f4_Node;
    549         if (f4_processrec(g, 0, root) || root->childCount() != 1)
     549        if (f4_processRecur(g, 0, root) || root->childCount() != 1)
    550550        {
    551551                delete root;
     
    607607
    608608// decide number of nodes to mutate
    609 n = (int)( 0.5f + rndDouble(1) * maxToMut );
     609n = (int)( 0.5 + rndDouble(1) * maxToMut );
    610610if (n<1) n=1;
    611611if (n>totNodes) n=totNodes;
     
    671671
    672672        // convert genotype strings into tree structures
    673         if (f4_processrec(g1, 0, &root1) || (root1.childCount() != 1)) return GENOPER_OPFAIL;
    674         if (f4_processrec(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;
    675675
    676676        // decide amounts of crossover, 0.25-0.75
Note: See TracChangeset for help on using the changeset viewer.