Ignore:
Timestamp:
06/06/18 01:45:18 (6 years ago)
Author:
Maciej Komosinski
Message:

A more complete implementation of fB, fH, fL

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/fL/fL_oper.cpp

    r780 r797  
     1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
     3// See LICENSE.txt for details.
     4
    15#include "fL_oper.h"
     6#include <common/loggers/loggers.h>
     7#include "../fH/fH_oper.h"
     8#include <algorithm>
     9
     10#define FIELDSTRUCT Geno_fL
     11static ParamEntry GENOfLparam_tab[] =
     12{
     13        {"Genetics: fL", 3, FL_OPCOUNT + FL_MUTGROUPSCOUNT + FL_CHG_COUNT + 2 + FL_ADD_COUNT, },
     14        {"Genetics: fL: Probabilities of mutating axiom and rules", },
     15        {"Genetics: fL: Probabilities of mutation types", },
     16        {"fL_maxdefinedwords", 0, 0, "Maximum number of defined words", "d 0 100 10", FIELD(maxdefinedwords), "Maximum number of words that can be defined in L-System", },
     17
     18        {"fL_axm_mut_prob", 1, 0, "Axiom mutation", "f 0 1 0.2", FIELD(groupprobabilities[FL_AXM_WORD_MUT_PROB]), "Probability of performing mutation operations on axiom", },
     19        {"fL_rul_mut_prob", 1, 0, "Rule's successor mutation", "f 0 1 0.8", FIELD(groupprobabilities[FL_RUL_WORD_MUT_PROB]), "Probability of performing mutation operations on the successor of random rule", },
     20
     21        {"fL_mut_addition", 2, 0, "Addition of word to sequence", "f 0 1 0.2", FIELD(operations[FL_ADD_WORD]), "Probability of adding random existing word to the axiom or one of successors", },
     22
     23        {"fL_mut_add_stick", 2, 0, " - addition of stick", "f 0 1 0.2", FIELD(addtypes[FL_ADD_STICK]), "Probability of adding stick", },
     24        {"fL_mut_add_neuro", 2, 0, " - addition of neuron", "f 0 1 0.2", FIELD(addtypes[FL_ADD_NEURO]), "Probability of adding neuron", },
     25        {"fL_mut_add_conn", 2, 0, " - addition of neuron connection", "f 0 1 0.2", FIELD(addtypes[FL_ADD_CONN]), "Probability of adding connection", },
     26        {"fL_mut_add_rot", 2, 0, " - addition of rotation words", "f 0 1 0.2", FIELD(addtypes[FL_ADD_ROT]), "Probability of adding one of rotation words", },
     27        {"fL_mut_add_branch", 2, 0, " - addition of branched stick", "f 0 1 0.2", FIELD(addtypes[FL_ADD_BRANCH]), "Probability of adding branch with rotation and stick", },
     28        {"fL_mut_add_other", 2, 0, " - addition of defined words", "f 0 1 0.4", FIELD(addtypes[FL_ADD_OTHER]), "Probability of adding other word, defined in genotype", },
     29
     30        {"fL_mut_worddefaddition", 2, 0, "Addition of new word definition", "f 0 1 0.05", FIELD(operations[FL_ADD_WDEF]), "Probability of adding new word definition to the genotype", },
     31        {"fL_mut_ruleaddition", 2, 0, "Addition of new rule definition", "f 0 1 0.1", FIELD(operations[FL_ADD_RULE]), "Probability of adding new rule definition for existing word", },
     32        {"fL_mut_rulecond", 2, 0, "Modification of rule condition", "f 0 1 0.1", FIELD(operations[FL_CHG_COND]), "Probability of modifying random rule condition", },
     33
     34        {"fL_mut_changeword", 2, 0, "Change of random word", "f 0 1 0.3", FIELD(operations[FL_CHG_WORD]), "Probability of changing word name or formula of a random word from axiom or one of successors", },
     35        {"fL_mut_changeword_formula", 2, 0, " - change of formula", "f 0 1 0.7", FIELD(chgoperations[FL_CHG_WORD_FORMULA]), "Probability of changing formula in word", },
     36        {"fL_mut_changeword_name", 2, 0, " - change of name", "f 0 1 0.3", FIELD(chgoperations[FL_CHG_WORD_NAME]), "Probability of changing name in word", },
     37
     38        {"fL_mut_changeiter", 2, 0, "Change of L-System iteration", "f 0 1 0.3", FIELD(operations[FL_CHG_ITER]), "Probability of changing number of iterations of L-Systems", },
     39        {"fL_mut_changeiter_step", 2, 0, "Step of iteration changing", "f 0 1 1.0", FIELD(iterchangestep), "Minimal step that should be used for changing iterations in L-Systems", },
     40        {"fL_mut_deletion", 2, 0, "Deletion of random word", "f 0 1 0.2", FIELD(operations[FL_DEL_WORD]), "Probability of deleting random word from axiom or random successor (also deletes rule if there is only one word in successor)", },
     41        { 0, },
     42};
     43#undef FIELDSTRUCT
    244
    345Geno_fL::Geno_fL()
    446{
    5         //      par.setParamTab(GENOfHparam_tab);
    6         //      par.select(this);
    7         //      par.setDefault();
    8         supported_format = 'H';
    9 }
     47        par.setParamTab(GENOfLparam_tab);
     48        par.select(this);
     49        par.setDefault();
     50        supported_format = 'L';
     51        iterchangestep = 1.0;
     52        maxdefinedwords = 10;
     53}
     54
     55int Geno_fL::checkValidity(const char *geno, const char *genoname)
     56{
     57        LoggerToMemory eh(LoggerBase::Enable | LoggerToMemory::StoreAllMessages, LOG_WARN);
     58        fL_Builder builder(false, false);
     59
     60        int err = builder.parseGenotype(geno);
     61        if (err != 0)
     62        {
     63                return err;
     64        }
     65
     66        if (builder.countSticksInSequence(builder.genotype) == 0)
     67        {
     68                return GENOPER_OPFAIL;
     69        }
     70        double neededtime = 0;
     71        Model *m = builder.developModel(neededtime);
     72        if (!m)
     73        {
     74                return GENOPER_OPFAIL;
     75        }
     76        if (!m->isValid())
     77        {
     78                delete m;
     79                return GENOPER_OPFAIL;
     80        }
     81        delete m;
     82
     83
     84        return GENOPER_OK;
     85}
     86
     87int Geno_fL::validate(char *&geno, const char *genoname)
     88{
     89        LoggerToMemory eh(LoggerBase::Enable | LoggerToMemory::StoreAllMessages, LOG_WARN);
     90        fL_Builder builder(false, false);
     91
     92        int err = builder.parseGenotype(geno);
     93        if (err != 0)
     94        {
     95                return err;
     96        }
     97        double neededtime = 0;
     98        Model *m = builder.developModel(neededtime);
     99        if (!m->isValid())
     100        {
     101                delete m;
     102                return GENOPER_OPFAIL;
     103        }
     104        if (neededtime != builder.time)
     105        {
     106                builder.time = neededtime;
     107                free(geno);
     108                geno = strdup(builder.toString().c_str());
     109                delete m;
     110                return GENOPER_OK;
     111        }
     112        delete m;
     113        return GENOPER_OK;
     114}
     115
     116bool Geno_fL::addWord(std::list<fL_Word *>* list, fL_Word *definition, std::list<fL_Word *>::iterator it)
     117{
     118        fL_Word *newword = new fL_Word();
     119        *newword = *definition;
     120
     121        // if word has parameters
     122        if (newword->npar > 0)
     123        {
     124                // create ParamObject that will hold parameter data
     125                newword->data = ParamObject::makeObject(newword->tab);
     126                Param par(newword->tab);
     127                par.select(newword->data);
     128                par.setDefault();
     129                for (int i = 0; i < par.getPropCount(); i++)
     130                {
     131                        newword->parevals.push_back(NULL);
     132                }
     133                if (newword->name.startsWith("rot"))
     134                {
     135                        double rot = 2 * rnd01;
     136                        MathEvaluation *eval = new MathEvaluation(0);
     137                        eval->convertString(SString::valueOf(rot).c_str());
     138                        newword->parevals[0] = eval;
     139                }
     140                else if (newword->name == "N")
     141                {
     142                        SString det;
     143                        NeuroClass *cls = getRandomNeuroClass();
     144                        if (!cls) cls = Neuro::getClass("N");
     145                        det = cls->getName();
     146                        Geno_fH::mutateNeuronProperties(det);
     147                        par.setStringById(FL_PE_NEURO_DET, det);
     148                }
     149                else if (newword->name == "C")
     150                {
     151                        MathEvaluation *eval = new MathEvaluation(0);
     152                        eval->convertString(SString::valueOf(2 * rnd01 - 1).c_str());
     153                        newword->parevals[0] = eval;
     154                }
     155        }
     156
     157        list->insert(it, newword);
     158        return true;
     159}
     160
     161std::list<fL_Word *>* Geno_fL::selectRandomSequence(fL_Builder *creature, int &numparams, int &ruleid)
     162{
     163        std::list<fL_Word *> *list = NULL;
     164        int axiomorrules = roulette(groupprobabilities, FL_MUTGROUPSCOUNT);
     165        bool axiomused = axiomorrules == FL_AXM_WORD_MUT_PROB || creature->rules.size() == 0;
     166        if (axiomused)
     167        {
     168                list = &creature->genotype;
     169                numparams = 0;
     170                ruleid = -1;
     171        }
     172        else
     173        {
     174                int rid = randomN(creature->rules.size());
     175                list = &creature->rules[rid]->objsucc;
     176                numparams = creature->rules[rid]->objpred->npar;
     177                ruleid = rid;
     178        }
     179        return list;
     180}
     181
     182fL_Word* Geno_fL::randomWordDefinition(fL_Builder *creature, int method)
     183{
     184        if (method == FL_ADD_OTHER && creature->builtincount < (int)creature->words.size())
     185        {
     186                return creature->words[creature->wordnames[creature->builtincount + randomN((int)creature->words.size() - creature->builtincount)]];
     187        }
     188        else
     189        {
     190                if (method == FL_ADD_OTHER) // we should be able to select stick, neuro or conn
     191                {
     192                        double alttypes[FL_ADD_COUNT - 2];
     193                        alttypes[FL_ADD_STICK] = addtypes[FL_ADD_STICK];
     194                        alttypes[FL_ADD_NEURO] = addtypes[FL_ADD_NEURO];
     195                        alttypes[FL_ADD_CONN] = addtypes[FL_ADD_CONN];
     196                        alttypes[FL_ADD_ROT] = addtypes[FL_ADD_ROT];
     197                        method = roulette(alttypes, FL_ADD_COUNT - 2);
     198                }
     199                switch (method)
     200                {
     201                case FL_ADD_STICK:
     202                        return creature->words["S"];
     203                case FL_ADD_NEURO:
     204                        return creature->words["N"];
     205                case FL_ADD_CONN:
     206                        return creature->words["C"];
     207                case FL_ADD_ROT:
     208                {
     209                        int rottype = randomN(3);
     210                        switch (rottype)
     211                        {
     212                        case 0:
     213                                return creature->words["rotX"];
     214                        case 1:
     215                                return creature->words["rotY"];
     216                        case 2:
     217                                return creature->words["rotZ"];
     218                        }
     219                        break;
     220                }
     221                case FL_ADD_BRANCH:
     222                        // return NULL
     223                        break;
     224                }
     225        }
     226        return NULL;
     227}
     228
     229void Geno_fL::deleteBranch(std::list<fL_Word *> *list, std::list<fL_Word *>::iterator openbranchposition)
     230{
     231        fL_Branch *branch = (fL_Branch *)(*openbranchposition);
     232        if (branch->btype == fL_Branch::BranchType::OPEN)
     233        {
     234                int bcount = 1;
     235                delete (*openbranchposition);
     236                openbranchposition = list->erase(openbranchposition);
     237                for (; openbranchposition != list->end(); openbranchposition++)
     238                {
     239                        if ((*openbranchposition)->type == fLElementType::BRANCH)
     240                        {
     241                                branch = (fL_Branch *)(*openbranchposition);
     242                                if (branch->btype == fL_Branch::BranchType::OPEN)
     243                                {
     244                                        bcount++;
     245                                }
     246                                else
     247                                {
     248                                        bcount--;
     249                                        if (bcount == 0)
     250                                        {
     251                                                delete branch;
     252                                                list->erase(openbranchposition);
     253                                                break;
     254                                        }
     255                                }
     256                        }
     257                }
     258        }
     259        else
     260        {
     261                openbranchposition++;
     262                if (openbranchposition != list->end())
     263                {
     264                        delete (*openbranchposition);
     265                        list->erase(openbranchposition);
     266                }
     267        }
     268}
     269
     270int Geno_fL::mutate(char *&geno, float& chg, int &method)
     271{
     272        fL_Builder *creature = new fL_Builder(false, false);
     273
     274        if (creature->parseGenotype(geno) != 0)
     275        {
     276                delete creature;
     277                return GENOPER_OPFAIL;
     278        }
     279
     280        int before = creature->countWordsInLSystem();
     281
     282        method = roulette(operations, FL_OPCOUNT);
     283        switch (method)
     284        {
     285                case FL_CHG_ITER:
     286                {
     287                        if (randomN(2) == 0)
     288                        {
     289                                creature->time = creature->time + iterchangestep <= ExtValue::getDouble(FL_MAXITER) ?
     290                                                creature->time + iterchangestep : creature->time - iterchangestep;
     291                        }
     292                        else
     293                        {
     294                                creature->time = creature->time - iterchangestep >= 0 ?
     295                                                creature->time - iterchangestep : creature->time + iterchangestep;
     296                        }
     297                        break;
     298                }
     299                case FL_CHG_COND:
     300                {
     301                        if (creature->rules.size() > 0)
     302                        {
     303                                int ruleid = randomN(creature->rules.size());
     304                                if (!creature->rules[ruleid]->condeval)
     305                                {
     306                                        creature->rules[ruleid]->condeval = new MathEvaluation(creature->rules[ruleid]->objpred->npar);
     307                                }
     308                                creature->rules[ruleid]->condeval->mutateConditional();
     309                                break;
     310                        }
     311                        // if there are no rules - create one
     312                }
     313                /* no break */
     314                case FL_ADD_RULE:
     315                {
     316                        std::unordered_map<std::string, fL_Word *>::iterator pred = creature->words.begin();
     317                        std::vector<fL_Word *> wordswithnorules;
     318                        for (; pred != creature->words.end(); pred++)
     319                        {
     320                                if (!pred->second->builtin)
     321                                {
     322                                        bool norules = true;
     323                                        for (fL_Rule * r : creature->rules)
     324                                        {
     325                                                if (pred->second->name == r->objpred->name &&
     326                                                                pred->second->npar == r->objpred->npar)
     327                                                {
     328                                                        norules = false;
     329                                                        break;
     330                                                }
     331                                        }
     332                                        if (norules)
     333                                        {
     334                                                wordswithnorules.push_back(pred->second);
     335                                        }
     336                                }
     337                        }
     338                        if (wordswithnorules.size() > 0)
     339                        {
     340                                int predid = randomN(wordswithnorules.size());
     341                                fL_Rule *newrule = new fL_Rule(0,0);
     342                                fL_Word *pred = new fL_Word();
     343                                *pred = *wordswithnorules[predid];
     344                                newrule->objpred = pred;
     345                                fL_Word *initdef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1)); // -1 to avoid branching
     346                                addWord(&newrule->objsucc, initdef, newrule->objsucc.begin());
     347                                creature->rules.push_back(newrule);
     348                                break;
     349                        }
     350                        else if (creature->rules.size() > 0)
     351                        {
     352                                int ruleid = randomN(creature->rules.size());
     353                                fL_Rule *newrule = new fL_Rule(0, 0);
     354                                fL_Word *pred = new fL_Word();
     355                                *pred = *creature->rules[ruleid]->objpred;
     356                                newrule->objpred = pred;
     357                                if (creature->rules[ruleid]->condeval)
     358                                {
     359                                        std::string formula = "";
     360                                        creature->rules[ruleid]->condeval->RPNToInfix(formula);
     361                                        if (formula.find("1.0-(") != 0)
     362                                        {
     363                                                std::string res = "1.0-(";
     364                                                res += formula;
     365                                                res += ")";
     366                                                newrule->condeval = new MathEvaluation(pred->npar);
     367                                                newrule->condeval->convertString(res);
     368                                        }
     369                                        else
     370                                        {
     371                                                newrule->condeval = new MathEvaluation(pred->npar);
     372                                                newrule->condeval->mutateConditional();
     373                                        }
     374                                }
     375                                else
     376                                {
     377                                        newrule->condeval = new MathEvaluation(pred->npar);
     378                                        newrule->condeval->mutateConditional();
     379                                }
     380                                fL_Word *worddef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1));
     381                                addWord(&newrule->objsucc, worddef, newrule->objsucc.begin());
     382                                creature->rules.push_back(newrule);
     383                                break;
     384                        }
     385                        // if there are no words, from which rules can be formed, then add one
     386                }
     387                /* no break */
     388                case FL_ADD_WDEF:
     389                {
     390                        if (creature->countDefinedWords() <= maxdefinedwords)
     391                        {
     392                                int npar = randomN(ExtValue::getInt(FL_MAXPARAMS, false));
     393                                for (int i = 0; i < maxdefinedwords; i++)
     394                                {
     395                                        std::string name = "w";
     396                                        name += std::to_string(i);
     397                                        if (creature->words.find(name) == creature->words.end())
     398                                        {
     399                                                fL_Word *word = new fL_Word(false, 0, 0);
     400                                                word->npar = npar;
     401                                                word->name = name.c_str();
     402                                                word->processDefinition(creature);
     403                                                break;
     404                                        }
     405                                }
     406                                break;
     407                        }
     408                        //no break at the end of case - if there is too many words, then
     409                        // deletion should be performed
     410                }
     411                /* no break */
     412                case FL_DEL_WORD:
     413                {
     414                        int numpars = 0;
     415                        int ruleid = 0;
     416                        std::list<fL_Word *> *list = selectRandomSequence(creature, numpars, ruleid);
     417                        if (ruleid == -1 && creature->countSticksInSequence((*list)) == 1)
     418                        {
     419                                if (list->size() > 1)
     420                                {
     421                                        int rndid = randomN(list->size() - 1);
     422                                        int j = 0;
     423                                        std::list<fL_Word *>::iterator it = list->begin();
     424                                        if ((*it)->name == "S")
     425                                        {
     426                                                it++;
     427                                        }
     428                                        while (it != list->end() && j < rndid && ((*it)->name == "S"))
     429                                        {
     430                                                if ((*it)->name != "S")
     431                                                {
     432                                                        j++;
     433                                                }
     434                                                it++;
     435                                        }
     436                                        if (it != list->end())
     437                                        {
     438                                                if ((*it)->type == fLElementType::BRANCH)
     439                                                {
     440                                                        deleteBranch(list, it);
     441                                                }
     442                                                else
     443                                                {
     444                                                        delete (*it);
     445                                                        list->erase(it);
     446                                                }
     447                                                break;
     448                                        }
     449                                        // else add word
     450                                }
     451                                // else add word
     452                        }
     453                        else
     454                        {
     455                                int rndid = randomN(list->size());
     456                                std::list<fL_Word *>::iterator it = list->begin();
     457                                std::advance(it, rndid);
     458                                if ((*it)->type == fLElementType::BRANCH)
     459                                {
     460                                        deleteBranch(list, it);
     461                                }
     462                                else
     463                                {
     464                                        delete (*it);
     465                                        list->erase(it);
     466                                }
     467                                if (ruleid > -1 && creature->rules[ruleid]->objsucc.size() == 0)
     468                                {
     469                                        delete creature->rules[ruleid];
     470                                        creature->rules.erase(creature->rules.begin() + ruleid);
     471                                }
     472                                break;
     473                        }
     474                        // if no words available, then add word
     475                }
     476                /* no break */
     477                case FL_ADD_WORD:
     478                {
     479                        int numpars = 0;
     480                        int tmp = 0;
     481                        std::list<fL_Word *> *list = selectRandomSequence(creature, numpars, tmp);
     482                        int rndid = randomN(list->size());
     483                        std::list<fL_Word *>::iterator it = list->begin();
     484                        std::advance(it, rndid);
     485                        int meth = roulette(addtypes, FL_ADD_COUNT);
     486                        if (tmp == -1)
     487                        { // if sequence is axiom and it does not have non-builtin words
     488                                bool hasdefined = false;
     489                                for (std::list<fL_Word *>::iterator elem = list->begin(); elem != list->end(); elem++)
     490                                {
     491                                        if (!(*elem)->builtin)
     492                                        {
     493                                                hasdefined = true;
     494                                                break;
     495                                        }
     496                                }
     497                                if (!hasdefined)
     498                                {
     499                                        meth = FL_ADD_OTHER;
     500                                }
     501
     502                        }
     503                        if (meth != FL_ADD_BRANCH)
     504                        {
     505                                fL_Word *worddef = randomWordDefinition(creature, meth);
     506                                addWord(list, worddef, it);
     507                        }
     508                        else
     509                        {
     510                                fL_Branch *start = new fL_Branch(fL_Branch::BranchType::OPEN, 0, 0);
     511                                list->insert(it, start);
     512                                int rottype = randomN(2);
     513                                switch (rottype)
     514                                {
     515                                case 0:
     516                                        addWord(list, creature->words["rotY"], it);
     517                                case 1:
     518                                        addWord(list, creature->words["rotZ"], it);
     519                                }
     520                                addWord(list, creature->words["S"], it);
     521                                fL_Branch *end = new fL_Branch(fL_Branch::BranchType::CLOSE, 0, 0);
     522                                list->insert(it, end);
     523                        }
     524                        break;
     525                }
     526                case FL_CHG_WORD:
     527                {
     528                        int numpars = 0;
     529                        int tmp = 0;
     530                        std::list<fL_Word *> *list = selectRandomSequence(creature, numpars, tmp);
     531                        int rndid = randomN(list->size());
     532                        std::list<fL_Word *>::iterator selectedword = list->begin();
     533                        std::advance(selectedword, rndid);
     534                        if ((*selectedword)->type == fLElementType::BRANCH)
     535                        {
     536                                break;
     537                        }
     538                        int chgtype = roulette(chgoperations, FL_CHG_COUNT);
     539                        if (creature->countSticksInSequence((*list)) == 1 && tmp == -1) // if sequence is axiom
     540                        {
     541                                fL_Word *worddef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1));
     542
     543                                int numpars = 0;
     544                                std::list<fL_Word *> *list = selectRandomSequence(creature, numpars, tmp);
     545                                int rndid = randomN(list->size());
     546                                std::list<fL_Word *>::iterator it = list->begin();
     547                                std::advance(it, rndid);
     548
     549                                addWord(list, worddef, it);
     550
     551                                break;
     552                        }
     553                        else if (chgtype == FL_CHG_WORD_NAME)
     554                        {
     555                                if ((*selectedword)->builtin)
     556                                {
     557                                        delete (*selectedword);
     558                                        selectedword = list->erase(selectedword);
     559                                        fL_Word *worddef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1));
     560                                        addWord(list, worddef, selectedword);
     561                                }
     562                                else
     563                                {
     564                                        std::vector<fL_Word *> available;
     565                                        for (std::unordered_map<std::string, fL_Word *>::iterator wit = creature->words.begin();
     566                                                        wit != creature->words.end(); wit++)
     567                                        {
     568                                                if ((*selectedword)->npar == wit->second->npar &&
     569                                                                (*selectedword)->name != wit->second->name &&
     570                                                                !wit->second->builtin)
     571                                                {
     572                                                        available.push_back(wit->second);
     573                                                }
     574                                        }
     575                                        if (available.size() > 0)
     576                                        {
     577                                                int newnameid = randomN(available.size());
     578                                                (*selectedword)->name = available[newnameid]->name;
     579                                        }
     580                                        else
     581                                        {
     582                                                delete (*selectedword);
     583                                                selectedword = list->erase(selectedword);
     584                                                fL_Word *worddef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1));
     585                                                addWord(list, worddef, selectedword);
     586                                        }
     587                                }
     588                        }
     589                        else
     590                        {
     591                                if ((*selectedword)->npar > 0)
     592                                {
     593                                        int randeval = randomN((*selectedword)->npar);
     594                                        Param par((*selectedword)->tab, (*selectedword)->data);
     595                                        if ((*selectedword)->builtin && (*selectedword)->name == "N"
     596                                                        && strcmp(par.id(randeval), FL_PE_NEURO_DET) == 0)
     597                                        {
     598                                                SString res = par.getStringById(FL_PE_NEURO_DET);
     599                                                Geno_fH::mutateNeuronProperties(res);
     600                                                par.setStringById(FL_PE_NEURO_DET, res);
     601                                        }
     602                                        else if ((*selectedword)->builtin &&
     603                                                        (*selectedword)->name == "C" &&
     604                                                        strcmp(par.id(randeval), FL_PE_CONN_ATTR) == 0)
     605                                        {
     606                                                SString strattractor = par.getStringById(FL_PE_CONN_ATTR);
     607                                                if (strattractor.len() > 0)
     608                                                {
     609                                                        fL_Word *w = NULL;
     610                                                        creature->createWord(strattractor, w, numpars, 0, 0);
     611                                                        // mutate attractor parameter
     612                                                        if (w->npar > 0)
     613                                                        {
     614                                                                int rndattr = randomN(w->npar);
     615                                                                if (!w->parevals[rndattr])
     616                                                                {
     617                                                                        w->parevals[rndattr] = new MathEvaluation(numpars);
     618                                                                }
     619                                                                w->parevals[rndattr]->mutate(false, false);
     620                                                        }
     621                                                        strattractor = w->stringify(true);
     622                                                        par.setStringById(FL_PE_CONN_ATTR, strattractor);
     623                                                        delete w;
     624                                                }
     625                                                else
     626                                                {
     627                                                        if (creature->builtincount < (int)creature->words.size())
     628                                                        {
     629                                                                fL_Word *wdef = randomWordDefinition(creature, FL_ADD_OTHER);
     630                                                                fL_Word *w = new fL_Word();
     631                                                                *w = *wdef;
     632                                                                w->data = ParamObject::makeObject(w->tab);
     633                                                                Param apar(w->tab);
     634                                                                apar.select(w->data);
     635                                                                apar.setDefault();
     636                                                                if (w->npar > 0)
     637                                                                {
     638                                                                        int rndattr = randomN(w->npar);
     639                                                                        for (int i = 0; i < w->npar; i++)
     640                                                                        {
     641                                                                                if (i == rndattr)
     642                                                                                {
     643                                                                                        MathEvaluation *ev = new MathEvaluation(numpars);
     644                                                                                        ev->mutate(false, false);
     645                                                                                        w->parevals.push_back(ev);
     646                                                                                }
     647                                                                                else
     648                                                                                {
     649                                                                                        w->parevals.push_back(NULL);
     650                                                                                }
     651                                                                        }
     652
     653                                                                }
     654                                                                strattractor = w->stringify(false);
     655                                                                par.setStringById(FL_PE_CONN_ATTR, strattractor);
     656                                                                delete w;
     657                                                        }
     658                                                }
     659                                        }
     660                                        else
     661                                        {
     662                                                if (!(*selectedword)->parevals[randeval])
     663                                                {
     664                                                        (*selectedword)->parevals[randeval] = new MathEvaluation(numpars);
     665                                                }
     666                                                (*selectedword)->parevals[randeval]->mutate(false, iterchangestep != 1.0);
     667                                        }
     668                                }
     669                        }
     670                        break;
     671                }
     672        }
     673
     674        free(geno);
     675        geno = strdup(creature->toString().c_str());
     676        chg = (double)abs(before - creature->countWordsInLSystem()) / before;
     677        delete creature;
     678
     679        return GENOPER_OK;
     680}
     681
     682fL_Word* Geno_fL::getAppropriateWord(fL_Builder *from, fL_Builder *to, fL_Word *fromword, std::unordered_map<std::string, std::string> &map)
     683{
     684        if (fromword->name == "[" || fromword->name == "]") // if words are branching words
     685        {
     686                fL_Branch *newword = new fL_Branch(fromword->name == "[" ? fL_Branch::BranchType::OPEN : fL_Branch::BranchType::CLOSE, 0, 0);
     687                return newword;
     688        }
     689        if (fromword->builtin)
     690        {
     691                fL_Word *newword = new fL_Word();
     692                (*newword) = (*to->words[fromword->name.c_str()]);
     693                return newword;
     694        }
     695        if (map.find(fromword->name.c_str()) != map.end()) // if word is already mapped
     696        {
     697                fL_Word *newword = new fL_Word();
     698                (*newword) = (*to->words[map[fromword->name.c_str()]]);
     699                return newword;
     700        }
     701        else if (to->words.find(fromword->name.c_str()) != to->words.end() &&
     702                        to->words[fromword->name.c_str()]->npar == fromword->npar) // if there is already same word with same number of parameters
     703        {
     704                fL_Word *newword = new fL_Word();
     705                map[fromword->name.c_str()] = fromword->name.c_str();
     706                (*newword) = (*to->words[map[fromword->name.c_str()]]);
     707                return newword;
     708        }
     709        for (std::unordered_map<std::string, fL_Word *>::iterator it = to->words.begin();
     710                        it != to->words.end(); it++)
     711        { // find word with same number of parameters
     712                if (fromword->npar == it->second->npar && map.find(fromword->name.c_str()) == map.end() && !it->second->builtin)
     713                { // if there is a word with same number of parameters
     714                        map[fromword->name.c_str()] = it->second->name.c_str();
     715                        fL_Word *newword = new fL_Word();
     716                        (*newword) = (*it->second);
     717                        return newword;
     718                }
     719        }
     720        fL_Word *newworddef = new fL_Word();
     721        (*newworddef) = (*fromword);
     722        newworddef->parevals.clear();
     723        if (to->words.find(newworddef->name.c_str()) != to->words.end())
     724        {
     725                int i = 0;
     726                while (true)
     727                {
     728                        std::string name = "w";
     729                        name += std::to_string(i);
     730                        if (to->words.find(name) == to->words.end())
     731                        {
     732                                newworddef->name = name.c_str();
     733                                break;
     734                        }
     735                        i++;
     736                }
     737        }
     738        newworddef->processDefinition(to);
     739        map[fromword->name.c_str()] = newworddef->name.c_str();
     740        fL_Word *newword = new fL_Word();
     741        (*newword) = (*to->words[map[fromword->name.c_str()]]);
     742        return newword;
     743}
     744
     745void Geno_fL::migrateRandomRules(fL_Builder *from, fL_Builder *to, int numselrules)
     746{
     747        std::unordered_map<std::string, std::string> map;
     748        if (from->rules.size() > 0)
     749        {
     750                for (int i = 0; i < numselrules; i++)
     751                {
     752                        int rulid = randomN(from->rules.size());
     753                        fL_Rule *rul = from->rules[rulid];
     754                        fL_Rule *newrule = new fL_Rule(0, 0);
     755                        newrule->objpred = getAppropriateWord(from, to, rul->objpred, map);
     756                        for (fL_Word *w : rul->objsucc)
     757                        {
     758                                fL_Word *el = getAppropriateWord(from, to, w, map);
     759                                if (el->type == fLElementType::BRANCH)
     760                                {
     761                                        newrule->objsucc.push_back(el);
     762                                        continue;
     763                                }
     764                                Param origpar(w->tab);
     765                                origpar.select(w->data);
     766                                el->data = ParamObject::makeObject(el->tab);
     767                                Param par(el->tab);
     768                                par.select(el->data);
     769                                par.setDefault();
     770                                for (int i = 0; i < el->npar; i++)
     771                                {
     772                                        std::string form;
     773                                        if (w->builtin && w->name == "N"
     774                                                        && strcmp(par.id(i), FL_PE_NEURO_DET) == 0)
     775                                        {
     776                                                SString res = origpar.getStringById(FL_PE_NEURO_DET);
     777                                                par.setStringById(FL_PE_NEURO_DET, res);
     778                                                el->parevals.push_back(NULL);
     779                                        }
     780                                        else if (w->builtin && w->name == "C"
     781                                                        && strcmp(par.id(i), FL_PE_CONN_ATTR) == 0)
     782                                        {
     783                                                SString strattractor = origpar.getStringById(FL_PE_CONN_ATTR);
     784                                                if (strattractor.len() > 0)
     785                                                {
     786                                                        fL_Word *tmp = NULL;
     787                                                        from->createWord(strattractor, tmp, newrule->objpred->npar, 0, 0);
     788                                                        fL_Word *newsuccword = getAppropriateWord(from, to, tmp, map);
     789                                                        newsuccword->data = ParamObject::makeObject(el->tab);
     790                                                        newsuccword->parevals = tmp->parevals;
     791                                                        tmp->parevals.clear();
     792                                                        strattractor = newsuccword->stringify(true);
     793                                                        par.setStringById(FL_PE_CONN_ATTR, strattractor);
     794                                                        delete newsuccword;
     795                                                        delete tmp;
     796                                                }
     797                                                par.setStringById(FL_PE_CONN_ATTR, strattractor);
     798                                                el->parevals.push_back(NULL);
     799                                        }
     800                                        else if (w->parevals[i])
     801                                        {
     802                                                MathEvaluation *eval = new MathEvaluation(newrule->objpred->npar);
     803                                                w->parevals[i]->RPNToInfix(form);
     804                                                eval->convertString(form);
     805                                                el->parevals.push_back(eval);
     806                                        }
     807                                        else
     808                                        {
     809                                                el->parevals.push_back(NULL);
     810                                        }
     811                                }
     812                                newrule->objsucc.push_back(el);
     813                        }
     814                        to->rules.push_back(newrule);
     815                }
     816        }
     817}
     818
     819int Geno_fL::crossOver(char *&g1, char *&g2, float& chg1, float& chg2)
     820{
     821        fL_Builder *creature1 = new fL_Builder(false, false);
     822        fL_Builder *creature1template = new fL_Builder(false, false);
     823        fL_Builder *creature2 = new fL_Builder(false, false);
     824        fL_Builder *creature2template = new fL_Builder(false, false);
     825
     826        int count1 = creature1->countWordsInLSystem();
     827        int count2 = creature2->countWordsInLSystem();
     828
     829        if (creature1->parseGenotype(g1) != 0 || creature2->parseGenotype(g2) != 0)
     830        {
     831                delete creature1;
     832                delete creature2;
     833                delete creature1template;
     834                delete creature2template;
     835                return GENOPER_OPFAIL;
     836        }
     837
     838        creature1template->parseGenotype(g1);
     839        creature2template->parseGenotype(g2);
     840
     841        int numselrules = 1 + randomN(XOVER_MAX_MIGRATED_RULES);
     842        numselrules = numselrules < (int)creature1->rules.size() ? numselrules : (int)creature1->rules.size();
     843
     844        migrateRandomRules(creature1template, creature2, numselrules);
     845
     846        numselrules = 1 + randomN(XOVER_MAX_MIGRATED_RULES);
     847        numselrules = numselrules < (int)creature1->rules.size() ? numselrules : (int)creature1->rules.size();
     848
     849        migrateRandomRules(creature2template, creature1, numselrules);
     850
     851        free(g1);
     852        free(g2);
     853
     854        g1 = strdup(creature1->toString().c_str());
     855        g2 = strdup(creature2->toString().c_str());
     856
     857        chg1 = (double)count1 / creature1->countWordsInLSystem();
     858        chg1 = (double)count2 / creature2->countWordsInLSystem();
     859
     860        delete creature1;
     861        delete creature2;
     862        delete creature1template;
     863        delete creature2template;
     864
     865        return GENOPER_OK;
     866}
     867
     868uint32_t Geno_fL::style(const char *geno, int pos)
     869{
     870        char ch = geno[pos];
     871        uint32_t style = GENSTYLE_CS(0, GENSTYLE_STRIKEOUT);
     872        if (pos == 0 || geno[pos - 1] == '\n' || ch == ':') // single-character line definition
     873        {
     874                style = GENSTYLE_CS(GENCOLOR_TEXT, GENSTYLE_BOLD);
     875        }
     876        else if (strchr("()", ch) != NULL)
     877        {
     878                style = GENSTYLE_RGBS(50, 50, 50, GENSTYLE_BOLD);
     879        }
     880        else if (isalpha(ch)) // properties name
     881        {
     882                style = GENSTYLE_RGBS(0, 200, 0, GENSTYLE_BOLD);
     883        }
     884        else if (isdigit(ch) || strchr(",.=", ch)) // properties values
     885        {
     886                style = GENSTYLE_CS(GENCOLOR_TEXT, GENSTYLE_NONE);
     887        }
     888        else if (ch == '\"')
     889        {
     890                style = GENSTYLE_RGBS(200, 0, 0, GENSTYLE_BOLD);
     891        }
     892
     893        return style;
     894}
Note: See TracChangeset for help on using the changeset viewer.