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

Last change on this file since 821 was 821, checked in by Maciej Komosinski, 5 months ago

Performance and stability improvements in fB, fH, and fL; improved parsing and math evaluations in fL

File size: 26.2 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                        det = cls->getName();
145                        Geno_fH::mutateNeuronProperties(det);
146                        par.setStringById(FL_PE_NEURO_DET, det);
147                }
148                else if (newword->name == "C")
149                {
150                        MathEvaluation *eval = new MathEvaluation(0);
151                        eval->convertString(SString::valueOf(2 * rnd01 - 1).c_str());
152                        newword->parevals[0] = eval;
153                }
154        }
155
156        list->insert(it, newword);
157        return true;
158}
159
160std::list<fL_Word *>* Geno_fL::selectRandomSequence(fL_Builder *creature, int &numparams, int &ruleid)
161{
162        std::list<fL_Word *> *list = NULL;
163        int axiomorrules = roulette(groupprobabilities, FL_MUTGROUPSCOUNT);
164        bool axiomused = axiomorrules == FL_AXM_WORD_MUT_PROB || creature->rules.size() == 0;
165        if (axiomused)
166        {
167                list = &creature->genotype;
168                numparams = 0;
169                ruleid = -1;
170        }
171        else
172        {
173                int rid = randomN(creature->rules.size());
174                list = &creature->rules[rid]->objsucc;
175                numparams = creature->rules[rid]->objpred->npar;
176                ruleid = rid;
177        }
178        return list;
179}
180
181fL_Word* Geno_fL::randomWordDefinition(fL_Builder *creature, int method)
182{
183        if (method == FL_ADD_OTHER && creature->builtincount < (int)creature->words.size())
184        {
185                return creature->words[creature->wordnames[creature->builtincount + randomN((int)creature->words.size() - creature->builtincount)]];
186        }
187        else
188        {
189                if (method == FL_ADD_OTHER) // we should be able to select stick, neuro or conn
190                {
191                        double alttypes[FL_ADD_COUNT - 2];
192                        alttypes[FL_ADD_STICK] = addtypes[FL_ADD_STICK];
193                        alttypes[FL_ADD_NEURO] = addtypes[FL_ADD_NEURO];
194                        alttypes[FL_ADD_CONN] = addtypes[FL_ADD_CONN];
195                        alttypes[FL_ADD_ROT] = addtypes[FL_ADD_ROT];
196                        method = roulette(alttypes, FL_ADD_COUNT - 2);
197                }
198                switch (method)
199                {
200                case FL_ADD_STICK:
201                        return creature->words["S"];
202                case FL_ADD_NEURO:
203                        if (getActiveNeuroClassCount() == 0)
204                                return creature->words["S"];
205                        else
206                                return creature->words["N"];
207                case FL_ADD_CONN:
208                        return creature->words["C"];
209                case FL_ADD_ROT:
210                {
211                        int rottype = randomN(3);
212                        switch (rottype)
213                        {
214                        case 0:
215                                return creature->words["rotX"];
216                        case 1:
217                                return creature->words["rotY"];
218                        case 2:
219                                return creature->words["rotZ"];
220                        }
221                        break;
222                }
223                case FL_ADD_BRANCH:
224                        // return NULL
225                        break;
226                }
227        }
228        return NULL;
229}
230
231void Geno_fL::deleteBranch(std::list<fL_Word *> *list, std::list<fL_Word *>::iterator openbranchposition)
232{
233        fL_Branch *branch = (fL_Branch *)(*openbranchposition);
234        if (branch->btype == fL_Branch::BranchType::OPEN)
235        {
236                int bcount = 1;
237                delete (*openbranchposition);
238                openbranchposition = list->erase(openbranchposition);
239                for (; openbranchposition != list->end(); openbranchposition++)
240                {
241                        if ((*openbranchposition)->type == fLElementType::BRANCH)
242                        {
243                                branch = (fL_Branch *)(*openbranchposition);
244                                if (branch->btype == fL_Branch::BranchType::OPEN)
245                                {
246                                        bcount++;
247                                }
248                                else
249                                {
250                                        bcount--;
251                                        if (bcount == 0)
252                                        {
253                                                delete branch;
254                                                list->erase(openbranchposition);
255                                                break;
256                                        }
257                                }
258                        }
259                }
260        }
261        else
262        {
263                openbranchposition++;
264                if (openbranchposition != list->end())
265                {
266                        delete (*openbranchposition);
267                        list->erase(openbranchposition);
268                }
269        }
270}
271
272int Geno_fL::mutate(char *&geno, float& chg, int &method)
273{
274        fL_Builder *creature = new fL_Builder(false, false);
275
276        if (creature->parseGenotype(geno) != 0)
277        {
278                delete creature;
279                return GENOPER_OPFAIL;
280        }
281
282        int before = creature->countWordsInLSystem();
283
284        method = roulette(operations, FL_OPCOUNT);
285        switch (method)
286        {
287                case FL_CHG_ITER:
288                {
289                        if (randomN(2) == 0)
290                        {
291                                creature->time = creature->time + iterchangestep <= ExtValue::getDouble(FL_MAXITER) ?
292                                                creature->time + iterchangestep : creature->time - iterchangestep;
293                        }
294                        else
295                        {
296                                creature->time = creature->time - iterchangestep >= 0 ?
297                                                creature->time - iterchangestep : creature->time + iterchangestep;
298                        }
299                        break;
300                }
301                case FL_CHG_COND:
302                {
303                        if (creature->rules.size() > 0)
304                        {
305                                int ruleid = randomN(creature->rules.size());
306                                if (!creature->rules[ruleid]->condeval)
307                                {
308                                        creature->rules[ruleid]->condeval = new MathEvaluation(creature->rules[ruleid]->objpred->npar);
309                                }
310                                creature->rules[ruleid]->condeval->mutateConditional();
311                                break;
312                        }
313                        // if there are no rules - create one
314                }
315                /* no break */
316                case FL_ADD_RULE:
317                {
318                        std::unordered_map<std::string, fL_Word *>::iterator pred = creature->words.begin();
319                        std::vector<fL_Word *> wordswithnorules;
320                        for (; pred != creature->words.end(); pred++)
321                        {
322                                if (!pred->second->builtin)
323                                {
324                                        bool norules = true;
325                                        for (fL_Rule * r : creature->rules)
326                                        {
327                                                if (pred->second->name == r->objpred->name &&
328                                                                pred->second->npar == r->objpred->npar)
329                                                {
330                                                        norules = false;
331                                                        break;
332                                                }
333                                        }
334                                        if (norules)
335                                        {
336                                                wordswithnorules.push_back(pred->second);
337                                        }
338                                }
339                        }
340                        if (wordswithnorules.size() > 0)
341                        {
342                                int predid = randomN(wordswithnorules.size());
343                                fL_Rule *newrule = new fL_Rule(0,0);
344                                fL_Word *pred = new fL_Word();
345                                *pred = *wordswithnorules[predid];
346                                newrule->objpred = pred;
347                                fL_Word *initdef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1)); // -1 to avoid branching
348                                addWord(&newrule->objsucc, initdef, newrule->objsucc.begin());
349                                creature->rules.push_back(newrule);
350                                break;
351                        }
352                        else if (creature->rules.size() > 0)
353                        {
354                                int ruleid = randomN(creature->rules.size());
355                                fL_Rule *newrule = new fL_Rule(0, 0);
356                                fL_Word *pred = new fL_Word();
357                                *pred = *creature->rules[ruleid]->objpred;
358                                newrule->objpred = pred;
359                                if (creature->rules[ruleid]->condeval)
360                                {
361                                        std::string formula = "";
362                                        creature->rules[ruleid]->condeval->RPNToInfix(formula);
363                                        if (formula.find("1.0-(") != 0)
364                                        {
365                                                std::string res = "1.0-(";
366                                                res += formula;
367                                                res += ")";
368                                                newrule->condeval = new MathEvaluation(pred->npar);
369                                                newrule->condeval->convertString(res);
370                                        }
371                                        else
372                                        {
373                                                newrule->condeval = new MathEvaluation(pred->npar);
374                                                newrule->condeval->mutateConditional();
375                                        }
376                                }
377                                else
378                                {
379                                        newrule->condeval = new MathEvaluation(pred->npar);
380                                        newrule->condeval->mutateConditional();
381                                }
382                                fL_Word *worddef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1));
383                                addWord(&newrule->objsucc, worddef, newrule->objsucc.begin());
384                                creature->rules.push_back(newrule);
385                                break;
386                        }
387                        // if there are no words, from which rules can be formed, then add one
388                }
389                /* no break */
390                case FL_ADD_WDEF:
391                {
392                        if (creature->countDefinedWords() <= maxdefinedwords)
393                        {
394                                int npar = randomN(ExtValue::getInt(FL_MAXPARAMS, false));
395                                for (int i = 0; i < maxdefinedwords; i++)
396                                {
397                                        std::string name = "w";
398                                        name += std::to_string(i);
399                                        if (creature->words.find(name) == creature->words.end())
400                                        {
401                                                fL_Word *word = new fL_Word(false, 0, 0);
402                                                word->npar = npar;
403                                                word->name = name.c_str();
404                                                word->processDefinition(creature);
405                                                break;
406                                        }
407                                }
408                                break;
409                        }
410                        //no break at the end of case - if there is too many words, then
411                        // deletion should be performed
412                }
413                /* no break */
414                case FL_DEL_WORD:
415                {
416                        int numpars = 0;
417                        int ruleid = 0;
418                        std::list<fL_Word *> *list = selectRandomSequence(creature, numpars, ruleid);
419                        if (ruleid == -1 && creature->countSticksInSequence(list) == 1)
420                        {
421                                if (list->size() > 1)
422                                {
423                                        int rndid = randomN(list->size() - 1);
424                                        int j = 0;
425                                        std::list<fL_Word *>::iterator it = list->begin();
426                                        if ((*it)->name == "S")
427                                        {
428                                                it++;
429                                        }
430                                        while (it != list->end() && j < rndid && ((*it)->name == "S"))
431                                        {
432                                                if ((*it)->name != "S")
433                                                {
434                                                        j++;
435                                                }
436                                                it++;
437                                        }
438                                        if (it != list->end())
439                                        {
440                                                if ((*it)->type == fLElementType::BRANCH)
441                                                {
442                                                        deleteBranch(list, it);
443                                                }
444                                                else
445                                                {
446                                                        delete (*it);
447                                                        list->erase(it);
448                                                }
449                                                break;
450                                        }
451                                        // else add word
452                                }
453                                // else add word
454                        }
455                        else
456                        {
457                                int rndid = randomN(list->size());
458                                std::list<fL_Word *>::iterator it = list->begin();
459                                std::advance(it, rndid);
460                                if ((*it)->type == fLElementType::BRANCH)
461                                {
462                                        deleteBranch(list, it);
463                                }
464                                else
465                                {
466                                        delete (*it);
467                                        list->erase(it);
468                                }
469                                if (ruleid > -1 && creature->rules[ruleid]->objsucc.size() == 0)
470                                {
471                                        delete creature->rules[ruleid];
472                                        creature->rules.erase(creature->rules.begin() + ruleid);
473                                }
474                                break;
475                        }
476                        // if no words available, then add word
477                }
478                /* no break */
479                case FL_ADD_WORD:
480                {
481                        int numpars = 0;
482                        int tmp = 0;
483                        std::list<fL_Word *> *list = selectRandomSequence(creature, numpars, tmp);
484                        int rndid = randomN(list->size());
485                        std::list<fL_Word *>::iterator it = list->begin();
486                        std::advance(it, rndid);
487                        int meth = roulette(addtypes, FL_ADD_COUNT);
488                        if (tmp == -1)
489                        { // if sequence is axiom and it does not have non-builtin words
490                                bool hasdefined = false;
491                                for (std::list<fL_Word *>::iterator elem = list->begin(); elem != list->end(); elem++)
492                                {
493                                        if (!(*elem)->builtin)
494                                        {
495                                                hasdefined = true;
496                                                break;
497                                        }
498                                }
499                                if (!hasdefined)
500                                {
501                                        meth = FL_ADD_OTHER;
502                                }
503
504                        }
505                        if (meth != FL_ADD_BRANCH)
506                        {
507                                fL_Word *worddef = randomWordDefinition(creature, meth);
508                                addWord(list, worddef, it);
509                        }
510                        else
511                        {
512                                fL_Branch *start = new fL_Branch(fL_Branch::BranchType::OPEN, 0, 0);
513                                list->insert(it, start);
514                                int rottype = randomN(2);
515                                switch (rottype)
516                                {
517                                case 0:
518                                        addWord(list, creature->words["rotY"], it);
519                                case 1:
520                                        addWord(list, creature->words["rotZ"], it);
521                                }
522                                addWord(list, creature->words["S"], it);
523                                fL_Branch *end = new fL_Branch(fL_Branch::BranchType::CLOSE, 0, 0);
524                                list->insert(it, end);
525                        }
526                        break;
527                }
528                case FL_CHG_WORD:
529                {
530                        int numpars = 0;
531                        int tmp = 0;
532                        std::list<fL_Word *> *list = selectRandomSequence(creature, numpars, tmp);
533                        int rndid = randomN(list->size());
534                        std::list<fL_Word *>::iterator selectedword = list->begin();
535                        std::advance(selectedword, rndid);
536                        if ((*selectedword)->type == fLElementType::BRANCH)
537                        {
538                                break;
539                        }
540                        int chgtype = roulette(chgoperations, FL_CHG_COUNT);
541                        if (creature->countSticksInSequence(list) == 1 && tmp == -1) // if sequence is axiom
542                        {
543                                fL_Word *worddef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1));
544
545                                int numpars = 0;
546                                std::list<fL_Word *> *list = selectRandomSequence(creature, numpars, tmp);
547                                int rndid = randomN(list->size());
548                                std::list<fL_Word *>::iterator it = list->begin();
549                                std::advance(it, rndid);
550
551                                addWord(list, worddef, it);
552
553                                break;
554                        }
555                        else if (chgtype == FL_CHG_WORD_NAME)
556                        {
557                                if ((*selectedword)->builtin)
558                                {
559                                        delete (*selectedword);
560                                        selectedword = list->erase(selectedword);
561                                        fL_Word *worddef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1));
562                                        addWord(list, worddef, selectedword);
563                                }
564                                else
565                                {
566                                        std::vector<fL_Word *> available;
567                                        for (std::unordered_map<std::string, fL_Word *>::iterator wit = creature->words.begin();
568                                                        wit != creature->words.end(); wit++)
569                                        {
570                                                if ((*selectedword)->npar == wit->second->npar &&
571                                                                (*selectedword)->name != wit->second->name &&
572                                                                !wit->second->builtin)
573                                                {
574                                                        available.push_back(wit->second);
575                                                }
576                                        }
577                                        if (available.size() > 0)
578                                        {
579                                                int newnameid = randomN(available.size());
580                                                (*selectedword)->name = available[newnameid]->name;
581                                        }
582                                        else
583                                        {
584                                                delete (*selectedword);
585                                                selectedword = list->erase(selectedword);
586                                                fL_Word *worddef = randomWordDefinition(creature, roulette(addtypes, FL_ADD_COUNT - 1));
587                                                addWord(list, worddef, selectedword);
588                                        }
589                                }
590                        }
591                        else
592                        {
593                                if ((*selectedword)->npar > 0)
594                                {
595                                        int randeval = randomN((*selectedword)->npar);
596                                        Param par((*selectedword)->tab, (*selectedword)->data);
597                                        if ((*selectedword)->builtin && (*selectedword)->name == "N"
598                                                        && strcmp(par.id(randeval), FL_PE_NEURO_DET) == 0)
599                                        {
600                                                SString res = par.getStringById(FL_PE_NEURO_DET);
601                                                Geno_fH::mutateNeuronProperties(res);
602                                                par.setStringById(FL_PE_NEURO_DET, res);
603                                        }
604                                        else if ((*selectedword)->builtin &&
605                                                        (*selectedword)->name == "C" &&
606                                                        strcmp(par.id(randeval), FL_PE_CONN_ATTR) == 0)
607                                        {
608                                                SString strattractor = par.getStringById(FL_PE_CONN_ATTR);
609                                                if (strattractor.len() > 0)
610                                                {
611                                                        fL_Word *w = NULL;
612                                                        creature->createWord(strattractor, w, numpars, 0, 0);
613                                                        // mutate attractor parameter
614                                                        if (w->npar > 0)
615                                                        {
616                                                                int rndattr = randomN(w->npar);
617                                                                if (!w->parevals[rndattr])
618                                                                {
619                                                                        w->parevals[rndattr] = new MathEvaluation(numpars);
620                                                                }
621                                                                w->parevals[rndattr]->mutate(false, false);
622                                                        }
623                                                        strattractor = w->stringify(true);
624                                                        par.setStringById(FL_PE_CONN_ATTR, strattractor);
625                                                        delete w;
626                                                }
627                                                else
628                                                {
629                                                        if (creature->builtincount < (int)creature->words.size())
630                                                        {
631                                                                fL_Word *wdef = randomWordDefinition(creature, FL_ADD_OTHER);
632                                                                fL_Word *w = new fL_Word();
633                                                                *w = *wdef;
634                                                                w->data = ParamObject::makeObject(w->tab);
635                                                                Param apar(w->tab);
636                                                                apar.select(w->data);
637                                                                apar.setDefault();
638                                                                if (w->npar > 0)
639                                                                {
640                                                                        int rndattr = randomN(w->npar);
641                                                                        for (int i = 0; i < w->npar; i++)
642                                                                        {
643                                                                                if (i == rndattr)
644                                                                                {
645                                                                                        MathEvaluation *ev = new MathEvaluation(numpars);
646                                                                                        ev->mutate(false, false);
647                                                                                        w->parevals.push_back(ev);
648                                                                                }
649                                                                                else
650                                                                                {
651                                                                                        w->parevals.push_back(NULL);
652                                                                                }
653                                                                        }
654
655                                                                }
656                                                                strattractor = w->stringify(false);
657                                                                par.setStringById(FL_PE_CONN_ATTR, strattractor);
658                                                                delete w;
659                                                        }
660                                                }
661                                        }
662                                        else
663                                        {
664                                                if (!(*selectedword)->parevals[randeval])
665                                                {
666                                                        (*selectedword)->parevals[randeval] = new MathEvaluation(numpars);
667                                                }
668                                                (*selectedword)->parevals[randeval]->mutate(false, iterchangestep != 1.0);
669                                        }
670                                }
671                        }
672                        break;
673                }
674        }
675
676        free(geno);
677        geno = strdup(creature->toString().c_str());
678        chg = (double)abs(before - creature->countWordsInLSystem()) / before;
679        delete creature;
680
681        return GENOPER_OK;
682}
683
684fL_Word* Geno_fL::getAppropriateWord(fL_Builder *from, fL_Builder *to, fL_Word *fromword, std::unordered_map<std::string, std::string> &map)
685{
686        if (fromword->name == "[" || fromword->name == "]") // if words are branching words
687        {
688                fL_Branch *newword = new fL_Branch(fromword->name == "[" ? fL_Branch::BranchType::OPEN : fL_Branch::BranchType::CLOSE, 0, 0);
689                return newword;
690        }
691        if (fromword->builtin)
692        {
693                fL_Word *newword = new fL_Word();
694                (*newword) = (*to->words[fromword->name.c_str()]);
695                return newword;
696        }
697        if (map.find(fromword->name.c_str()) != map.end()) // if word is already mapped
698        {
699                fL_Word *newword = new fL_Word();
700                (*newword) = (*to->words[map[fromword->name.c_str()]]);
701                return newword;
702        }
703        else if (to->words.find(fromword->name.c_str()) != to->words.end() &&
704                        to->words[fromword->name.c_str()]->npar == fromword->npar) // if there is already same word with same number of parameters
705        {
706                fL_Word *newword = new fL_Word();
707                map[fromword->name.c_str()] = fromword->name.c_str();
708                (*newword) = (*to->words[map[fromword->name.c_str()]]);
709                return newword;
710        }
711        for (std::unordered_map<std::string, fL_Word *>::iterator it = to->words.begin();
712                        it != to->words.end(); it++)
713        { // find word with same number of parameters
714                if (fromword->npar == it->second->npar && map.find(fromword->name.c_str()) == map.end() && !it->second->builtin)
715                { // if there is a word with same number of parameters
716                        map[fromword->name.c_str()] = it->second->name.c_str();
717                        fL_Word *newword = new fL_Word();
718                        (*newword) = (*it->second);
719                        return newword;
720                }
721        }
722        fL_Word *newworddef = new fL_Word();
723        (*newworddef) = (*fromword);
724        newworddef->parevals.clear();
725        if (to->words.find(newworddef->name.c_str()) != to->words.end())
726        {
727                int i = 0;
728                while (true)
729                {
730                        std::string name = "w";
731                        name += std::to_string(i);
732                        if (to->words.find(name) == to->words.end())
733                        {
734                                newworddef->name = name.c_str();
735                                break;
736                        }
737                        i++;
738                }
739        }
740        newworddef->processDefinition(to);
741        map[fromword->name.c_str()] = newworddef->name.c_str();
742        fL_Word *newword = new fL_Word();
743        (*newword) = (*to->words[map[fromword->name.c_str()]]);
744        return newword;
745}
746
747void Geno_fL::migrateRandomRules(fL_Builder *from, fL_Builder *to, int numselrules)
748{
749        std::unordered_map<std::string, std::string> map;
750        if (from->rules.size() > 0)
751        {
752                for (int i = 0; i < numselrules; i++)
753                {
754                        int rulid = randomN(from->rules.size());
755                        fL_Rule *rul = from->rules[rulid];
756                        fL_Rule *newrule = new fL_Rule(0, 0);
757                        newrule->objpred = getAppropriateWord(from, to, rul->objpred, map);
758                        for (fL_Word *w : rul->objsucc)
759                        {
760                                fL_Word *el = getAppropriateWord(from, to, w, map);
761                                if (el->type == fLElementType::BRANCH)
762                                {
763                                        newrule->objsucc.push_back(el);
764                                        continue;
765                                }
766                                Param origpar(w->tab);
767                                origpar.select(w->data);
768                                el->data = ParamObject::makeObject(el->tab);
769                                Param par(el->tab);
770                                par.select(el->data);
771                                par.setDefault();
772                                for (int i = 0; i < el->npar; i++)
773                                {
774                                        std::string form;
775                                        if (w->builtin && w->name == "N"
776                                                        && strcmp(par.id(i), FL_PE_NEURO_DET) == 0)
777                                        {
778                                                SString res = origpar.getStringById(FL_PE_NEURO_DET);
779                                                par.setStringById(FL_PE_NEURO_DET, res);
780                                                el->parevals.push_back(NULL);
781                                        }
782                                        else if (w->builtin && w->name == "C"
783                                                        && strcmp(par.id(i), FL_PE_CONN_ATTR) == 0)
784                                        {
785                                                SString strattractor = origpar.getStringById(FL_PE_CONN_ATTR);
786                                                if (strattractor.len() > 0)
787                                                {
788                                                        fL_Word *tmp = NULL;
789                                                        from->createWord(strattractor, tmp, newrule->objpred->npar, 0, 0);
790                                                        fL_Word *newsuccword = getAppropriateWord(from, to, tmp, map);
791                                                        newsuccword->data = ParamObject::makeObject(el->tab);
792                                                        newsuccword->parevals = tmp->parevals;
793                                                        tmp->parevals.clear();
794                                                        strattractor = newsuccword->stringify(true);
795                                                        par.setStringById(FL_PE_CONN_ATTR, strattractor);
796                                                        delete newsuccword;
797                                                        delete tmp;
798                                                }
799                                                par.setStringById(FL_PE_CONN_ATTR, strattractor);
800                                                el->parevals.push_back(NULL);
801                                        }
802                                        else if (w->parevals[i])
803                                        {
804                                                MathEvaluation *eval = new MathEvaluation(newrule->objpred->npar);
805                                                w->parevals[i]->RPNToInfix(form);
806                                                eval->convertString(form);
807                                                el->parevals.push_back(eval);
808                                        }
809                                        else
810                                        {
811                                                el->parevals.push_back(NULL);
812                                        }
813                                }
814                                newrule->objsucc.push_back(el);
815                        }
816                        to->rules.push_back(newrule);
817                }
818        }
819}
820
821int Geno_fL::crossOver(char *&g1, char *&g2, float& chg1, float& chg2)
822{
823        fL_Builder *creature1 = new fL_Builder(false, false);
824        fL_Builder *creature1template = new fL_Builder(false, false);
825        fL_Builder *creature2 = new fL_Builder(false, false);
826        fL_Builder *creature2template = new fL_Builder(false, false);
827
828        int count1 = creature1->countWordsInLSystem();
829        int count2 = creature2->countWordsInLSystem();
830
831        if (creature1->parseGenotype(g1) != 0 || creature2->parseGenotype(g2) != 0)
832        {
833                delete creature1;
834                delete creature2;
835                delete creature1template;
836                delete creature2template;
837                return GENOPER_OPFAIL;
838        }
839
840        creature1template->parseGenotype(g1);
841        creature2template->parseGenotype(g2);
842
843        int numselrules = 1 + randomN(XOVER_MAX_MIGRATED_RULES);
844        numselrules = numselrules < (int)creature1->rules.size() ? numselrules : (int)creature1->rules.size();
845
846        migrateRandomRules(creature1template, creature2, numselrules);
847
848        numselrules = 1 + randomN(XOVER_MAX_MIGRATED_RULES);
849        numselrules = numselrules < (int)creature1->rules.size() ? numselrules : (int)creature1->rules.size();
850
851        migrateRandomRules(creature2template, creature1, numselrules);
852
853        free(g1);
854        free(g2);
855
856        g1 = strdup(creature1->toString().c_str());
857        g2 = strdup(creature2->toString().c_str());
858
859        chg1 = (double)count1 / creature1->countWordsInLSystem();
860        chg1 = (double)count2 / creature2->countWordsInLSystem();
861
862        delete creature1;
863        delete creature2;
864        delete creature1template;
865        delete creature2template;
866
867        return GENOPER_OK;
868}
869
870uint32_t Geno_fL::style(const char *geno, int pos)
871{
872        char ch = geno[pos];
873        uint32_t style = GENSTYLE_CS(0, GENSTYLE_STRIKEOUT);
874        if (pos == 0 || geno[pos - 1] == '\n' || ch == ':') // single-character line definition
875        {
876                style = GENSTYLE_CS(GENCOLOR_TEXT, GENSTYLE_BOLD);
877        }
878        else if (strchr("()", ch) != NULL)
879        {
880                style = GENSTYLE_RGBS(50, 50, 50, GENSTYLE_BOLD);
881        }
882        else if (isalpha(ch)) // properties name
883        {
884                style = GENSTYLE_RGBS(0, 200, 0, GENSTYLE_BOLD);
885        }
886        else if (isdigit(ch) || strchr(",.=", ch)) // properties values
887        {
888                style = GENSTYLE_CS(GENCOLOR_TEXT, GENSTYLE_NONE);
889        }
890        else if (ch == '\"')
891        {
892                style = GENSTYLE_RGBS(200, 0, 0, GENSTYLE_BOLD);
893        }
894
895        return style;
896}
Note: See TracBrowser for help on using the repository browser.