Changeset 522 for cpp/frams/model
- Timestamp:
- 06/23/16 00:15:59 (8 years ago)
- Location:
- cpp/frams/model
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/model/model.cpp
r519 r522 11 11 Model::Model() 12 12 { 13 autobuildmaps=false;14 init();13 autobuildmaps = false; 14 init(); 15 15 } 16 16 17 17 void Model::init() 18 18 { 19 partmappingchanged=0;20 buildstatus=empty;21 modelfromgenotype=0;22 startenergy=1.0;23 checklevel=1;19 partmappingchanged = 0; 20 buildstatus = empty; 21 modelfromgenotype = 0; 22 startenergy = 1.0; 23 checklevel = 1; 24 24 #ifdef MODEL_V1_COMPATIBLE 25 oldneurocount=-1; // == unknown26 oldconnections=0;25 oldneurocount=-1; // == unknown 26 oldconnections=0; 27 27 #endif 28 map=0;29 f0map=0;30 f0genoknown=1;31 shape=SHAPE_UNKNOWN;28 map = 0; 29 f0map = 0; 30 f0genoknown = 1; 31 shape = SHAPE_UNKNOWN; 32 32 } 33 33 34 34 void Model::moveElementsFrom(Model &source) 35 35 { 36 int i;37 open();38 for (i=0;i<source.getPartCount();i++)39 addPart(source.getPart(i));40 for (i=0;i<source.getJointCount();i++)41 addJoint(source.getJoint(i));42 for (i=0;i<source.getNeuroCount();i++)43 addNeuro(source.getNeuro(i));44 source.parts.clear(); source.joints.clear(); source.neurons.clear();45 source.clear();36 int i; 37 open(); 38 for (i = 0; i < source.getPartCount(); i++) 39 addPart(source.getPart(i)); 40 for (i = 0; i < source.getJointCount(); i++) 41 addJoint(source.getJoint(i)); 42 for (i = 0; i < source.getNeuroCount(); i++) 43 addNeuro(source.getNeuro(i)); 44 source.parts.clear(); source.joints.clear(); source.neurons.clear(); 45 source.clear(); 46 46 } 47 47 48 48 void Model::internalCopy(const Model &mod) 49 49 { 50 geno=mod.geno;51 f0genoknown=0;52 startenergy=mod.startenergy;53 if (mod.getStatus()==valid)54 { 55 modelfromgenotype=mod.modelfromgenotype;56 {for (int i=0;i<mod.getPartCount();i++)57 addPart(new Part(*mod.getPart(i)));}58 {for (int i =0;i<mod.getJointCount();i++)59 60 Joint *oldj =mod.getJoint(i);61 Joint *j =new Joint(*oldj);50 geno = mod.geno; 51 f0genoknown = 0; 52 startenergy = mod.startenergy; 53 if (mod.getStatus() == valid) 54 { 55 modelfromgenotype = mod.modelfromgenotype; 56 {for (int i = 0; i < mod.getPartCount(); i++) 57 addPart(new Part(*mod.getPart(i))); } 58 {for (int i = 0; i < mod.getJointCount(); i++) 59 { 60 Joint *oldj = mod.getJoint(i); 61 Joint *j = new Joint(*oldj); 62 62 addJoint(j); 63 j->attachToParts(oldj->part1->refno, oldj->part2->refno);64 65 {for (int i =0;i<mod.getNeuroCount();i++)66 67 Neuro *oldn =mod.getNeuro(i);68 Neuro *n =new Neuro(*oldn);63 j->attachToParts(oldj->part1->refno, oldj->part2->refno); 64 }} 65 {for (int i = 0; i < mod.getNeuroCount(); i++) 66 { 67 Neuro *oldn = mod.getNeuro(i); 68 Neuro *n = new Neuro(*oldn); 69 69 addNeuro(n); 70 if (oldn->part_refno >=0) n->attachToPart(oldn->part_refno);70 if (oldn->part_refno >= 0) n->attachToPart(oldn->part_refno); 71 71 else n->attachToJoint(oldn->joint_refno); 72 73 for (int i=0;i<mod.getNeuroCount();i++)74 { 75 Neuro *oldn=mod.getNeuro(i);76 Neuro *n=getNeuro(i);77 for (int ni=0;ni < oldn->getInputCount();ni++)72 }} 73 for (int i = 0; i < mod.getNeuroCount(); i++) 74 { 75 Neuro *oldn = mod.getNeuro(i); 76 Neuro *n = getNeuro(i); 77 for (int ni = 0; ni < oldn->getInputCount(); ni++) 78 78 { 79 double w;80 Neuro *oldinput=oldn->getInput(ni,w);81 SString info=n->getInputInfo(ni);82 n->addInput(getNeuro(oldinput->refno),w,&info);79 double w; 80 Neuro *oldinput = oldn->getInput(ni, w); 81 SString info = n->getInputInfo(ni); 82 n->addInput(getNeuro(oldinput->refno), w, &info); 83 83 } 84 84 } … … 87 87 88 88 89 Model::Model(const Geno &src, bool buildmaps)89 Model::Model(const Geno &src, bool buildmaps) 90 90 :autobuildmaps(buildmaps) 91 {init(src);} 91 { 92 init(src); 93 } 92 94 93 95 void Model::operator=(const Model &mod) 94 96 { 95 clear();96 open();97 internalCopy(mod);98 buildstatus=mod.buildstatus;99 } 100 101 Model::Model(const Model &mod, bool buildmaps)97 clear(); 98 open(); 99 internalCopy(mod); 100 buildstatus = mod.buildstatus; 101 } 102 103 Model::Model(const Model &mod, bool buildmaps) 102 104 :autobuildmaps(buildmaps) 103 105 { 104 init();105 open();106 internalCopy(mod);107 buildstatus=mod.buildstatus;106 init(); 107 open(); 108 internalCopy(mod); 109 buildstatus = mod.buildstatus; 108 110 } 109 111 110 112 void Model::init(const Geno &src) 111 113 { 112 init();113 modelfromgenotype=1;114 geno=src;115 build();114 init(); 115 modelfromgenotype = 1; 116 geno = src; 117 build(); 116 118 } 117 119 118 120 void Model::resetAllDelta() 119 121 { 120 for (int i=0;i<getJointCount();i++)121 getJoint(i)->resetDelta();122 for (int i = 0; i < getJointCount(); i++) 123 getJoint(i)->resetDelta(); 122 124 } 123 125 124 126 void Model::useAllDelta(bool yesno) 125 127 { 126 for (int i=0;i<getJointCount();i++)127 getJoint(i)->useDelta(yesno);128 for (int i = 0; i < getJointCount(); i++) 129 getJoint(i)->useDelta(yesno); 128 130 } 129 131 130 132 Model::~Model() 131 133 { 132 delmodel_list.action((intptr_t)this);133 clear();134 delmodel_list.action((intptr_t)this); 135 clear(); 134 136 } 135 137 136 138 void Model::clear() 137 139 { 138 FOREACH(Part*,p,parts) 140 FOREACH(Part*, p, parts) 141 delete p; 142 FOREACH(Joint*, j, joints) 143 delete j; 144 FOREACH(Neuro*, n, neurons) 145 delete n; 146 parts.clear(); joints.clear(); neurons.clear(); 147 delMap(); 148 delF0Map(); 149 init(); 150 geno = Geno(); 151 f0geno = Geno(); 152 } 153 154 Part *Model::addPart(Part *p) 155 { 156 p->owner = this; 157 p->refno = parts.size(); 158 parts += p; 159 return p; 160 } 161 162 Joint *Model::addJoint(Joint *j) 163 { 164 j->owner = this; 165 j->refno = joints.size(); 166 joints += j; 167 return j; 168 } 169 170 Neuro *Model::addNeuro(Neuro *n) 171 { 172 n->owner = this; 173 n->refno = neurons.size(); 174 neurons += n; 175 return n; 176 } 177 178 void Model::removeNeuros(SList &nlist) 179 { 180 FOREACH(Neuro*, nu, nlist) 181 { 182 int i = findNeuro(nu); 183 if (i >= 0) removeNeuro(i); 184 } 185 } 186 187 void Model::removePart(int partindex, int removeattachedjoints, int removeattachedneurons) 188 { 189 Part *p = getPart(partindex); 190 if (removeattachedjoints) 191 { 192 SList jlist; 193 findJoints(jlist, p); 194 FOREACH(Joint*, j, jlist) 195 { 196 int i = findJoint(j); 197 if (i >= 0) removeJoint(i, removeattachedneurons); 198 } 199 } 200 if (removeattachedneurons) 201 { 202 SList nlist; 203 findNeuros(nlist, 0, p); 204 removeNeuros(nlist); 205 } 206 parts -= partindex; 139 207 delete p; 140 FOREACH(Joint*,j,joints) 208 } 209 210 void Model::removeJoint(int jointindex, int removeattachedneurons) 211 { 212 Joint *j = getJoint(jointindex); 213 if (removeattachedneurons) 214 { 215 SList nlist; 216 findNeuros(nlist, 0, 0, j); 217 removeNeuros(nlist); 218 } 219 joints -= jointindex; 141 220 delete j; 142 FOREACH(Neuro*,n,neurons) 143 delete n; 144 parts.clear(); joints.clear(); neurons.clear(); 145 delMap(); 146 delF0Map(); 147 init(); 148 geno=Geno(); 149 f0geno=Geno(); 150 } 151 152 Part *Model::addPart(Part *p) 153 { 154 p->owner=this; 155 p->refno=parts.size(); 156 parts+=p; 157 return p; 158 } 159 160 Joint *Model::addJoint(Joint *j) 161 { 162 j->owner=this; 163 j->refno=joints.size(); 164 joints+=j; 165 return j; 166 } 167 168 Neuro *Model::addNeuro(Neuro *n) 169 { 170 n->owner=this; 171 n->refno=neurons.size(); 172 neurons+=n; 173 return n; 174 } 175 176 void Model::removeNeuros(SList &nlist) 177 { 178 FOREACH(Neuro*,nu,nlist) 179 { 180 int i=findNeuro(nu); 181 if (i>=0) removeNeuro(i); 182 } 183 } 184 185 void Model::removePart(int partindex,int removeattachedjoints,int removeattachedneurons) 186 { 187 Part *p=getPart(partindex); 188 if (removeattachedjoints) 189 { 190 SList jlist; 191 findJoints(jlist,p); 192 FOREACH(Joint*,j,jlist) 193 { 194 int i=findJoint(j); 195 if (i>=0) removeJoint(i,removeattachedneurons); 196 } 197 } 198 if (removeattachedneurons) 199 { 200 SList nlist; 201 findNeuros(nlist,0,p); 202 removeNeuros(nlist); 203 } 204 parts-=partindex; 205 delete p; 206 } 207 208 void Model::removeJoint(int jointindex,int removeattachedneurons) 209 { 210 Joint *j=getJoint(jointindex); 211 if (removeattachedneurons) 212 { 213 SList nlist; 214 findNeuros(nlist,0,0,j); 215 removeNeuros(nlist); 216 } 217 joints-=jointindex; 218 delete j; 219 } 220 221 void Model::removeNeuro(int neuroindex,bool removereferences) 222 { 223 Neuro* thisN=getNeuro(neuroindex); 224 225 if (removereferences) 226 { 227 Neuro* n; 228 // remove all references to thisN 229 for (int i=0;n=(Neuro*)neurons(i);i++) 230 { 231 Neuro *inp; 232 for (int j=0;inp=n->getInput(j);j++) 233 if (inp==thisN) 221 } 222 223 void Model::removeNeuro(int neuroindex, bool removereferences) 224 { 225 Neuro* thisN = getNeuro(neuroindex); 226 227 if (removereferences) 228 { 229 Neuro* n; 230 // remove all references to thisN 231 for (int i = 0; n = (Neuro*)neurons(i); i++) 232 { 233 Neuro *inp; 234 for (int j = 0; inp = n->getInput(j); j++) 235 if (inp == thisN) 234 236 { 235 237 n->removeInput(j); … … 239 241 } 240 242 241 neurons-=neuroindex;242 delete thisN;243 neurons -= neuroindex; 244 delete thisN; 243 245 } 244 246 245 247 MultiMap& Model::getMap() 246 248 { 247 if (!map) map=new MultiMap();248 return *map;249 if (!map) map = new MultiMap(); 250 return *map; 249 251 } 250 252 251 253 void Model::delMap() 252 254 { 253 if (map) {delete map; map=0;}255 if (map) { delete map; map = 0; } 254 256 } 255 257 void Model::delF0Map() 256 258 { 257 if (f0map) {delete f0map; f0map=0;}258 } 259 260 void Model::makeGenToGenMap(MultiMap& result, const MultiMap& gen1tomodel,const MultiMap& gen2tomodel)261 { 262 result.clear();263 MultiMap m;264 m.addReversed(gen2tomodel);265 result.addCombined(gen1tomodel,m);259 if (f0map) { delete f0map; f0map = 0; } 260 } 261 262 void Model::makeGenToGenMap(MultiMap& result, const MultiMap& gen1tomodel, const MultiMap& gen2tomodel) 263 { 264 result.clear(); 265 MultiMap m; 266 m.addReversed(gen2tomodel); 267 result.addCombined(gen1tomodel, m); 266 268 } 267 269 268 270 void Model::getCurrentToF0Map(MultiMap& result) 269 271 { 270 result.clear();271 if (!map) return;272 const MultiMap& f0m=getF0Map();273 makeGenToGenMap(result,*map,f0m);272 result.clear(); 273 if (!map) return; 274 const MultiMap& f0m = getF0Map(); 275 makeGenToGenMap(result, *map, f0m); 274 276 } 275 277 276 278 void Model::rebuild(bool buildm) 277 279 { 278 autobuildmaps=buildm;279 clear();280 build();280 autobuildmaps = buildm; 281 clear(); 282 build(); 281 283 } 282 284 283 285 void Model::initMap() 284 286 { 285 if (!map) map=new MultiMap();286 else map->clear();287 if (!map) map = new MultiMap(); 288 else map->clear(); 287 289 } 288 290 289 291 void Model::initF0Map() 290 292 { 291 if (!f0map) f0map=new MultiMap();292 else f0map->clear();293 if (!f0map) f0map = new MultiMap(); 294 else f0map->clear(); 293 295 } 294 296 295 297 void Model::build() 296 298 { 297 f0errorposition=-1; 298 f0warnposition=-1; 299 MultiMap *convmap=autobuildmaps ? new MultiMap() : NULL; 300 f0geno=(geno.getFormat()=='0')? geno : geno.getConverted('0',convmap); 301 f0genoknown=1; 302 if (f0geno.isInvalid()) 303 { 304 buildstatus=invalid; 305 if (convmap) delete convmap; 306 return; 307 } 308 SString f0txt=f0geno.getGene(); 309 buildstatus=building; // was: open(); 310 if (autobuildmaps) 311 { 312 partmappingchanged=0; 313 initMap(); 314 initF0Map(); 315 } 316 int pos=0,lnum=1,lastpos=0; 317 SString line; 318 MultiRange frommap; 319 LoggerToMemory mh(LoggerBase::Enable | LoggerBase::DontBlock); 320 for (;f0txt.getNextToken(pos,line,'\n');lnum++) 321 { 322 if (autobuildmaps) 323 { 324 frommap.clear(); 325 frommap.add(lastpos,pos-1); 326 } 327 mh.reset(); 328 if (singleStepBuild(line,lnum,autobuildmaps ? (&frommap) : 0) == -1) 329 { 330 buildstatus=invalid; 331 f0errorposition=lastpos; 299 f0errorposition = -1; 300 f0warnposition = -1; 301 MultiMap *convmap = autobuildmaps ? new MultiMap() : NULL; 302 f0geno = (geno.getFormat() == '0') ? geno : geno.getConverted('0', convmap); 303 f0genoknown = 1; 304 if (f0geno.isInvalid()) 305 { 306 buildstatus = invalid; 332 307 if (convmap) delete convmap; 333 308 return; 334 } 335 if (mh.getWarningCount()) 336 {if (f0warnposition<0) f0warnposition=lastpos;} 337 lastpos=pos; 338 } 339 mh.disable(); 340 close(); 341 if (convmap) 342 { 343 *f0map=*map; 344 if (geno.getFormat()!='0') 345 { 346 MultiMap tmp; 347 tmp.addCombined(*convmap,getMap()); 348 *map=tmp; 349 } 350 delete convmap; 309 } 310 SString f0txt = f0geno.getGene(); 311 buildstatus = building; // was: open(); 312 if (autobuildmaps) 313 { 314 partmappingchanged = 0; 315 initMap(); 316 initF0Map(); 317 } 318 int pos = 0, lnum = 1, lastpos = 0; 319 SString line; 320 MultiRange frommap; 321 LoggerToMemory mh(LoggerBase::Enable | LoggerBase::DontBlock); 322 for (; f0txt.getNextToken(pos, line, '\n'); lnum++) 323 { 324 if (autobuildmaps) 325 { 326 frommap.clear(); 327 frommap.add(lastpos, pos - 1); 328 } 329 mh.reset(); 330 if (singleStepBuild(line, lnum, autobuildmaps ? (&frommap) : 0) == -1) 331 { 332 buildstatus = invalid; 333 f0errorposition = lastpos; 334 if (convmap) delete convmap; 335 return; 336 } 337 if (mh.getWarningCount()) 338 { 339 if (f0warnposition < 0) f0warnposition = lastpos; 340 } 341 lastpos = pos; 342 } 343 mh.disable(); 344 close(); 345 if (convmap) 346 { 347 *f0map = *map; 348 if (geno.getFormat() != '0') 349 { 350 MultiMap tmp; 351 tmp.addCombined(*convmap, getMap()); 352 *map = tmp; 353 } 354 delete convmap; 351 355 } 352 356 } … … 354 358 const MultiMap& Model::getF0Map() 355 359 { 356 if (!f0map)357 { 358 f0map=new MultiMap();359 makeGeno(f0geno,f0map);360 f0genoknown=1;361 } 362 return *f0map;360 if (!f0map) 361 { 362 f0map = new MultiMap(); 363 makeGeno(f0geno, f0map); 364 f0genoknown = 1; 365 } 366 return *f0map; 363 367 } 364 368 365 369 Geno Model::rawGeno() 366 370 { 367 Geno tmpgen;368 makeGeno(tmpgen);369 return tmpgen;370 } 371 372 void Model::makeGeno(Geno &g, MultiMap *map,bool handle_defaults)373 { 374 if ((buildstatus!=valid)&&(buildstatus!=building))375 { 376 g=Geno(0,0,0,"invalid model");377 return;378 } 379 380 SString gen;381 382 Param modelparam(f0_model_paramtab);383 Param partparam(f0_part_paramtab);384 Param jointparam(f0_joint_paramtab);385 Param neuroparam(f0_neuro_paramtab);386 Param connparam(f0_neuroconn_paramtab);387 388 static Part defaultpart;389 static Joint defaultjoint;390 static Neuro defaultneuro;391 static Model defaultmodel;392 static NeuroConn defaultconn;393 //static NeuroItem defaultneuroitem;394 395 Part *p;396 Joint *j;397 Neuro *n;398 int i;399 int len;400 int a,b;401 //NeuroItem *ni;402 403 SString mod_props;404 modelparam.select(this);405 modelparam.save2(mod_props,handle_defaults ? &defaultmodel : NULL,true,!handle_defaults);406 if (mod_props.len()>1) //are there any non-default values? ("\n" is empty)407 { 408 gen+="m:";409 gen+=mod_props;410 } 411 412 for (i=0;p=(Part*)parts(i);i++)413 { 414 partparam.select(p);415 len=gen.len();416 gen+="p:";417 partparam.save2(gen,handle_defaults ? &defaultpart : NULL,true,!handle_defaults);418 if (map)419 map->add(len,gen.len()-1,partToMap(i));420 } 421 for (i=0;j=(Joint*)joints(i);i++)422 { 423 jointparam.select(j);424 len=gen.len();425 jointparam.setParamTab(j->usedelta?f0_joint_paramtab:f0_nodeltajoint_paramtab);426 gen+="j:";427 jointparam.save2(gen,handle_defaults ? &defaultjoint : NULL,true,!handle_defaults);428 if (map)429 map->add(len,gen.len()-1,jointToMap(i));430 } 431 for (i=0;n=(Neuro*)neurons(i);i++)432 { 433 neuroparam.select(n);434 len=gen.len();435 gen+="n:";436 neuroparam.save2(gen,handle_defaults ? &defaultneuro : NULL,true,!handle_defaults);437 if (map)438 map->add(len,gen.len()-1,neuroToMap(i));439 } 440 for (a=0;a<neurons.size();a++)371 Geno tmpgen; 372 makeGeno(tmpgen); 373 return tmpgen; 374 } 375 376 void Model::makeGeno(Geno &g, MultiMap *map, bool handle_defaults) 377 { 378 if ((buildstatus != valid) && (buildstatus != building)) 379 { 380 g = Geno(0, 0, 0, "invalid model"); 381 return; 382 } 383 384 SString gen; 385 386 Param modelparam(f0_model_paramtab); 387 Param partparam(f0_part_paramtab); 388 Param jointparam(f0_joint_paramtab); 389 Param neuroparam(f0_neuro_paramtab); 390 Param connparam(f0_neuroconn_paramtab); 391 392 static Part defaultpart; 393 static Joint defaultjoint; 394 static Neuro defaultneuro; 395 static Model defaultmodel; 396 static NeuroConn defaultconn; 397 //static NeuroItem defaultneuroitem; 398 399 Part *p; 400 Joint *j; 401 Neuro *n; 402 int i; 403 int len; 404 int a, b; 405 //NeuroItem *ni; 406 407 SString mod_props; 408 modelparam.select(this); 409 modelparam.save2(mod_props, handle_defaults ? &defaultmodel : NULL, true, !handle_defaults); 410 if (mod_props.len() > 1) //are there any non-default values? ("\n" is empty) 411 { 412 gen += "m:"; 413 gen += mod_props; 414 } 415 416 for (i = 0; p = (Part*)parts(i); i++) 417 { 418 partparam.select(p); 419 len = gen.len(); 420 gen += "p:"; 421 partparam.save2(gen, handle_defaults ? &defaultpart : NULL, true, !handle_defaults); 422 if (map) 423 map->add(len, gen.len() - 1, partToMap(i)); 424 } 425 for (i = 0; j = (Joint*)joints(i); i++) 426 { 427 jointparam.select(j); 428 len = gen.len(); 429 jointparam.setParamTab(j->usedelta ? f0_joint_paramtab : f0_nodeltajoint_paramtab); 430 gen += "j:"; 431 jointparam.save2(gen, handle_defaults ? &defaultjoint : NULL, true, !handle_defaults); 432 if (map) 433 map->add(len, gen.len() - 1, jointToMap(i)); 434 } 435 for (i = 0; n = (Neuro*)neurons(i); i++) 436 { 437 neuroparam.select(n); 438 len = gen.len(); 439 gen += "n:"; 440 neuroparam.save2(gen, handle_defaults ? &defaultneuro : NULL, true, !handle_defaults); 441 if (map) 442 map->add(len, gen.len() - 1, neuroToMap(i)); 443 } 444 for (a = 0; a < neurons.size(); a++) 441 445 { // inputs 442 n=(Neuro*)neurons(a);443 // if ((n->getInputCount()==1)&&(n->getInput(0).refno <= n->refno))444 // continue; // already done with Neuro::conn_refno445 446 for (b=0;b<n->getInputCount();b++)447 { 448 double w;449 NeuroConn nc;450 Neuro* n2=n->getInput(b,w);451 // if (((n2.parentcount==1)&&(n2.parent)&&(n2.parent->refno < n2.refno)) ^452 // (n2.neuro_refno>=0))453 // printf("!!!! bad Neuro::neuro_refno ?!\n");454 455 // if ((n2.parentcount==1)&&(n2.parent)&&(n2.parent->refno < n2.refno))456 // if (n2.neuro_refno>=0)457 // continue; // already done with Neuro::neuro_refno458 459 nc.n1_refno=n->refno; nc.n2_refno=n2->refno;460 nc.weight=w;461 SString **s=n->inputInfo(b);462 if ((s)&&(*s))463 nc.info=**s;464 connparam.select(&nc);465 len=gen.len();466 gen+="c:";467 connparam.save2(gen,handle_defaults ? &defaultconn : NULL,true,!handle_defaults);468 if (map)469 map->add(len,gen.len()-1,neuroToMap(n->refno));470 } 471 } 472 g=Geno(gen.c_str(),'0');446 n = (Neuro*)neurons(a); 447 // if ((n->getInputCount()==1)&&(n->getInput(0).refno <= n->refno)) 448 // continue; // already done with Neuro::conn_refno 449 450 for (b = 0; b < n->getInputCount(); b++) 451 { 452 double w; 453 NeuroConn nc; 454 Neuro* n2 = n->getInput(b, w); 455 // if (((n2.parentcount==1)&&(n2.parent)&&(n2.parent->refno < n2.refno)) ^ 456 // (n2.neuro_refno>=0)) 457 // printf("!!!! bad Neuro::neuro_refno ?!\n"); 458 459 // if ((n2.parentcount==1)&&(n2.parent)&&(n2.parent->refno < n2.refno)) 460 // if (n2.neuro_refno>=0) 461 // continue; // already done with Neuro::neuro_refno 462 463 nc.n1_refno = n->refno; nc.n2_refno = n2->refno; 464 nc.weight = w; 465 SString **s = n->inputInfo(b); 466 if ((s) && (*s)) 467 nc.info = **s; 468 connparam.select(&nc); 469 len = gen.len(); 470 gen += "c:"; 471 connparam.save2(gen, handle_defaults ? &defaultconn : NULL, true, !handle_defaults); 472 if (map) 473 map->add(len, gen.len() - 1, neuroToMap(n->refno)); 474 } 475 } 476 g = Geno(gen.c_str(), '0'); 473 477 } 474 478 … … 477 481 void Model::open() 478 482 { 479 if (buildstatus==building) return;480 buildstatus=building;481 modelfromgenotype=0;482 partmappingchanged=0;483 f0genoknown=0;484 delMap();483 if (buildstatus == building) return; 484 buildstatus = building; 485 modelfromgenotype = 0; 486 partmappingchanged = 0; 487 f0genoknown = 0; 488 delMap(); 485 489 } 486 490 … … 490 494 void Model::setGeno(const Geno& newgeno) 491 495 { 492 geno=newgeno;496 geno = newgeno; 493 497 } 494 498 495 499 void Model::clearMap() 496 500 { 497 Part *p; Joint *j; Neuro *n;498 int i;499 delMap();500 delF0Map();501 for (i=0;p=(Part*)parts(i);i++)502 p->clearMapping();503 for (i=0;j=(Joint*)joints(i);i++)504 j->clearMapping();505 for (i=0;n=(Neuro*)neurons(i);i++)506 n->clearMapping();501 Part *p; Joint *j; Neuro *n; 502 int i; 503 delMap(); 504 delF0Map(); 505 for (i = 0; p = (Part*)parts(i); i++) 506 p->clearMapping(); 507 for (i = 0; j = (Joint*)joints(i); i++) 508 j->clearMapping(); 509 for (i = 0; n = (Neuro*)neurons(i); i++) 510 n->clearMapping(); 507 511 } 508 512 509 513 int Model::close() 510 514 { 511 if (buildstatus!=building)512 logPrintf("Model","close",LOG_WARN,"Unexpected close() - no open()");513 if (internalcheck(1)>0)514 { 515 buildstatus=valid;516 517 if (partmappingchanged)518 { 519 getMap();520 Part *p; Joint *j; Neuro *n;521 int i;522 for (i=0;p=(Part*)parts(i);i++)523 if (p->getMapping())524 map->add(*p->getMapping(),partToMap(i));525 for (i=0;j=(Joint*)joints(i);i++)526 if (j->getMapping())527 map->add(*j->getMapping(),jointToMap(i));528 for (i=0;n=(Neuro*)neurons(i);i++)529 if (n->getMapping())530 map->add(*n->getMapping(),neuroToMap(i));531 } 532 } 533 else 534 buildstatus=invalid;535 536 return (buildstatus==valid);515 if (buildstatus != building) 516 logPrintf("Model", "close", LOG_WARN, "Unexpected close() - no open()"); 517 if (internalcheck(1) > 0) 518 { 519 buildstatus = valid; 520 521 if (partmappingchanged) 522 { 523 getMap(); 524 Part *p; Joint *j; Neuro *n; 525 int i; 526 for (i = 0; p = (Part*)parts(i); i++) 527 if (p->getMapping()) 528 map->add(*p->getMapping(), partToMap(i)); 529 for (i = 0; j = (Joint*)joints(i); i++) 530 if (j->getMapping()) 531 map->add(*j->getMapping(), jointToMap(i)); 532 for (i = 0; n = (Neuro*)neurons(i); i++) 533 if (n->getMapping()) 534 map->add(*n->getMapping(), neuroToMap(i)); 535 } 536 } 537 else 538 buildstatus = invalid; 539 540 return (buildstatus == valid); 537 541 } 538 542 539 543 int Model::validate() 540 544 { 541 return internalcheck(0);542 } 543 544 Pt3D Model::whereDelta(const Part& start, const Pt3D& rot, const Pt3D& delta)545 { 546 Orient roto;547 roto=rot;548 Orient o;549 roto.transform(o,start.o);550 //o.x=start.o/roto.x;551 //o.y=start.o/roto.y;552 //o.z=start.o/roto.z;553 return o.transform(delta)+start.p;554 } 555 556 int Model::singleStepBuild(const SString &singleline, const MultiRange* srcrange)557 { 558 return singleStepBuild(singleline,0,srcrange);559 } 560 561 int Model::singleStepBuild(const SString &singleline, int line_num,const MultiRange* srcrange)562 { 563 SString error_message;564 int result=singleStepBuildNoLog(singleline,error_message,srcrange);565 if (result<0)566 { 567 if (error_message.len()==0) // generic error when no detailed message is available568 error_message="Invalid f0 code";569 if (line_num>0)570 error_message+=SString::sprintf(", line #%d",line_num);571 error_message+=nameForErrors();572 logPrintf("Model","build",LOG_ERROR,"%s",error_message.c_str());573 } 574 return result;575 } 576 577 int Model::singleStepBuildNoLog(const SString &line, SString& error_message,const MultiRange* srcrange)578 { 579 error_message=SString::empty();580 int pos=0; const char*t=line.c_str();581 for (;*t;t++,pos++)582 if (!strchr(" \r\t",*t)) break;583 if (*t=='#') return 0;584 if (!*t) return 0;585 if (!strncmp(t,"p:",2))586 { 587 Param partparam(f0_part_paramtab);588 Part *p=new Part();589 partparam.select(p);590 pos+=2;591 if (partparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete p; error_message="Invalid 'p:'"; return -1;}592 p->o.rotate(p->rot);593 parts+=p;594 p->owner=this;595 if (srcrange) p->setMapping(*srcrange);596 return getPartCount()-1;597 } 598 if (!strncmp(t,"m:",2))599 { 600 Param modelparam(f0_model_paramtab);601 modelparam.select(this);602 pos+=2;603 if (modelparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message="Invalid 'm:'"; return -1;}604 return 0;605 } 606 else if (!strncmp(t,"j:",2))607 { 608 Param jointparam(f0_joint_paramtab);609 Joint *j=new Joint();610 jointparam.select(j);611 pos+=2;612 j->owner=this;613 if (jointparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete j; error_message="Invalid 'j:'"; return -1;}614 bool p1_ok=false, p2_ok=false;615 if ((p1_ok=((j->p1_refno>=0)&&(j->p1_refno<getPartCount())))&&616 (p2_ok=((j->p2_refno>=0)&&(j->p2_refno<getPartCount()))))617 { 618 addJoint(j);619 if ((j->d.x != JOINT_DELTA_MARKER) || (j->d.y != JOINT_DELTA_MARKER) || (j->d.z != JOINT_DELTA_MARKER))545 return internalcheck(0); 546 } 547 548 Pt3D Model::whereDelta(const Part& start, const Pt3D& rot, const Pt3D& delta) 549 { 550 Orient roto; 551 roto = rot; 552 Orient o; 553 roto.transform(o, start.o); 554 //o.x=start.o/roto.x; 555 //o.y=start.o/roto.y; 556 //o.z=start.o/roto.z; 557 return o.transform(delta) + start.p; 558 } 559 560 int Model::singleStepBuild(const SString &singleline, const MultiRange* srcrange) 561 { 562 return singleStepBuild(singleline, 0, srcrange); 563 } 564 565 int Model::singleStepBuild(const SString &singleline, int line_num, const MultiRange* srcrange) 566 { 567 SString error_message; 568 int result = singleStepBuildNoLog(singleline, error_message, srcrange); 569 if (result < 0) 570 { 571 if (error_message.len() == 0) // generic error when no detailed message is available 572 error_message = "Invalid f0 code"; 573 if (line_num>0) 574 error_message += SString::sprintf(", line #%d", line_num); 575 error_message += nameForErrors(); 576 logPrintf("Model", "build", LOG_ERROR, "%s", error_message.c_str()); 577 } 578 return result; 579 } 580 581 int Model::singleStepBuildNoLog(const SString &line, SString& error_message, const MultiRange* srcrange) 582 { 583 error_message = SString::empty(); 584 int pos = 0; const char*t = line.c_str(); 585 for (; *t; t++, pos++) 586 if (!strchr(" \r\t", *t)) break; 587 if (*t == '#') return 0; 588 if (!*t) return 0; 589 if (!strncmp(t, "p:", 2)) 590 { 591 Param partparam(f0_part_paramtab); 592 Part *p = new Part(); 593 partparam.select(p); 594 pos += 2; 595 if (partparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { delete p; error_message = "Invalid 'p:'"; return -1; } 596 p->o.rotate(p->rot); 597 parts += p; 598 p->owner = this; 599 if (srcrange) p->setMapping(*srcrange); 600 return getPartCount() - 1; 601 } 602 if (!strncmp(t, "m:", 2)) 603 { 604 Param modelparam(f0_model_paramtab); 605 modelparam.select(this); 606 pos += 2; 607 if (modelparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message = "Invalid 'm:'"; return -1; } 608 return 0; 609 } 610 else if (!strncmp(t, "j:", 2)) 611 { 612 Param jointparam(f0_joint_paramtab); 613 Joint *j = new Joint(); 614 jointparam.select(j); 615 pos += 2; 616 j->owner = this; 617 if (jointparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { delete j; error_message = "Invalid 'j:'"; return -1; } 618 bool p1_ok = false, p2_ok = false; 619 if ((p1_ok = ((j->p1_refno >= 0) && (j->p1_refno < getPartCount()))) && 620 (p2_ok = ((j->p2_refno >= 0) && (j->p2_refno < getPartCount())))) 621 { 622 addJoint(j); 623 if ((j->d.x != JOINT_DELTA_MARKER) || (j->d.y != JOINT_DELTA_MARKER) || (j->d.z != JOINT_DELTA_MARKER)) 620 624 { 621 j->useDelta(1);622 j->resetDeltaMarkers();625 j->useDelta(1); 626 j->resetDeltaMarkers(); 623 627 } 624 j->attachToParts(j->p1_refno,j->p2_refno);625 if (srcrange) j->setMapping(*srcrange);626 return j->refno;627 } 628 else629 { 630 error_message=SString::sprintf("Invalid reference to Part #%d",p1_ok?j->p1_refno:j->p2_refno);631 delete j;632 return -1;633 } 634 } 635 else if (!strncmp(t,"n:",2)) // neuro (or the old neuro object as the special case)636 { 637 Param neuroparam(f0_neuro_paramtab);638 Neuro *nu=new Neuro();639 neuroparam.select(nu);640 pos+=2;641 if (neuroparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete nu; error_message="Invalid 'n:'"; return -1;}628 j->attachToParts(j->p1_refno, j->p2_refno); 629 if (srcrange) j->setMapping(*srcrange); 630 return j->refno; 631 } 632 else 633 { 634 error_message = SString::sprintf("Invalid reference to Part #%d", p1_ok ? j->p1_refno : j->p2_refno); 635 delete j; 636 return -1; 637 } 638 } 639 else if (!strncmp(t, "n:", 2)) // neuro (or the old neuro object as the special case) 640 { 641 Param neuroparam(f0_neuro_paramtab); 642 Neuro *nu = new Neuro(); 643 neuroparam.select(nu); 644 pos += 2; 645 if (neuroparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { delete nu; error_message = "Invalid 'n:'"; return -1; } 642 646 #ifdef MODEL_V1_COMPATIBLE 643 if (nu->neuro_refno>=0) // parent specified... 644 { 645 if (nu->neuro_refno >= getNeuroCount()) // and it's illegal 647 if (nu->neuro_refno>=0) // parent specified... 648 { 649 if (nu->neuro_refno >= getNeuroCount()) // and it's illegal 650 { 651 delete nu; 652 return -1; 653 } 654 Neuro *parentNU=getNeuro(nu->neuro_refno); 655 parentNU->addInput(nu,nu->weight); 656 // default class for parented units: n-n link 657 //if (nu->moredata.len()==0) nu->moredata="-"; 658 } 659 else 660 #endif 661 { 662 // default class for unparented units: standard neuron 663 if (nu->getClassName().len() == 0) nu->setClassName("N"); 664 } 665 /* 666 if (nu->conn_refno>=0) // input specified... 667 { 668 if (nu->conn_refno >= getNeuroCount()) // and it's illegal 646 669 { 647 670 delete nu; 648 671 return -1; 649 672 } 650 Neuro *parentNU=getNeuro(nu->neuro_refno);651 parentNU->addInput(nu,nu->weight);652 // default class for parented units: n-n link653 //if (nu->moredata.len()==0) nu->moredata="-";654 } 655 else673 Neuro *inputNU=getNeuro(nu->conn_refno); 674 nu->addInput(inputNU,nu->weight); 675 } 676 */ 677 #ifdef MODEL_V1_COMPATIBLE 678 nu->weight=1.0; 656 679 #endif 657 { 658 // default class for unparented units: standard neuron 659 if (nu->getClassName().len()==0) nu->setClassName("N"); 660 } 661 /* 662 if (nu->conn_refno>=0) // input specified... 663 { 664 if (nu->conn_refno >= getNeuroCount()) // and it's illegal 665 { 680 nu->owner = this; 681 // attach to part/joint 682 if (nu->part_refno >= 0) 683 nu->attachToPart(nu->part_refno); 684 if (nu->joint_refno >= 0) 685 nu->attachToJoint(nu->joint_refno); 686 if (srcrange) nu->setMapping(*srcrange); 687 // todo: check part/joint ref# 688 #ifdef MODEL_V1_COMPATIBLE 689 if (hasOldNeuroLayout()) 690 { 691 int count=old_getNeuroCount(); 692 neurons.insert(count,nu); 693 oldneurocount=count+1; 694 return oldneurocount-1; 695 } 696 else 697 #endif 698 { 699 neurons += nu; 700 return neurons.size() - 1; 701 } 702 } 703 else if (!strncmp(t, "c:", 2)) // add input 704 { 705 Param ncparam(f0_neuroconn_paramtab); 706 NeuroConn c; 707 ncparam.select(&c); 708 pos += 2; 709 if (ncparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message = "Invalid 'c:'"; return -1; } 710 bool n1_ok = false, n2_ok = false; 711 if ((n1_ok = ((c.n1_refno >= 0) && (c.n1_refno < getNeuroCount()))) 712 && (n2_ok = ((c.n2_refno >= 0) && (c.n2_refno < getNeuroCount())))) 713 { 714 Neuro *na = getNeuro(c.n1_refno); 715 Neuro *nb = getNeuro(c.n2_refno); 716 na->addInput(nb, c.weight, &c.info); 717 if (srcrange) 718 na->addMapping(*srcrange); 719 return 0; 720 } 721 error_message = SString::sprintf("Invalid reference to Neuro #%d", n1_ok ? c.n2_refno : c.n1_refno); 722 return -1; 723 } 724 #ifdef MODEL_V1_COMPATIBLE 725 else if (!strncmp(t,"ni:",3)) // old neuroitem 726 { 727 // we always use old layout for "ni:" 728 Param neuroitemparam(f0_neuroitem_paramtab); 729 Neuro *nu=new Neuro(); 730 neuroitemparam.select(nu); 731 pos+=3; 732 if (neuroitemparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete nu; return -1;} 733 // illegal parent? 734 if ((nu->neuro_refno<0)||(nu->neuro_refno>=old_getNeuroCount())) 735 { 666 736 delete nu; 667 737 return -1; 668 } 669 Neuro *inputNU=getNeuro(nu->conn_refno); 670 nu->addInput(inputNU,nu->weight); 671 } 672 */ 673 #ifdef MODEL_V1_COMPATIBLE 674 nu->weight=1.0; 738 } 739 Neuro *parentN=getNeuro(nu->neuro_refno); 740 // copy part/joint refno from parent, if possible 741 if ((nu->part_refno<0)&&(parentN->part_refno>=0)) 742 nu->part_refno=parentN->part_refno; 743 if ((nu->joint_refno<0)&&(parentN->joint_refno>=0)) 744 nu->joint_refno=parentN->joint_refno; 745 nu->owner=this; 746 // attach to part/joint 747 if (nu->part_refno>=0) 748 nu->attachToPart(nu->part_refno); 749 if (nu->joint_refno>=0) 750 nu->attachToJoint(nu->joint_refno); 751 if (srcrange) 752 nu->setMapping(*srcrange); 753 // special case: old muscles 754 // PARENT neuron will be set up to be the CHILD of the current one (!) 755 if (nu->isOldEffector()) 756 { 757 nu->neuro_refno=parentN->refno; 758 neurons+=nu; 759 nu->owner=this; 760 nu->addInput(parentN,nu->weight); // (!) 761 nu->weight=1.0; 762 parentN->invalidateOldItems(); 763 return 0; // !!! -> ...getItemCount()-1; 764 } 765 parentN->addInput(nu,nu->weight); 766 neurons+=nu; 767 parentN->invalidateOldItems(); 768 if (nu->getClassName().len()==0) 769 { 770 nu->setClassName("-"); 771 // for compatibility, "ni" can define a n-n connection 772 // referring to non-existent neuron (which will be hopefully defined later) 773 // internal check will add the proper input to this unit 774 // if conn_refno >=0 and input count==0 775 oldconnections=1; 776 if (srcrange) 777 parentN->addMapping(*srcrange); 778 } 779 else 780 nu->weight=1.0; 781 return 0; // !!! -> ...getItemCount()-1; 782 } 675 783 #endif 676 nu->owner=this; 677 // attach to part/joint 678 if (nu->part_refno>=0) 679 nu->attachToPart(nu->part_refno); 680 if (nu->joint_refno>=0) 681 nu->attachToJoint(nu->joint_refno); 682 if (srcrange) nu->setMapping(*srcrange); 683 // todo: check part/joint ref# 684 #ifdef MODEL_V1_COMPATIBLE 685 if (hasOldNeuroLayout()) 686 { 687 int count=old_getNeuroCount(); 688 neurons.insert(count,nu); 689 oldneurocount=count+1; 690 return oldneurocount-1; 691 } 692 else 693 #endif 694 { 695 neurons+=nu; 696 return neurons.size()-1; 697 } 698 } 699 else if (!strncmp(t,"c:",2)) // add input 700 { 701 Param ncparam(f0_neuroconn_paramtab); 702 NeuroConn c; 703 ncparam.select(&c); 704 pos+=2; 705 if (ncparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message="Invalid 'c:'"; return -1; } 706 bool n1_ok=false,n2_ok=false; 707 if ((n1_ok=((c.n1_refno>=0)&&(c.n1_refno<getNeuroCount()))) 708 && (n2_ok=((c.n2_refno>=0)&&(c.n2_refno<getNeuroCount())))) 709 { 710 Neuro *na=getNeuro(c.n1_refno); 711 Neuro *nb=getNeuro(c.n2_refno); 712 na->addInput(nb,c.weight,&c.info); 713 if (srcrange) 714 na->addMapping(*srcrange); 715 return 0; 716 } 717 error_message=SString::sprintf("Invalid reference to Neuro #%d",n1_ok ? c.n2_refno : c.n1_refno); 718 return -1; 719 } 720 #ifdef MODEL_V1_COMPATIBLE 721 else if (!strncmp(t,"ni:",3)) // old neuroitem 722 { 723 // we always use old layout for "ni:" 724 Param neuroitemparam(f0_neuroitem_paramtab); 725 Neuro *nu=new Neuro(); 726 neuroitemparam.select(nu); 727 pos+=3; 728 if (neuroitemparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete nu; return -1;} 729 // illegal parent? 730 if ((nu->neuro_refno<0)||(nu->neuro_refno>=old_getNeuroCount())) 731 { 732 delete nu; 733 return -1; 734 } 735 Neuro *parentN=getNeuro(nu->neuro_refno); 736 // copy part/joint refno from parent, if possible 737 if ((nu->part_refno<0)&&(parentN->part_refno>=0)) 738 nu->part_refno=parentN->part_refno; 739 if ((nu->joint_refno<0)&&(parentN->joint_refno>=0)) 740 nu->joint_refno=parentN->joint_refno; 741 nu->owner=this; 742 // attach to part/joint 743 if (nu->part_refno>=0) 744 nu->attachToPart(nu->part_refno); 745 if (nu->joint_refno>=0) 746 nu->attachToJoint(nu->joint_refno); 747 if (srcrange) 748 nu->setMapping(*srcrange); 749 // special case: old muscles 750 // PARENT neuron will be set up to be the CHILD of the current one (!) 751 if (nu->isOldEffector()) 752 { 753 nu->neuro_refno=parentN->refno; 754 neurons+=nu; 755 nu->owner=this; 756 nu->addInput(parentN,nu->weight); // (!) 757 nu->weight=1.0; 758 parentN->invalidateOldItems(); 759 return 0; // !!! -> ...getItemCount()-1; 760 } 761 parentN->addInput(nu,nu->weight); 762 neurons+=nu; 763 parentN->invalidateOldItems(); 764 if (nu->getClassName().len()==0) 765 { 766 nu->setClassName("-"); 767 // for compatibility, "ni" can define a n-n connection 768 // referring to non-existent neuron (which will be hopefully defined later) 769 // internal check will add the proper input to this unit 770 // if conn_refno >=0 and input count==0 771 oldconnections=1; 772 if (srcrange) 773 parentN->addMapping(*srcrange); 774 } 775 else 776 nu->weight=1.0; 777 return 0; // !!! -> ...getItemCount()-1; 778 } 779 #endif 780 else return -1; 784 else return -1; 781 785 } 782 786 … … 784 788 int Model::addOldConnectionsInputs() 785 789 { 786 if (!oldconnections) return 1;787 Neuro* n;788 for (int i=0;i<neurons.size();i++)789 { 790 n=(Neuro*)neurons(i);791 if (n->conn_refno>=0)792 if (n->isNNConnection())793 if (n->conn_refno < old_getNeuroCount())790 if (!oldconnections) return 1; 791 Neuro* n; 792 for (int i=0;i<neurons.size();i++) 793 { 794 n=(Neuro*)neurons(i); 795 if (n->conn_refno>=0) 796 if (n->isNNConnection()) 797 if (n->conn_refno < old_getNeuroCount()) 794 798 { // good reference 795 796 797 798 799 800 799 Neuro* parent=n->parent; // nn connection has exactly one parent 800 int inp=parent->findInput(n); 801 Neuro* target=getNeuro(n->conn_refno); 802 parent->setInput(inp,target,n->weight); 803 removeNeuro(i,0); // no need to remove references 804 i--; 801 805 } 806 else 807 { 808 logPrintf("Model","internalCheck",LOG_ERROR, 809 "illegal N-N connection #%d (reference to #%d)%s", 810 i,n->conn_refno,nameForErrors().c_str()); 811 return 0; 812 } 813 } 814 oldconnections=0; 815 return 1; 816 } 817 #endif 818 819 ///////////// 820 821 /** change the sequence of neuro units 822 and fix references in "-" objects (n-n connections) */ 823 void Model::moveNeuro(int oldpos, int newpos) 824 { 825 if (oldpos == newpos) return; // nop! 826 Neuro *n = getNeuro(oldpos); 827 neurons -= oldpos; 828 neurons.insert(newpos, n); 829 // conn_refno could be broken -> fix it 830 #ifdef MODEL_V1_COMPATIBLE 831 for (int i=0;i<neurons.size();i++) 832 { 833 Neuro *n2=getNeuro(i); 834 if (n2->isNNConnection()) 835 if (n2->conn_refno == oldpos) n2->conn_refno=newpos; 802 836 else 803 { 804 logPrintf("Model","internalCheck",LOG_ERROR, 805 "illegal N-N connection #%d (reference to #%d)%s", 806 i,n->conn_refno,nameForErrors().c_str()); 807 return 0; 808 } 809 } 810 oldconnections=0; 811 return 1; 812 } 813 #endif 814 815 ///////////// 816 817 /** change the sequence of neuro units 818 and fix references in "-" objects (n-n connections) */ 819 void Model::moveNeuro(int oldpos,int newpos) 820 { 821 if (oldpos==newpos) return; // nop! 822 Neuro *n=getNeuro(oldpos); 823 neurons-=oldpos; 824 neurons.insert(newpos,n); 825 // conn_refno could be broken -> fix it 826 #ifdef MODEL_V1_COMPATIBLE 827 for (int i=0;i<neurons.size();i++) 828 { 829 Neuro *n2=getNeuro(i); 830 if (n2->isNNConnection()) 831 if (n2->conn_refno == oldpos) n2->conn_refno=newpos; 832 else 833 { if (n2->conn_refno > oldpos) n2->conn_refno--; 834 if (n2->conn_refno >= newpos) n2->conn_refno++; } 835 } 836 invalidateOldNeuroCount(); 837 { if (n2->conn_refno > oldpos) n2->conn_refno--; 838 if (n2->conn_refno >= newpos) n2->conn_refno++; } 839 } 840 invalidateOldNeuroCount(); 837 841 #endif 838 842 } … … 840 844 #ifdef MODEL_V1_COMPATIBLE 841 845 /** move all old neurons (class "N") to the front of the neurons list. 842 843 846 @return number of old neurons 847 */ 844 848 int Model::reorderToOldLayout() 845 849 { 846 Neuro *n;847 int neurocount=0;848 for (int i=0;i<neurons.size();i++)849 { 850 n=(Neuro*)neurons(i);851 if (n->isOldNeuron())852 { 853 moveNeuro(i,neurocount);854 neurocount++;855 i=neurocount-1;856 } 857 } 858 return neurocount;850 Neuro *n; 851 int neurocount=0; 852 for (int i=0;i<neurons.size();i++) 853 { 854 n=(Neuro*)neurons(i); 855 if (n->isOldNeuron()) 856 { 857 moveNeuro(i,neurocount); 858 neurocount++; 859 i=neurocount-1; 860 } 861 } 862 return neurocount; 859 863 } 860 864 #endif … … 863 867 void Model::updateNeuroRefno() 864 868 { 865 for (int i=0;i<neurons.size();i++)866 { 867 Neuro* n=(Neuro*)neurons(i);868 n->refno=i;869 for (int i = 0; i < neurons.size(); i++) 870 { 871 Neuro* n = (Neuro*)neurons(i); 872 n->refno = i; 869 873 } 870 874 } … … 882 886 void Model::updateRefno() 883 887 { 884 int i;885 for (i=0;i<getPartCount();i++) getPart(i)->refno=i;886 for (i=0;i<getJointCount();i++) getJoint(i)->refno=i;887 for (i=0;i<getNeuroCount();i++) getNeuro(i)->refno=i;888 int i; 889 for (i = 0; i < getPartCount(); i++) getPart(i)->refno = i; 890 for (i = 0; i < getJointCount(); i++) getJoint(i)->refno = i; 891 for (i = 0; i < getNeuroCount(); i++) getNeuro(i)->refno = i; 888 892 } 889 893 890 894 SString Model::nameForErrors() const 891 895 { 892 if (geno.getName().len()>0)893 return SString::sprintf(" in '%s'",geno.getName().c_str());894 return SString::empty();896 if (geno.getName().len()>0) 897 return SString::sprintf(" in '%s'", geno.getName().c_str()); 898 return SString::empty(); 895 899 } 896 900 897 901 int Model::internalcheck(int final) 898 902 { 899 Part *p; 900 Joint *j; 901 Neuro *n; 902 int i,k; 903 int ret=1; 904 shape=SHAPE_UNKNOWN; 905 if ((parts.size()==0)&&(neurons.size()==0)) return 0; 906 if (parts.size()==0) 907 size=Pt3D_0; 908 else 909 { 910 Pt3D bbmin=((Part*)parts(0))->p, bbmax=bbmin; 911 for (i=0;i<parts.size();i++) 912 { 913 p=(Part*)parts(i); 914 p->owner=this; 915 p->refno=i; 916 if (p->shape==0) 917 { 918 if (checklevel>0) 919 p->mass=0.0; 920 } 921 // VALIDMINMAX(p,part,mass); 922 VALIDMINMAX(p,Part,size); 923 VALIDMINMAX(p,Part,density); 924 VALIDMINMAX(p,Part,friction); 925 VALIDMINMAX(p,Part,ingest); 926 VALIDMINMAX(p,Part,assim); 927 p->flags&=~LINKFLAG; // for delta joint cycle detection 928 if (p->p.x-p->size < bbmin.x) bbmin.x=p->p.x-p->size; 929 if (p->p.y-p->size < bbmin.y) bbmin.y=p->p.y-p->size; 930 if (p->p.z-p->size < bbmin.z) bbmin.z=p->p.z-p->size; 931 if (p->p.x+p->size > bbmax.x) bbmax.x=p->p.x+p->size; 932 if (p->p.y+p->size > bbmax.y) bbmax.y=p->p.y+p->size; 933 if (p->p.z+p->size > bbmax.z) bbmax.z=p->p.z+p->size; 934 if (shape==SHAPE_UNKNOWN) 935 shape=(p->shape==Part::SHAPE_DEFAULT)?SHAPE_OLD:SHAPE_NEW; 936 else if (shape!=SHAPE_ILLEGAL) 937 { 938 if ((p->shape==Part::SHAPE_DEFAULT) ^ (shape==SHAPE_OLD)) 903 Part *p; 904 Joint *j; 905 Neuro *n; 906 int i, k; 907 int ret = 1; 908 shape = SHAPE_UNKNOWN; 909 if ((parts.size() == 0) && (neurons.size() == 0)) return 0; 910 if (parts.size() == 0) 911 size = Pt3D_0; 912 else 913 { 914 Pt3D bbmin = ((Part*)parts(0))->p, bbmax = bbmin; 915 for (i = 0; i < parts.size(); i++) 916 { 917 p = (Part*)parts(i); 918 p->owner = this; 919 p->refno = i; 920 if (p->shape == 0) 939 921 { 940 shape=SHAPE_ILLEGAL;941 logPrintf("Model","internalCheck",LOG_WARN,"Inconsistent part shapes (mixed old and new shapes)%s",nameForErrors().c_str());922 if (checklevel > 0) 923 p->mass = 0.0; 942 924 } 943 }944 }945 size=bbmax-bbmin;946 for (i=0;i<joints.size();i++) 947 {948 j=(Joint*)joints(i);949 VALIDMINMAX(j,Joint,stamina);950 VALIDMINMAX(j,Joint,stif);951 VALIDMINMAX(j,Joint,rotstif);952 j->refno=i;953 j->owner=this;954 if (j->part1 && j->part2 && (j->part1 != j->part2))955 {956 j->p1_refno=j->part1->refno;957 j->p2_refno=j->part2->refno;958 if (checklevel>0)925 // VALIDMINMAX(p,part,mass); 926 VALIDMINMAX(p, Part, size); 927 VALIDMINMAX(p, Part, density); 928 VALIDMINMAX(p, Part, friction); 929 VALIDMINMAX(p, Part, ingest); 930 VALIDMINMAX(p, Part, assim); 931 p->flags &= ~LINKFLAG; // for delta joint cycle detection 932 if (p->p.x - p->size < bbmin.x) bbmin.x = p->p.x - p->size; 933 if (p->p.y - p->size < bbmin.y) bbmin.y = p->p.y - p->size; 934 if (p->p.z - p->size < bbmin.z) bbmin.z = p->p.z - p->size; 935 if (p->p.x + p->size > bbmax.x) bbmax.x = p->p.x + p->size; 936 if (p->p.y + p->size > bbmax.y) bbmax.y = p->p.y + p->size; 937 if (p->p.z + p->size > bbmax.z) bbmax.z = p->p.z + p->size; 938 if (shape == SHAPE_UNKNOWN) 939 shape = (p->shape == Part::SHAPE_DEFAULT) ? SHAPE_OLD : SHAPE_NEW; 940 else if (shape != SHAPE_ILLEGAL) 959 941 { 960 if (j->part1->shape==0) 961 j->part1->mass+=1.0; 962 if (j->part2->shape==0) 963 j->part2->mass+=1.0; 964 } 965 if ((j->usedelta)&&((j->d.x!=JOINT_DELTA_MARKER)||(j->d.y!=JOINT_DELTA_MARKER)||(j->d.z!=JOINT_DELTA_MARKER))) 966 { // delta positioning -> calc. orient. 967 if (j->part2->flags & LINKFLAG) 942 if ((p->shape == Part::SHAPE_DEFAULT) ^ (shape == SHAPE_OLD)) 968 943 { 969 ret=0; 970 logPrintf("Model","internalCheck",LOG_ERROR, 971 "Delta joint cycle detected at Joint #%d%s", 972 i,nameForErrors().c_str()); 973 } 974 j->resetDeltaMarkers(); 975 j->o=j->rot; 976 j->part1->o.transform(j->part2->o,j->o); 977 // j->part2->o.x=j->part1->o/j->o.x; 978 // j->part2->o.y=j->part1->o/j->o.y; 979 // j->part2->o.z=j->part1->o/j->o.z; 980 j->part2->p=j->part2->o.transform(j->d)+j->part1->p; 981 j->part2->flags|=LINKFLAG; j->part1->flags|=LINKFLAG; // for delta joint cycle detection 982 } 983 else 984 { // abs.positioning -> calc. delta 985 if (final) 986 { 987 // calc orient delta 988 // Orient tmpo(j->part2->o); 989 // tmpo*=j->part1->o; 990 Orient tmpo; 991 j->part1->o.revTransform(tmpo,j->part2->o); 992 tmpo.getAngles(j->rot); 993 j->o=j->rot; 994 // calc position delta 995 Pt3D tmpp(j->part2->p); 996 tmpp-=j->part1->p; 997 j->d=j->part2->o.revTransform(tmpp); 998 } 999 } 1000 if (final) 1001 { 1002 if (j->shape!=Joint::SHAPE_SOLID) 1003 { 1004 if (j->d()>getMaxJoint().d.x) 1005 { 1006 ret=0; 1007 logPrintf("Model","internalCheck",LOG_ERROR,"Joint #%d too long%s",i,nameForErrors().c_str()); 1008 } 944 shape = SHAPE_ILLEGAL; 945 logPrintf("Model", "internalCheck", LOG_WARN, "Inconsistent part shapes (mixed old and new shapes)%s", nameForErrors().c_str()); 1009 946 } 1010 947 } 1011 948 } 1012 else 1013 { 1014 logPrintf("Model","internalCheck",LOG_ERROR,"Illegal part references in Joint #%d%s",i,nameForErrors().c_str()); 1015 ret=0; 1016 } 1017 if (shape!=SHAPE_ILLEGAL) 1018 { 1019 if ((j->shape==Joint::SHAPE_DEFAULT) ^ (shape==SHAPE_OLD)) 949 size = bbmax - bbmin; 950 for (i = 0; i < joints.size(); i++) 951 { 952 j = (Joint*)joints(i); 953 VALIDMINMAX(j, Joint, stamina); 954 VALIDMINMAX(j, Joint, stif); 955 VALIDMINMAX(j, Joint, rotstif); 956 j->refno = i; 957 j->owner = this; 958 if (j->part1 && j->part2 && (j->part1 != j->part2)) 1020 959 { 1021 shape=SHAPE_ILLEGAL; 1022 logPrintf("Model","internalCheck",LOG_WARN,"Inconsistent joint shapes (mixed old and new shapes)%s",nameForErrors().c_str()); 1023 } 1024 } 1025 } 1026 } 1027 #ifdef MODEL_V1_COMPATIBLE 1028 if (!addOldConnectionsInputs()) 1029 return 0; 1030 #endif 1031 1032 updateNeuroRefno(); // valid refno is important for n-n connections check (later) 1033 1034 for (i=0;i<neurons.size();i++) 1035 { 1036 n=(Neuro*)neurons(i); 1037 VALIDMINMAX(n,Neuro,state); 1038 #ifdef MODEL_V1_COMPATIBLE 1039 VALIDMINMAX(n,Neuro,inertia); 1040 VALIDMINMAX(n,Neuro,force); 1041 VALIDMINMAX(n,Neuro,sigmo); 1042 n->conn_refno=-1; 1043 n->weight=1.0; 1044 n->neuro_refno=-1; 1045 #endif 1046 n->part_refno=(n->part)?n->part->refno:-1; 1047 n->joint_refno=(n->joint)?n->joint->refno:-1; 1048 } 1049 1050 if (parts.size()&&(checklevel>0)) 1051 { 1052 for (i=0;i<parts.size();i++) 1053 { 1054 p=(Part*)parts(i); 1055 if (p->shape==0) 1056 if (p->mass<=0.001) 1057 p->mass=1.0; 1058 p->flags&=~LINKFLAG; 1059 } 1060 getPart(0)->flags|=LINKFLAG; 1061 int change=1; 1062 while(change) 1063 { 1064 change=0; 1065 for (i=0;i<joints.size();i++) 1066 { 1067 j=(Joint*)joints(i); 1068 if (j->part1->flags&LINKFLAG) 960 j->p1_refno = j->part1->refno; 961 j->p2_refno = j->part2->refno; 962 if (checklevel > 0) 1069 963 { 1070 if (!(j->part2->flags&LINKFLAG)) 964 if (j->part1->shape == 0) 965 j->part1->mass += 1.0; 966 if (j->part2->shape == 0) 967 j->part2->mass += 1.0; 968 } 969 if ((j->usedelta) && ((j->d.x != JOINT_DELTA_MARKER) || (j->d.y != JOINT_DELTA_MARKER) || (j->d.z != JOINT_DELTA_MARKER))) 970 { // delta positioning -> calc. orient. 971 if (j->part2->flags & LINKFLAG) 1071 972 { 1072 change=1; 1073 j->part2->flags|=LINKFLAG; 973 ret = 0; 974 logPrintf("Model", "internalCheck", LOG_ERROR, 975 "Delta joint cycle detected at Joint #%d%s", 976 i, nameForErrors().c_str()); 977 } 978 j->resetDeltaMarkers(); 979 j->o = j->rot; 980 j->part1->o.transform(j->part2->o, j->o); 981 // j->part2->o.x=j->part1->o/j->o.x; 982 // j->part2->o.y=j->part1->o/j->o.y; 983 // j->part2->o.z=j->part1->o/j->o.z; 984 j->part2->p = j->part2->o.transform(j->d) + j->part1->p; 985 j->part2->flags |= LINKFLAG; j->part1->flags |= LINKFLAG; // for delta joint cycle detection 986 } 987 else 988 { // abs.positioning -> calc. delta 989 if (final) 990 { 991 // calc orient delta 992 // Orient tmpo(j->part2->o); 993 // tmpo*=j->part1->o; 994 Orient tmpo; 995 j->part1->o.revTransform(tmpo, j->part2->o); 996 tmpo.getAngles(j->rot); 997 j->o = j->rot; 998 // calc position delta 999 Pt3D tmpp(j->part2->p); 1000 tmpp -= j->part1->p; 1001 j->d = j->part2->o.revTransform(tmpp); 1074 1002 } 1075 1003 } 1076 else 1077 if (j->part2->flags&LINKFLAG) 1004 if (final) 1078 1005 { 1079 if (!(j->part1->flags&LINKFLAG))1006 if (j->shape != Joint::SHAPE_SOLID) 1080 1007 { 1081 change=1; 1082 j->part1->flags|=LINKFLAG; 1008 if (j->d() > getMaxJoint().d.x) 1009 { 1010 ret = 0; 1011 logPrintf("Model", "internalCheck", LOG_ERROR, "Joint #%d too long%s", i, nameForErrors().c_str()); 1012 } 1083 1013 } 1084 1014 } 1085 1015 } 1086 } 1087 for (i=0;i<parts.size();i++) 1088 { 1089 p=(Part*)parts(i); 1090 if (!(p->flags&LINKFLAG)) 1016 else 1091 1017 { 1092 logPrintf("Model","internalCheck",LOG_ERROR,"Not all parts connected (eg. Part #0 and Part #%d)%s",i,nameForErrors().c_str()); 1093 ret=0; 1018 logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal part references in Joint #%d%s", i, nameForErrors().c_str()); 1019 ret = 0; 1020 } 1021 if (shape != SHAPE_ILLEGAL) 1022 { 1023 if ((j->shape == Joint::SHAPE_DEFAULT) ^ (shape == SHAPE_OLD)) 1024 { 1025 shape = SHAPE_ILLEGAL; 1026 logPrintf("Model", "internalCheck", LOG_WARN, "Inconsistent joint shapes (mixed old and new shapes)%s", nameForErrors().c_str()); 1027 } 1028 } 1029 } 1030 } 1031 #ifdef MODEL_V1_COMPATIBLE 1032 if (!addOldConnectionsInputs()) 1033 return 0; 1034 #endif 1035 1036 updateNeuroRefno(); // valid refno is important for n-n connections check (later) 1037 1038 for (i = 0; i < neurons.size(); i++) 1039 { 1040 n = (Neuro*)neurons(i); 1041 VALIDMINMAX(n, Neuro, state); 1042 #ifdef MODEL_V1_COMPATIBLE 1043 VALIDMINMAX(n,Neuro,inertia); 1044 VALIDMINMAX(n,Neuro,force); 1045 VALIDMINMAX(n,Neuro,sigmo); 1046 n->conn_refno=-1; 1047 n->weight=1.0; 1048 n->neuro_refno=-1; 1049 #endif 1050 n->part_refno = (n->part) ? n->part->refno : -1; 1051 n->joint_refno = (n->joint) ? n->joint->refno : -1; 1052 } 1053 1054 if (parts.size() && (checklevel > 0)) 1055 { 1056 for (i = 0; i < parts.size(); i++) 1057 { 1058 p = (Part*)parts(i); 1059 if (p->shape == 0) 1060 if (p->mass <= 0.001) 1061 p->mass = 1.0; 1062 p->flags &= ~LINKFLAG; 1063 } 1064 getPart(0)->flags |= LINKFLAG; 1065 int change = 1; 1066 while (change) 1067 { 1068 change = 0; 1069 for (i = 0; i < joints.size(); i++) 1070 { 1071 j = (Joint*)joints(i); 1072 if (j->part1->flags&LINKFLAG) 1073 { 1074 if (!(j->part2->flags&LINKFLAG)) 1075 { 1076 change = 1; 1077 j->part2->flags |= LINKFLAG; 1078 } 1079 } 1080 else 1081 if (j->part2->flags&LINKFLAG) 1082 { 1083 if (!(j->part1->flags&LINKFLAG)) 1084 { 1085 change = 1; 1086 j->part1->flags |= LINKFLAG; 1087 } 1088 } 1089 } 1090 } 1091 for (i = 0; i < parts.size(); i++) 1092 { 1093 p = (Part*)parts(i); 1094 if (!(p->flags&LINKFLAG)) 1095 { 1096 logPrintf("Model", "internalCheck", LOG_ERROR, "Not all parts connected (eg. Part #0 and Part #%d)%s", i, nameForErrors().c_str()); 1097 ret = 0; 1098 break; 1099 } 1100 } 1101 } 1102 1103 for (i = 0; i < joints.size(); i++) 1104 { 1105 j = (Joint*)joints(i); 1106 if (j->p1_refno == j->p2_refno) 1107 { 1108 logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal self connection, Joint #%d%s", i, nameForErrors().c_str()); 1109 ret = 0; 1094 1110 break; 1111 } 1112 for (k = i + 1; k < joints.size(); k++) 1113 { 1114 Joint* j2 = (Joint*)joints(k); 1115 if (((j->p1_refno == j2->p1_refno) && (j->p2_refno == j2->p2_refno)) 1116 || ((j->p1_refno == j2->p2_refno) && (j->p2_refno == j2->p1_refno))) 1117 { 1118 logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal duplicate Joint #%d and Joint #%d%s", i, k, nameForErrors().c_str()); 1119 ret = 0; 1120 break; 1095 1121 } 1096 1122 } 1097 1123 } 1098 1099 for (i=0;i<joints.size();i++) 1100 { 1101 j=(Joint*)joints(i); 1102 if (j->p1_refno==j->p2_refno) 1103 { 1104 logPrintf("Model","internalCheck",LOG_ERROR,"Illegal self connection, Joint #%d%s",i,nameForErrors().c_str()); 1105 ret=0; 1106 break; 1107 } 1108 for (k=i+1;k<joints.size();k++) 1109 { 1110 Joint* j2=(Joint*)joints(k); 1111 if (((j->p1_refno==j2->p1_refno)&&(j->p2_refno==j2->p2_refno)) 1112 || ((j->p1_refno==j2->p2_refno)&&(j->p2_refno==j2->p1_refno))) 1113 { 1114 logPrintf("Model","internalCheck",LOG_ERROR,"Illegal duplicate Joint #%d and Joint #%d%s",i,k,nameForErrors().c_str()); 1115 ret=0; 1116 break; 1117 } 1118 } 1119 } 1120 if (shape==SHAPE_ILLEGAL) 1121 ret=0; 1122 return ret; 1124 if (shape == SHAPE_ILLEGAL) 1125 ret = 0; 1126 return ret; 1123 1127 } 1124 1128 … … 1127 1131 int Model::getErrorPosition(bool includingwarnings) 1128 1132 { 1129 return includingwarnings?1130 ((f0errorposition>=0) ? f0errorposition : f0warnposition)1131 :1132 f0errorposition;1133 return includingwarnings ? 1134 ((f0errorposition >= 0) ? f0errorposition : f0warnposition) 1135 : 1136 f0errorposition; 1133 1137 } 1134 1138 1135 1139 const Geno& Model::getGeno() const 1136 1140 { 1137 return geno;1141 return geno; 1138 1142 } 1139 1143 1140 1144 const Geno Model::getF0Geno() 1141 1145 { 1142 if (buildstatus==building)1143 logPrintf("Model","getGeno",LOG_WARN,"Model was not completed - missing close()");1144 if (buildstatus!=valid)1145 return Geno("",'0',"","invalid");1146 if (!f0genoknown)1147 { 1148 if (autobuildmaps)1149 { 1150 initF0Map();1151 makeGeno(f0geno,f0map);1152 } 1153 else1154 { 1155 delF0Map();1156 makeGeno(f0geno);1157 } 1158 f0genoknown=1;1159 } 1160 return f0geno;1146 if (buildstatus == building) 1147 logPrintf("Model", "getGeno", LOG_WARN, "Model was not completed - missing close()"); 1148 if (buildstatus != valid) 1149 return Geno("", '0', "", "invalid"); 1150 if (!f0genoknown) 1151 { 1152 if (autobuildmaps) 1153 { 1154 initF0Map(); 1155 makeGeno(f0geno, f0map); 1156 } 1157 else 1158 { 1159 delF0Map(); 1160 makeGeno(f0geno); 1161 } 1162 f0genoknown = 1; 1163 } 1164 return f0geno; 1161 1165 } 1162 1166 1163 1167 int Model::getPartCount() const 1164 1168 { 1165 return parts.size();1169 return parts.size(); 1166 1170 } 1167 1171 1168 1172 Part* Model::getPart(int i) const 1169 1173 { 1170 return ((Part*)parts(i));1174 return ((Part*)parts(i)); 1171 1175 } 1172 1176 1173 1177 int Model::getJointCount() const 1174 1178 { 1175 return joints.size();1179 return joints.size(); 1176 1180 } 1177 1181 1178 1182 Joint* Model::getJoint(int i) const 1179 1183 { 1180 return ((Joint*)joints(i));1181 } 1182 1183 int Model::findJoints(SList& result, const Part* part)1184 { 1185 Joint *j;1186 int n0=result.size();1187 if (part)1188 for(int i=0;j=(Joint*)joints(i);i++)1189 if ((j->part1 == part) || (j->part2 == part)) result+=(void*)j;1190 return result.size()-n0;1184 return ((Joint*)joints(i)); 1185 } 1186 1187 int Model::findJoints(SList& result, const Part* part) 1188 { 1189 Joint *j; 1190 int n0 = result.size(); 1191 if (part) 1192 for (int i = 0; j = (Joint*)joints(i); i++) 1193 if ((j->part1 == part) || (j->part2 == part)) result += (void*)j; 1194 return result.size() - n0; 1191 1195 } 1192 1196 1193 1197 int Model::findNeuro(Neuro* n) 1194 {return neurons.find(n);} 1198 { 1199 return neurons.find(n); 1200 } 1195 1201 1196 1202 int Model::findPart(Part* p) 1197 {return parts.find(p);} 1203 { 1204 return parts.find(p); 1205 } 1198 1206 1199 1207 int Model::findJoint(Joint* j) 1200 {return joints.find(j);} 1208 { 1209 return joints.find(j); 1210 } 1201 1211 1202 1212 int Model::findJoint(Part *p1, Part *p2) 1203 1213 { 1204 Joint* j;1205 for(int i=0;j=getJoint(i);i++)1206 if ((j->part1==p1)&&(j->part2==p2)) return i;1207 return -1;1214 Joint* j; 1215 for (int i = 0; j = getJoint(i); i++) 1216 if ((j->part1 == p1) && (j->part2 == p2)) return i; 1217 return -1; 1208 1218 } 1209 1219 … … 1214 1224 void Model::calcOldNeuroCount() 1215 1225 { 1216 if (oldneurocount>=0) return;1217 oldneurocount=reorderToOldLayout();1226 if (oldneurocount>=0) return; 1227 oldneurocount=reorderToOldLayout(); 1218 1228 } 1219 1229 1220 1230 int Model::old_getNeuroCount() 1221 1231 { calcOldNeuroCount(); 1222 1232 return oldneurocount;} 1223 1233 1224 1234 Neuro* Model::old_getNeuro(int i) … … 1233 1243 Neuro *Model::old_addNewNeuro() 1234 1244 { 1235 int count=old_getNeuroCount();1236 Neuro *nu=addNewNeuro();1237 nu->setClassName("N");1238 moveNeuro(nu->refno,oldneurocount);1239 oldneurocount=count+1;1240 return (Neuro*)nu;1245 int count=old_getNeuroCount(); 1246 Neuro *nu=addNewNeuro(); 1247 nu->setClassName("N"); 1248 moveNeuro(nu->refno,oldneurocount); 1249 oldneurocount=count+1; 1250 return (Neuro*)nu; 1241 1251 } 1242 1252 #endif … … 1245 1255 1246 1256 int Model::getNeuroCount() const 1247 {return neurons.size();} 1257 { 1258 return neurons.size(); 1259 } 1248 1260 1249 1261 Neuro* Model::getNeuro(int i) const 1250 {return (Neuro*)neurons(i);} 1262 { 1263 return (Neuro*)neurons(i); 1264 } 1251 1265 1252 1266 int Model::getConnectionCount() const 1253 1267 { 1254 int n=0;1255 for(int i=0;i<getNeuroCount();i++)1256 n+=getNeuro(i)->getInputCount();1257 return n;1268 int n = 0; 1269 for (int i = 0; i < getNeuroCount(); i++) 1270 n += getNeuro(i)->getInputCount(); 1271 return n; 1258 1272 } 1259 1273 1260 1274 int Model::findNeuros(SList& result, 1261 const char* classname,const Part* part,const Joint* joint)1262 { 1263 Neuro *nu;1264 SString cn(classname);1265 int n0=result.size();1266 for(int i=0;nu=(Neuro*)neurons(i);i++)1267 { 1268 if (part)1269 if (nu->part != part) continue;1270 if (joint)1271 if (nu->joint != joint) continue;1272 if (classname)1273 if (nu->getClassName() != cn) continue;1274 result+=(void*)nu;1275 } 1276 return result.size()-n0;1275 const char* classname, const Part* part, const Joint* joint) 1276 { 1277 Neuro *nu; 1278 SString cn(classname); 1279 int n0 = result.size(); 1280 for (int i = 0; nu = (Neuro*)neurons(i); i++) 1281 { 1282 if (part) 1283 if (nu->part != part) continue; 1284 if (joint) 1285 if (nu->joint != joint) continue; 1286 if (classname) 1287 if (nu->getClassName() != cn) continue; 1288 result += (void*)nu; 1289 } 1290 return result.size() - n0; 1277 1291 } 1278 1292 … … 1281 1295 void Model::disturb(double amount) 1282 1296 { 1283 int i;1284 if (amount<=0) return;1285 for(i=0;i<parts.size();i++)1286 { 1287 Part *p=getPart(i);1288 p->p.x+=(rnd01-0.5)*amount;1289 p->p.y+=(rnd01-0.5)*amount;1290 p->p.z+=(rnd01-0.5)*amount;1291 } 1292 for(i=0;i<joints.size();i++)1293 { 1294 Joint *j=getJoint(i);1295 Pt3D tmpp(j->part2->p);1296 tmpp-=j->part1->p;1297 j->d=j->part2->o.revTransform(tmpp);1297 int i; 1298 if (amount <= 0) return; 1299 for (i = 0; i < parts.size(); i++) 1300 { 1301 Part *p = getPart(i); 1302 p->p.x += (rnd01 - 0.5)*amount; 1303 p->p.y += (rnd01 - 0.5)*amount; 1304 p->p.z += (rnd01 - 0.5)*amount; 1305 } 1306 for (i = 0; i < joints.size(); i++) 1307 { 1308 Joint *j = getJoint(i); 1309 Pt3D tmpp(j->part2->p); 1310 tmpp -= j->part1->p; 1311 j->d = j->part2->o.revTransform(tmpp); 1298 1312 } 1299 1313 } … … 1301 1315 void Model::move(const Pt3D& shift) 1302 1316 { 1303 FOREACH(Part*,p,parts)1304 p->p+=shift;1317 FOREACH(Part*, p, parts) 1318 p->p += shift; 1305 1319 } 1306 1320 1307 1321 void Model::rotate(const Orient& rotation) 1308 1322 { 1309 FOREACH(Part*,p,parts)1310 { 1311 p->p=rotation.transform(p->p);1312 p->setOrient(rotation.transform(p->o));1323 FOREACH(Part*, p, parts) 1324 { 1325 p->p = rotation.transform(p->p); 1326 p->setOrient(rotation.transform(p->o)); 1313 1327 } 1314 1328 } … … 1316 1330 void Model::buildUsingNewShapes(const Model& old, Part::Shape default_shape, float thickness) 1317 1331 { 1318 for(int i=0;i<old.getJointCount();i++)1319 { 1320 Joint *oj=old.getJoint(i);1321 Part *p = addNewPart(default_shape);1322 p->p=(oj->part1->p+oj->part2->p)/2;1323 Orient o;1324 o.lookAt(oj->part1->p-oj->part2->p);1325 p->rot=o.getAngles();1326 p->scale.x=oj->part1->p.distanceTo(oj->part2->p)/2;1327 p->scale.y = thickness;1328 p->scale.z = thickness;1329 } 1330 for(int i=0;i<old.getPartCount();i++)1331 { 1332 Part *op=old.getPart(i);1333 for(int j=0;j<old.getJointCount();j++)1334 { 1335 Joint *oj=old.getJoint(j);1336 if ((oj->part1==op)||(oj->part2==op))1332 for (int i = 0; i < old.getJointCount(); i++) 1333 { 1334 Joint *oj = old.getJoint(i); 1335 Part *p = addNewPart(default_shape); 1336 p->p = (oj->part1->p + oj->part2->p) / 2; 1337 Orient o; 1338 o.lookAt(oj->part1->p - oj->part2->p); 1339 p->rot = o.getAngles(); 1340 p->scale.x = oj->part1->p.distanceTo(oj->part2->p) / 2; 1341 p->scale.y = thickness; 1342 p->scale.z = thickness; 1343 } 1344 for (int i = 0; i < old.getPartCount(); i++) 1345 { 1346 Part *op = old.getPart(i); 1347 for (int j = 0; j < old.getJointCount(); j++) 1348 { 1349 Joint *oj = old.getJoint(j); 1350 if ((oj->part1 == op) || (oj->part2 == op)) 1337 1351 { 1338 for(int j2=j+1;j2<old.getJointCount();j2++)1352 for (int j2 = j + 1; j2 < old.getJointCount(); j2++) 1339 1353 { 1340 Joint *oj2=old.getJoint(j2);1341 if ((oj2->part1==op)||(oj2->part2==op))1354 Joint *oj2 = old.getJoint(j2); 1355 if ((oj2->part1 == op) || (oj2->part2 == op)) 1342 1356 { 1343 addNewJoint(getPart(j),getPart(j2),Joint::SHAPE_SOLID);1357 addNewJoint(getPart(j), getPart(j2), Joint::SHAPE_SOLID); 1344 1358 } 1345 1359 } 1346 break;1360 break; 1347 1361 } 1348 1362 } … … 1352 1366 ////////////////////// 1353 1367 1354 class MinPart : public Part {public: MinPart() {Param par(f0_part_paramtab,this);par.setMin();}};1355 class MaxPart : public Part {public: MaxPart() {Param par(f0_part_paramtab,this);par.setMax();}};1356 class MinJoint : public Joint {public: MinJoint() {Param par(f0_joint_paramtab,this);par.setMin();}};1357 class MaxJoint : public Joint {public: MaxJoint() {Param par(f0_joint_paramtab,this);par.setMax();}};1358 class MinNeuro : public Neuro {public: MinNeuro() {Param par(f0_neuro_paramtab,this);par.setMin();}};1359 class MaxNeuro : public Neuro {public: MaxNeuro() {Param par(f0_neuro_paramtab,this);par.setMax();}};1360 1361 Part& Model::getMinPart() { static MinPart part; return part;}1362 Part& Model::getMaxPart() { static MaxPart part; return part;}1363 Part& Model::getDefPart() { static Part part; return part;}1364 Joint& Model::getMinJoint() { static MinJoint joint; return joint;}1365 Joint& Model::getMaxJoint() { static MaxJoint joint; return joint;}1366 Joint& Model::getDefJoint() { static Joint joint; return joint;}1367 Neuro& Model::getMinNeuro() { static MinNeuro neuro; return neuro;}1368 Neuro& Model::getMaxNeuro() { static MaxNeuro neuro; return neuro;}1369 Neuro& Model::getDefNeuro() { static Neuro neuro; return neuro;}1368 class MinPart : public Part { public: MinPart() { Param par(f0_part_paramtab, this); par.setMin(); } }; 1369 class MaxPart : public Part { public: MaxPart() { Param par(f0_part_paramtab, this); par.setMax(); } }; 1370 class MinJoint : public Joint { public: MinJoint() { Param par(f0_joint_paramtab, this); par.setMin(); } }; 1371 class MaxJoint : public Joint { public: MaxJoint() { Param par(f0_joint_paramtab, this); par.setMax(); } }; 1372 class MinNeuro : public Neuro { public: MinNeuro() { Param par(f0_neuro_paramtab, this); par.setMin(); } }; 1373 class MaxNeuro : public Neuro { public: MaxNeuro() { Param par(f0_neuro_paramtab, this); par.setMax(); } }; 1374 1375 Part& Model::getMinPart() { static MinPart part; return part; } 1376 Part& Model::getMaxPart() { static MaxPart part; return part; } 1377 Part& Model::getDefPart() { static Part part; return part; } 1378 Joint& Model::getMinJoint() { static MinJoint joint; return joint; } 1379 Joint& Model::getMaxJoint() { static MaxJoint joint; return joint; } 1380 Joint& Model::getDefJoint() { static Joint joint; return joint; } 1381 Neuro& Model::getMinNeuro() { static MinNeuro neuro; return neuro; } 1382 Neuro& Model::getMaxNeuro() { static MaxNeuro neuro; return neuro; } 1383 Neuro& Model::getDefNeuro() { static Neuro neuro; return neuro; } -
cpp/frams/model/model.h
r495 r522 18 18 //#define EASYMAPDEBUG 19 19 20 enum ModelBuildStatus { empty,building,invalid,valid};20 enum ModelBuildStatus { empty, building, invalid, valid }; 21 21 22 22 class MultiMap; … … 25 25 26 26 /** 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 \f[(dot)45 digraph Model46 47 48 49 50 51 52 53 54 55 \f]56 */57 58 class Model : public DestrBase27 "Model" is the skeleton of the Framsticks creature. 28 This object can be used for 2 purposes: 29 - you can build a creature from any supported Framsticks genotype 30 format 31 - or generate low level f0 genotype from existing construct. 32 33 In both cases you have access to geometry and neuron net data. 34 Using this standard class assures compatibility and good 35 integration with core Framsticks engine. 36 37 Model contains 3 kinds of objects: 38 - Parts (class Part). 39 - Joints (class Joint). Each Joint is connected with 2 Parts. (@see Joint::attachToParts()). 40 - Neurons (class Neuro). Neuron can have 0 or more inputs - other neurons. (@see Neuro::addInput()). 41 Each Neuron can be located on the physical structure, i.e. it can ba attached to Part or Joint 42 (@see Neuro::attachToPart(), Neuro::attachToJoint()). 43 44 \f[(dot) 45 digraph Model 46 { 47 Joint1; Joint2; 48 node [ shape=box ] 49 Part1; Part2; Part3; 50 Joint1 -> Part1; Joint1 -> Part2; Joint2 -> Part2; Joint2 -> Part3 51 node [ shape=diamond ] 52 Neuro1 -> Neuro2; Neuro1 -> Neuro3; Neuro2 -> Neuro2; Neuro3 -> Neuro2; 53 Neuro1 -> Part1; Neuro2 -> Joint2; 54 } 55 \f] 56 */ 57 58 class Model : public DestrBase 59 59 { 60 61 Geno geno,f0geno;62 char modelfromgenotype;63 char f0genoknown;64 /// make model map in build()65 bool autobuildmaps;66 /// valid if build from f0 genotype67 int f0errorposition;68 /// valid if build from f0 genotype69 int f0warnposition;70 71 ModelBuildStatus buildstatus;72 /// NULL if the map is not (yet) created73 MultiMap *map,*f0map;74 75 SList parts,joints,neurons;76 char partmappingchanged;60 protected: 61 Geno geno, f0geno; 62 char modelfromgenotype; 63 char f0genoknown; 64 /// make model map in build() 65 bool autobuildmaps; 66 /// valid if build from f0 genotype 67 int f0errorposition; 68 /// valid if build from f0 genotype 69 int f0warnposition; 70 71 ModelBuildStatus buildstatus; 72 /// NULL if the map is not (yet) created 73 MultiMap *map, *f0map; 74 75 SList parts, joints, neurons; 76 char partmappingchanged; 77 77 78 78 #ifdef MODEL_V1_COMPATIBLE 79 /** NeuroCount value.80 81 82 */83 int oldneurocount;84 char oldconnections;85 86 /** calculate oldNeuroCount */87 void calcOldNeuroCount();88 /** some new calls can invalidate old compatibility data */89 void invalidateOldNeuroCount() {oldneurocount=-1;}90 /**91 for compatibility with old NeuroClass the layout of Neurons92 is changed when old 'Neuro' accessing methods are in use.93 Neurons:94 0 .. compatibility_neurocount-1 : old Neurons (class "N")95 compatibility_neurocount .. neurons.size()-1 : other units96 */97 int reorderToOldLayout();98 99 /** check if compatibility should be preserved */100 int hasOldNeuroLayout() {return oldneurocount>=0;}101 102 /** add inputs to the old "-" units.103 104 int addOldConnectionsInputs();79 /** NeuroCount value. 80 compatibility_neurocount = -1 if its value is unknown and the layout is not compatible 81 @see reorderToOldLayout() 82 */ 83 int oldneurocount; 84 char oldconnections; 85 86 /** calculate oldNeuroCount */ 87 void calcOldNeuroCount(); 88 /** some new calls can invalidate old compatibility data */ 89 void invalidateOldNeuroCount() {oldneurocount=-1;} 90 /** 91 for compatibility with old NeuroClass the layout of Neurons 92 is changed when old 'Neuro' accessing methods are in use. 93 Neurons: 94 0 .. compatibility_neurocount-1 : old Neurons (class "N") 95 compatibility_neurocount .. neurons.size()-1 : other units 96 */ 97 int reorderToOldLayout(); 98 99 /** check if compatibility should be preserved */ 100 int hasOldNeuroLayout() {return oldneurocount>=0;} 101 102 /** add inputs to the old "-" units. 103 @return 1=ok, 0=invalid input detected */ 104 int addOldConnectionsInputs(); 105 105 #endif 106 106 107 void internalCopy(const Model &mod); 108 109 /// make the model from current genotype 110 void build(); 111 112 friend class NeuroNetFactory; 113 friend class VisualModel; 114 friend class GLVisualModel; 115 friend class Creature; 116 friend class PartBase; 117 118 int checklevel; 119 120 public: 121 enum Shape {SHAPE_UNKNOWN,SHAPE_ILLEGAL,SHAPE_OLD,SHAPE_NEW}; 122 protected: 123 Shape shape; 124 125 void updateNeuroRefno(); // set Neuro::refno for all neurons 126 SString nameForErrors() const; 127 int internalcheck(int final); 128 129 void moveNeuro(int oldpos,int newpos); 130 131 void init(const Geno &srcgen); 132 void init(); 133 134 void delMap(); 135 void delF0Map(); 136 void initMap(); 137 void initF0Map(); 107 void internalCopy(const Model &mod); 108 109 /// make the model from current genotype 110 void build(); 111 112 friend class NeuroNetFactory; 113 friend class VisualModel; 114 friend class GLVisualModel; 115 friend class Creature; 116 friend class PartBase; 117 118 int checklevel; 138 119 139 120 public: 140 /** get current model state. 141 \f[(dot) 142 digraph M 143 { 144 node [fontsize=12] 145 edge [fontsize=10] 146 building [label="building = can be modified"] 147 valid -> building [label="open()"] 148 building -> valid [label="close()"] 149 invalid -> building [label="open()"] 150 building -> invalid [label="close() [failed]"] 151 empty -> building [label="open()"] 152 } 153 \f] 154 */ 155 ModelBuildStatus getStatus() const {return buildstatus;} 156 int isValid() const {return buildstatus==valid;} 157 int getErrorPosition(bool includingwarnings=false); 158 Shape getShape() {return shape;} 159 160 void updateRefno(); // set ::refno for all elements 161 162 /// The bounding box size. Valid if the model is valid. Read only. 163 Pt3D size; 164 165 SString vis_style; 166 double startenergy; 167 Callback delmodel_list; 168 ModelUserTags userdata; 169 170 /// Create empty model with invalid empty genotype 171 Model(); 172 173 /** Create a model based on provided genotype 174 @param buildmaps if not 0, generate mapping information for the model. 175 default is 0, because mapping uses additional time and memory. 176 @see getMap() 177 */ 178 Model(const Geno &src,bool buildmaps=false); 179 Model(const Model &mod,bool buildmaps=false); 180 /** duplicate the model. 181 the resulting object's status is 'building' (opened). 182 @see getStatus() 183 */ 184 void operator=(const Model &source); 185 186 /** move all elements from 'source' into our model object. 187 'source' becomes empty after this operation. 188 the model will be opened if it is not already open. 189 @see addElementsFrom(const Model &source); 190 */ 191 void moveElementsFrom(Model &source); 192 193 /** copy all elements from 'source' into our model object 194 without affecting the 'source'. 195 the model will be opened if it is not already open. 196 @see moveElementsFrom(Model &source); 197 */ 198 void addElementsFrom(const Model &source) 199 {Model m(source); moveElementsFrom(m);} 200 201 void operator+=(const Model &source) 202 {addElementsFrom(source);} 203 204 ~Model(); 205 206 /** @return source genotype. 207 @warn source genotype will not automatically change 208 when the model is modified. this behaviour is inconsistent 209 with the previous release. use getF0Geno() if you need 210 the updated genotype. 211 @see getF0Geno(), setGeno() 212 */ 213 const Geno &getGeno() const; 214 215 /// change source genotype 216 void setGeno(const Geno& newgeno); 217 218 /** @return f0 genotype - generated from current model state 219 don't use between open()-close() 220 */ 221 const Geno getF0Geno(); 222 223 /// make f0 genotype from current construction (low level version of getF0Geno) 224 void makeGeno(Geno &,MultiMap *map=0,bool handle_defaults=true); 225 226 /** @return Mapping from source genotype (0-based position in text) to model elements reference numbers. 227 Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf 228 The map can be empty if the mapping hasn't been requested earlier (in constructor) 229 or the converters don't support mapping. 230 If you create or modify the model using singleStepBuild() or direct manipulation 231 the map will be not changed or created automatically - it is your responsibility. 232 @see Model(const Geno &src,int buildmaps=0), singleStepBuild(), PartBase::addMapping() 233 @see clearMap() 234 @see convmap 235 236 */ 237 MultiMap &getMap(); 238 239 /** Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf 240 @return mapping from f0 genotype (0-based position in text) to model elements reference numbers 241 */ 242 const MultiMap &getF0Map(); 243 244 /** discard all mapping information for this model. 245 getMap().clear() also works, but it doesn't remove mappings from model elements. 246 If there are any mappings, they will be incorporated into model map during close(). 247 @see close(), getMap(), PartBase::clearMapping() 248 */ 249 void clearMap(); 250 251 /** Generate mapping from the current genotype to the f0 genotype. 252 This works only if both current and f0 maps are already known. 253 Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf 254 @see convmap 255 */ 256 void getCurrentToF0Map(MultiMap& m); 257 258 void setValidationLevel(int level) 259 {checklevel=level;} 260 261 /// calculate location of the new part connected to the existing one 262 /// using delta option 263 Pt3D whereDelta(const Part& start,const Pt3D& rot, const Pt3D& delta); 264 265 /// create the whole model from scratch, using current genotype 266 void rebuild(bool buildmaps); 267 268 /// setGeno(newgeno); rebuild(); 269 void rebuild(const Geno& newgeno,bool buildmaps) {setGeno(newgeno); rebuild(buildmaps);} 270 271 /// reuse current model object but discard all model data 272 void clear(); 273 274 /** Execute single line of <B>f0</B> genotype. 275 Return value is non-negative reference number of the created item, 276 or negative value. reference number can be used to access 277 the item using getPart(int), getJoint(int) and getNeuroItem(int) methods. 278 @param line_num optional line number used in error messages 279 @param srcrange source genotype range which will be mapped to this element 280 */ 281 int singleStepBuild(const SString &singleline,int line_num,const MultiRange* srcrange=NULL); 282 /** Execute single line of <B>f0</B> genotype - compatiblity variant */ 283 int singleStepBuild(const SString &singleline,const MultiRange* srcrange=NULL); 284 /** Execute single line of <B>f0</B> genotype - low level variant, used by Model::build(), error messages returned as string instead of calling logger */ 285 int singleStepBuildNoLog(const SString &singleline,SString& error_message,const MultiRange* srcrange=0); 286 287 /// separate build stages (for future use) 288 void checkpoint(); 289 290 /// call resetDelta() on all joints 291 void resetAllDelta(); 292 293 /// call useDelta() on all joints 294 void useAllDelta(bool yesno); 295 296 /// Final validity check of the model, all model data has to be available at this point. 297 /// If the model was modified, the genotype will be also updated. 298 /// It also calls "validate" with all side effects. 299 /// @return > 0 means "valid" 300 int close(); 301 302 /// Enable model building. 303 /// You should use it if you need to create new model, modify the model after close 304 /// or modify the model created from the genotype. 305 /// Between open() and close() the model is not fully usable. 306 void open(); 307 308 /// Current model written as f0 genotype while building 309 /// (not cached, not validated, probably unusable and bad if used before close(). But good for debugging.) 310 Geno rawGeno(); 311 312 /// partial validity check - you can use this call 313 /// anytime between open - close. 314 /// this function will check (and repair) 315 /// - part-joint-neuro connections 316 /// - model geometry (if "delta option" was used) 317 /// - physical/biological limits 318 /// @return 1 = valid 319 /// @return 0 = invalid 320 /// validate doesn't make the model fully usable (for simulation) 321 /// you still need to use close if you have changed anything 322 int validate(); 323 324 int getPartCount() const; 325 /// you can access parts 0 .. getPartCount()-1. 326 Part *getPart(int i) const; 327 328 int getJointCount() const; 329 /// you can access joints 0 .. getJointCount()-1. 330 Joint *getJoint(int i) const; 331 332 int getNeuroCount() const; 333 int getConnectionCount() const; 334 /// you can access neurons 0 .. getNeuroCount()-1. 335 Neuro *getNeuro(int i) const; 121 enum Shape { SHAPE_UNKNOWN, SHAPE_ILLEGAL, SHAPE_OLD, SHAPE_NEW }; 122 protected: 123 Shape shape; 124 125 void updateNeuroRefno(); // set Neuro::refno for all neurons 126 SString nameForErrors() const; 127 int internalcheck(int final); 128 129 void moveNeuro(int oldpos, int newpos); 130 131 void init(const Geno &srcgen); 132 void init(); 133 134 void delMap(); 135 void delF0Map(); 136 void initMap(); 137 void initF0Map(); 138 139 public: 140 /** get current model state. 141 \f[(dot) 142 digraph M 143 { 144 node [fontsize=12] 145 edge [fontsize=10] 146 building [label="building = can be modified"] 147 valid -> building [label="open()"] 148 building -> valid [label="close()"] 149 invalid -> building [label="open()"] 150 building -> invalid [label="close() [failed]"] 151 empty -> building [label="open()"] 152 } 153 \f] 154 */ 155 ModelBuildStatus getStatus() const { return buildstatus; } 156 int isValid() const { return buildstatus == valid; } 157 int getErrorPosition(bool includingwarnings = false); 158 Shape getShape() { return shape; } 159 160 void updateRefno(); // set ::refno for all elements 161 162 /// The bounding box size. Valid if the model is valid. Read only. 163 Pt3D size; 164 165 SString vis_style; 166 double startenergy; 167 Callback delmodel_list; 168 ModelUserTags userdata; 169 170 /// Create empty model with invalid empty genotype 171 Model(); 172 173 /** Create a model based on provided genotype 174 @param buildmaps if not 0, generate mapping information for the model. 175 default is 0, because mapping uses additional time and memory. 176 @see getMap() 177 */ 178 Model(const Geno &src, bool buildmaps = false); 179 Model(const Model &mod, bool buildmaps = false); 180 /** duplicate the model. 181 the resulting object's status is 'building' (opened). 182 @see getStatus() 183 */ 184 void operator=(const Model &source); 185 186 /** move all elements from 'source' into our model object. 187 'source' becomes empty after this operation. 188 the model will be opened if it is not already open. 189 @see addElementsFrom(const Model &source); 190 */ 191 void moveElementsFrom(Model &source); 192 193 /** copy all elements from 'source' into our model object 194 without affecting the 'source'. 195 the model will be opened if it is not already open. 196 @see moveElementsFrom(Model &source); 197 */ 198 void addElementsFrom(const Model &source) 199 { 200 Model m(source); moveElementsFrom(m); 201 } 202 203 void operator+=(const Model &source) 204 { 205 addElementsFrom(source); 206 } 207 208 ~Model(); 209 210 /** @return source genotype. 211 @warn source genotype will not automatically change 212 when the model is modified. this behaviour is inconsistent 213 with the previous release. use getF0Geno() if you need 214 the updated genotype. 215 @see getF0Geno(), setGeno() 216 */ 217 const Geno &getGeno() const; 218 219 /// change source genotype 220 void setGeno(const Geno& newgeno); 221 222 /** @return f0 genotype - generated from current model state 223 don't use between open()-close() 224 */ 225 const Geno getF0Geno(); 226 227 /// make f0 genotype from current construction (low level version of getF0Geno) 228 void makeGeno(Geno &, MultiMap *map = 0, bool handle_defaults = true); 229 230 /** @return Mapping from source genotype (0-based position in text) to model elements reference numbers. 231 Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf 232 The map can be empty if the mapping hasn't been requested earlier (in constructor) 233 or the converters don't support mapping. 234 If you create or modify the model using singleStepBuild() or direct manipulation 235 the map will be not changed or created automatically - it is your responsibility. 236 @see Model(const Geno &src,int buildmaps=0), singleStepBuild(), PartBase::addMapping() 237 @see clearMap() 238 @see convmap 239 240 */ 241 MultiMap &getMap(); 242 243 /** Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf 244 @return mapping from f0 genotype (0-based position in text) to model elements reference numbers 245 */ 246 const MultiMap &getF0Map(); 247 248 /** discard all mapping information for this model. 249 getMap().clear() also works, but it doesn't remove mappings from model elements. 250 If there are any mappings, they will be incorporated into model map during close(). 251 @see close(), getMap(), PartBase::clearMapping() 252 */ 253 void clearMap(); 254 255 /** Generate mapping from the current genotype to the f0 genotype. 256 This works only if both current and f0 maps are already known. 257 Read about how mappings work: http://www.framsticks.com/files/common/GeneticMappingsInArtificialGenomes.pdf 258 @see convmap 259 */ 260 void getCurrentToF0Map(MultiMap& m); 261 262 void setValidationLevel(int level) 263 { 264 checklevel = level; 265 } 266 267 /// calculate location of the new part connected to the existing one 268 /// using delta option 269 Pt3D whereDelta(const Part& start, const Pt3D& rot, const Pt3D& delta); 270 271 /// create the whole model from scratch, using current genotype 272 void rebuild(bool buildmaps); 273 274 /// setGeno(newgeno); rebuild(); 275 void rebuild(const Geno& newgeno, bool buildmaps) { setGeno(newgeno); rebuild(buildmaps); } 276 277 /// reuse current model object but discard all model data 278 void clear(); 279 280 /** Execute single line of <B>f0</B> genotype. 281 Return value is non-negative reference number of the created item, 282 or negative value. reference number can be used to access 283 the item using getPart(int), getJoint(int) and getNeuroItem(int) methods. 284 @param line_num optional line number used in error messages 285 @param srcrange source genotype range which will be mapped to this element 286 */ 287 int singleStepBuild(const SString &singleline, int line_num, const MultiRange* srcrange = NULL); 288 /** Execute single line of <B>f0</B> genotype - compatiblity variant */ 289 int singleStepBuild(const SString &singleline, const MultiRange* srcrange = NULL); 290 /** Execute single line of <B>f0</B> genotype - low level variant, used by Model::build(), error messages returned as string instead of calling logger */ 291 int singleStepBuildNoLog(const SString &singleline, SString& error_message, const MultiRange* srcrange = 0); 292 293 /// separate build stages (for future use) 294 void checkpoint(); 295 296 /// call resetDelta() on all joints 297 void resetAllDelta(); 298 299 /// call useDelta() on all joints 300 void useAllDelta(bool yesno); 301 302 /// Final validity check of the model, all model data has to be available at this point. 303 /// If the model was modified, the genotype will be also updated. 304 /// It also calls "validate" with all side effects. 305 /// @return > 0 means "valid" 306 int close(); 307 308 /// Enable model building. 309 /// You should use it if you need to create new model, modify the model after close 310 /// or modify the model created from the genotype. 311 /// Between open() and close() the model is not fully usable. 312 void open(); 313 314 /// Current model written as f0 genotype while building 315 /// (not cached, not validated, probably unusable and bad if used before close(). But good for debugging.) 316 Geno rawGeno(); 317 318 /// partial validity check - you can use this call 319 /// anytime between open - close. 320 /// this function will check (and repair) 321 /// - part-joint-neuro connections 322 /// - model geometry (if "delta option" was used) 323 /// - physical/biological limits 324 /// @return 1 = valid 325 /// @return 0 = invalid 326 /// validate doesn't make the model fully usable (for simulation) 327 /// you still need to use close if you have changed anything 328 int validate(); 329 330 int getPartCount() const; 331 /// you can access parts 0 .. getPartCount()-1. 332 Part *getPart(int i) const; 333 334 int getJointCount() const; 335 /// you can access joints 0 .. getJointCount()-1. 336 Joint *getJoint(int i) const; 337 338 int getNeuroCount() const; 339 int getConnectionCount() const; 340 /// you can access neurons 0 .. getNeuroCount()-1. 341 Neuro *getNeuro(int i) const; 336 342 337 343 #ifdef MODEL_V1_COMPATIBLE 338 /* compatibility calls for accessing old Neuro objects */339 340 /// @deprecated Neuro class will be removed soon341 /// @see compat342 int old_getNeuroCount();343 /// you can access neurons 0 .. getNeuroCount()-1.344 /// @deprecated Neuro class will be removed soon345 Neuro *old_getNeuro(int i);346 /// @see addNewNeuro, addNeuro347 /// @deprecated Neuro class will be removed soon348 Neuro *old_addNewNeuro();349 /// @return neuro index or -1 if not found350 /// @deprecated Neuro class will be removed soon351 int old_findNeuro(Neuro* n);344 /* compatibility calls for accessing old Neuro objects */ 345 346 /// @deprecated Neuro class will be removed soon 347 /// @see compat 348 int old_getNeuroCount(); 349 /// you can access neurons 0 .. getNeuroCount()-1. 350 /// @deprecated Neuro class will be removed soon 351 Neuro *old_getNeuro(int i); 352 /// @see addNewNeuro, addNeuro 353 /// @deprecated Neuro class will be removed soon 354 Neuro *old_addNewNeuro(); 355 /// @return neuro index or -1 if not found 356 /// @deprecated Neuro class will be removed soon 357 int old_findNeuro(Neuro* n); 352 358 #endif 353 359 354 /** create new Part and add it to the model. @see addPart() */355 Part *addNewPart(Part::Shape shape=Part::SHAPE_DEFAULT) {return addPart(new Part(shape));}356 /** create new Joint and add it to the model. @see addJoint() */357 Joint *addNewJoint(Part *p1=NULL,Part *p2=NULL,Joint::Shape shape=Joint::SHAPE_DEFAULT) { Joint *j=addJoint(new Joint()); j->shape=shape; if ((p1!=NULL)&&(p2!=NULL)) j->attachToParts(p1,p2); return j;}358 /** create new Neuro and add it to the model. @see addNeuro() */359 Neuro *addNewNeuro() {return addNeuro(new Neuro());}360 361 /** add p to the model. p->refno is adjusted. @return the Part just added (==p). */362 Part *addPart(Part *p);363 /** add j to the model. j->refno is adjusted. @return the Joint just added (==j). */364 Joint *addJoint(Joint *j);365 /** add n to the model. n->refno is adjusted. @return the Neuro just added (==n). */366 Neuro *addNeuro(Neuro *n);367 368 /** remove the part from model.369 370 371 void removePart(int partindex,int removeattachedjoints=1,int removeattachedneurons=1);372 373 /** remove the joint from model.374 375 void removeJoint(int jointindex,int removeattachedneurons=1);376 377 /** remove the neuron from model.378 379 380 void removeNeuro(int neuroindex,bool removereferences=true);381 382 void removeNeuros(SList &nlist);383 384 /// @return part index or -1 if not found in the model385 int findPart(Part* p);386 /// @return joint index or -1 if not found in the model387 int findJoint(Joint* j);388 /// @return neuro index or -1 if not found in the model389 int findNeuro(Neuro* nu);390 /// @return joint index or -1 if not found in the model391 int findJoint(Part *p1, Part *p2);392 393 /** make the list of neuros satisfying given search criteria: classname,part,joint394 395 396 int findNeuros(SList& result,const char* classname=0,const Part* part=0,const Joint* joint=0);397 398 /** search for joints connected to the part399 400 @return number of objects found */ 401 int findJoints(SList& result,const Part* part=0);402 403 void disturb(double amount);404 void move(const Pt3D& shift);405 /// rotate around the origin (move-rotate-move to rotate around arbitrary point)406 void rotate(const Orient& rotation);407 /// rotate around the origin (move-rotate-move to rotate around arbitrary point)408 void rotate(const Pt3D& angles) {Orient o=Orient_1; o.rotate(angles); rotate(o);}409 410 /// build this model using new shapes, based on the provided model that uses old shapes. See also shapeconvert.cpp.411 void buildUsingNewShapes(const Model& src_old_shapes, Part::Shape default_shape = Part::SHAPE_CYLINDER, float thickness = 0.2);360 /** create new Part and add it to the model. @see addPart() */ 361 Part *addNewPart(Part::Shape shape = Part::SHAPE_DEFAULT) { return addPart(new Part(shape)); } 362 /** create new Joint and add it to the model. @see addJoint() */ 363 Joint *addNewJoint(Part *p1 = NULL, Part *p2 = NULL, Joint::Shape shape = Joint::SHAPE_DEFAULT) { Joint *j = addJoint(new Joint()); j->shape = shape; if ((p1 != NULL) && (p2 != NULL)) j->attachToParts(p1, p2); return j; } 364 /** create new Neuro and add it to the model. @see addNeuro() */ 365 Neuro *addNewNeuro() { return addNeuro(new Neuro()); } 366 367 /** add p to the model. p->refno is adjusted. @return the Part just added (==p). */ 368 Part *addPart(Part *p); 369 /** add j to the model. j->refno is adjusted. @return the Joint just added (==j). */ 370 Joint *addJoint(Joint *j); 371 /** add n to the model. n->refno is adjusted. @return the Neuro just added (==n). */ 372 Neuro *addNeuro(Neuro *n); 373 374 /** remove the part from model. 375 @param removeattachedjoints if not 0 -> remove all joints connected with this part 376 @param removeattachedneurons if not 0 -> remove neurons attached to this part */ 377 void removePart(int partindex, int removeattachedjoints = 1, int removeattachedneurons = 1); 378 379 /** remove the joint from model. 380 @param removeattachedneurons if not 0 -> remove neurons attached to this joint */ 381 void removeJoint(int jointindex, int removeattachedneurons = 1); 382 383 /** remove the neuron from model. 384 @param removereferences if true -> look for references to this neuron 385 (i.e. connections from other neurons) and remove them as well */ 386 void removeNeuro(int neuroindex, bool removereferences = true); 387 388 void removeNeuros(SList &nlist); 389 390 /// @return part index or -1 if not found in the model 391 int findPart(Part* p); 392 /// @return joint index or -1 if not found in the model 393 int findJoint(Joint* j); 394 /// @return neuro index or -1 if not found in the model 395 int findNeuro(Neuro* nu); 396 /// @return joint index or -1 if not found in the model 397 int findJoint(Part *p1, Part *p2); 398 399 /** make the list of neuros satisfying given search criteria: classname,part,joint 400 @param result objects will be appended here 401 @return number of objects found */ 402 int findNeuros(SList& result, const char* classname = 0, const Part* part = 0, const Joint* joint = 0); 403 404 /** search for joints connected to the part 405 @param result objects will be appended here 406 @return number of objects found */ 407 int findJoints(SList& result, const Part* part = 0); 408 409 void disturb(double amount); 410 void move(const Pt3D& shift); 411 /// rotate around the origin (move-rotate-move to rotate around arbitrary point) 412 void rotate(const Orient& rotation); 413 /// rotate around the origin (move-rotate-move to rotate around arbitrary point) 414 void rotate(const Pt3D& angles) { Orient o = Orient_1; o.rotate(angles); rotate(o); } 415 416 /// build this model using new shapes, based on the provided model that uses old shapes. See also shapeconvert.cpp. 417 void buildUsingNewShapes(const Model& src_old_shapes, Part::Shape default_shape = Part::SHAPE_CYLINDER, float thickness = 0.2); 412 418 413 419 #ifdef EASYMAPDEBUG 414 static int partToMap(int i) {return 0+i;}415 static int jointToMap(int i) {return 10+i;}416 static int neuroToMap(int i) {return 20+i;}417 static int mapToPart(int i) {return i-0;}418 static int mapToJoint(int i) {return i-10;}419 static int mapToNeuro(int i) {return i-20;}420 static int partToMap(int i) {return 0+i;} 421 static int jointToMap(int i) {return 10+i;} 422 static int neuroToMap(int i) {return 20+i;} 423 static int mapToPart(int i) {return i-0;} 424 static int mapToJoint(int i) {return i-10;} 425 static int mapToNeuro(int i) {return i-20;} 420 426 #else 421 static int partToMap(int i) {return 0x10000000+i;}422 static int jointToMap(int i) {return 0x20000000+i;}423 static int neuroToMap(int i) {return 0x30000000+i;}424 static int mapToPart(int i) {return i-0x10000000;}425 static int mapToJoint(int i) {return i-0x20000000;}426 static int mapToNeuro(int i) {return i-0x30000000;}427 static int partToMap(int i) { return 0x10000000 + i; } 428 static int jointToMap(int i) { return 0x20000000 + i; } 429 static int neuroToMap(int i) { return 0x30000000 + i; } 430 static int mapToPart(int i) { return i - 0x10000000; } 431 static int mapToJoint(int i) { return i - 0x20000000; } 432 static int mapToNeuro(int i) { return i - 0x30000000; } 427 433 #endif 428 434 429 static void makeGenToGenMap(MultiMap& result,const MultiMap& gen1tomodel,const MultiMap& gen2tomodel);430 431 ///////////////////////////432 433 static Part& getMinPart();434 static Part& getMaxPart();435 static Part& getDefPart();436 static Joint& getMinJoint();437 static Joint& getMaxJoint();438 static Joint& getDefJoint();439 static Neuro& getMinNeuro();440 static Neuro& getMaxNeuro();441 static Neuro& getDefNeuro();435 static void makeGenToGenMap(MultiMap& result, const MultiMap& gen1tomodel, const MultiMap& gen2tomodel); 436 437 /////////////////////////// 438 439 static Part& getMinPart(); 440 static Part& getMaxPart(); 441 static Part& getDefPart(); 442 static Joint& getMinJoint(); 443 static Joint& getMaxJoint(); 444 static Joint& getDefJoint(); 445 static Neuro& getMinNeuro(); 446 static Neuro& getMaxNeuro(); 447 static Neuro& getDefNeuro(); 442 448 }; 443 449
Note: See TracChangeset
for help on using the changeset viewer.