source: cpp/frams/genetics/fL/fL_oper.cpp @ 797

Last change on this file since 797 was 797, checked in by Maciej Komosinski, 3 years ago

A more complete implementation of fB, fH, fL

File size: 26.1 KB
Line 
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
5#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
44
45Geno_fL::Geno_fL()
46{
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 TracBrowser for help on using the repository browser.