Ignore:
Timestamp:
03/25/14 03:22:37 (10 years ago)
Author:
Maciej Komosinski
Message:

Updated f4 sources and made f4 available for GDK demo apps

Location:
cpp/frams/genetics/f4
Files:
1 added
1 moved

Legend:

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

    r193 r196  
    1 /*
    2  *  geno_f4.cpp - f4 genetic operators.
    3  *
    4  *  f4genotype - f4 format genotype conversions for FramSticks
    5  *
    6  *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
    7  *  Copyright (C) 2001-2004  Maciej Komosinski
    8  *
    9  *  This library is free software; you can redistribute it and/or
    10  *  modify it under the terms of the GNU Lesser General Public
    11  *  License as published by the Free Software Foundation; either
    12  *  version 2.1 of the License, or (at your option) any later version.
    13  *
    14  *  This library is distributed in the hope that it will be useful,
    15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    17  *  Lesser General Public License for more details.
    18  *
    19  *  You should have received a copy of the GNU Lesser General Public
    20  *  License along with this library; if not, write to the Free Software
    21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    22  *
    23  */
    24 
    25 #include "geno_f4.h"
    26 #include "nonstd.h"
    27 #include "sstring.h"
    28 #include "framsg.h"
     1// This file is a part of the Framsticks GDK.
     2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
     3// Refer to http://www.framsticks.com/ for further information.
     4
     5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// Copyright (C) since 2001 Maciej Komosinski
     7
     8#include "oper_f4.h"
     9#include <frams/util/sstring.h>
     10#include <common/framsg.h>
    2911
    3012#include <stdio.h>
    3113#include <stdlib.h>
    32 #include <math.h>
     14#include "common/nonstd_math.h"
    3315#include <string.h>
    3416
     
    3618#define FIELDSTRUCT Geno_f4
    3719
    38 static ParamEntry GENO4param_tab[]=
    39 {
    40  {"Genetics: f4",1,F4_COUNT+F4_ADD_COUNT,},
    41  {"f4_mut_add", 0, 0, "Add node", "f 0 100 50", FIELD(prob[F4_ADD]),"mutation: probability of adding a node", },
    42  {"f4_mut_add_div", 0, 0, "- add division", "f 0 100 20", FIELD(probadd[F4_ADD_DIV]),"add node mutation: probability of adding a division", },
    43  {"f4_mut_add_conn", 0, 0, "- add connection", "f 0 100 15", FIELD(probadd[F4_ADD_CONN]),"add node mutation: probability of adding a neural connection", },
    44  {"f4_mut_add_neupar", 0, 0, "- add neuron property", "f 0 100 5", FIELD(probadd[F4_ADD_NEUPAR]),"add node mutation: probability of adding a neuron property/modifier", },
    45  {"f4_mut_add_rep", 0, 0, "- add repetition", "f 0 100 10",FIELD(probadd[F4_ADD_REP]),"add node mutation: probability of adding a repetition", },
    46  {"f4_mut_add_simp", 0, 0, "- add simple node", "f 0 100 50",FIELD(probadd[F4_ADD_SIMP]),"add node mutation: probability of adding a random, simple gene", },
    47  {"f4_mut_del", 0, 0, "Delete node", "f 0 100 20", FIELD(prob[F4_DEL]),"mutation: probability of deleting a node", },
    48  {"f4_mut_mod", 0, 0, "Modify node", "f 0 100 30", FIELD(prob[F4_MOD]),"mutation: probability of changing a node", },
    49  {0,},
     20static ParamEntry GENO4param_tab[] =
     21{
     22        { "Genetics: f4", 1, F4_COUNT + F4_ADD_COUNT, },
     23        { "f4_mut_add", 0, 0, "Add node", "f 0 100 50", FIELD(prob[F4_ADD]), "mutation: probability of adding a node", },
     24        { "f4_mut_add_div", 0, 0, "- add division", "f 0 100 20", FIELD(probadd[F4_ADD_DIV]), "add node mutation: probability of adding a division", },
     25        { "f4_mut_add_conn", 0, 0, "- add connection", "f 0 100 15", FIELD(probadd[F4_ADD_CONN]), "add node mutation: probability of adding a neural connection", },
     26        { "f4_mut_add_neupar", 0, 0, "- add neuron property", "f 0 100 5", FIELD(probadd[F4_ADD_NEUPAR]), "add node mutation: probability of adding a neuron property/modifier", },
     27        { "f4_mut_add_rep", 0, 0, "- add repetition", "f 0 100 10", FIELD(probadd[F4_ADD_REP]), "add node mutation: probability of adding a repetition", },
     28        { "f4_mut_add_simp", 0, 0, "- add simple node", "f 0 100 50", FIELD(probadd[F4_ADD_SIMP]), "add node mutation: probability of adding a random, simple gene", },
     29        { "f4_mut_del", 0, 0, "Delete node", "f 0 100 20", FIELD(prob[F4_DEL]), "mutation: probability of deleting a node", },
     30        { "f4_mut_mod", 0, 0, "Modify node", "f 0 100 30", FIELD(prob[F4_MOD]), "mutation: probability of changing a node", },
     31        { 0, },
    5032};
    5133
     
    5537Geno_f4::Geno_f4()
    5638{
    57    supported_format='4';
    58    par.setParamTab(GENO4param_tab);
    59    par.select(this);
    60    par.setDefault();
    61 
    62    mutation_method_names=new char*[F4_COUNT+F4_ADD_COUNT-1];
    63    int index=0;
    64    mutation_method_names[index++]="added division";
    65    mutation_method_names[index++]="added neural connection";
    66    mutation_method_names[index++]="added neuron property";
    67    mutation_method_names[index++]="added repetition gene";
    68    mutation_method_names[index++]="added a simple node";
    69    mutation_method_names[index++]="deleted a node";
    70    mutation_method_names[index++]="modified a node";
    71    if (index!=F4_COUNT+F4_ADD_COUNT-1) FramMessage("Geno_f4","Constructor","Mutation names init error",3);
     39        supported_format = '4';
     40        par.setParamTab(GENO4param_tab);
     41        par.select(this);
     42        par.setDefault();
     43
     44        mutation_method_names = new char*[F4_COUNT + F4_ADD_COUNT - 1];
     45        int index = 0;
     46        mutation_method_names[index++] = "added division";
     47        mutation_method_names[index++] = "added neural connection";
     48        mutation_method_names[index++] = "added neuron property";
     49        mutation_method_names[index++] = "added repetition gene";
     50        mutation_method_names[index++] = "added a simple node";
     51        mutation_method_names[index++] = "deleted a node";
     52        mutation_method_names[index++] = "modified a node";
     53        if (index != F4_COUNT + F4_ADD_COUNT - 1) FramMessage("Geno_f4", "Constructor", "Mutation names init error", 3);
    7254}
    7355
    7456int Geno_f4::ValidateRec(f4_node * geno, int retrycount) const
    7557{
    76   // ! the genotype is geno->child (not geno) !
    77   // build from it with repair on
    78 
    79   f4_Cells cells( geno->child, 1);
    80   cells.simulate();  //we should simulate?!
    81 
    82   // errors not fixed:
    83   if (GENOPER_OPFAIL == cells.geterror())
    84   {
    85     if (cells.geterrorpos() >= 0) return 1+cells.geterrorpos();
    86     return GENOPER_OPFAIL;
    87   }
    88   // errors can be fixed
    89   if (GENOPER_REPAIR == cells.geterror())
    90   {
    91     cells.repairGeno(geno, 1);
    92     // note: geno might have been fixed
    93     // check again
    94     int res2 = GENOPER_OK;
    95     if (retrycount>0)
    96       res2 = ValidateRec( geno, retrycount-1 );
    97 
    98     if (res2==GENOPER_OK) return GENOPER_REPAIR;
    99     return res2;
    100   }
    101   // no errors:
    102   return GENOPER_OK;
     58        // ! the genotype is geno->child (not geno) !
     59        // build from it with repair on
     60
     61        f4_Cells cells(geno->child, 1);
     62        cells.simulate();  //we should simulate?!
     63
     64        // errors not fixed:
     65        if (GENOPER_OPFAIL == cells.geterror())
     66        {
     67                if (cells.geterrorpos() >= 0) return 1 + cells.geterrorpos();
     68                return GENOPER_OPFAIL;
     69        }
     70        // errors can be fixed
     71        if (GENOPER_REPAIR == cells.geterror())
     72        {
     73                cells.repairGeno(geno, 1);
     74                // note: geno might have been fixed
     75                // check again
     76                int res2 = GENOPER_OK;
     77                if (retrycount > 0)
     78                        res2 = ValidateRec(geno, retrycount - 1);
     79
     80                if (res2 == GENOPER_OK) return GENOPER_REPAIR;
     81                return res2;
     82        }
     83        // no errors:
     84        return GENOPER_OK;
    10385}
    10486
     
    10688int Geno_f4::validate(char *& geno)
    10789{
    108   // convert geno to tree, then try to validate 20 times
    109   f4_node root;
    110   if (f4_processrec(geno, 0, &root) || root.childCount()!=1) return GENOPER_OK; // cannot repair
    111   if (ValidateRec( &root, 20 )==GENOPER_REPAIR) // if repaired, make it back to string
    112   {
    113     geno[0]=0;
    114     root.child->sprintAdj(geno);
    115   }
    116   return GENOPER_OK;
     90        // convert geno to tree, then try to validate 20 times
     91        f4_node root;
     92        if (f4_processrec(geno, 0, &root) || root.childCount() != 1) return GENOPER_OK; // cannot repair
     93        if (ValidateRec(&root, 20) == GENOPER_REPAIR) // if repaired, make it back to string
     94        {
     95                geno[0] = 0;
     96                root.child->sprintAdj(geno);
     97        }
     98        return GENOPER_OK;
    11799}
    118100
     
    120102int Geno_f4::checkValidity(const char * geno)
    121103{
    122   f4_node root;
    123   int res = f4_processrec(geno, 0, &root);
    124   if (res) return res;  // errorpos, >0
    125   if (root.childCount()!=1) return 1; //earlier: GENOPER_OPFAIL
    126   f4_Cells cells( root.child, 0);
    127   cells.simulate();
    128   if (cells.geterror()==GENOPER_OPFAIL || cells.geterror()==GENOPER_REPAIR)
    129   {
    130     if (cells.geterrorpos() >= 0) return 1+cells.geterrorpos();
    131       else return 1; //earlier: GENOPER_OPFAIL;
    132   } else return GENOPER_OK;
    133 }
    134 
    135 
    136 int Geno_f4::MutateOne(f4_node *& g,int &method) const
    137 {
    138   // ! the genotype is g->child (not g) !
    139 
    140   // codes that can be changed (apart being added/deleted)
    141   #define MUT_CHAN_CODES "<[#"
    142   #define ADD_SIMPLE_CODES ",XlLcCrRaAiIsSmMfFwWeEN@|"
    143   #define REP_MAXCOUNT 19
    144 
    145   f4_node * n1, * n2, * n3, * n4, * n5;
    146   int i, j;
    147 
    148   // do the mutation
    149   // pick a random node
    150   n1 = g->child->randomNode();
    151   //DB( printf("%c\n", n1->name); )
    152 
    153   switch(roulette(prob,F4_COUNT))
    154   {
    155     case F4_ADD:
    156     {
    157       // add a node
    158       switch(method=roulette(probadd,F4_ADD_COUNT))
    159       {
    160         case F4_ADD_DIV:
    161         {
    162           // add division ('<')
    163           n3 = n1->parent;
    164           n3->removeChild(n1);
    165           n2 = new f4_node('<', n3, n3->pos );
    166           n2->addChild(n1);
    167           // new cell is stick or neuron
    168           // "X>" or "N>"
    169           double pr = rnd01;
    170           pr -= 0.5;
    171           if (pr<0) n3 = new f4_node('X', n2, n2->pos);
    172           else
    173           {
    174             pr -= 0.5;
    175             if (pr<0)
    176             {
    177               // if neuron, make muscle and add a link
    178               n3 = new f4_node('N', n2, n2->pos);
    179               if (randomN(2) == 0)
    180                 n4 = new f4_node('|', n3, n2->pos);
    181               else
    182                 n4 = new f4_node('@', n3, n2->pos);
    183               n5 = new f4_node('[', n4, n2->pos);
    184               linkNodeMakeRandom(n5);
    185             }
    186           }
    187           new f4_node('>', n3, n3->pos);
    188           n1->parent = n2;
    189           // now with 50% chance swap children
    190           if (randomN(2) == 0)
    191           {
    192             n3 = n2->child;
    193             n2->child = n2->child2;
    194             n2->child2 = n3;
    195           }
    196         }
    197         break;
    198         case F4_ADD_CONN:
    199         {
    200           // add link
    201           n1->parent->removeChild(n1);
    202           n2 = new f4_node('[', n1->parent, n1->parent->pos);
    203           linkNodeMakeRandom(n2);
    204           n2->addChild(n1);
    205           n1->parent = n2;
    206         }
    207         break;
    208         case F4_ADD_NEUPAR:
    209         {
    210           // add neuron modifier
    211           n1->parent->removeChild(n1);
    212           n2 = new f4_node(':', n1->parent, n1->parent->pos);
    213           nparNodeMakeRandom(n2);
    214           n2->addChild(n1);
    215           n1->parent = n2;
    216         }
    217         break;
    218         case F4_ADD_REP:
    219         {
    220           // add repetition ('#')
    221           // repeated code (left child) is the original, right child is empty, count is 2
    222           n3 = n1->parent;
    223           n3->removeChild(n1);
    224           n2 = new f4_node('#', n3, n3->pos );
    225           n2->i1 = 2;
    226           n2->addChild(n1);
    227           new f4_node('>', n2, n2->pos);
    228           n1->parent = n2;
    229         }
    230         break;
    231         case F4_ADD_SIMP:
    232         {
    233           // add simple node
    234           // choose a simple node from ADD_SIMPLE_CODES
    235           n1->parent->removeChild(n1);
    236           n2 = new f4_node(ADD_SIMPLE_CODES[randomN(strlen(ADD_SIMPLE_CODES))], n1->parent, n1->parent->pos );
    237           n2->addChild(n1);
    238           n1->parent = n2;
    239         }
    240         break;
    241       }
    242     }
    243     break;
    244 
    245     case F4_DEL:
    246     {
    247       method=F4_ADD_COUNT-1+F4_DEL;
    248       // delete a node
    249       // must pick a node with parent, and at least one child
    250       // already picked a node, but repeat may be needed
    251       for (i=0; i<10; i++) {
    252         if ((NULL != n1->parent) && (g != n1->parent))
    253           if (NULL != n1->child)
    254             break;
    255         // try a new one
    256         n1 = g->child->randomNode();
    257       }
    258       if ((NULL != n1->parent) && (g != n1->parent))
    259       {
    260         switch (n1->childCount())
    261         {
    262          case 0: break;
    263          case 1:  // one child
    264          {
    265             n2 = n1->parent;
    266             n2->removeChild(n1);
    267             if (NULL != n1->child) {
    268               n1->child->parent = n2;
    269               n2->addChild(n1->child);
    270               n1->child = NULL;
    271             }
    272             if (NULL != n1->child2) {
    273               n1->child2->parent = n2;
    274               n2->addChild(n1->child2);
    275               n1->child2 = NULL;
    276             }
    277             // destroy n1
    278             n1->parent=NULL;
    279             delete n1;
    280          }
    281          break;
    282 
    283          case 2:  // two children
    284          {
    285             // two children
    286             n2 = n1->parent;
    287             n2->removeChild(n1);
    288             // n1 has two children. pick one randomly 50-50, destroy other
    289             if (randomN(2) == 0)
    290             {
    291               n1->child->parent = n2;
    292               n2->addChild(n1->child);
    293               n1->child = NULL;
    294               n1->child2->parent = NULL;
    295             } else
    296             {
    297               n1->child2->parent = n2;
    298               n2->addChild(n1->child2);
    299               n1->child2 = NULL;
    300               n1->child->parent = NULL;
    301             }
    302             // destroy n1
    303             n1->parent=NULL;
    304             delete n1;
    305          }
    306          break;
    307         }
    308       } else return GENOPER_OPFAIL;
    309     }
    310     break;
    311     case F4_MOD:
    312     {
    313       method=F4_ADD_COUNT-1+F4_MOD;
    314       // change a node
    315       // the only nodes that are modifiable are MUT_CHAN_CODES
    316       // try to get a modifiable node
    317       // already picked a node, but repeat may be needed
    318       i=0;
    319       while (1)
    320       {
    321         if (strchr(MUT_CHAN_CODES, n1->name)) break;
    322         // try a new one
    323         n1 = g->child->randomNode();
    324         i++;
    325         if (i>=20) return GENOPER_OPFAIL;
    326       }
    327       switch (n1->name) {
    328         case '<':
    329           // swap children
    330           n2 = n1->child; n1->child = n1->child2; n1->child2 = n2;
    331           break;
    332         case '[':
    333           linkNodeChangeRandom(n1);
    334           break;
    335         case '#':
    336           repeatNodeChangeRandom(n1);
    337           break;
    338       }
    339     }
    340     break;
    341 
    342     default: //no mutations allowed?
    343     return GENOPER_OPFAIL;
    344   }
    345 
    346   return GENOPER_OK;
     104        f4_node root;
     105        int res = f4_processrec(geno, 0, &root);
     106        if (res) return res;  // errorpos, >0
     107        if (root.childCount() != 1) return 1; //earlier: GENOPER_OPFAIL
     108        f4_Cells cells(root.child, 0);
     109        cells.simulate();
     110        if (cells.geterror() == GENOPER_OPFAIL || cells.geterror() == GENOPER_REPAIR)
     111        {
     112                if (cells.geterrorpos() >= 0) return 1 + cells.geterrorpos();
     113                else return 1; //earlier: GENOPER_OPFAIL;
     114        }
     115        else return GENOPER_OK;
     116}
     117
     118
     119int Geno_f4::MutateOne(f4_node *& g, int &method) const
     120{
     121        // ! the genotype is g->child (not g) !
     122
     123        // codes that can be changed (apart being added/deleted)
     124#define MUT_CHAN_CODES "<[#"
     125#define ADD_SIMPLE_CODES ",XlLcCrRaAiIsSmMfFwWeEN@|"
     126#define REP_MAXCOUNT 19
     127
     128        f4_node * n1, *n2, *n3, *n4, *n5;
     129
     130        // do the mutation
     131        // pick a random node
     132        n1 = g->child->randomNode();
     133        //DB( printf("%c\n", n1->name); )
     134
     135        switch (roulette(prob, F4_COUNT))
     136        {
     137        case F4_ADD:
     138        {
     139                // add a node
     140                switch (method = roulette(probadd, F4_ADD_COUNT))
     141                {
     142                case F4_ADD_DIV:
     143                {
     144                        // add division ('<')
     145                        n3 = n1->parent;
     146                        n3->removeChild(n1);
     147                        n2 = new f4_node('<', n3, n3->pos);
     148                        n2->addChild(n1);
     149                        // new cell is stick or neuron
     150                        // "X>" or "N>"
     151                        double pr = rnd01;
     152                        pr -= 0.5;
     153                        if (pr < 0) n3 = new f4_node('X', n2, n2->pos);
     154                        else
     155                        {
     156                                pr -= 0.5;
     157                                if (pr < 0)
     158                                {
     159                                        // if neuron, make muscle and add a link
     160                                        n3 = new f4_node('N', n2, n2->pos);
     161                                        if (randomN(2) == 0)
     162                                                n4 = new f4_node('|', n3, n2->pos);
     163                                        else
     164                                                n4 = new f4_node('@', n3, n2->pos);
     165                                        n5 = new f4_node('[', n4, n2->pos);
     166                                        linkNodeMakeRandom(n5);
     167                                }
     168                        }
     169                        new f4_node('>', n3, n3->pos);
     170                        n1->parent = n2;
     171                        // now with 50% chance swap children
     172                        if (randomN(2) == 0)
     173                        {
     174                                n3 = n2->child;
     175                                n2->child = n2->child2;
     176                                n2->child2 = n3;
     177                        }
     178                }
     179                        break;
     180                case F4_ADD_CONN:
     181                {
     182                        // add link
     183                        n1->parent->removeChild(n1);
     184                        n2 = new f4_node('[', n1->parent, n1->parent->pos);
     185                        linkNodeMakeRandom(n2);
     186                        n2->addChild(n1);
     187                        n1->parent = n2;
     188                }
     189                        break;
     190                case F4_ADD_NEUPAR:
     191                {
     192                        // add neuron modifier
     193                        n1->parent->removeChild(n1);
     194                        n2 = new f4_node(':', n1->parent, n1->parent->pos);
     195                        nparNodeMakeRandom(n2);
     196                        n2->addChild(n1);
     197                        n1->parent = n2;
     198                }
     199                        break;
     200                case F4_ADD_REP:
     201                {
     202                        // add repetition ('#')
     203                        // repeated code (left child) is the original, right child is empty, count is 2
     204                        n3 = n1->parent;
     205                        n3->removeChild(n1);
     206                        n2 = new f4_node('#', n3, n3->pos);
     207                        n2->i1 = 2;
     208                        n2->addChild(n1);
     209                        new f4_node('>', n2, n2->pos);
     210                        n1->parent = n2;
     211                }
     212                        break;
     213                case F4_ADD_SIMP:
     214                {
     215                        // add simple node
     216                        // choose a simple node from ADD_SIMPLE_CODES
     217                        n1->parent->removeChild(n1);
     218                        n2 = new f4_node(ADD_SIMPLE_CODES[randomN(strlen(ADD_SIMPLE_CODES))], n1->parent, n1->parent->pos);
     219                        n2->addChild(n1);
     220                        n1->parent = n2;
     221                }
     222                        break;
     223                }
     224        }
     225                break;
     226
     227        case F4_DEL:
     228        {
     229                method = F4_ADD_COUNT - 1 + F4_DEL;
     230                // delete a node
     231                // must pick a node with parent, and at least one child
     232                // already picked a node, but repeat may be needed
     233                for (int i = 0; i < 10; i++) {
     234                        if ((NULL != n1->parent) && (g != n1->parent))
     235                                if (NULL != n1->child)
     236                                        break;
     237                        // try a new one
     238                        n1 = g->child->randomNode();
     239                }
     240                if ((NULL != n1->parent) && (g != n1->parent))
     241                {
     242                        switch (n1->childCount())
     243                        {
     244                        case 0: break;
     245                        case 1:  // one child
     246                        {
     247                                n2 = n1->parent;
     248                                n2->removeChild(n1);
     249                                if (NULL != n1->child) {
     250                                        n1->child->parent = n2;
     251                                        n2->addChild(n1->child);
     252                                        n1->child = NULL;
     253                                }
     254                                if (NULL != n1->child2) {
     255                                        n1->child2->parent = n2;
     256                                        n2->addChild(n1->child2);
     257                                        n1->child2 = NULL;
     258                                }
     259                                // destroy n1
     260                                n1->parent = NULL;
     261                                delete n1;
     262                        }
     263                                break;
     264
     265                        case 2:  // two children
     266                        {
     267                                // two children
     268                                n2 = n1->parent;
     269                                n2->removeChild(n1);
     270                                // n1 has two children. pick one randomly 50-50, destroy other
     271                                if (randomN(2) == 0)
     272                                {
     273                                        n1->child->parent = n2;
     274                                        n2->addChild(n1->child);
     275                                        n1->child = NULL;
     276                                        n1->child2->parent = NULL;
     277                                }
     278                                else
     279                                {
     280                                        n1->child2->parent = n2;
     281                                        n2->addChild(n1->child2);
     282                                        n1->child2 = NULL;
     283                                        n1->child->parent = NULL;
     284                                }
     285                                // destroy n1
     286                                n1->parent = NULL;
     287                                delete n1;
     288                        }
     289                                break;
     290                        }
     291                }
     292                else return GENOPER_OPFAIL;
     293        }
     294                break;
     295        case F4_MOD:
     296        {
     297                method = F4_ADD_COUNT - 1 + F4_MOD;
     298                // change a node
     299                // the only nodes that are modifiable are MUT_CHAN_CODES
     300                // try to get a modifiable node
     301                // already picked a node, but repeat may be needed
     302                int i = 0;
     303                while (1)
     304                {
     305                        if (strchr(MUT_CHAN_CODES, n1->name)) break;
     306                        // try a new one
     307                        n1 = g->child->randomNode();
     308                        i++;
     309                        if (i >= 20) return GENOPER_OPFAIL;
     310                }
     311                switch (n1->name) {
     312                case '<':
     313                        // swap children
     314                        n2 = n1->child; n1->child = n1->child2; n1->child2 = n2;
     315                        break;
     316                case '[':
     317                        linkNodeChangeRandom(n1);
     318                        break;
     319                case '#':
     320                        repeatNodeChangeRandom(n1);
     321                        break;
     322                }
     323        }
     324                break;
     325
     326        default: //no mutations allowed?
     327                return GENOPER_OPFAIL;
     328        }
     329
     330        return GENOPER_OK;
    347331}
    348332
     
    350334void Geno_f4::linkNodeMakeRandom(f4_node * nn) const
    351335{
    352   int i;
    353   float prob1;
    354 
    355   i = 0;
    356   // 35% chance one of *GTS
    357   prob1 = 1.0f / RAND_MAX * rand();
    358   prob1 -= 0.35f;
    359   if (prob1 < 0)
    360   {
    361     // '*', 'G', 'T', or 'S', 1/4 chance each
    362     i = 1 + (int)(3.999f / RAND_MAX * rand());
    363   }
    364   nn->i1 = i;
    365   nn->l1 = 0;
    366   if (0 == i) {
    367      // relative input link
    368      nn->l1 = (int)(4.0f * (1.0f /  RAND_MAX * rand() - 0.5f));
    369   }
    370   // weight
    371   nn->f1 = 10.0f * (1.0f / RAND_MAX * rand() - 0.5f);
     336        int i;
     337        float prob1;
     338
     339        i = 0;
     340        // 35% chance one of *GTS
     341        prob1 = rnd01;
     342        prob1 -= 0.35f;
     343        if (prob1 < 0)
     344        {
     345                // '*', 'G', 'T', or 'S', 1/4 chance each
     346                i = 1 + (int)(3.999f * rnd01);
     347        }
     348        nn->i1 = i;
     349        nn->l1 = 0;
     350        if (0 == i) {
     351                // relative input link
     352                nn->l1 = (int)(4.0f * (rnd01 - 0.5f));
     353        }
     354        // weight
     355        nn->f1 = 10.0f * (rnd01 - 0.5f);
    372356}
    373357
     
    375359void Geno_f4::linkNodeChangeRandom(f4_node * nn) const      //rewritten by M.K. - should work as before (not tested)
    376360{
    377   int i;
    378   float prob2;
    379 
    380   double probs[3]={0.1, 0.3, 0.6};
    381   // 10% change type
    382   // 30% change link
    383   // 60% change weight
    384 
    385   switch (roulette(probs,3))
    386   {
    387      case 0: // change type
    388           i = 0;
    389           // * G, 10% chance each
    390           prob2 = rnd01 - 0.10f;
    391           if (prob2 < 0) i=1; else {prob2 -= 0.10f; if (prob2 < 0) i=2;}
    392           nn->i1 = i;
    393           break;
    394      case 1: // change link
    395           if (0 == nn->i1) // relative input link
    396              nn->l1 += (int)(2.0f * (rnd01 - 0.5f));
    397           break;
    398      case 2: // change weight
    399           nn->f1 += 1.0f * (rnd01 - 0.5f);
    400           break;
    401   }
     361        int i;
     362        float prob2;
     363
     364        double probs[3] = { 0.1, 0.3, 0.6 };
     365        // 10% change type
     366        // 30% change link
     367        // 60% change weight
     368
     369        switch (roulette(probs, 3))
     370        {
     371        case 0: // change type
     372                i = 0;
     373                // * G, 10% chance each
     374                prob2 = rnd01 - 0.10f;
     375                if (prob2 < 0) i = 1; else { prob2 -= 0.10f; if (prob2 < 0) i = 2; }
     376                nn->i1 = i;
     377                break;
     378        case 1: // change link
     379                if (0 == nn->i1) // relative input link
     380                        nn->l1 += (int)(2.0f * (rnd01 - 0.5f));
     381                break;
     382        case 2: // change weight
     383                nn->f1 += 1.0f * (rnd01 - 0.5f);
     384                break;
     385        }
    402386}
    403387
     
    405389void Geno_f4::nparNodeMakeRandom(f4_node * nn) const
    406390{
    407   int sign = (int)( 2.0f / RAND_MAX * rand() );
    408   int param = (int)( 3.0f / RAND_MAX * rand() );
    409   if (param>2) param=2;
    410   nn->l1 = sign;
    411   nn->i1 = "!=/"[param];
     391        int sign = (int)(2.0f * rnd01);
     392        int param = (int)(3.0f * rnd01);
     393        if (param > 2) param = 2;
     394        nn->l1 = sign;
     395        nn->i1 = "!=/"[param];
    412396}
    413397
     
    415399void Geno_f4::repeatNodeChangeRandom(f4_node * nn) const
    416400{
    417   int count;
    418   float prob1;
    419 
    420   // change count
    421   count = nn->i1;
    422   prob1 = 1.0f / RAND_MAX * rand();
    423   if (prob1 < 0.5f) count++;
    424                else count--;
    425   if (count<1) count=1;
    426   if (count>REP_MAXCOUNT) count=REP_MAXCOUNT;
    427   nn->i1 = count;
    428 }
    429 
    430 
    431 int Geno_f4::MutateOneValid(f4_node *& g,int &method) const
     401        int count;
     402        float prob1;
     403
     404        // change count
     405        count = nn->i1;
     406        prob1 = rnd01;
     407        if (prob1 < 0.5f) count++;
     408        else count--;
     409        if (count<1) count = 1;
     410        if (count>REP_MAXCOUNT) count = REP_MAXCOUNT;
     411        nn->i1 = count;
     412}
     413
     414
     415int Geno_f4::MutateOneValid(f4_node *& g, int &method) const
    432416// mutate one, until a valid genotype is obtained
    433417{
    434   // ! the genotype is g->child (not g) !
    435   int i, res;
    436   f4_node * gcopy = NULL;
    437   // try this max 20 times:
    438   //   copy, mutate, then validate
    439 
    440   for (i=0; i<20; i++)
    441   {
    442     gcopy = g->duplicate();
    443 
    444     res = MutateOne(gcopy,method);
    445 
    446     if (GENOPER_OK != res)
    447     {
    448       // mutation failed, try again
    449       delete gcopy;
    450       continue;  // for
    451     }
    452     // try to validate it
    453     res = ValidateRec(gcopy, 10);
    454     // accept if it is OK, or was repaired
    455     if (GENOPER_OK == res)
    456      //(GENOPER_REPAIR == res)
    457     {
    458       // destroy the original one
    459       g->destroy();
    460       // make it the new one
    461       *g = *gcopy;
    462       gcopy->child=NULL;
    463       gcopy->child2=NULL;
    464       delete gcopy;
    465       res = GENOPER_OK;
    466       goto retm1v;
    467     }
    468     delete gcopy;
    469   }
    470   // attempts failed
    471   res = GENOPER_OPFAIL;
     418        // ! the genotype is g->child (not g) !
     419        int i, res;
     420        f4_node * gcopy = NULL;
     421        // try this max 20 times:
     422        //   copy, mutate, then validate
     423
     424        for (i = 0; i < 20; i++)
     425        {
     426                gcopy = g->duplicate();
     427
     428                res = MutateOne(gcopy, method);
     429
     430                if (GENOPER_OK != res)
     431                {
     432                        // mutation failed, try again
     433                        delete gcopy;
     434                        continue;  // for
     435                }
     436                // try to validate it
     437                res = ValidateRec(gcopy, 10);
     438                // accept if it is OK, or was repaired
     439                if (GENOPER_OK == res)
     440                        //(GENOPER_REPAIR == res)
     441                {
     442                        // destroy the original one
     443                        g->destroy();
     444                        // make it the new one
     445                        *g = *gcopy;
     446                        gcopy->child = NULL;
     447                        gcopy->child2 = NULL;
     448                        delete gcopy;
     449                        res = GENOPER_OK;
     450                        goto retm1v;
     451                }
     452                delete gcopy;
     453        }
     454        // attempts failed
     455        res = GENOPER_OPFAIL;
    472456retm1v:
    473   return res;
    474 }
    475 
    476 
    477 int Geno_f4::mutate(char *& g, float & chg,int &method)
    478 {
    479   f4_node *root=new f4_node;
    480   if (f4_processrec(g, 0, root) || root->childCount()!=1)
    481      {delete root; return GENOPER_OPFAIL;} // could not convert or bad: fail
    482   // mutate one node, set chg as this percent
    483   chg = 1.0/float(root->child->count());
    484   if (MutateOneValid(root,method)!=GENOPER_OK)
    485      {delete root; return GENOPER_OPFAIL;}
    486   // OK, convert back to string
    487   g[0]=0;
    488   root->child->sprintAdj(g);
    489   delete root;
    490   return GENOPER_OK;
     457        return res;
     458}
     459
     460
     461int Geno_f4::mutate(char *& g, float & chg, int &method)
     462{
     463        f4_node *root = new f4_node;
     464        if (f4_processrec(g, 0, root) || root->childCount() != 1)
     465        {
     466                delete root; return GENOPER_OPFAIL;
     467        } // could not convert or bad: fail
     468        // mutate one node, set chg as this percent
     469        chg = 1.0 / float(root->child->count());
     470        if (MutateOneValid(root, method) != GENOPER_OK)
     471        {
     472                delete root; return GENOPER_OPFAIL;
     473        }
     474        // OK, convert back to string
     475        g[0] = 0;
     476        root->child->sprintAdj(g);
     477        delete root;
     478        return GENOPER_OK;
    491479}
    492480
     
    497485// make a number of mutations
    498486{
    499   int res, n, i;
    500   int totNodes = 0;
    501   int maxToMut = 0;
    502 
    503   // convert to tree
    504   f4_node * root;
    505   root = new f4_node();
    506   res = f4_processrec(g, 0, root);
    507   if (res) {
    508     // could not convert, fail
    509     goto retm;
    510   }
    511   if (1 != root->childCount()) {
    512     res = GENOPER_OPFAIL;
    513     goto retm;
    514   }
    515 
    516   // check if original is valid
    517   res = ValidateRec( root, 20 );
    518   // might have been repaired!
    519   if (GENOPER_REPAIR==res) {
    520     res = GENOPER_OK;
    521   }
    522   if (GENOPER_OK != res) {
    523     goto retm;
    524   }
    525 
    526   // decide number of nodes to mutate
    527   // decide maximum number of nodes to mutate: 0.25*nodes, min 2
    528   totNodes = root->child->count();
    529   maxToMut = (int)( 0.25f * totNodes);
    530   if (maxToMut<2) maxToMut=2;
    531   if (maxToMut>totNodes) maxToMut=totNodes;
    532 
    533   // decide number of nodes to mutate
    534   n = (int)( 0.5f + 1.0f/RAND_MAX * rand() * maxToMut );
    535   if (n<1) n=1;
    536   if (n>totNodes) n=totNodes;
    537   // set chg as this percent
    538   chg = ((float)n) / ((float)totNodes);
    539   for (i=0; i<n; i++)
    540   {
    541     res = MutateOneValid(root);
    542     if (GENOPER_OK != res)
    543     {
    544       res = GENOPER_OPFAIL;
    545       goto retm;
    546     }
    547   }
    548   // OK, convert back to string
    549   g[0]=0;
    550   root->child->sprintAdj(g);
     487int res, n, i;
     488int totNodes = 0;
     489int maxToMut = 0;
     490
     491// convert to tree
     492f4_node * root;
     493root = new f4_node();
     494res = f4_processrec(g, 0, root);
     495if (res) {
     496// could not convert, fail
     497goto retm;
     498}
     499if (1 != root->childCount()) {
     500res = GENOPER_OPFAIL;
     501goto retm;
     502}
     503
     504// check if original is valid
     505res = ValidateRec( root, 20 );
     506// might have been repaired!
     507if (GENOPER_REPAIR==res) {
     508res = GENOPER_OK;
     509}
     510if (GENOPER_OK != res) {
     511goto retm;
     512}
     513
     514// decide number of nodes to mutate
     515// decide maximum number of nodes to mutate: 0.25*nodes, min 2
     516totNodes = root->child->count();
     517maxToMut = (int)( 0.25f * totNodes);
     518if (maxToMut<2) maxToMut=2;
     519if (maxToMut>totNodes) maxToMut=totNodes;
     520
     521// decide number of nodes to mutate
     522n = (int)( 0.5f + rnd01 * maxToMut );
     523if (n<1) n=1;
     524if (n>totNodes) n=totNodes;
     525// set chg as this percent
     526chg = ((float)n) / ((float)totNodes);
     527for (i=0; i<n; i++)
     528{
     529res = MutateOneValid(root);
     530if (GENOPER_OK != res)
     531{
     532res = GENOPER_OPFAIL;
     533goto retm;
     534}
     535}
     536// OK, convert back to string
     537g[0]=0;
     538root->child->sprintAdj(g);
    551539retm:
    552   delete root;
    553   return res;
     540delete root;
     541return res;
    554542}
    555543*/
     
    558546int Geno_f4::CrossOverOne(f4_node * g1, f4_node * g2, float chg) const
    559547{
    560   // ! the genotypes are g1->child and g2->child (not g1 g2) !
    561   // single offspring in g1
    562   int smin, smax;
    563   float size;
    564   f4_node * n1, * n2, * n1p, * n2p;
    565 
    566   // determine desired size
    567   size = (1-chg) * (float)g1->count();
    568   smin = (int)(size*0.9f-1);
    569   smax = (int)(size*1.1f+1);
    570   // get a random node with desired size
    571   n1 = g1->child->randomNodeWithSize(smin, smax);
    572 
    573   // determine desired size
    574   size = (1-chg) * (float)g2->count();
    575   smin = (int)(size*0.9f-1);
    576   smax = (int)(size*1.1f+1);
    577   // get a random node with desired size
    578   n2 = g2->child->randomNodeWithSize(smin, smax);
    579 
    580   // exchange the two nodes:
    581   n1p = n1->parent;
    582   n2p = n2->parent;
    583   n1p->removeChild(n1);
    584   n1p->addChild(n2);
    585   n2p->removeChild(n2);
    586   n2p->addChild(n1);
    587   n1->parent = n2p;
    588   n2->parent = n1p;
    589 
    590   return GENOPER_OK;
     548        // ! the genotypes are g1->child and g2->child (not g1 g2) !
     549        // single offspring in g1
     550        int smin, smax;
     551        float size;
     552        f4_node * n1, *n2, *n1p, *n2p;
     553
     554        // determine desired size
     555        size = (1 - chg) * (float)g1->count();
     556        smin = (int)(size*0.9f - 1);
     557        smax = (int)(size*1.1f + 1);
     558        // get a random node with desired size
     559        n1 = g1->child->randomNodeWithSize(smin, smax);
     560
     561        // determine desired size
     562        size = (1 - chg) * (float)g2->count();
     563        smin = (int)(size*0.9f - 1);
     564        smax = (int)(size*1.1f + 1);
     565        // get a random node with desired size
     566        n2 = g2->child->randomNodeWithSize(smin, smax);
     567
     568        // exchange the two nodes:
     569        n1p = n1->parent;
     570        n2p = n2->parent;
     571        n1p->removeChild(n1);
     572        n1p->addChild(n2);
     573        n2p->removeChild(n2);
     574        n2p->addChild(n1);
     575        n1->parent = n2p;
     576        n2->parent = n1p;
     577
     578        return GENOPER_OK;
    591579}
    592580
    593581int Geno_f4::crossOver(char *&g1, char *&g2, float &chg1, float &chg2)
    594582{
    595   f4_node root1, root2, *copy1, *copy2;
    596 
    597   // convert genotype strings into tree structures
    598   if (f4_processrec(g1,0,&root1) || (root1.childCount()!=1)) return GENOPER_OPFAIL;
    599   if (f4_processrec(g2,0,&root2) || (root2.childCount()!=1)) return GENOPER_OPFAIL;
    600 
    601   // decide amounts of crossover, 0.25-0.75
    602   // adam: seems 0.1-0.9 -- MacKo
    603   chg1 = 0.1f + 0.8f*rnd01;
    604   chg2 = 0.1f + 0.8f*rnd01;
    605 
    606   copy1 = root1.duplicate();
    607   if (CrossOverOne(copy1, &root2, chg1) != GENOPER_OK) {delete copy1; copy1=NULL;}
    608   copy2 = root2.duplicate();
    609   if (CrossOverOne(copy2, &root1, chg2) != GENOPER_OK) {delete copy2; copy2=NULL;}
    610 
    611   g1[0]=0;
    612   g2[0]=0;
    613   if (copy1) {copy1->child->sprintAdj(g1); delete copy1;}
    614   if (copy2) {copy2->child->sprintAdj(g2); delete copy2;}
    615   if (g1[0] || g2[0]) return GENOPER_OK; else return GENOPER_OPFAIL;
     583        f4_node root1, root2, *copy1, *copy2;
     584
     585        // convert genotype strings into tree structures
     586        if (f4_processrec(g1, 0, &root1) || (root1.childCount() != 1)) return GENOPER_OPFAIL;
     587        if (f4_processrec(g2, 0, &root2) || (root2.childCount() != 1)) return GENOPER_OPFAIL;
     588
     589        // decide amounts of crossover, 0.25-0.75
     590        // adam: seems 0.1-0.9 -- MacKo
     591        chg1 = 0.1f + 0.8f*rnd01;
     592        chg2 = 0.1f + 0.8f*rnd01;
     593
     594        copy1 = root1.duplicate();
     595        if (CrossOverOne(copy1, &root2, chg1) != GENOPER_OK) { delete copy1; copy1 = NULL; }
     596        copy2 = root2.duplicate();
     597        if (CrossOverOne(copy2, &root1, chg2) != GENOPER_OK) { delete copy2; copy2 = NULL; }
     598
     599        g1[0] = 0;
     600        g2[0] = 0;
     601        if (copy1) { copy1->child->sprintAdj(g1); delete copy1; }
     602        if (copy2) { copy2->child->sprintAdj(g2); delete copy2; }
     603        if (g1[0] || g2[0]) return GENOPER_OK; else return GENOPER_OPFAIL;
    616604}
    617605
     
    620608unsigned long Geno_f4::style(const char *g, int pos)
    621609{
    622   char ch = g[pos];
    623   // style categories
    624   #define STYL4CAT_MODIFIC "LlRrCcQqAaIiSsMmFfWwEe,"
    625   #define STYL4CAT_NEUMOD "[]|@*GTS:+-/!="
    626   #define STYL4CAT_DIGIT "0123456789."
    627   #define STYL4CAT_REST "XN<># "
    628   if (!strchr(STYL4CAT_MODIFIC STYL4CAT_NEUMOD STYL4CAT_DIGIT STYL4CAT_REST, ch))
    629     return GENSTYLE_CS(0,GENSTYLE_INVALID);
    630   unsigned long style=GENSTYLE_CS(0,GENSTYLE_STRIKEOUT); //default, should be changed below
    631   if (strchr("X ", ch))              style=GENSTYLE_CS(0,GENSTYLE_NONE);
    632   if (strchr("N", ch))               style=GENSTYLE_RGBS(0,200,0,GENSTYLE_NONE); 
    633   if (strchr("<", ch))               style=GENSTYLE_RGBS(0,0,200,GENSTYLE_BOLD); 
    634   if (strchr(">", ch))               style=GENSTYLE_RGBS(0,0,100,GENSTYLE_NONE); 
    635   if (strchr(STYL4CAT_DIGIT, ch))     style=GENSTYLE_RGBS(100,100,100,GENSTYLE_NONE);
    636   if (strchr(STYL4CAT_MODIFIC, ch))   style=GENSTYLE_RGBS(100,100,100,GENSTYLE_NONE);
    637   if (strchr(STYL4CAT_NEUMOD, ch))    style=GENSTYLE_RGBS(0,150,0,GENSTYLE_NONE);
    638   return style;
    639 }
    640 
    641 
     610        char ch = g[pos];
     611        // style categories
     612#define STYL4CAT_MODIFIC "LlRrCcQqAaIiSsMmFfWwEe,"
     613#define STYL4CAT_NEUMOD "[]|@*GTS:+-/!="
     614#define STYL4CAT_DIGIT "0123456789."
     615#define STYL4CAT_REST "XN<># "
     616        if (!strchr(STYL4CAT_MODIFIC STYL4CAT_NEUMOD STYL4CAT_DIGIT STYL4CAT_REST, ch))
     617                return GENSTYLE_CS(0, GENSTYLE_INVALID);
     618        unsigned long style = GENSTYLE_CS(0, GENSTYLE_STRIKEOUT); //default, should be changed below
     619        if (strchr("X ", ch))              style = GENSTYLE_CS(0, GENSTYLE_NONE);
     620        if (strchr("N", ch))               style = GENSTYLE_RGBS(0, 200, 0, GENSTYLE_NONE);
     621        if (strchr("<", ch))               style = GENSTYLE_RGBS(0, 0, 200, GENSTYLE_BOLD);
     622        if (strchr(">", ch))               style = GENSTYLE_RGBS(0, 0, 100, GENSTYLE_NONE);
     623        if (strchr(STYL4CAT_DIGIT, ch))     style = GENSTYLE_RGBS(100, 100, 100, GENSTYLE_NONE);
     624        if (strchr(STYL4CAT_MODIFIC, ch))   style = GENSTYLE_RGBS(100, 100, 100, GENSTYLE_NONE);
     625        if (strchr(STYL4CAT_NEUMOD, ch))    style = GENSTYLE_RGBS(0, 150, 0, GENSTYLE_NONE);
     626        return style;
     627}
Note: See TracChangeset for help on using the changeset viewer.