source: cpp/frams/genetics/fL/fL_general.h @ 780

Last change on this file since 780 was 780, checked in by Maciej Komosinski, 6 years ago

Added sources for genetic encodings fB, fH, fL

File size: 13.4 KB
Line 
1#ifndef _FL_GENERAL_
2
3#define _FL_GENERAL_
4
5#include <frams/util/sstring.h>
6#include <frams/param/mutableparam.h>
7#include <frams/param/paramobj.h>
8#include <vector>
9#include <list>
10#include <unordered_map>
11#include <frams/model/model.h>
12#include "fL_matheval.h"
13
14/// determines to which class fL element belongs
15enum fLElementType {
16        TERM, ///< word of L-System
17        INFO, ///< fL_Builder object
18        RULE, ///< rule of L-System
19        BRANCH ///< special type of fL word, which represents branch
20};
21
22/** @name Constants used in fL methods */
23//@{
24#define PART_PROPS_COUNT   4 ///<Count of part properties
25#define JOINT_PROPS_COUNT  3 ///<Count of joint properties
26#define PE_NEURO_DET       "d" ///<Id of details type definition in f0_neuro_paramtab
27#define PE_CONN_WEIGHT     "w" ///<Id of weight type definition in f0_neuroconn_paramtab
28//@}
29
30extern const char *fL_part_names[];
31extern const char *fL_joint_names[];
32extern const char *fL_joint_fullnames[JOINT_PROPS_COUNT];
33extern const char *fL_part_fullnames[PART_PROPS_COUNT];
34
35#define LSYSTEM_PARAM_TYPE "s" ///< standard type of L-System elements
36
37class fL_Builder;
38
39/**
40 * Most abstract class of L-System. It requires from inheriting classes to implement
41 * methods processDefinition and toString.
42 */
43class fL_Element
44{
45public:
46        fLElementType type; ///< type of fL_Element
47
48        fL_Element(fLElementType type) : type(type) {}
49        virtual ~fL_Element() { }
50
51        /**
52         * Performs connecting current element to fL_Builder and parsing of input
53         * with respect of builder.
54         * @param builder fL_Builder object responsible for creating this element
55         * @return 0 if processing went successfully, other values otherwise
56         */
57        virtual int processDefinition(fL_Builder *builder) = 0;
58
59        /**
60         * Creates string line for current element. This method is used by Builder
61         * to create string representation of words, rules and informations of L-System.
62         * @return stringified element
63         */
64        virtual SString toString() = 0;
65};
66
67/**
68 * Represents word objects of L-System representation. They are used in axiom,
69 * produced sequences and rules.
70 */
71class fL_Word : public fL_Element
72{
73public:
74        SString name; ///<name of word
75        int npar; ///<number of word parameters
76        MutableParam mut; ///<MutableParam for word parameters
77        ParamEntry *tab; ///<ParamTab used for loading and saving properties of word
78        void *data; ///<pointer to properties of word
79        bool builtin; ///<determines if word is built-in (true) or not (false).
80        std::vector<MathEvaluation *> parevals; ///<stores MathEvaluation objects with parameter functions
81        double creationiter; ///<this helper field is used during L-System iterations and determines when word was created
82        fL_Word(bool builtin = false) :
83                fL_Element(fLElementType::TERM), mut("Word", "Properties"), //TODO change Word to Term everywhere
84                builtin(builtin)
85        {
86                name = "";
87                npar = 0;
88                tab = NULL;
89                data = NULL;
90                creationiter = 0;
91        }
92
93        /**
94         * Destroys data ParamObject and MathEvaluation objects. ParamTab for Word
95         * should be deleted separately, because all words with same name share same
96         * pointer to ParamTab.
97         */
98        ~fL_Word()
99        {
100                if (data)
101                        ParamObject::freeObject(data);
102                for (MathEvaluation *ev : parevals)
103                {
104                        delete ev;
105                }
106                parevals.clear();
107        }
108
109        /**
110         * Checks if there is no other word stored in the builder with the same name,
111         * prepares ParamTab for defined word and adds created word definition to the
112         * builder.
113         * @param builder pointer to the builder that process this word definition
114         * @return 0 if word is added, 1 if word is redefined
115         */
116        int processDefinition(fL_Builder *builder);
117
118        /**
119         * Operator copies name string, npar value, pointer to ParamTab and pointers
120         * to MathEvaluation objects for parameters. It sets data of this word to
121         * NULL.
122         * @param src source word
123         */
124        void operator=(const fL_Word& src);
125
126        /**
127         * TODO
128         */
129        bool operator==(const fL_Word& other) const;
130
131        /**
132         * Returns 'w:' line defining word in genotype.
133         * @return string representation of word definition
134         */
135        virtual SString toString();
136
137        /**
138         * Returns token version of this word. It is used during converting successor's
139         * list or axiom list into strings. Flag 'keepformulas' should be set to true
140         * if word parameters should be represented as formulas, and set to false if
141         * word parameters should contain the result of evaluation.
142         * @param keepformulas true if parameters should have mathematical formula, false if it should have result of evaluation
143         */
144        virtual SString stringify(bool keepformulas = true);
145
146        /**
147         * Saves formulas or evaluations of parameters in ParamObject.
148         * @param keepformulas true if parameters should have mathematical formula, false if it should have result of evaluation
149         * @return 0 if method successfully managed to save data, 1 if an error occured
150         */
151        int saveEvals(bool keepformulas);
152};
153
154/**
155 * Represents special branching word in L-System genotype.
156 */
157class fL_Branch : public fL_Word
158{
159public:
160        /// Determines if branching parenthesis is opened or closed
161        enum BranchType {
162                OPEN,
163                CLOSE
164        };
165        BranchType btype; ///< branch parenthesis type
166        fL_Branch(BranchType branchtype) : fL_Word()
167        {
168                type = fLElementType::BRANCH;
169                btype = branchtype;
170                name = stringify();
171        }
172        SString toString() { return ""; };
173        SString stringify(bool keepformulas = false) { return btype == BranchType::OPEN ? "[" : "]"; }
174};
175
176/**
177 * Represents rules in L-System genotype. Every rule has predecessor and successors.
178 * The optional argument is a condition of deploying rule. Every rule is ran
179 * synchronously for every letter of the current genotype. If condition and
180 * predecessor are satisfied, then predecessor is replaced by successors.
181 */
182class fL_Rule : public fL_Element
183{
184public:
185        SString predecessor; ///<string representation of the predecessor
186        SString condition; ///<string representation of the condition
187        SString successor; ///<string representation of the successor
188
189        fL_Word *objpred; ///<object representation of the predecessor
190        MathEvaluation *condeval; ///<object representation of the condition
191
192        std::list<fL_Word *> objsucc; ///<objec representation of successors
193
194        int start; ///<beginning of the rule definition in genotype
195        int end; ///<end of the rule definition in genotype
196
197        fL_Rule(int start, int end) : fL_Element(fLElementType::RULE),
198                start(start), end(end)
199        {
200                predecessor = "";
201                condition = "";
202                successor = "";
203                objpred = NULL;
204                condeval = NULL;
205        }
206
207        ~fL_Rule()
208        {
209                if (objpred) delete objpred;
210                if (condeval) delete condeval;
211                for (fL_Word *word : objsucc)
212                {
213                        delete word;
214                }
215                objsucc.clear();
216        }
217
218        /**
219         * Loads rule definition from the genotype, checks if word defined in
220         * predecessor does exist, tokenizes successor and condition.
221         * @param builder pointer to the builder that process this word definition
222         * @return 0 if word is added, 1 if an error occured during parsing
223         */
224        int processDefinition(fL_Builder *builder);
225
226        SString toString();
227
228        /**
229         * Runs rule for a given word, if all conditions and starting rules are satisfied.
230         * Method alters given list of tokens by removing matching word pointed by
231         * pointer and iterator of list and inserting successor sequence into list.
232         * Final iterator value points to the first word after processed word.
233         * @param in word that is currently processed
234         * @param it iterator of genotype list which determines position of current analysis
235         * @param genotype current genotype. Words on the left of genotype are processed and possibly replaced by previous rules
236         * @param currtime value representing continuous time value for rule
237         * @return 0 if rule processed current word, 1 if rule is no applicable
238         */
239        int deploy(fL_Word *in, std::list<fL_Word *>::iterator &it, std::list<fL_Word *> &genotype, double currtime);
240};
241
242struct fL_State
243{
244        Pt3D direction; ///<Direction of turtle
245        Part *currpart; ///<Latest created part
246        Neuro *currneuron; ///<Latest created neuron
247        fL_State() : direction(1, 0, 0), currpart(NULL), currneuron(NULL)
248        { }
249};
250
251/**
252 * Main class of L-System processing. It holds all information required to perform
253 * steps of development of a creature. It allows to create Timed D0L-Systems with
254 * following limitations:
255 *
256 *  - fractions of time affect only parameters of currently produced words,
257 *  - integer steps deploy rules in order to develop new elements of body,
258 *  - if parameter should use time fraction, then $t variable must be used,
259 *  - $t variable always contain values from 0 to 1 that represent current fraction
260 *    of step.
261 */
262class fL_Builder : public fL_Element
263{
264public:
265        SString axiom; ///<starting sequence of genotype
266        double time; ///<time of creature development
267        int numckp; ///<number of checkpoints per growth step - checkpoints are always created after rules deployment in integer steps, numckp determines how many checkpoints should be created within single step (to watch changes of parameters)
268
269        std::list<fL_Word *> genotype; ///<list of current words of genotype
270        std::unordered_map<std::string, fL_Word *> words; ///<map from string to words existing in L-System
271        std::vector<fL_Rule *> rules; ///<rules available in system
272
273        fL_Builder() : fL_Element(fLElementType::INFO)
274        {
275                axiom = "";
276                time = 1.0;
277                numckp = 1;
278        }
279        ~fL_Builder();
280
281        /**
282         * Helper function for trimming leading and trailing spaces from sequence.
283         * @param data input string
284         * @return string with trimmed spaces
285         */
286        static std::string trimSpaces(std::string data);
287
288        /**
289         * Processes single line of input sequence and load line properties with use
290         * of proper ParamTab.
291         * @param type which type of line is this
292         * @param line line to be processed
293         * @param obj variable storing pointer to created L-System element
294         * @param linenumber for error messages
295         * @param begin index of first character of line
296         * @param end index of last character of line
297         * @return 0 if processing ended successfully, 1-based position of error otherwise
298         */
299        int processLine(fLElementType type, SString line, fL_Element *&obj, int linenumber, int begin, int end);
300
301        /**
302         * Parses input genotype with words, information and rules. First of all,
303         * model-specific words defined in addModelWords method are added to words map.
304         * Every genotype should start with words definitions. They cannot collide
305         * with model words and with each other. Secondly, information line, containing
306         * axiom and number of iteration must be processed. In the end, all rules
307         * have to be processed by builder. After determining line type and creating
308         * fL_Element specialized object, the builder runs object's processDefinition
309         * method to generate all important objects and register element in builder
310         * structures.
311         * @param genotype input genotype
312         * @return 0 if processing finished successfully, 1-based position of error if it occured
313         */
314        int parseGenotype(SString genotype);
315
316        /**
317         * Prepares structures and tokenizes axiom.
318         * @param builder this method should receive pointer to itself
319         * @return 0 if processing went successfully, 1 otherwise
320         */
321        int processDefinition(fL_Builder *builder);
322
323        /**
324         * Adds words used for Framsticks body and brain development.
325         */
326        void addModelWords();
327
328        /**
329         * Helper method that tokenizes string sequence by closing parenthesis
330         * with respect to parenthesis nesting.
331         * @param pos index of character, from which next token needs to be extracted. Method replaces this parameter with next starting position, or -1 if there was an error during parsing, like parenthesis mismatch
332         * @param src original sequence
333         * @param token reference to variable holding new token
334         * @return true if new token is found, false if there is no more tokens or when there was parenthesis mismatch (if pos == -1, then it is parenthesis mismatch)
335         */
336        bool getNextObject(int &pos, SString src, SString &token);
337
338        /**
339         * Helper function that converts input sequence into list of L-System words.
340         * @param sequence input sequence of stringified word objects
341         * @param result reference to list holding generated words
342         * @param numparams number of parameters that can be used for words stored in result list
343         * @return 0 if tokenizing finished successfully, 1 otherwise
344         */
345        int tokenize(SString sequence, std::list<fL_Word *> &result, int numparams);
346
347        /**
348         * Uses rules to process current genotype and make next iteration step for
349         * L-System development.
350         * @param currtime current time of genotype processing
351         * @return always 0
352         */
353        int iterate(double currtime);
354
355        /**
356         * Alters only parameters that depend on time. Should be used if only fraction
357         * of iteration has changed, not integer part.
358         * @param currtime current time of processing
359         * @return always 0
360         */
361        int alterTimedProperties(double currtime);
362
363        /**
364         * Developes L-System from given genotype and builds Framsticks Model from it.
365         */
366        int develop();
367
368        /**
369         * Creates new checkpoint for a given model based on current state of genotype.
370         * @param model reference to model
371         * @return 0 if developing went successfully, 1 otherwise
372         */
373        int developModel(Model &model);
374
375        /**
376         * Returns stringified product of L-System development.
377         * @return stringified words of developed L-System
378         */
379        SString getStringifiedProducts();
380
381        /**
382         * Returns genotype stored by objects in fL_Builder.
383         * @return genotype converted from L-System objects
384         */
385        SString toString();
386
387        /**
388         * TODO
389         */
390        int alterPartProperties(Part *part, fL_Word *stickword, double &alterationcount);
391
392        /**
393         * TODO
394         */
395        Neuro *findInputNeuron(std::list<fL_Word *> genotype, std::list<fL_Word *>::iterator it, fL_Word *attractor);
396
397        /**
398         * TODO
399         */
400        void findNext(fL_Word *word, std::list<fL_Word *> genotype, std::list<fL_Word *>::iterator &it);
401};
402
403#endif // _FL_GENERAL_
Note: See TracBrowser for help on using the repository browser.