source: cpp/frams/genetics/f4/f4_general.h @ 774

Last change on this file since 774 was 774, checked in by Maciej Komosinski, 15 months ago

Removed unused "state" field (issue number 19), improved docs (issues number 20,21,23), code formatting (issue number 24) [closes #62]

  • Property svn:eol-style set to native
File size: 18.2 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
6
7#ifndef _F4_GENERAL_H_
8#define _F4_GENERAL_H_
9
10#include <frams/util/3d.h>
11#include <frams/util/sstring.h>
12#include <frams/util/multirange.h>
13#include <frams/genetics/geneprops.h>
14
15#ifdef DMALLOC
16#include <dmalloc.h>
17#endif
18
19/**
20 * Performs single rotation angle decrementation on a given value.
21 * @param v pointer to the decremented value
22 */
23void rolling_dec(double *v);
24
25/**
26 * Performs single rotation angle incrementation on a given value.
27 * @param v pointer to the incremented value
28 */
29void rolling_inc(double *v);
30
31class f4_node;   // later
32class f4_Cell;   // later
33class f4_Cells;  // later
34
35
36/** @name Types of f4_Cell's */
37//@{
38#define T_UNDIFF4 40 ///<undifferentiated cell
39#define T_STICK4  41 ///<differentiated to stick, cannot divide
40#define T_NEURON4 42 ///<differentiated to neuron, can divide
41//@}
42
43/**
44 * Scans f4 genotype string for a stopping character and returns the position of
45 * this stopping character or 1 if the end of string was reached. This method is used
46 * for closing braces, like ), >, ]. It runs recursively when opening braces
47 * like (, <, # are found.
48 * @param s string with the f4 genotype
49 * @param slen length of a given string
50 * @param stopchar character to be found
51 * @return 1 if end of string was reached, or position of found character in sequence
52 */
53int scanrec(const char* s, unsigned int slen, char stopchar);
54
55
56class f4_CellLink;
57
58/** @name Constraints of f4 genotype structures */
59//@{
60#define MAXINPUTS 100 ///<maximum number of neuron inputs
61#define MAX4CELLS 100 ///<maximum number of f4 organism cells
62//@}
63
64/**
65 * Abstract cell type - the representation of single component in the  developmental
66 * encoding. In the beginning, each f4_Cell is undifferentiated. During the process
67 * of development it can divide or differentiate into a stick or a neuron. If it
68 * differentiates to a neuron, then it preserves the ability to divide, but divided
69 * cells will be the same type as the parent cell. If it is a stick, then it cannot
70 * be divided anymore.
71 *
72 * From f4_Cell array the final Model of a creature is created.
73 */
74class f4_Cell
75{
76public:
77        /**
78         * Represents the repetition marker. It holds information about the pointer
79         * to the repetition node and the count of repetitions.
80         */
81        class repeat_ptr
82        {
83        public:
84                repeat_ptr() : node(NULL), count(-1) { };
85
86                /**
87                 * A constructor that takes the pointer to the repetition node and the count of repetitions.
88                 * @param a pointer to f4_node for repetition character
89                 * @param b the number of repetitions
90                 */
91                repeat_ptr(f4_node *a, int b) : node(a), count(b) { };
92
93                inline void makeNull() { node = NULL; count = -1; };
94
95                inline bool isNull() const { return ((node == NULL) || (count <= 0)); };
96
97                inline void dec() { count--; };
98                f4_node    *node; ///<pointer to the repetition code
99                int       count; ///<repetition counter
100        };
101
102        /**
103         * Represents the stack of repeat_ptr objects. The objects are
104         * pushed to the stack when '#' repetition symbol appears, and are popped when
105         * the end of the current cell definition, i.e. the '>' character, appears. After the
106         * '>' character, the cell is duplicated as many times as it is defined after the
107         * repetition marker.
108         */
109        class repeat_stack
110        {
111        public:
112                repeat_stack() { top = 0; }
113
114                inline void clear() { top = 0; }
115
116                /**
117                 * Pushes repeat_ptr object onto the stack. If the stack size is exceeded, then no
118                 * information is provided.
119                 * @param rn repetition node info
120                 */
121                inline void push(repeat_ptr rn) { if (top >= stackSize) return; ptr[top] = rn; top++; }
122
123                inline void pop() { if (top > 0) top--; }
124
125                /**
126                 * Gets the current top element.
127                 * @return pointer to the element on top of the repeat_stack object
128                 */
129                inline repeat_ptr* first() { return &(ptr[top - (top > 0)]); };
130                static const int stackSize = 4;  ///<max 4 nested levels
131                repeat_ptr ptr[stackSize]; ///<array holding pointers to repeat_ptr
132                short int top;  ///<index of the top of the stack
133        };
134
135        /**
136         * Creates a new f4_Cell object.
137         * @param nname name of a cell, can be T_UNDIFF4, T_STICK4 or T_NEURON4
138         * @param ndad pointer to the parent of the created cell
139         * @param nangle the amount of commas affecting branch angles
140         * @param newP genotype properties of a given cell
141         */
142        f4_Cell(int nname, f4_Cell *ndad, int nangle, GeneProps newP);
143        /**
144         * Creates a new f4_Cell object.
145         * @param nO pointer to an organism containing the cell
146         * @param nname name of the cell, can be T_UNDIFF4, T_STICK4 or T_NEURON4
147         * @param ngeno pointer to the root of the genotype tree
148         * @param ngcur pointer to the f4_node representing the current cell in the genotype tree
149         * @param ndad pointer to the parent of the created cell
150         * @param nangle the number of commas affecting branch angles
151         * @param newP genotype properties of a given cell
152         */
153        f4_Cell(f4_Cells *nO, int nname, f4_node *ngeno, f4_node *ngcur, f4_Cell *ndad, int nangle, GeneProps newP);
154
155        ~f4_Cell();
156
157        /**
158         * Performs a single step of cell development. This method requires a pointer to
159         * the f4_Cells object in org attribute. If the current node in genotype tree
160         * is the branching character '<', the cell divides into two cells, unless the
161         * cell was already differentiated into the stick cell. Otherwise, the current
162         * differentiation or modification is performed on the cell. If current node is
163         * creating a connection between two neuron nodes and the input node is not
164         * yet developed, the simulation of the development of the current cell waits until
165         * the input node is created. The onestep method is deployed for every cell
166         * at least once. If one cell requires another one to develop, onestep
167         * should be deployed again on this cell. This method, unlike genotype tree
168         * creation, checks semantics. This means that this function will fail if:
169         *  - the cell differentiated as a stick will have branching node '<',
170         *  - the undifferentiated cell will have termination node '>' (end of cell development without differentiation),
171         *  - the stack of repetition marker '#' will exceed maximum allowed value of repetition,
172         *  - the stick modifiers, like rotation, will be applied on neuron cell,
173         *  - the differentiated cell will be differentiated again,
174         *  - the neuron class inside cell connection (i.e. N[G:5]) is not a sensor,
175         *  - the connection between neurons cannot be established,
176         *  - the neuron class is not valid.
177         *
178         * @return 0 if development was successful, 1 if there was an error in genotype tree
179         */
180        int onestep();
181
182        /**
183         * Adds a link between this neuron cell and a given neuron cell in nfrom. If the nfrom object
184         * is not given, neuron type in nt should be a sensor type.
185         * @param nfrom input neuron cell, or NULL if not given
186         * @param nw weight of connection
187         * @param nt empty string or name of sensor class
188         * @return 0 if link is established, -1 otherwise
189         */
190        int   addlink(f4_Cell *nfrom, double nw, string nt);
191
192        /**
193         * Adjusts properties of stick objects.
194         */
195        void  adjustRec();
196
197        int        name;               ///<name of cell (number)
198        int        type;               ///<type
199        f4_Cell *dadlink;              ///<pointer to cell parent
200        f4_Cells  *org;                ///<uplink to organism
201
202        f4_node *genot;                    ///<genotype tree
203        f4_node *gcur;                 ///<current genotype execution pointer
204        int active;                    ///<determines whether development is still active
205        repeat_stack repeat;           ///<stack holding repetition nodes and counters
206        int recProcessedFlag;          ///<used during recursive traverse
207        MultiRange genoRange;          ///<remember the genotype codes affecting this cell so far
208
209        GeneProps    P;                ///<properties
210        int          anglepos;         ///<number of position within dad's children (,)
211        int          childcount;       ///<number of children
212        int          commacount;       ///<number of postitions at lastend (>=childcount)
213        double       rolling;          ///<rolling angle ('R') (around x)
214        double       xrot;                         ///<rotation angle around x
215        double       zrot;             ///<horizontal rotation angle due to branching (around z)
216
217        double       mz;               ///<freedom in z
218        int          p2_refno;         ///<the number of the last end part object, used in f0
219        int          joint_refno;      ///<the number of the joint object, used in f0
220        int          neuro_refno;      ///<the number of the neuro object, used in f0
221
222        int          ctrl;             ///<neuron type
223        double       inertia;          ///<inertia of neuron
224        double       force;            ///<force of neuron
225        double       sigmo;            ///<sigmoid of neuron
226        f4_CellLink *links[MAXINPUTS]; ///<array of neuron links
227        int          nolink;           ///<number of links
228        NeuroClass *neuclass;          ///<pointer to neuron class
229};
230
231/**
232 * Class representing link between neuron cells.
233 */
234class f4_CellLink
235{
236public:
237        /**
238         * Constructor for f4_CellLink class. Parameter nfrom represents input
239         * neuron cell or NULL if connection has defined sensor type inside, like "[G:5]".
240         * The name of sensor class defined inside neuron connection is stored in the nt
241         * parameter.
242         * @param nfrom pointer to input neuron cell or NULL
243         * @param nw weight of connection
244         * @param nt name of neuron class or empty string
245         */
246        f4_CellLink(f4_Cell *nfrom, double nw, string nt);
247
248        f4_Cell *from; ///<pointer to input neuron cell
249        string t;      ///<empty if 'from' cell is given, NeuroClass name otherwise
250        double w;      ///<weight of connection
251};
252
253
254/**
255 * A class representing a collection of cells. It is equivalent to an organism.
256 */
257class f4_Cells
258{
259public:
260
261        /**
262         * Constructor taking genotype in a form of a tree.
263         * @param genome genotype tree
264         * @param nrepair 0 if nothing to repair
265         */
266        f4_Cells(f4_node *genome, int nrepair);
267
268        /**
269         * Constructor taking genotype in a form of a string.
270         * @param genome genotype string
271         * @param nrepair 0 if nothing to repair
272         */
273        f4_Cells(SString &genome, int nrepair);
274
275        /**
276         * Destructor removing cells from memory.
277         */
278        ~f4_Cells();
279
280        /**
281         * Adds a new cell to organism.
282         * @param newcell cell to be added
283         */
284        void addCell(f4_Cell *newcell);
285
286        /**
287         * Creates an approximate genotype in the f1 encoding and stores it in a given parameter.
288         * @param out the string in which the approximate f1 genotype will be stored
289         */
290        void toF1Geno(SString &out);
291
292        /**
293         * Performs a single step of organism development. It runs each active cell
294         * in the organism.
295         * @return 0 if all cells are developed, or 1 otherwise
296         */
297        int  onestep();
298
299        /**
300         * Performs the full development of organism and returns error code if something
301         * went wrong.
302         * @return 0 if organism developed successfully, error code if something went wrong
303         */
304        int  simulate();
305
306        /**
307         * Returns error code of the last simulation.
308         * @return error code
309         */
310        int  geterror() { return error; };
311
312        /**
313         * Returns position of an error in genotype.
314         * @return position of an error
315         */
316        int  geterrorpos() { return errorpos; };
317
318        /**
319         * Sets error code GENOPER_OPFAIL for a simulation on a given position.
320         * @param nerrpos position of an error
321         */
322        void setError(int nerrpos);
323
324        /**
325         * Sets the element of genotype to be repaired by removal.
326         * @param nerrpos position of an error in genotype
327         * @param rem the f4_node to be removed from the  genotype tree in order to repair
328         */
329        void setRepairRemove(int nerrpos, f4_node *rem);
330
331        /**
332         * Sets repairing of a genotype by inserting a new node to the current genotype.
333         * @param nerrpos position of an error in genotype
334         * @param parent the parent of a new element
335         * @param insert the element to be inserted
336         * @return 0 if repair can be performed, or -1 otherwise because the repair flag wasn't set in the constructor
337         */
338        int  setRepairInsert(int nerrpos, f4_node *parent, f4_node *insert);
339
340        /**
341         * Repairs the genotype according to setRepairRemove or setRepairInsert methods.
342         * @param geno pointer to the genotype tree
343         * @param whichchild 1 if first child, 2 otherwise
344         */
345        void repairGeno(f4_node *geno, int whichchild);
346
347        // the cells
348        f4_Cell *C[MAX4CELLS];  ///<Array of all cells of an organism
349        int       nc;           ///<Number of cells in an organism
350
351private:
352        // for error reporting / genotype fixing
353        int repair;
354        int error;
355        int errorpos;
356        f4_node *repair_remove;
357        f4_node *repair_parent;
358        f4_node *repair_insert;
359        void toF1GenoRec(int curc, SString &out);
360        f4_Cell *tmpcel;                // needed by toF1Geno
361        f4_node *f4rootnode;          // used by constructor
362};
363
364
365/**
366 * A class to organize a f4 genotype in a tree structure.
367 */
368class f4_node
369{
370public:
371        string name; ///<one-letter 'name', multiple characters for classes
372        f4_node *parent; ///<parent link or NULL
373        f4_node *child; ///<child or NULL
374        f4_node *child2; ///<second child or NULL
375        int pos; ///<original position in the string
376        int i1; ///<internal int  parameter1
377        int l1; ///<internal long parameter1
378        double f1; ///<internal double parameter1
379        string s1; ///<internal string parameter1
380
381        f4_node();
382
383        /**
384         * Multiple-character name constructor.
385         * @param nname string from genotype representing node
386         * @param nparent pointer to parent of the node
387         * @param npos position of node substring in the genotype string
388         */
389        f4_node(string nname, f4_node *nparent, int npos);
390
391        /**
392         * Single-character name constructor.
393         * @param nname character from genotype representing node
394         * @param nparent pointer to parent of the node
395         * @param npos position of node character in the genotype string
396         */
397        f4_node(char nname, f4_node *nparent, int npos);
398
399        ~f4_node();
400
401        /**
402         * Adds the child to the node.
403         * @param nchi the child to be added to the node
404         * @return 0 if the child could be added, -1 otherwise
405         */
406        int addChild(f4_node *nchi);
407
408        /**
409         * Removes the child from the node.
410         * @param nchi the child to be removed from the node
411         * @return 0 if child could be removed, -1 otherwise
412         */
413        int removeChild(f4_node *nchi);
414
415        /**
416         * Returns the number of children.
417         * @return 0, 1 or 2
418         */
419        int childCount();
420
421        /**
422         * Returns the number of nodes coming from this node in a recursive way.
423         * @return the number of nodes from this node
424         */
425        int count();
426
427        /**
428         * Returns the nth subnode (0-)
429         * @param n index of the child to be found
430         * @return pointer to the nth subnode or NULL if not found
431         */
432        f4_node* ordNode(int n);
433
434        /**
435         * Returns a random subnode.
436         * @return random subnode
437         */
438        f4_node* randomNode();
439
440        /**
441         * Returns a random subnode with a given size.
442         * @param min minimum size
443         * @param max maximum size
444         * @return a random subnode with a given size or NULL
445         */
446        f4_node* randomNodeWithSize(int min, int max);
447
448        /**
449         * Prints recursively the tree from a given node.
450         * @param buf variable to store printing result
451         */
452        void      sprintAdj(char *&buf);
453
454        /**
455         * Recursively copies the genotype tree from this node.
456         * @return pointer to a tree copy
457         */
458        f4_node* duplicate();
459
460        /**
461         * Recursively releases memory from all node children.
462         */
463        void      destroy();
464private:
465        void     sprint(SString &out);  // print recursively
466};
467
468/**
469 * The main function for converting a string of f4 encoding to a tree structure. Prepares
470 * f4_node root of tree and runs f4_processrec function for it.
471 * @param geno the string representing an f4 genotype
472 * @return a pointer to the f4_node object representing the f4 tree root
473 */
474f4_node* f4_processtree(const char *geno);
475
476/**
477 * Scans a genotype string starting from a given position. This recursive method creates
478 * a tree of f4_node objects. This method extracts each potentially functional element
479 * of a genotype string to a separate f4_nodes. When the branching character '<' occurs,
480 * f4_processrec is deployed for the latest f4_node element. This method does not
481 * analyse the genotype semantically, it only checks if the syntax is proper. The only
482 * semantic aspect is neuron class name extraction, where the GenoOperators
483 * class is used to parse the potential neuron class name.
484 * @param genot the string holding all the genotype
485 * @param pos0 the current position of processing in string
486 * @param parent current parent of the analysed branch of the genotype
487 * @return 0 if processing was successful, otherwise returns the position of an error in the genotype
488 */
489int f4_processrec(const char *genot, unsigned pos0, f4_node *parent);
490
491/**
492 * Parses notation of the neuron connection - takes the beginning of the connection
493 * definition, extracts the relative position of input neurons and the weight of the connection.
494 * After successful parsing, returns the pointer to the first character after the connection
495 * definition, or NULL if the connection definition was not valid due to the lack of [, :, ]
496 * characters or an invalid value of relfrom or weight.
497 * @param fragm the beginning of connection definition, should be the '[' character
498 * @param relfrom the reference to an int variable in which the relative position of the input neuron will be stored
499 * @param weight the reference to a double variable in which the weight of the connection will be stored
500 * @return the pointer to the first character in string after connection definition
501 */
502const char *parseConnection(const char *fragm, int &relfrom, double &weight);
503
504/**
505 * Parses the notation of the neuron connection with neuron definition - takes
506 * the beginning of the connection definition, extracts the name of neuron class
507 * that will be the input for the current neuron and the weight of the connection.
508 * After successful parsing, returns a pointer to the first character after the connection
509 * definition, or NULL if the connection definition was not valid due to the lack of [, :, ]
510 * characters, an invalid value of the weight or an invalid neuron class name.
511 * @param fragm the beginning of the connection definition, should be the '[' character
512 * @param neutype the reference to a string representing the input neuron class name. The name of the class is validated with GenoOperators::parseNeuroClass()
513 * @param weight the reference to a double variable in which the weight of the connection will be stored
514 * @return the pointer to the first character in string after the connection definition
515 */
516const char *parseConnectionWithNeuron(const char *fragm, string &neutype, double &weight);
517
518#endif
Note: See TracBrowser for help on using the repository browser.