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

A more complete implementation of fB, fH, fL

File:
1 edited

Legend:

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

    r780 r797  
     1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
     3// See LICENSE.txt for details.
     4
    15#include <algorithm>
    26#include <stack>
    37#include "fL_general.h"
    4 
    5 const char *fL_part_names[PART_PROPS_COUNT] = { "dn", "fr", "ing", "as" };
    6 const char *fL_part_fullnames[PART_PROPS_COUNT] = { "details", "friction", "ingestion", "assimilation" };
    7 
    8 const char *fL_joint_names[JOINT_PROPS_COUNT] = { "stif", "rotstif", "stam" };
    9 const char *fL_joint_fullnames[JOINT_PROPS_COUNT] = { "stiffness", "rotation stiffness", "stamina" };
     8#include <frams/util/multirange.h>
     9#include <iterator>
     10
     11const char *fL_part_names[FL_PART_PROPS_COUNT] = { "dn", "fr", "ing", "as" };
     12const char *fL_part_fullnames[FL_PART_PROPS_COUNT] = { "details", "friction", "ingestion", "assimilation" };
     13
     14const char *fL_joint_names[FL_JOINT_PROPS_COUNT] = { "stif", "rotstif", "stam" };
     15const char *fL_joint_fullnames[FL_JOINT_PROPS_COUNT] = { "stiffness", "rotation stiffness", "stamina" };
    1016
    1117#define FIELDSTRUCT fL_Word
     
    1420        { "Word", 1, 2, "w" },
    1521        { "name", 0, PARAM_CANOMITNAME, "word name", "s", FIELD(name), },
    16         { "npar", 0, PARAM_CANOMITNAME, "number of parameters", "d 0 3 0", FIELD(npar), },
     22        { "npar", 0, PARAM_CANOMITNAME, "number of parameters", "d 0 " FL_MAXPARAMS " 0", FIELD(npar), },
    1723        { 0, 0, 0, }
    1824};
     
    2329{
    2430        { "Rule", 1, 3, "r" },
    25         { "pred", 0, PARAM_CANOMITNAME, "predecessor", "s", FIELD(predecessor), },
    26         { "cond", 0, PARAM_CANOMITNAME, "parameter condition", "s", FIELD(condition), },
    27         { "succ", 0, PARAM_CANOMITNAME, "successor", "s", FIELD(successor), },
     31        { "pred", 0, 0, "predecessor", "s", FIELD(predecessor), },
     32        { "cond", 0, 0, "parameter condition", "s", FIELD(condition), },
     33        { "succ", 0, 0, "successor", "s", FIELD(successor), },
    2834        { 0, 0, 0, }
    2935};
     
    3339ParamEntry fL_builder_paramtab[] =
    3440{
    35         { "LSystemInfo", 1, 3, "i" },
    36         { "axiom", 0, PARAM_CANOMITNAME, "starting sequence of L-System", "s", FIELD(axiom), },
    37         { "time", 0, PARAM_CANOMITNAME, "development time", "f 1.0 100.0 1.0", FIELD(time), },
    38         { "numckp", 0, PARAM_CANOMITNAME, "number of checkpoints", "d 1 50 1", FIELD(numckp), },
    39         { 0, 0, 0, }
     41                {"LSystemInfo", 1, 4, "i"},
     42                {"axiom", 0, 0, "starting sequence of L-System", "s", FIELD(axiom),},
     43                {"time", 0, PARAM_CANOMITNAME, "development time", "f 0.0 " FL_MAXITER " 1.0", FIELD(time),},
     44                {"numckp", 0, PARAM_CANOMITNAME, "number of checkpoints", "d 1 50 1", FIELD(numckp),},
     45                {"maxwords", 0, PARAM_CANOMITNAME, "Maximum number of words within genotype sequence", "d -1 9999 -1", FIELD(maxwords),},
     46                {0,0,0,}
    4047};
    4148#undef FIELDSTRUCT
     
    134141}
    135142
    136 int fL_Builder::tokenize(SString sequence, std::list<fL_Word *> &result, int numparams)
     143int fL_Builder::createWord(SString token, fL_Word *&word, int numparams, int begin, int end)
     144{
     145        SString wordn;
     146        int tokpos = 0;
     147        // if word name cannot be extracted, then return error
     148        if (!token.getNextToken(tokpos, wordn, '('))
     149        {
     150                return 1;
     151        }
     152        std::string wordname = fL_Builder::trimSpaces(wordn.c_str());
     153        // if word cannot be found in available words, then return error
     154        if (words.find(wordname) == words.end())
     155        {
     156                SString message = "Word '";
     157                message += wordname.c_str();
     158                message += "' in sequence does not exist";
     159                logMessage("fL_Builder", "createWord", LOG_ERROR, message.c_str());
     160                return 1;
     161        }
     162
     163        if (word) delete word;
     164        // create new word and assign parameters
     165        word = new fL_Word(false, begin, end);
     166
     167        *word = *words[wordname];
     168
     169        SString temp;
     170        temp = token.substr(tokpos);
     171        temp = temp.substr(0, temp.len() - 1);
     172
     173        // if word has parameters
     174        if (word->npar > 0)
     175        {
     176                // create ParamObject that will hold parameter data
     177                word->data = ParamObject::makeObject(word->tab);
     178                Param par(word->tab);
     179                par.select(word->data);
     180                par.setDefault();
     181                ParamInterface::LoadOptions opts;
     182
     183                // load parameters from string
     184                par.load(ParamInterface::FormatSingleLine, temp, &opts);
     185                for (int i = 0; i < par.getPropCount(); i++)
     186                {
     187                        SString t(par.id(i));
     188                        if (word->builtin && (t == SString("d") || t == SString(FL_PE_CONN_ATTR)))
     189                        {
     190                                word->parevals.push_back(NULL);
     191                        }
     192                        else
     193                        {
     194                                // create MathEvaluation object to check if string contained by
     195                                // parameter is valid
     196                                double tmp;
     197                                MathEvaluation *eval = NULL;
     198                                SString seq = par.getString(i);
     199                                // if string is empty, then evaluate this with 0
     200                                // if sequence could not be evaluated, then return error
     201                                if (seq.len() > 0)
     202                                {
     203                                        eval = new MathEvaluation(numparams);
     204                                        if (eval->evaluate(seq.c_str(), tmp) != 0)
     205                                        {
     206                                                SString message = "Word in sequence has invalid parameter:  ";
     207                                                message += temp;
     208                                                logMessage("fL_Builder", "createWord", LOG_ERROR, message.c_str());
     209                                                delete eval;
     210                                                delete word;
     211                                                word = NULL;
     212                                                return 1;
     213                                        }
     214                                }
     215                                word->parevals.push_back(eval);
     216                        }
     217                }
     218        }
     219        else if (word->npar == 0 && temp.len() > 0)
     220        {
     221                SString message = "Too many parameters for word:  ";
     222                message += token;
     223                logMessage("fL_Builder", "createWord", LOG_ERROR, message.c_str());
     224                delete word;
     225                word = NULL;
     226                return 1;
     227        }
     228        return 0;
     229}
     230
     231int fL_Builder::tokenize(SString sequence, std::list<fL_Word *> &result, int numparams, int begin, int end)
    137232{
    138233        int pos = 0;
     
    153248                if (token.indexOf("[", 0) != -1)
    154249                {
    155                         fL_Branch *word = new fL_Branch(fL_Branch::BranchType::OPEN);
     250                        fL_Branch *word = new fL_Branch(fL_Branch::BranchType::OPEN, begin, end);
    156251                        result.push_back(word);
    157252                        branchcount++;
     
    168263                                return 1;
    169264                        }
    170                         fL_Branch *word = new fL_Branch(fL_Branch::BranchType::CLOSE);
     265                        fL_Branch *word = new fL_Branch(fL_Branch::BranchType::CLOSE, begin, end);
    171266                        result.push_back(word);
    172267                        branchcount--;
    173268                        continue;
    174269                }
    175                 SString wordn;
    176                 int tokpos = 0;
    177                 // if word name cannot be extracted, then return error
    178                 if (!token.getNextToken(tokpos, wordn, '('))
     270                fL_Word *word = NULL;
     271                if (createWord(token, word, numparams, begin, end) != 0)
    179272                {
    180273                        SString message = "Error during parsing words sequence:  ";
     
    183276                        return 1;
    184277                }
    185                 std::string wordname = fL_Builder::trimSpaces(wordn.c_str());
    186                 // if word cannot be found in available words, then return error
    187                 if (words.find(wordname) == words.end())
    188                 {
    189                         SString message = "Word '";
    190                         message += wordname.c_str();
    191                         message += "' in sequence does not exist";
    192                         logMessage("fL_Builder", "tokenize", LOG_ERROR, message.c_str());
    193                         return 1;
    194                 }
    195 
    196                 // create new word and assign parameters
    197                 fL_Word *word = new fL_Word();
    198 
    199                 *word = *words[wordname];
    200 
    201                 // if word has parameters
    202                 if (word->npar > 0)
    203                 {
    204                         // create ParamObject that will hold parameter data
    205                         word->data = ParamObject::makeObject(word->tab);
    206                         Param par(word->tab);
    207                         par.select(word->data);
    208                         par.setDefault();
    209                         ParamInterface::LoadOptions opts;
    210 
    211                         SString temp;
    212                         temp = token.substr(tokpos);
    213                         temp = temp.substr(0, temp.len() - 1);
    214                         // load parameters from string
    215                         par.load(ParamInterface::FormatSingleLine, temp, &opts);
    216                         for (int i = 0; i < par.getPropCount(); i++)
    217                         {
    218                                 // create MathEvaluation object to check if string contained by
    219                                 // parameter is valid
    220                                 double tmp;
    221                                 MathEvaluation *eval = new MathEvaluation(numparams);
    222                                 SString seq = par.getString(i);
    223                                 // if string is empty, then evaluate this with 0
    224                                 if (seq.len() == 0)
    225                                 {
    226                                         eval->evaluate("0", tmp);
    227                                 }
    228                                 // if sequence could not be evaluated, then return error
    229                                 else if (eval->evaluate(seq.c_str(), tmp) != 0)
    230                                 {
    231                                         SString message = "Word in sequence has invalid parameter:  ";
    232                                         message += temp;
     278                if (word->name == "C")
     279                {
     280                        Param par(word->tab, word->data);
     281                        SString attr = par.getStringById(FL_PE_CONN_ATTR);
     282                        if (attr.indexOf("$t", 0) != -1)
     283                        {
     284                                logMessage("fL_Builder", "tokenize", LOG_ERROR, "Attractor definition cannot contain time variable");
     285                                delete word;
     286                                return 1;
     287
     288                        }
     289                        if (attr != "")
     290                        {
     291                                fL_Word *attrword = NULL;
     292                                if (createWord(attr, attrword, numparams, begin, end) != 0)
     293                                {
     294                                        SString message = "Error during parsing attractor word:  ";
     295                                        message += attr;
    233296                                        logMessage("fL_Builder", "tokenize", LOG_ERROR, message.c_str());
    234                                         delete eval;
    235297                                        delete word;
     298                                        if (attrword) delete attrword;
    236299                                        return 1;
    237300                                }
    238                                 word->parevals.push_back(eval);
     301                                if (attrword->builtin)
     302                                {
     303                                        logMessage("fL_Builder", "tokenize", LOG_ERROR, "Attractor words cannot be built-in");
     304                                        delete word;
     305                                        delete attrword;
     306                                        return 1;
     307                                }
     308                                delete attrword;
    239309                        }
    240310                }
     
    272342                parevals = src.parevals;
    273343
     344                builtin = src.builtin;
     345
    274346                data = NULL; // properties cannot be copied
    275347        }
     
    303375
    304376        builder->words[this->name.c_str()] = this;
     377        builder->wordnames.push_back(this->name.c_str());
    305378        return 0;
    306379}
     
    318391        *objpred = *builder->words[predecessor.c_str()];
    319392
     393        if (objpred->builtin)
     394        {
     395                logMessage("fL_Rule", "processDefinition", LOG_ERROR, "Builtin words cannot be predecessors");
     396                return 1;
     397        }
     398
    320399        // parse condition
    321400        if (condition != "")
    322401        {
     402                if (objpred->builtin && (objpred->name == "N" || objpred->name == "C"))
     403                {
     404                        logMessage("fL_Rule", "processDefinition", LOG_ERROR, "Rules with neuron/connection word predecessors cannot contain conditions");
     405                        return 1;
     406                }
    323407                std::string cond = condition.c_str();
    324408                condeval = new MathEvaluation(objpred->npar);
     
    340424        }
    341425
    342         if (builder->tokenize(successor, objsucc, objpred->npar) != 0)
     426        if (builder->tokenize(successor, objsucc, objpred->npar, begin, end) != 0)
    343427        {
    344428                logMessage("fL_Rule", "processDefinition", LOG_ERROR, "Unable to process successor sequence");
     
    353437{
    354438        // tokenize axiom
    355         if (tokenize(axiom, genotype, 0) != 0)
     439        if (tokenize(axiom, genotype, 0, begin, end) != 0)
    356440        {
    357441                logMessage("fL_Builder", "processDefinition", LOG_ERROR, "Unable to process axiom sequence");
     
    372456        switch (type)
    373457        {
    374         case fLElementType::TERM:
    375         {
    376                 tab = fL_word_paramtab;
    377                 obj = new fL_Word();
    378                 break;
    379         }
    380         case fLElementType::INFO:
    381         {
    382                 tab = fL_builder_paramtab;
    383                 obj = this;
    384                 break;
    385         }
    386         case fLElementType::RULE:
    387         {
    388                 tab = fL_rule_paramtab;
    389                 obj = new fL_Rule(begin, end);
    390                 break;
    391         }
    392         default:
    393                 break;
     458                case fLElementType::TERM:
     459                {
     460                        tab = fL_word_paramtab;
     461                        obj = new fL_Word();
     462                        break;
     463                }
     464                case fLElementType::INFO:
     465                {
     466                        tab = fL_builder_paramtab;
     467                        obj = this;
     468                        break;
     469                }
     470                case fLElementType::RULE:
     471                {
     472                        tab = fL_rule_paramtab;
     473                        obj = new fL_Rule(begin, end);
     474                        break;
     475                }
     476                default:
     477                        break;
    394478        }
    395479        Param par(tab);
     
    417501        stick->name = "S";
    418502        stick->npar = 8;
    419         for (int i = 0; i < PART_PROPS_COUNT; i++)
     503        for (int i = 0; i < FL_PART_PROPS_COUNT; i++)
    420504        {
    421505                stick->mut.addProperty(NULL, fL_part_names[i], "s", fL_part_fullnames[i], fL_part_fullnames[i], PARAM_CANOMITNAME, 0, -1);
    422506        }
    423507
    424         for (int i = 0; i < JOINT_PROPS_COUNT; i++)
     508        for (int i = 0; i < FL_JOINT_PROPS_COUNT; i++)
    425509        {
    426510                stick->mut.addProperty(NULL, fL_joint_names[i], "s", fL_joint_fullnames[i], fL_joint_fullnames[i], PARAM_CANOMITNAME, 0, -1);
     
    430514        stick->tab = ParamObject::makeParamTab((ParamInterface *)&stick->mut, 0, 0, stick->mut.firstMutableIndex());
    431515        words["S"] = stick;
     516        wordnames.push_back("S");
    432517
    433518        // neuron N
     
    435520        neuron->name = "N";
    436521        neuron->npar = 1;
    437         neuron->mut.addProperty(NULL, "d", "s", "details", "details", PARAM_CANOMITNAME, 0, -1);
     522        neuron->mut.addProperty(NULL, "d", "s", "details", "details", 0, 0, -1);
    438523        neuron->tab = ParamObject::makeParamTab((ParamInterface *)&neuron->mut, 0, 0, neuron->mut.firstMutableIndex());
    439524        words["N"] = neuron;
     525        wordnames.push_back("N");
    440526
    441527        // connection C
     
    443529        connection->name = "C";
    444530        connection->npar = 2;
    445         connection->mut.addProperty(NULL, "w", "s", "weight", "weight", PARAM_CANOMITNAME, 0, -1);
    446         connection->mut.addProperty(NULL, "attr", "s", "attractor", "connection attractor", PARAM_CANOMITNAME, 0, -1);
     531        connection->mut.addProperty(NULL, FL_PE_CONN_WEIGHT, "s", "weight", "weight", PARAM_CANOMITNAME, 0, -1);
     532        connection->mut.addProperty(NULL, FL_PE_CONN_ATTR, "s", "attractor", "connection attractor", PARAM_CANOMITNAME, 0, -1);
    447533        connection->tab = ParamObject::makeParamTab((ParamInterface *)&connection->mut, 0, 0, connection->mut.firstMutableIndex());
    448534        words["C"] = connection;
     535        wordnames.push_back("C");
    449536
    450537        // rotation objects
     
    463550        rotz->npar = 1;
    464551        rotz->processDefinition(this);
     552
     553        //fL_Branch *branch = new fL_Branch(fL_Branch::BranchType::OPEN, 0, 0);
     554        //branch->processDefinition(this);
     555
     556        builtincount = words.size();
    465557}
    466558
     
    521613                                return res;
    522614                        }
     615                        if (obj == this)
     616                        {
     617                                begin = lastpos;
     618                                end = pos - 1;
     619                        }
    523620                        res = obj->processDefinition(this);
    524621                        if (res != 0)
     
    546643                for (int i = 0; i < npar; i++)
    547644                {
     645                        SString t(par.id(i));
    548646                        if (parevals[i] != NULL)
    549647                        {
     
    667765        }
    668766        getStringifiedProducts();
     767        removeRedundantRules();
    669768        Param par(fL_builder_paramtab);
    670769        fL_Builder *obj = new fL_Builder();
     
    681780}
    682781
    683 int fL_Rule::deploy(fL_Word *in, std::list<fL_Word *>::iterator &it, std::list<fL_Word *> &genotype, double currtime)
     782int fL_Rule::deploy(fL_Builder *builder, fL_Word *in, std::list<fL_Word *>::iterator &it, double currtime)
    684783{
    685784        // if predecessor and given word differ, then rule is not applicable
     
    720819
    721820        // remove predecessor word from genotype and replace it with successor
    722         it = genotype.erase(it);
     821        it = builder->genotype.erase(it);
    723822        for (std::list<fL_Word *>::iterator word = objsucc.begin(); word != objsucc.end(); word++)
    724823        {
    725824                // create new word and copy properties from word definition
    726                 fL_Word *nword = new fL_Word();
     825                fL_Word *nword = new fL_Word(false, begin, end);
    727826                *nword = **word;
    728827                // store information about when word has been created
     
    735834                // calculate word parameters and store MathEvaluation objects for further
    736835                // time manipulations.
     836                Param par((*word)->tab, (*word)->data);
     837                Param npar(nword->tab, nword->data);
    737838                for (int q = 0; q < nword->npar; q++)
    738839                {
    739840                        if ((*word)->parevals[q] == NULL)
    740841                        {
    741                                 MathEvaluation *ev = new MathEvaluation(0);
    742                                 ev->convertString("0");
    743                                 nword->parevals.push_back(ev);
     842                                if ((*word)->builtin && (strcmp(npar.id(q), "d") == 0))
     843                                {
     844                                        SString t = par.getString(q);
     845                                        npar.setString(q, t);
     846                                        nword->parevals.push_back(NULL);
     847                                }
     848                                if ((*word)->builtin && (strcmp(npar.id(q), FL_PE_CONN_ATTR) == 0))
     849                                {
     850                                        SString t = par.getString(q);
     851                                        if (t.len() > 0)
     852                                        {
     853                                                fL_Word *attrword = NULL;
     854                                                builder->createWord(t, attrword, in->npar, begin, end);
     855                                                for (int j = 0; j < attrword->npar; j++)
     856                                                {
     857                                                        if (attrword->parevals[j])
     858                                                        {
     859                                                                for (int i = 0; i < in->npar; i++)
     860                                                                {
     861                                                                        attrword->parevals[j]->modifyVariable(i, inwordvalues[i]);
     862                                                                }
     863                                                        }
     864                                                }
     865                                                SString res = attrword->stringify(false);
     866                                                npar.setString(q, res);
     867                                                nword->parevals.push_back(NULL);
     868                                                delete attrword;
     869                                        }
     870                                }
     871                                else
     872                                {
     873                                        //MathEvaluation *ev = new MathEvaluation(0);
     874                                        //ev->convertString("0");
     875                                        //nword->parevals.push_back(ev);
     876                                        nword->parevals.push_back(NULL);
     877                                }
    744878                        }
    745879                        else
     
    757891                        }
    758892                }
    759                 genotype.insert(it, nword);
     893                builder->genotype.insert(it, nword);
    760894        }
    761895        delete[] inwordvalues;
     
    773907                for (fL_Rule * rule : rules)
    774908                {
    775                         if (rule->deploy((*word), word, genotype, currtime) == 0)
     909                        if (rule->deploy(this, (*word), word, currtime) == 0)
    776910                        {
    777911                                deployed = true;
     
    806940        Param par(stickword->tab, stickword->data);
    807941        Param ppar = part->properties();
    808         for (int i = 0; i < PART_PROPS_COUNT; i++)
    809         {
    810                 double partprop;
     942        for (int i = 0; i < FL_PART_PROPS_COUNT; i++)
     943        {
     944                double mn, mx, df;
     945                ppar.getMinMaxDouble(ppar.findId(fL_part_names[i]), mn, mx, df);
    811946                double currval;
    812                 if (!ExtValue::parseDouble(par.getStringById(fL_part_names[i]).c_str(), currval, false))
    813                 {
    814                         logMessage("fL_Builder", "alterPartProperties", LOG_ERROR,
    815                                 "Error parsing word parameter");
    816                         return 1;
    817                 }
    818                 partprop = (ppar.getDoubleById(fL_part_names[i]) * alterationcount +
    819                         currval) / (alterationcount + 1.0);
     947                if (!stickword->parevals[i])
     948                {
     949                        currval = df;
     950                }
     951                else
     952                {
     953                        stickword->parevals[i]->evaluateRPN(currval);
     954                        currval = sigmoidTransform(currval, mn, mx);
     955                }
     956                double partprop = (ppar.getDoubleById(fL_part_names[i]) * alterationcount +
     957                                currval) / (alterationcount + 1.0);
    820958                ppar.setDoubleById(fL_part_names[i], partprop);
    821959        }
     
    823961}
    824962
    825 bool fL_Word::operator==(const fL_Word& other) const
    826 {
    827         if (name == other.name) return false;
    828         if (npar == other.npar) return false;
     963double fL_Word::distance(fL_Word *right)
     964{
     965        if (name != right->name || npar != right->npar)
     966        {
     967                return -1;
     968        }
     969        double distance = 0;
    829970        for (int i = 0; i < npar; i++)
    830971        {
    831                 if (parevals[i] && other.parevals[i])
    832                 {
    833                         double first;
    834                         double second;
    835                         parevals[i]->evaluateRPN(first);
    836                         other.parevals[i]->evaluateRPN(second);
    837                         if (first != second)
    838                         {
    839                                 return false;
    840                         }
    841                 }
    842                 else
    843                 {
    844                         return false;
    845                 }
    846         }
    847         return true;
    848 }
    849 
    850 void fL_Builder::findNext(fL_Word *word, std::list<fL_Word *> genotype, std::list<fL_Word *>::iterator &it)
    851 {
    852         int rightdist = 0;
    853         std::list<fL_Word *>::iterator iter(it);
    854         for (; iter != genotype.end(); iter++)
    855         {
    856                 if (*word == **iter)
    857                 {
    858                         break;
    859                 }
    860                 rightdist++;
    861         }
    862         int leftdist = 0;
    863         std::list<fL_Word *>::reverse_iterator riter(it);
    864         for (; riter != genotype.rend(); riter++)
    865         {
    866                 if (*word == **riter)
    867                 {
    868                         break;
    869                 }
    870                 leftdist++;
    871         }
    872         if (iter == genotype.end())
    873         {
    874                 it = riter.base();
    875         }
    876         else if (riter == genotype.rend())
    877         {
    878                 it = iter;
    879         }
    880         else if (leftdist < rightdist)
    881         {
    882                 it = riter.base();
     972                double l = 0;
     973                double r = 0;
     974                if (parevals[i]) parevals[i]->evaluateRPN(l);
     975                if (right->parevals[i]) right->parevals[i]->evaluateRPN(r);
     976                distance += (l - r) * (l - r);
     977        }
     978        return sqrt(distance);
     979}
     980
     981Neuro *fL_Builder::findInputNeuron(std::pair<std::list<fL_Word *>::iterator, Neuro *> currneu, fL_Word *attractor)
     982{
     983        if (!attractor)
     984        {
     985                std::list<fL_Word *>::reverse_iterator riter(currneu.first);
     986                std::list<fL_Word *>::iterator iter(currneu.first);
     987                iter++;
     988                while (riter != genotype.rend() || iter != genotype.end())
     989                {
     990                        if (iter != genotype.end())
     991                        {
     992                                if ((*iter)->name == "N" && (*iter)->bodyelementpointer != currneu.second)
     993                                {
     994                                        return (Neuro *)(*iter)->bodyelementpointer;
     995                                }
     996                                iter++;
     997                        }
     998                        if (riter != genotype.rend())
     999                        {
     1000                                if ((*riter)->name == "N" && (*riter)->bodyelementpointer != currneu.second)
     1001                                {
     1002                                        return (Neuro *)(*riter)->bodyelementpointer;
     1003                                }
     1004                                riter++;
     1005                        }
     1006                }
     1007                return NULL;
    8831008        }
    8841009        else
    8851010        {
    886                 it = iter;
    887         }
    888 }
    889 
    890 Neuro *fL_Builder::findInputNeuron(std::list<fL_Word *> genotype, std::list<fL_Word *>::iterator it, fL_Word *attractor)
    891 {
    892         if (!attractor)
    893         {
    894                 attractor = new fL_Word();
    895                 *attractor = *(*it);
    896                 attractor->data = NULL;
    897                 // TODO implement
     1011                double mindistance = -1;
     1012                std::list<fL_Word *>::iterator minit = genotype.end();
     1013                for (std::list<fL_Word *>::iterator it = genotype.begin(); it != genotype.end(); it++)
     1014                {
     1015                        double currdist = attractor->distance((*it));
     1016                        if (currdist != -1 && (currdist < mindistance || mindistance == -1))
     1017                        {
     1018                                mindistance = currdist;
     1019                                minit = it;
     1020                        }
     1021                }
     1022                if (minit != genotype.end())
     1023                {
     1024                        for (; minit != genotype.end(); minit++)
     1025                        {
     1026                                if ((*minit)->name == "N" && (*minit)->bodyelementpointer)
     1027                                {
     1028                                        Neuro *n = (Neuro *)(*minit)->bodyelementpointer;
     1029                                        if (n->getClass()->getPreferredOutput() != 0)
     1030                                        {
     1031                                                return n;
     1032                                        }
     1033                                }
     1034                        }
     1035                }
    8981036        }
    8991037        return NULL;
    9001038}
    9011039
    902 int fL_Builder::developModel(Model &model)
    903 {
    904         // TODO implement
     1040double fL_Builder::sigmoidTransform(double input, double mn, double mx)
     1041{
     1042        return mn + (mx - mn) * (1.0 / (1.0 + exp(-input)));
     1043}
     1044
     1045int fL_Builder::buildModelFromSequence(Model *model)
     1046{
    9051047        fL_State currstate;
    9061048        std::unordered_map<Part *, double> counters;
     
    9231065                                                firstpart->p = Pt3D_0;
    9241066                                                counters[firstpart] = 0;
    925                                                 model.addPart(firstpart);
     1067                                                model->addPart(firstpart);
     1068                                                if (using_mapping) firstpart->addMapping(IRange(word->begin, word->end));
    9261069                                        }
    9271070                                        currstate.currpart = firstpart;
     
    9411084                                Param par(word->tab, word->data);
    9421085                                double length;
    943                                 if (!ExtValue::parseDouble(par.getStringById("l").c_str(), length, false))
    944                                 {
    945                                         delete newpart;
    946                                         logMessage("fL_Builder", "alterPartProperties", LOG_ERROR,
    947                                                 "Error parsing word parameter");
    948                                         return 1;
     1086                                if (!word->parevals[FL_PART_PROPS_COUNT + FL_JOINT_PROPS_COUNT])
     1087                                {
     1088                                        length = FL_DEFAULT_LENGTH; // default length value
     1089                                }
     1090                                else
     1091                                {
     1092                                        double parsedval = 0.0;
     1093                                        if (word->parevals[FL_PART_PROPS_COUNT + FL_JOINT_PROPS_COUNT]->evaluateRPN(parsedval) != 0)
     1094                                        {
     1095                                                delete newpart;
     1096                                                logMessage("fL_Builder", "developModel", LOG_ERROR,
     1097                                                                "Error parsing word parameter");
     1098                                                return 1;
     1099                                        }
     1100                                        length = sigmoidTransform(parsedval, FL_MINIMAL_LENGTH, FL_MAXIMAL_LENGTH);
    9491101                                }
    9501102                                newpart->p = currstate.currpart->p + currstate.direction * length;
    9511103                                counters[newpart] += 1;
    952                                 model.addPart(newpart);
    953 
     1104                                model->addPart(newpart);
     1105                                if (using_mapping) newpart->addMapping(IRange(word->begin, word->end));
    9541106                                Joint *newjoint = new Joint();
    9551107                                newjoint->attachToParts(currstate.currpart, newpart);
    9561108
    9571109                                Param jpar = newjoint->properties();
    958                                 for (int i = 0; i < JOINT_PROPS_COUNT; i++)
    959                                 {
     1110                                for (int i = 0; i < FL_JOINT_PROPS_COUNT; i++)
     1111                                {
     1112                                        double mn, mx, df;
     1113                                        jpar.getMinMaxDouble(jpar.findId(fL_joint_names[i]), mn, mx, df);
    9601114                                        double jointprop;
    961                                         if (!ExtValue::parseDouble(par.getStringById(fL_joint_names[i]).c_str(), jointprop, false))
     1115                                        if (!word->parevals[FL_PART_PROPS_COUNT + i])
    9621116                                        {
    963                                                 logMessage("fL_Builder", "developModel", LOG_ERROR,
    964                                                         "Error parsing word parameter");
    965                                                 delete newjoint;
    966                                                 return 1;
     1117                                                jointprop = df; // assign default value
     1118                                        }
     1119                                        else
     1120                                        {
     1121                                                if (word->parevals[FL_PART_PROPS_COUNT + i]->evaluateRPN(jointprop) != 0)
     1122                                                {
     1123                                                        logMessage("fL_Builder", "developModel", LOG_ERROR,
     1124                                                                        "Error parsing word parameter");
     1125                                                        delete newjoint;
     1126                                                        return 1;
     1127                                                }
     1128                                                jointprop = sigmoidTransform(jointprop, mn, mx);
    9671129                                        }
    9681130                                        jpar.setDoubleById(fL_joint_names[i], jointprop);
    9691131                                }
    970                                 model.addJoint(newjoint);
     1132                                model->addJoint(newjoint);
     1133                                if (using_mapping) newjoint->addMapping(IRange(word->begin, word->end));
    9711134                                currstate.currpart = newpart;
    9721135                        }
     
    9751138                                Param npar(word->tab, word->data);
    9761139                                Neuro *neu = new Neuro();
    977                                 neu->setDetails(npar.getStringById("d"));
     1140                                SString details = npar.getStringById("d");
     1141                                if (details == "")
     1142                                {
     1143                                        details = "N";
     1144                                }
     1145                                neu->setDetails(details);
    9781146                                if (!neu->getClass())
    9791147                                {
     
    9821150                                        return 1;
    9831151                                }
    984                                 model.addNeuro(neu);
    985                                 currstate.currneuron = neu;
     1152                                model->addNeuro(neu);
     1153                                if (using_mapping) neu->addMapping(IRange(word->begin, word->end));
     1154                                if (neu->getClass()->getPreferredInputs() != 0)
     1155                                {
     1156                                        currstate.currneuron = neu;
     1157                                }
     1158                                word->bodyelementpointer = neu;
    9861159                        }
    9871160                        else if (word->name == "C")
    9881161                        {
    989                                 connsbuffer.push_back({ w, currstate.currneuron });
     1162                                connsbuffer.push_back({w, currstate.currneuron});
    9901163                        }
    9911164                        else if (word->name.startsWith("rot"))
    9921165                        {
    993                                 Orient rotmatrix;
     1166                                Orient rotmatrix = Orient_1;
    9941167                                double rot;
    995                                 if (word->parevals[0]->evaluateRPN(rot) != 0)
    996                                 {
    997                                         logMessage("fL_Builder", "developModel", LOG_ERROR, "Error parsing neuron class");
     1168                                if (!word->parevals[0])
     1169                                {
     1170                                        rot = 0;
     1171                                }
     1172                                else if (word->parevals[0]->evaluateRPN(rot) != 0)
     1173                                {
     1174                                        logMessage("fL_Builder", "developModel", LOG_ERROR, "Error parsing rotation word");
    9981175                                        return 1;
    9991176                                }
     1177
     1178                                rot = sigmoidTransform(rot, -M_PI, M_PI);
     1179
    10001180                                if (word->name == "rotX")
    10011181                                {
    1002                                         rotmatrix.rotate(Pt3D(rot, 0.0, 0.0));
     1182                                        rotmatrix.rotate(Pt3D(rot,0,0));
    10031183                                }
    10041184                                else if (word->name == "rotY")
    10051185                                {
    1006                                         rotmatrix.rotate(Pt3D(0.0, rot, 0.0));
     1186                                        rotmatrix.rotate(Pt3D(0,rot,0));
    10071187                                }
    10081188                                else if (word->name == "rotZ")
    10091189                                {
    1010                                         rotmatrix.rotate(Pt3D(0.0, 0.0, rot));
     1190                                        rotmatrix.rotate(Pt3D(0,0,rot));
    10111191                                }
    10121192                                currstate.direction = rotmatrix.transform(currstate.direction);
     1193                                currstate.direction.normalize();
    10131194                        }
    10141195                        else if (word->name == "[")
     
    10251206
    10261207        // connections need
    1027         //      for (std::pair<std::list<fL_Word *>::iterator, Neuro *> conndata : connsbuffer)
    1028         //      {
    1029         //
    1030         //      }
     1208        // std::pair<std::list<fL_Word *>::iterator, Neuro *> conndata : connsbuffer
     1209        for (unsigned int i = 0; i < connsbuffer.size(); i++)
     1210        {
     1211                if (connsbuffer[i].second == NULL ||
     1212                                (connsbuffer[i].second->getClass()->getPreferredInputs() != -1 &&
     1213                                connsbuffer[i].second->getInputCount() >=
     1214                                connsbuffer[i].second->getClass()->getPreferredInputs()))
     1215                {
     1216                        // since connections are separated entities from neurons, it may happen
     1217                        // that there will be no neuron to connect to
     1218                        // logMessage("fL_Builder", "developModel", LOG_DEBUG, "Connection could not be established");
     1219                }
     1220                else
     1221                {
     1222                        Param par((*connsbuffer[i].first)->tab, (*connsbuffer[i].first)->data);
     1223                        SString attr = par.getStringById(FL_PE_CONN_ATTR);
     1224                        fL_Word *attractor = NULL;
     1225                        if (attr.len() > 0)
     1226                        {
     1227                                createWord(attr, attractor, 0, (*connsbuffer[i].first)->begin, (*connsbuffer[i].first)->end);
     1228                        }
     1229                        Neuro *neu = findInputNeuron(connsbuffer[i], attractor);
     1230                        double weight = 0.0;
     1231                        if ((*connsbuffer[i].first)->parevals[0])
     1232                        {
     1233                                if ((*connsbuffer[i].first)->parevals[0]->evaluateRPN(weight) != 0)
     1234                                {
     1235                                        logMessage("fL_Builder", "developModel", LOG_ERROR,
     1236                                                        "Error parsing word parameter");
     1237                                        delete attractor;
     1238                                        return 1;
     1239                                }
     1240                        }
     1241                        if (neu)
     1242                        {
     1243                                connsbuffer[i].second->addInput(neu, weight);
     1244                                if (using_mapping) neu->addMapping(
     1245                                                IRange((*connsbuffer[i].first)->begin,
     1246                                                                (*connsbuffer[i].first)->end));
     1247                        }
     1248                        else
     1249                        {
     1250                                connsbuffer[i].second->addInput(connsbuffer[i].second, weight);
     1251                                if (using_mapping) neu->addMapping(
     1252                                                IRange((*connsbuffer[i].first)->begin,
     1253                                                                (*connsbuffer[i].first)->end));
     1254                        }
     1255                        delete attractor;
     1256                }
     1257        }
    10311258        return 0;
    10321259}
    10331260
    1034 int fL_Builder::develop()
    1035 {
    1036         Model m;
     1261void fL_Builder::clearModelElements(Model *m)
     1262{
     1263        for (int i = 0; i < m->getJointCount(); i++)
     1264        {
     1265                m->removeJoint(i, 0);
     1266        }
     1267        for (int i = 0; i < m->getNeuroCount(); i++)
     1268        {
     1269                m->removeNeuro(i, true);
     1270        }
     1271        for (int i = 0; i < m->getNeuroCount(); i++)
     1272        {
     1273                m->removePart(i, 0, 0);
     1274        }
     1275        m->clearMap();
     1276}
     1277
     1278Model* fL_Builder::developModel(double &neededtime)
     1279{
    10371280        double curriter = 0;
    10381281        double timestamp = 1.0 / numckp;
    10391282        double t = 0;
    1040         for (; t <= time; t += timestamp)
     1283        Model *m = new Model();
     1284        m->open(using_checkpoints);
     1285        bool wordsexceeded = false;
     1286        for (; t <= time; t+= timestamp)
    10411287        {
    10421288                alterTimedProperties(t); // always alter timed properties in the beginning
     
    10451291                {
    10461292                        iterate(t);
    1047                         curriter += 1.0;
    1048                 }
    1049         }
     1293                        curriter+=1.0;
     1294                }
     1295                if (using_checkpoints)
     1296                {
     1297                        clearModelElements(m);
     1298                        if (buildModelFromSequence(m) != 0)
     1299                        {
     1300                                delete m;
     1301                                return NULL;
     1302                        }
     1303                        m->checkpoint();
     1304                }
     1305                if (maxwords != -1 && genotype.size() > (unsigned int)maxwords)
     1306                {
     1307                        wordsexceeded = true;
     1308                        break;
     1309                }
     1310        }
     1311
     1312        if (wordsexceeded)
     1313        {
     1314                neededtime = t;
     1315        }
     1316        else
     1317        {
     1318                neededtime = time;
     1319        }
     1320
    10501321        // if exact time of development was not reached due to floating point errors,
    10511322        // then alter timed properties
     
    10541325                alterTimedProperties(time);
    10551326        }
    1056         return 0;
    1057 }
     1327        clearModelElements(m);
     1328        if (buildModelFromSequence(m) != 0)
     1329        {
     1330                delete m;
     1331                return NULL;
     1332        }
     1333        if (using_checkpoints)
     1334        {
     1335                m->checkpoint();
     1336        }
     1337        m->close();
     1338        return m;
     1339}
     1340
     1341int fL_Builder::countSticksInSequence(std::list<fL_Word *> sequence)
     1342{
     1343        int count = 0;
     1344        for (std::list<fL_Word *>::iterator it = sequence.begin(); it != sequence.end(); it++)
     1345        {
     1346                if ((*it)->builtin && (*it)->name == "S")
     1347                {
     1348                        count++;
     1349                }
     1350        }
     1351        return count;
     1352}
     1353
     1354int fL_Builder::countDefinedWords()
     1355{
     1356        return words.size() - builtincount;
     1357}
     1358
     1359int fL_Builder::countWordsInLSystem()
     1360{
     1361        int count = genotype.size();
     1362        for (fL_Rule *rul: rules)
     1363        {
     1364                count += rul->objsucc.size();
     1365        }
     1366        count += words.size();
     1367        return count;
     1368}
     1369
     1370void fL_Builder::removeRedundantRules()
     1371{
     1372        for (std::vector<fL_Rule *>::iterator it = rules.begin();
     1373                        it != rules.end(); it++)
     1374        {
     1375                std::vector<fL_Rule *>::iterator it2 = it;
     1376                it2++;
     1377                while (it2 != rules.end())
     1378                {
     1379                        bool todelete = false;
     1380                        if ((*it)->objpred->name == (*it2)->objpred->name)
     1381                        {
     1382                                if ((*it)->condeval == NULL && (*it2)->condeval == NULL)
     1383                                {
     1384                                        todelete = true;
     1385                                }
     1386                                else if ((*it)->condeval == NULL && (*it2)->condeval != NULL)
     1387                                {
     1388                                        std::iter_swap(it, it2);
     1389                                }
     1390                                else if ((*it)->condeval != NULL && (*it2)->condeval != NULL)
     1391                                {
     1392                                        if ((*it)->condeval->getStringifiedRPN() ==
     1393                                                        (*it2)->condeval->getStringifiedRPN())
     1394                                        {
     1395                                                todelete = true;
     1396                                        }
     1397                                }
     1398                        }
     1399                        if (todelete)
     1400                        {
     1401                                delete (*it2);
     1402                                it2 = rules.erase(it2);
     1403                        }
     1404                        else
     1405                        {
     1406                                it2++;
     1407                        }
     1408                }
     1409        }
     1410}
Note: See TracChangeset for help on using the changeset viewer.