Changeset 797 for cpp/frams/genetics/fL/fL_general.cpp
- Timestamp:
- 06/06/18 01:45:18 (6 years ago)
- 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 1 5 #include <algorithm> 2 6 #include <stack> 3 7 #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 11 const char *fL_part_names[FL_PART_PROPS_COUNT] = { "dn", "fr", "ing", "as" }; 12 const char *fL_part_fullnames[FL_PART_PROPS_COUNT] = { "details", "friction", "ingestion", "assimilation" }; 13 14 const char *fL_joint_names[FL_JOINT_PROPS_COUNT] = { "stif", "rotstif", "stam" }; 15 const char *fL_joint_fullnames[FL_JOINT_PROPS_COUNT] = { "stiffness", "rotation stiffness", "stamina" }; 10 16 11 17 #define FIELDSTRUCT fL_Word … … 14 20 { "Word", 1, 2, "w" }, 15 21 { "name", 0, PARAM_CANOMITNAME, "word name", "s", FIELD(name), }, 16 { "npar", 0, PARAM_CANOMITNAME, "number of parameters", "d 0 30", FIELD(npar), },22 { "npar", 0, PARAM_CANOMITNAME, "number of parameters", "d 0 " FL_MAXPARAMS " 0", FIELD(npar), }, 17 23 { 0, 0, 0, } 18 24 }; … … 23 29 { 24 30 { "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), }, 28 34 { 0, 0, 0, } 29 35 }; … … 33 39 ParamEntry fL_builder_paramtab[] = 34 40 { 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,} 40 47 }; 41 48 #undef FIELDSTRUCT … … 134 141 } 135 142 136 int fL_Builder::tokenize(SString sequence, std::list<fL_Word *> &result, int numparams) 143 int 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 231 int fL_Builder::tokenize(SString sequence, std::list<fL_Word *> &result, int numparams, int begin, int end) 137 232 { 138 233 int pos = 0; … … 153 248 if (token.indexOf("[", 0) != -1) 154 249 { 155 fL_Branch *word = new fL_Branch(fL_Branch::BranchType::OPEN );250 fL_Branch *word = new fL_Branch(fL_Branch::BranchType::OPEN, begin, end); 156 251 result.push_back(word); 157 252 branchcount++; … … 168 263 return 1; 169 264 } 170 fL_Branch *word = new fL_Branch(fL_Branch::BranchType::CLOSE );265 fL_Branch *word = new fL_Branch(fL_Branch::BranchType::CLOSE, begin, end); 171 266 result.push_back(word); 172 267 branchcount--; 173 268 continue; 174 269 } 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) 179 272 { 180 273 SString message = "Error during parsing words sequence: "; … … 183 276 return 1; 184 277 } 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; 233 296 logMessage("fL_Builder", "tokenize", LOG_ERROR, message.c_str()); 234 delete eval;235 297 delete word; 298 if (attrword) delete attrword; 236 299 return 1; 237 300 } 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; 239 309 } 240 310 } … … 272 342 parevals = src.parevals; 273 343 344 builtin = src.builtin; 345 274 346 data = NULL; // properties cannot be copied 275 347 } … … 303 375 304 376 builder->words[this->name.c_str()] = this; 377 builder->wordnames.push_back(this->name.c_str()); 305 378 return 0; 306 379 } … … 318 391 *objpred = *builder->words[predecessor.c_str()]; 319 392 393 if (objpred->builtin) 394 { 395 logMessage("fL_Rule", "processDefinition", LOG_ERROR, "Builtin words cannot be predecessors"); 396 return 1; 397 } 398 320 399 // parse condition 321 400 if (condition != "") 322 401 { 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 } 323 407 std::string cond = condition.c_str(); 324 408 condeval = new MathEvaluation(objpred->npar); … … 340 424 } 341 425 342 if (builder->tokenize(successor, objsucc, objpred->npar ) != 0)426 if (builder->tokenize(successor, objsucc, objpred->npar, begin, end) != 0) 343 427 { 344 428 logMessage("fL_Rule", "processDefinition", LOG_ERROR, "Unable to process successor sequence"); … … 353 437 { 354 438 // tokenize axiom 355 if (tokenize(axiom, genotype, 0 ) != 0)439 if (tokenize(axiom, genotype, 0, begin, end) != 0) 356 440 { 357 441 logMessage("fL_Builder", "processDefinition", LOG_ERROR, "Unable to process axiom sequence"); … … 372 456 switch (type) 373 457 { 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; 394 478 } 395 479 Param par(tab); … … 417 501 stick->name = "S"; 418 502 stick->npar = 8; 419 for (int i = 0; i < PART_PROPS_COUNT; i++)503 for (int i = 0; i < FL_PART_PROPS_COUNT; i++) 420 504 { 421 505 stick->mut.addProperty(NULL, fL_part_names[i], "s", fL_part_fullnames[i], fL_part_fullnames[i], PARAM_CANOMITNAME, 0, -1); 422 506 } 423 507 424 for (int i = 0; i < JOINT_PROPS_COUNT; i++)508 for (int i = 0; i < FL_JOINT_PROPS_COUNT; i++) 425 509 { 426 510 stick->mut.addProperty(NULL, fL_joint_names[i], "s", fL_joint_fullnames[i], fL_joint_fullnames[i], PARAM_CANOMITNAME, 0, -1); … … 430 514 stick->tab = ParamObject::makeParamTab((ParamInterface *)&stick->mut, 0, 0, stick->mut.firstMutableIndex()); 431 515 words["S"] = stick; 516 wordnames.push_back("S"); 432 517 433 518 // neuron N … … 435 520 neuron->name = "N"; 436 521 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); 438 523 neuron->tab = ParamObject::makeParamTab((ParamInterface *)&neuron->mut, 0, 0, neuron->mut.firstMutableIndex()); 439 524 words["N"] = neuron; 525 wordnames.push_back("N"); 440 526 441 527 // connection C … … 443 529 connection->name = "C"; 444 530 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); 447 533 connection->tab = ParamObject::makeParamTab((ParamInterface *)&connection->mut, 0, 0, connection->mut.firstMutableIndex()); 448 534 words["C"] = connection; 535 wordnames.push_back("C"); 449 536 450 537 // rotation objects … … 463 550 rotz->npar = 1; 464 551 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(); 465 557 } 466 558 … … 521 613 return res; 522 614 } 615 if (obj == this) 616 { 617 begin = lastpos; 618 end = pos - 1; 619 } 523 620 res = obj->processDefinition(this); 524 621 if (res != 0) … … 546 643 for (int i = 0; i < npar; i++) 547 644 { 645 SString t(par.id(i)); 548 646 if (parevals[i] != NULL) 549 647 { … … 667 765 } 668 766 getStringifiedProducts(); 767 removeRedundantRules(); 669 768 Param par(fL_builder_paramtab); 670 769 fL_Builder *obj = new fL_Builder(); … … 681 780 } 682 781 683 int fL_Rule::deploy(fL_ Word *in, std::list<fL_Word *>::iterator &it, std::list<fL_Word *> &genotype, double currtime)782 int fL_Rule::deploy(fL_Builder *builder, fL_Word *in, std::list<fL_Word *>::iterator &it, double currtime) 684 783 { 685 784 // if predecessor and given word differ, then rule is not applicable … … 720 819 721 820 // remove predecessor word from genotype and replace it with successor 722 it = genotype.erase(it);821 it = builder->genotype.erase(it); 723 822 for (std::list<fL_Word *>::iterator word = objsucc.begin(); word != objsucc.end(); word++) 724 823 { 725 824 // 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); 727 826 *nword = **word; 728 827 // store information about when word has been created … … 735 834 // calculate word parameters and store MathEvaluation objects for further 736 835 // time manipulations. 836 Param par((*word)->tab, (*word)->data); 837 Param npar(nword->tab, nword->data); 737 838 for (int q = 0; q < nword->npar; q++) 738 839 { 739 840 if ((*word)->parevals[q] == NULL) 740 841 { 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 } 744 878 } 745 879 else … … 757 891 } 758 892 } 759 genotype.insert(it, nword);893 builder->genotype.insert(it, nword); 760 894 } 761 895 delete[] inwordvalues; … … 773 907 for (fL_Rule * rule : rules) 774 908 { 775 if (rule->deploy( (*word), word, genotype, currtime) == 0)909 if (rule->deploy(this, (*word), word, currtime) == 0) 776 910 { 777 911 deployed = true; … … 806 940 Param par(stickword->tab, stickword->data); 807 941 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); 811 946 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); 820 958 ppar.setDoubleById(fL_part_names[i], partprop); 821 959 } … … 823 961 } 824 962 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; 963 double fL_Word::distance(fL_Word *right) 964 { 965 if (name != right->name || npar != right->npar) 966 { 967 return -1; 968 } 969 double distance = 0; 829 970 for (int i = 0; i < npar; i++) 830 971 { 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 981 Neuro *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; 883 1008 } 884 1009 else 885 1010 { 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 } 898 1036 } 899 1037 return NULL; 900 1038 } 901 1039 902 int fL_Builder::developModel(Model &model) 903 { 904 // TODO implement 1040 double fL_Builder::sigmoidTransform(double input, double mn, double mx) 1041 { 1042 return mn + (mx - mn) * (1.0 / (1.0 + exp(-input))); 1043 } 1044 1045 int fL_Builder::buildModelFromSequence(Model *model) 1046 { 905 1047 fL_State currstate; 906 1048 std::unordered_map<Part *, double> counters; … … 923 1065 firstpart->p = Pt3D_0; 924 1066 counters[firstpart] = 0; 925 model.addPart(firstpart); 1067 model->addPart(firstpart); 1068 if (using_mapping) firstpart->addMapping(IRange(word->begin, word->end)); 926 1069 } 927 1070 currstate.currpart = firstpart; … … 941 1084 Param par(word->tab, word->data); 942 1085 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); 949 1101 } 950 1102 newpart->p = currstate.currpart->p + currstate.direction * length; 951 1103 counters[newpart] += 1; 952 model .addPart(newpart);953 1104 model->addPart(newpart); 1105 if (using_mapping) newpart->addMapping(IRange(word->begin, word->end)); 954 1106 Joint *newjoint = new Joint(); 955 1107 newjoint->attachToParts(currstate.currpart, newpart); 956 1108 957 1109 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); 960 1114 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]) 962 1116 { 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); 967 1129 } 968 1130 jpar.setDoubleById(fL_joint_names[i], jointprop); 969 1131 } 970 model.addJoint(newjoint); 1132 model->addJoint(newjoint); 1133 if (using_mapping) newjoint->addMapping(IRange(word->begin, word->end)); 971 1134 currstate.currpart = newpart; 972 1135 } … … 975 1138 Param npar(word->tab, word->data); 976 1139 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); 978 1146 if (!neu->getClass()) 979 1147 { … … 982 1150 return 1; 983 1151 } 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; 986 1159 } 987 1160 else if (word->name == "C") 988 1161 { 989 connsbuffer.push_back({ w, currstate.currneuron});1162 connsbuffer.push_back({w, currstate.currneuron}); 990 1163 } 991 1164 else if (word->name.startsWith("rot")) 992 1165 { 993 Orient rotmatrix ;1166 Orient rotmatrix = Orient_1; 994 1167 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"); 998 1175 return 1; 999 1176 } 1177 1178 rot = sigmoidTransform(rot, -M_PI, M_PI); 1179 1000 1180 if (word->name == "rotX") 1001 1181 { 1002 rotmatrix.rotate(Pt3D(rot, 0.0, 0.0));1182 rotmatrix.rotate(Pt3D(rot,0,0)); 1003 1183 } 1004 1184 else if (word->name == "rotY") 1005 1185 { 1006 rotmatrix.rotate(Pt3D(0 .0, rot, 0.0));1186 rotmatrix.rotate(Pt3D(0,rot,0)); 1007 1187 } 1008 1188 else if (word->name == "rotZ") 1009 1189 { 1010 rotmatrix.rotate(Pt3D(0 .0, 0.0,rot));1190 rotmatrix.rotate(Pt3D(0,0,rot)); 1011 1191 } 1012 1192 currstate.direction = rotmatrix.transform(currstate.direction); 1193 currstate.direction.normalize(); 1013 1194 } 1014 1195 else if (word->name == "[") … … 1025 1206 1026 1207 // 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 } 1031 1258 return 0; 1032 1259 } 1033 1260 1034 int fL_Builder::develop() 1035 { 1036 Model m; 1261 void 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 1278 Model* fL_Builder::developModel(double &neededtime) 1279 { 1037 1280 double curriter = 0; 1038 1281 double timestamp = 1.0 / numckp; 1039 1282 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) 1041 1287 { 1042 1288 alterTimedProperties(t); // always alter timed properties in the beginning … … 1045 1291 { 1046 1292 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 1050 1321 // if exact time of development was not reached due to floating point errors, 1051 1322 // then alter timed properties … … 1054 1325 alterTimedProperties(time); 1055 1326 } 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 1341 int 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 1354 int fL_Builder::countDefinedWords() 1355 { 1356 return words.size() - builtincount; 1357 } 1358 1359 int 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 1370 void 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.