Ignore:
Timestamp:
05/02/23 01:36:15 (12 months ago)
Author:
Maciej Komosinski
Message:
  • Thanks to r1230, it is possible to detect (and repair=remove) junk trailing genes that are left after successful parsing (after last '>')
  • The validate() function may attempt to repair a genotype where earlier it would give up
  • Stricter parsing of the '#' gene
File:
1 edited

Legend:

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

    r1230 r1231  
    1111// 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
    1212// 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.
    1414//
    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.
    1615//
    1716// 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 '['.
     
    8786}
    8887
    89 int Geno_f4::ValidateRec(f4_Node *geno, int retrycount) const
     88int Geno_f4::ValidateRecur(f4_Node *geno, int retrycount) const
    9089{
    9190        // ! the genotype is geno->child (not geno) !
    9291        // build from it with repair on
    9392
    94         f4_Cells cells(geno->child, 1);
     93        f4_Cells cells(geno->child, true);
    9594        cells.simulate();  //we should simulate?!
    9695
     
    109108                int res2 = GENOPER_OK;
    110109                if (retrycount > 0)
    111                         res2 = ValidateRec(geno, retrycount - 1);
     110                        res2 = ValidateRecur(geno, retrycount - 1);
    112111
    113112                if (res2 == GENOPER_OK) return GENOPER_REPAIR;
     
    123122        // convert geno to a tree, then try to validate
    124123        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)
    128128        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),
    130131        {
    131132                geno[0] = 0;
    132                 root.child->sprintAdj(geno);
     133                root.child->sprintAdj(geno); //make it back to string
    133134        }
    134135        return GENOPER_OK;
     
    139140{
    140141        f4_Node root;
    141         int _ = 0;
    142         int res = f4_processRecur(geno, _, &root);
     142        int res = f4_process(geno, &root);
    143143        if (res) return res;  // errorpos, >0
    144         if (root.childCount() != 1) return 1; //earlier: GENOPER_OPFAIL
    145         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);
    146146        cells.simulate();
    147147        if (cells.getErrorCode() == GENOPER_OPFAIL || cells.getErrorCode() == GENOPER_REPAIR)
    148148        {
    149149                if (cells.getErrorPos() >= 0) return 1 + cells.getErrorPos();
    150                 else return 1; //earlier: GENOPER_OPFAIL;
     150                else return 1; //error, no known position
    151151        }
    152152        else return GENOPER_OK;
     
    525525                }
    526526                // try to validate it
    527                 res = ValidateRec(gcopy, 10);
     527                res = ValidateRecur(gcopy, 10);
    528528                // accept if it is OK, or was repaired
    529529                if (GENOPER_OK == res)
     
    552552{
    553553        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)
    556555        {
    557556                delete root;
     
    677676
    678677        // 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;
    682680
    683681        // decide amounts of crossover, 0.1-0.9
Note: See TracChangeset for help on using the changeset viewer.