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

Last change on this file since 767 was 767, checked in by Maciej Komosinski, 7 years ago

More strict parsing of the repetition counter; bug fixes; improved docs [refs #62]

  • Property svn:eol-style set to native
File size: 18.3 KB
RevLine 
[286]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.
[193]4
[196]5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
6
[193]7#ifndef _F4_GENERAL_H_
8#define _F4_GENERAL_H_
9
[196]10#include <frams/util/3d.h>
11#include <frams/util/sstring.h>
12#include <frams/util/multirange.h>
[760]13#include <frams/genetics/geneprops.h>
[193]14
15#ifdef DMALLOC
16#include <dmalloc.h>
17#endif
18
[760]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);
[193]24
[760]25/**
26 * Performs single rotation angle incrementation on a given value.
27 * @param v pointer to the incremented value
28 */
[193]29void rolling_inc(double * v);
30
31class f4_node;   // later
32class f4_Cell;   // later
33class f4_Cells;  // later
34
35
[760]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//@}
[193]42
[760]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 */
[193]53int scanrec(const char * s, unsigned int slen, char stopchar);
54
55
56class f4_CellLink;
57
[760]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 */
[193]74class f4_Cell
75{
76public:
[760]77        /**
78         * Represents the repetition marker. It holds information about the pointer
79         * to the repetition node and the count of repetitions.
80         */
[196]81        class repeat_ptr
82        {
83        public:
84                repeat_ptr() : node(NULL), count(-1) { };
[760]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
[196]95                inline bool isNull() const { return ((node == NULL) || (count <= 0)); };
[760]96
[196]97                inline void dec() { count--; };
[760]98                f4_node    *node; ///<pointer to the repetition code
[767]99                int       count; ///<repetition counter
[196]100        };
[193]101
[760]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
[196]110        {
111        public:
[760]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
[196]133        };
[193]134
[760]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         */
[767]142        f4_Cell(int nname, f4_Cell *ndad, int nangle, GeneProps newP);
[760]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         */
[767]153        f4_Cell(f4_Cells *nO, int nname, f4_node *ngeno, f4_node *ngcur, f4_Cell *ndad, int nangle, GeneProps newP);
[760]154
[196]155        ~f4_Cell();
[193]156
[760]157        /**
[767]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
[760]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:
[767]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,
[760]172         *  - the stick modifiers, like rotation, will be applied on neuron cell,
173         *  - the differentiated cell will be differentiated again,
[767]174         *  - the neuron class inside cell connection (i.e. N[G:5]) is not a sensor,
175         *  - the connection between neurons cannot be established,
[760]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         */
[767]180        int onestep();
[193]181
[760]182        /**
[767]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.
[760]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         */
[767]190        int   addlink(f4_Cell *nfrom, double nw, string nt);
[760]191
192        /**
193         * Adjusts properties of stick objects.
194         */
[196]195        void  adjustRec();
[193]196
[767]197        int        name;               ///<name of cell (number)
[760]198        int        type;               ///<type
[767]199        f4_Cell *dadlink;              ///<pointer to cell parent
200        f4_Cells  *org;                ///<uplink to organism
[193]201
[767]202        f4_node *genot;                    ///<genotype tree
203        f4_node *gcur;                 ///<current genotype execution pointer
204        int active;                    ///<determines whether development is still active
[760]205        repeat_stack repeat;           ///<stack holding repetition nodes and counters
[767]206        int recProcessedFlag;          ///<used during recursive traverse
[760]207        MultiRange genoRange;          ///<remember the genotype codes affecting this cell so far
[193]208
[767]209        GeneProps    P;                ///<properties
[760]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)
[193]216
[760]217        double       mz;               ///<freedom in z
[767]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
[760]221
222        int          ctrl;             ///<neuron type
223        double       state;            ///<state of neuron
224        double       inertia;          ///<inertia of neuron
225        double       force;            ///<force of neuron
226        double       sigmo;            ///<sigmoid of neuron
[767]227        f4_CellLink *links[MAXINPUTS]; ///<array of neuron links
[760]228        int          nolink;           ///<number of links
[767]229        NeuroClass *neuclass;          ///<pointer to neuron class
[193]230};
231
[760]232/**
233 * Class representing link between neuron cells.
234 */
[193]235class f4_CellLink
236{
237public:
[760]238        /**
[767]239         * Constructor for f4_CellLink class. Parameter nfrom represents input
240         * neuron cell or NULL if connection has defined sensor type inside, like "[G:5]".
241         * The name of sensor class defined inside neuron connection is stored in the nt
242         * parameter.
[760]243         * @param nfrom pointer to input neuron cell or NULL
244         * @param nw weight of connection
245         * @param nt name of neuron class or empty string
246         */
[767]247        f4_CellLink(f4_Cell *nfrom, double nw, string nt);
[760]248
[767]249        f4_Cell *from; ///<pointer to input neuron cell
250        string t;      ///<empty if 'from' cell is given, NeuroClass name otherwise
251        double w;      ///<weight of connection
[193]252};
253
254
255// a collection of cells, like Organism, for developmental encoding
[760]256/**
[767]257 * A class representing a collection of cells. It is equivalent to an organism.
[760]258 */
[193]259class f4_Cells
260{
[196]261public:
[760]262
263        /**
264         * Constructor taking genotype in a form of a tree.
265         * @param genome genotype tree
266         * @param nrepair 0 if nothing to repair
267         */
[767]268        f4_Cells(f4_node *genome, int nrepair);
[760]269
270        /**
271         * Constructor taking genotype in a form of a string.
272         * @param genome genotype string
273         * @param nrepair 0 if nothing to repair
274         */
[196]275        f4_Cells(SString &genome, int nrepair);
[760]276
277        /**
278         * Destructor removing cells from memory.
279         */
[196]280        ~f4_Cells();
[760]281
282        /**
[767]283         * Adds a new cell to organism.
[760]284         * @param newcell cell to be added
285         */
[767]286        void addCell(f4_Cell *newcell);
[760]287
288        /**
[767]289         * Creates an approximate genotype in the f1 encoding and stores it in a given parameter.
290         * @param out the string in which the approximate f1 genotype will be stored
[760]291         */
292        void toF1Geno(SString &out);
293
294        /**
[767]295         * Performs a single step of organism development. It runs each active cell
296         * in the organism.
297         * @return 0 if all cells are developed, 1 otherwise
[760]298         */
299        int  onestep();
300
301        /**
[767]302         * Performs the full development of organism and returns error code if something
[760]303         * went wrong.
304         * @return 0 if organism developed successfully, error code if something went wrong
305         */
306        int  simulate();
307
308        /**
[767]309         * Returns error code of the last simulation.
[760]310         * @return error code
311         */
[196]312        int  geterror() { return error; };
[760]313
314        /**
[767]315         * Returns position of an error in genotype.
316         * @return position of an error
[760]317         */
[196]318        int  geterrorpos() { return errorpos; };
[760]319
320        /**
[767]321         * Sets error code GENOPER_OPFAIL for a simulation on a given position.
322         * @param nerrpos position of an error
[760]323         */
[196]324        void setError(int nerrpos);
[760]325
326        /**
327         * Sets the element of genotype to be repaired by removal.
[767]328         * @param nerrpos position of an error in genotype
329         * @param rem the f4_node to be removed from the  genotype tree in order to repair
[760]330         */
[767]331        void setRepairRemove(int nerrpos, f4_node *rem);
[760]332
333        /**
[767]334         * Sets repairing of a genotype by inserting a new node to the current genotype.
335         * @param nerrpos position of an error in genotype
336         * @param parent the parent of a new element
[760]337         * @param insert the element to be inserted
338         * @return 0 if repair can be performed, -1 otherwise (the repair flag wasn't set in constructor)
339         */
[767]340        int  setRepairInsert(int nerrpos, f4_node *parent, f4_node *insert);
[760]341
342        /**
[767]343         * Repairs the genotype according to setRepairRemove or setRepairInsert methods.
344         * @param geno pointer to the genotype tree
[760]345         * @param whichchild 1 if first child, 2 otherwise
346         */
[767]347        void repairGeno(f4_node *geno, int whichchild);
[193]348
[196]349        // the cells
[767]350        f4_Cell *C[MAX4CELLS];  ///<Array of all cells of an organism
351        int       nc;           ///<Number of cells in an organism
[193]352
353private:
[196]354        // for error reporting / genotype fixing
355        int repair;
356        int error;
357        int errorpos;
[767]358        f4_node *repair_remove;
359        f4_node *repair_parent;
360        f4_node *repair_insert;
[196]361        void toF1GenoRec(int curc, SString &out);
[767]362        f4_Cell *tmpcel;                // needed by toF1Geno
363        f4_node *f4rootnode;          // used by constructor
[193]364};
365
366
367/**
[767]368 * A class to organize a f4 genotype in a tree structure.
[193]369 */
370class f4_node
371{
372public:
[760]373        string name; ///<one-letter 'name', multiple characters for classes
[767]374        f4_node *parent; ///<parent link or NULL
375        f4_node *child; ///<child or NULL
376        f4_node *child2; ///<second child or NULL
377        int pos; ///<original position in the string
378        int i1; ///<internal int  parameter1
379        int l1; ///<internal long parameter1
380        double f1; ///<internal double parameter1
[760]381        string s1; ///<internal string parameter1
[193]382
[196]383        f4_node();
[760]384
385        /**
386         * Multiple-character name constructor.
387         * @param nname string from genotype representing node
[767]388         * @param nparent pointer to parent of the node
389         * @param npos position of node substring in the genotype string
[760]390         */
[767]391        f4_node(string nname, f4_node *nparent, int npos);
[760]392
393        /**
[767]394         * Single-character name constructor.
[760]395         * @param nname character from genotype representing node
[767]396         * @param nparent pointer to parent of the node
397         * @param npos position of node character in the genotype string
[760]398         */
[767]399        f4_node(char nname, f4_node *nparent, int npos);
[760]400
[196]401        ~f4_node();
[760]402
403        /**
[767]404         * Adds the child to the node.
405         * @param nchi the child to be added to the node
406         * @return 0 if the child could be added, -1 otherwise
[760]407         */
[767]408        int addChild(f4_node *nchi);
[760]409
410        /**
[767]411         * Removes the child from the node.
412         * @param nchi the child to be removed from the node
[760]413         * @return 0 if child could be removed, -1 otherwise
414         */
[767]415        int removeChild(f4_node *nchi);
[760]416
417        /**
[767]418         * Returns the number of children.
[760]419         * @return 0, 1 or 2
420         */
[767]421        int childCount();
[760]422
423        /**
[767]424         * Returns the number of nodes coming from this node in a recursive way.
425         * @return the number of nodes from this node
[760]426         */
[767]427        int count();
[760]428
429        /**
430         * Returns the nth subnode (0-)
[767]431         * @param n index of the child to be found
432         * @return pointer to the nth subnode or NULL if not found
[760]433         */
434        f4_node * ordNode(int n);
435
436        /**
437         * Returns a random subnode.
438         * @return random subnode
439         */
440        f4_node * randomNode();
441
442        /**
[767]443         * Returns a random subnode with a given size.
[760]444         * @param min minimum size
445         * @param max maximum size
[767]446         * @return a random subnode with a given size or NULL
[760]447         */
448        f4_node * randomNodeWithSize(int min, int max);
449
450        /**
[767]451         * Prints recursively the tree from a given node.
452         * @param buf variable to store printing result
[760]453         */
[767]454        void      sprintAdj(char *&buf);
[760]455
456        /**
[767]457         * Recursively copies the genotype tree from this node.
[760]458         * @return pointer to a tree copy
459         */
460        f4_node * duplicate();
461
462        /**
463         * Recursively releases memory from all node children.
464         */
465        void      destroy();
[193]466private:
[767]467        void     sprint(SString &out);  // print recursively
[193]468};
469
470// convert f4 geno string to tree structure (internal)
[760]471
472/**
[767]473 * The main function for converting a string of f4 encoding to a tree structure. Prepares
[760]474 * f4_node root of tree and runs f4_processrec function for it.
[767]475 * @param geno the string representing an f4 genotype
476 * @return a pointer to the f4_node object representing the f4 tree root
[760]477 */
[767]478f4_node * f4_processtree(const char *geno);
[760]479
480/**
[767]481 * Scans a genotype string starting from a given position. This recursive method creates
482 * a tree of f4_node objects. This method extracts each potentially functional element
483 * of a genotype string to a separate f4_nodes. When the branching character '<' occurs,
484 * f4_processrec is deployed for the latest f4_node element. This method does not
485 * analyse the genotype semantically, it only checks if the syntax is proper. The only
486 * semantic aspect is neuron class name extraction, where the GenoOperators
487 * class is used to parse the potential neuron class name.
488 * @param genot the string holding all the genotype
[760]489 * @param pos0 the current position of processing in string
[767]490 * @param current parent of the analysed branch of the genotype
491 * @return 0 if processing was successful, otherwise returns the position of an error in the genotype
[760]492 */
[767]493int f4_processrec(const char *genot, unsigned pos0, f4_node *parent);
[193]494
[760]495/**
[767]496 * Parses notation of the neuron connection - takes the beginning of the connection
497 * definition, extracts the relative position of input neurons and the weight of the connection.
498 * After successful parsing, returns the pointer to the first character after the connection
499 * definition, or NULL if the connection definition was not valid due to the lack of [, :, ]
500 * characters or an invalid value of relfrom or weight.
501 * @param fragm the beginning of connection definition, should be the '[' character
502 * @param relfrom the reference to an int variable in which the relative position of the input neuron will be stored
503 * @param weight the reference to a double variable in which the weight of the connection will be stored
504 * @return the pointer to the first character in string after connection definition
[760]505 */
[767]506const char * parseConnection(const char *fragm, int &relfrom, double &weight);
[193]507
[760]508/**
[767]509 * Parses the notation of the neuron connection with neuron definition - takes
510 * the beginning of the connection definition, extracts the name of neuron class
511 * that will be the input for the current neuron and the weight of the connection.
512 * After successful parsing, returns a pointer to the first character after the connection
513 * definition, or NULL if the connection definition was not valid due to the lack of [, :, ]
514 * characters, an invalid value of the weight or an invalid neuron class name.
515 * @param fragm the beginning of the connection definition, should be the '[' character
516 * @param neutype the reference to a string representing the input neuron class name. The name of the class is validated with GenoOperators::parseNeuroClass()
517 * @param weight the reference to a double variable in which the weight of the connection will be stored
518 * @return the pointer to the first character in string after the connection definition
[760]519 */
[767]520const char * parseConnectionWithNeuron(const char *fragm, string &neutype, double &weight);
[760]521
[193]522#endif
Note: See TracBrowser for help on using the repository browser.