source: cpp/gdk/model.h @ 5

Last change on this file since 5 was 5, checked in by sz, 15 years ago

added the GDK (Genotype Development Kit)

File size: 13.2 KB
Line 
1// This file is a part of Framsticks GDK library.
2// Copyright (C) 2002-2006  Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.frams.alife.pl/ for further information.
4
5#ifndef _MODEL_H_
6#define _MODEL_H_
7
8#include <stdlib.h>
9#include <math.h>
10#include <stdio.h>
11
12#include "modelparts.h"
13#include "advlist.h"
14#include "usertags.h"
15
16extern ParamEntry f0_model_paramtab[];
17
18//#define EASYMAPDEBUG
19
20enum ModelBuildStatus {empty,building,invalid,valid};
21
22class MultiMap;
23
24class VisualModel;
25
26/**
27    "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)
45digraph 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
58class Model: public DestrBase
59{
60  protected:
61Geno geno,f0geno;
62char modelfromgenotype;
63char f0genoknown;
64/// make model map in build()
65char autobuildmaps;
66/// valid if build from f0 genotype
67int f0errorposition;
68/// valid if build from f0 genotype
69int f0warnposition;
70
71ModelBuildStatus buildstatus;
72/// NULL if the map is not (yet) created
73MultiMap *map,*f0map;
74
75SList parts,joints,neurons;
76char partmappingchanged;
77
78#ifdef MODEL_V1_COMPATIBLE
79/** NeuroCount value.
80    compatibility_neurocount = -1 if its value is unknown and the layout is not compatible
81    @see reorderToOldLayout()
82*/
83int oldneurocount;
84char oldconnections;
85
86/** calculate oldNeuroCount */
87void calcOldNeuroCount();
88/** some new calls can invalidate old compatibility data */
89void 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*/
97int reorderToOldLayout();
98
99/** check if compatibility should be preserved */
100int hasOldNeuroLayout() {return oldneurocount>=0;}
101
102/** add inputs to the old "-" units.
103    @return 1=ok, 0=invalid input detected  */
104int addOldConnectionsInputs();
105#endif
106
107void internalCopy(const Model &mod);
108
109/// make the model from current genotype
110void build();
111
112/// make f0 genotype from current construction
113void makeGeno(Geno &,MultiMap *map=0);
114
115friend class NeuroNetFactory;
116friend class VisualModel;
117friend class GLVisualModel;
118friend class Creature;
119friend class PartBase;
120
121int checklevel;
122
123void updateNeuroRefno(); // set Neuro::refno for all neurons
124int internalcheck(int final);
125
126void moveNeuro(int oldpos,int newpos);
127
128void init(const Geno &srcgen);
129void init();
130
131void delMap();
132void delF0Map();
133void initMap();
134void initF0Map();
135
136public:
137/** get current model state.
138\f[(dot)
139digraph M
140 {
141 node [fontsize=12]
142 edge [fontsize=10]
143 building [label="building = can be modified"]
144 valid -> building [label="open()"]
145 building -> valid [label="close()"]
146 invalid -> building [label="open()"]
147 building -> invalid [label="close() [failed]"]
148 empty -> building [label="open()"]
149 }
150\f]
151*/
152ModelBuildStatus getStatus() const {return buildstatus;}
153int isValid() const {return buildstatus==valid;}
154int getErrorPosition(bool includingwarnings=false);
155
156void updateRefno(); // set ::refno for all elements
157
158/// The bounding box size. Valid if the model is valid. Read only.
159Pt3D size;
160
161SString vis_style;
162double startenergy;
163Callback delmodel_list;
164ModelUserTags userdata;
165
166/// Create empty model with invalid empty genotype
167Model();
168
169/** Create a model based on provided genotype
170   @param buildmaps if not 0, generate mapping information for the model.
171   default is 0, because mapping uses additional time and memory.
172   @see getMap()
173 */
174Model(const Geno &src,int buildmaps=0);
175Model(const Model &mod,int buildmaps=0);
176/** duplicate the model.
177    the resulting object's status is 'building' (opened).
178    @see getStatus()
179 */
180void operator=(const Model &source);
181
182/** move all elements from 'source' into our model object.
183    'source' becomes empty after this operation.
184    the model will be opened if it is not already open.
185    @see addElementsFrom(const Model &source);
186 */
187void moveElementsFrom(Model &source);
188
189/** copy all elements from 'source' into our model object
190    without affecting the 'source'.
191    the model will be opened if it is not already open.
192    @see moveElementsFrom(Model &source);
193 */
194void addElementsFrom(const Model &source)
195{Model m(source); moveElementsFrom(m);}
196
197void operator+=(const Model &source)
198{addElementsFrom(source);}
199
200~Model();
201
202/** @return source genotype.
203    @warn source genotype will not automatically change
204    when the model is modified. this behaviour is inconsistent
205    with the previous release. use getF0Geno() if you need
206    the updated genotype.
207    @see getF0Geno(), setGeno()
208*/
209const Geno &getGeno() const;
210
211/// change source genotype
212void setGeno(const Geno& newgeno);
213
214/** @return f0 genotype - generated from current model state
215    don't use between open()-close()
216*/
217const Geno &getF0Geno();
218
219/** @return mapping from source genotype (0-based position in text) to model elements reference numbers.
220    the map can be empty if the mapping hasn't been requested earlier (in constructor)
221    or the converters don't support mapping.
222    if you create or modify the model using singleStepBuild() or direct manipulation
223    the map will be not changed or created automatically - it is your responsibility.
224    @see Model(const Geno &src,int buildmaps=0), singleStepBuild(), PartBase::addMapping()
225    @see clearMap()
226    @see convmap
227
228*/
229MultiMap &getMap();
230
231/** @return mapping from f0 genotype (0-based position in text) to model elements reference numbers
232 */
233const MultiMap &getF0Map();
234
235/** discard all mapping information for this model.
236    getMap().clear() also works, but it doesn't remove mappings from model elements.
237    if there are any, the will be incorporated into model map during close().
238    @see close(), getMap(), PartBase::clearMapping()
239 */
240void clearMap();
241
242/** generate mapping from the current genotype to the f0 genotype.
243    this works only if both current and f0 maps are already known.
244    @see convmap
245*/
246void getCurrentToF0Map(MultiMap& m);
247
248void setValidationLevel(int level)
249        {checklevel=level;}
250
251/// calculate location of the new part connected to the existing one
252/// using delta option
253Pt3D whereDelta(const Part& start,const Pt3D& rot, const Pt3D& delta);
254
255/// create the whole model from scratch, using current genotype
256void rebuild(int buildmaps);
257
258/// setGeno(newgeno); rebuild();
259void rebuild(const Geno& newgeno,int buildmaps) {setGeno(newgeno);rebuild(buildmaps);}
260
261/// reuse current model object but discard all model data
262void clear();
263
264/** execute single line of <B>f0</B> genotype.
265    return value is non-negative reference number of the created item,
266    or negative value. reference number can be used to access
267    the item using getPart(int), getJoint(int) and getNeuroItem(int) methods.
268    @param srcrange source genotype range which will be mapped to this element
269*/
270int singleStepBuild(const SString &singleline,const MultiRange* srcrange=0);
271
272/// separate build stages (for future use)
273void checkpoint();
274
275/// call resetDelta() on all joints
276void resetAllDelta();
277
278/// call useDelta() on all joints
279void useAllDelta(bool yesno);
280
281/// final validity check of the model, all model data has to be available at this point.
282/// if the model was modified, the genotype will be also updated.
283/// it also calls "validate" with all side effects.
284/// @return > 0 means "valid"
285int close();
286
287/// enable model building.
288/// you should use it if you need to create new model, modify the model after close
289/// or modify the model created from the genotype.
290/// between open() and close() the model is not fully usable,
291void open();
292
293/// current model written as f0 genotype while building
294/// (not cached, not validated, probably unusable and bad if used before close(). but good for debugging.)
295Geno rawGeno();
296
297/// partial validity check - you can use this call
298/// anytime between open - close.
299/// this function will check (and repair)
300/// - part-joint-neuro connections
301/// - model geometry (if "delta option" was used)
302/// - physical/biological limits
303/// @return 1 = valid
304/// @return 0 = invalid
305/// validate doesn't make the model fully usable (for simulation)
306/// you still need to use close if you have changed anything
307int validate();
308
309int getPartCount() const;
310/// you can access parts 0 .. getPartCount()-1.
311Part *getPart(int i) const;
312
313int getJointCount() const;
314/// you can access joints 0 .. getJointCount()-1.
315Joint *getJoint(int i) const;
316
317int getNeuroCount() const;
318int getConnectionCount() const;
319/// you can access neurons 0 .. getNeuroCount()-1.
320Neuro *getNeuro(int i) const;
321
322#ifdef MODEL_V1_COMPATIBLE
323/* compatibility calls for accessing old Neuro objects */
324
325/// @deprecated Neuro class will be removed soon
326/// @see compat
327int old_getNeuroCount();
328/// you can access neurons 0 .. getNeuroCount()-1.
329/// @deprecated Neuro class will be removed soon
330Neuro *old_getNeuro(int i);
331/// @see addNewNeuro, addNeuro
332/// @deprecated Neuro class will be removed soon
333Neuro *old_addNewNeuro();
334/// @return neuro index or -1 if not found
335/// @deprecated Neuro class will be removed soon
336int old_findNeuro(Neuro* n);
337#endif
338
339/** create new Part and add it to the model. @see addPart()  */
340Part *addNewPart() {return addPart(new Part());}
341/** create new Joint and add it to the model. @see addJoint() */
342Joint *addNewJoint() {return addJoint(new Joint());}
343/** create new Neuro and add it to the model. @see addNeuro() */
344Neuro *addNewNeuro() {return addNeuro(new Neuro());}
345
346/** add p to the model. p->refno is adjusted. @return the Part just added (==p). */
347Part *addPart(Part *p);
348/** add j to the model. j->refno is adjusted. @return the Joint just added (==j). */
349Joint *addJoint(Joint *j);
350/** add n to the model. n->refno is adjusted. @return the Neuro just added (==n). */
351Neuro *addNeuro(Neuro *n);
352
353/** remove the part from model.
354    @param removeattachedjoints if not 0 -> remove all joints connected with this part
355    @param removeattachedneurons if not 0 -> remove neurons attached to this part */
356void removePart(int partindex,int removeattachedjoints=1,int removeattachedneurons=1);
357
358/** remove the joint from model.
359    @param removeattachedneurons if not 0 -> remove neurons attached to this joint */
360void removeJoint(int jointindex,int removeattachedneurons=1);
361
362/** remove the neuron from model.
363    @param removereferences if true -> look for references to this neuron
364    (i.e. connections from other neurons) and remove them as well */
365void removeNeuro(int neuroindex,bool removereferences=true);
366
367void removeNeuros(SList &nlist);
368
369/// @return part index or -1 if not found in the model
370int findPart(Part* p);
371/// @return joint index or -1 if not found in the model
372int findJoint(Joint* j);
373/// @return neuro index or -1 if not found in the model
374int findNeuro(Neuro* nu);
375/// @return joint index or -1 if not found in the model
376int findJoint(Part *p1, Part *p2);
377
378/** make the list of neuros satisfying given search criteria: classname,part,joint
379    @param result objects will be appended here
380    @return number of objects found  */
381int findNeuros(SList& result,const char* classname=0,const Part* part=0,const Joint* joint=0);
382
383/** search for joints connected to the part
384    @param result objects will be appended here
385    @return number of objects found  */
386int findJoints(SList& result,const Part* part=0);
387
388void disturb(double amount);
389
390#ifdef EASYMAPDEBUG
391static int partToMap(int i) {return 0+i;}
392static int jointToMap(int i) {return 10+i;}
393static int neuroToMap(int i) {return 20+i;}
394static int mapToPart(int i) {return i-0;}
395static int mapToJoint(int i) {return i-10;}
396static int mapToNeuro(int i) {return i-20;}
397#else
398static int partToMap(int i) {return 0x10000000+i;}
399static int jointToMap(int i) {return 0x20000000+i;}
400static int neuroToMap(int i) {return 0x30000000+i;}
401static int mapToPart(int i) {return i-0x10000000;}
402static int mapToJoint(int i) {return i-0x20000000;}
403static int mapToNeuro(int i) {return i-0x30000000;}
404#endif
405
406static void makeGenToGenMap(MultiMap& result,const MultiMap& gen1tomodel,const MultiMap& gen2tomodel);
407
408///////////////////////////
409
410static const Part& getMinPart();
411static const Part& getMaxPart();
412static const Part& getDefPart();
413static const Joint& getMinJoint();
414static const Joint& getMaxJoint();
415static const Joint& getDefJoint();
416static const Neuro& getMinNeuro();
417static const Neuro& getMaxNeuro();
418static const Neuro& getDefNeuro();
419};
420
421#endif
Note: See TracBrowser for help on using the repository browser.