source: cpp/frams/genetics/fB/fB_conv.cpp @ 1139

Last change on this file since 1139 was 1130, checked in by Maciej Komosinski, 4 years ago

Used std::min(), std::max() explicitly to avoid compiler confusion. Used std::size() explicitly instead of the equivalent macro

File size: 6.6 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2021  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "fB_conv.h"
6
7#include <frams/param/paramobj.h>
8#include <vector>
9#include <algorithm>
10#include <frams/util/multimap.h>
11#include "fB_general.h"
12
13double GenoConv_fBH::convertCharacterTo01(char c)
14{
15        return (double)(c - 'a') / 25.0;
16}
17
18double GenoConv_fBH::convertCharacterToWeight(char c)
19{
20        if (c <= 'm')
21        {
22                return -0.001 * pow(2.0, (double)('m' - c));
23        }
24        else
25        {
26                return 0.001 * pow(2.0, (double)(c - 'n'));
27        }
28}
29
30fH_Handle* GenoConv_fBH::convertCharacterToHandle(char c, int dims, int start, int end, std::vector<IRange> ranges[3])
31{
32        fH_Handle *handle = NULL;
33        if (c >= 'a' && c <= 'i')
34        {
35                handle = new fH_StickHandle(dims, start, end);
36                ranges[0].push_back(IRange(start, end));
37        }
38        else if (c >= 'j' && c <= 'p')
39        {
40                handle = new fH_NeuronHandle(dims, start, end);
41                ranges[1].push_back(IRange(start, end));
42        }
43        else
44        {
45                handle = new fH_ConnectionHandle(dims, start, end);
46                ranges[2].push_back(IRange(start, end));
47        }
48        return handle;
49}
50
51SString GenoConv_fBH::convert(SString &i, MultiMap *map, bool using_checkpoints)
52{
53        // if there is no genotype to load, then return error
54
55        std::vector<IRange> ranges[3];
56
57        int pos = 0;
58        SString line;
59        i.getNextToken(pos, line, '\n');
60        int dims = 0;
61        // extract dimensions
62        if (!ExtValue::parseInt(line.c_str(), dims, true, false))
63        {
64                logMessage("f2::Builder", "parseGenotype", LOG_ERROR, "Could not parse number of dimensions");
65                return "";
66        }
67
68        if (dims < 1)
69        {
70                logMessage("f2::Builder", "parseGenotype", LOG_ERROR, "Number of dimensions cannot be lower than 1");
71                return "";
72        }
73
74        fH_Builder creature(dims, false);
75
76        for (int q = 0; q < fB_GenoHelpers::geneCount(i); q++)
77        {
78                int start, end;
79                SString gene = fB_GenoHelpers::getGene(q, i, start, end);
80                end -= 1; // last character is included in range, so decrementation is required
81                int endoffset = 0;
82                if (gene.indexOf("zz", 0) != -1) endoffset = 2;
83                if (gene.length() - endoffset < 3)
84                {
85                        fH_StickHandle *handle = new fH_StickHandle(dims, start, end);
86                        ParamEntry *tab = creature.getParamTab(handle->type);
87                        void *obj = ParamObject::makeObject(tab);
88                        Param par(tab, NULL);
89                        par.select(obj);
90                        par.setDefault();
91                        handle->loadProperties(par);
92                        ranges[0].push_back(IRange(start, end));
93                        creature.addHandle(handle);
94                        continue;
95                }
96                int hclasspos = 2;
97                if (gene[2] == '"')
98                {
99                        hclasspos--;
100                        if (!getNextCharId(gene, hclasspos))
101                        {
102                                return "";
103                        }
104                }
105                fH_Handle *handle = convertCharacterToHandle(gene[hclasspos], dims, start, end, ranges);
106                ParamEntry *tab = creature.getParamTab(handle->type);
107                void *obj = ParamObject::makeObject(tab);
108                Param par(tab, NULL);
109                par.select(obj);
110                par.setDefault();
111
112                int propindex = 0;
113                int z = hclasspos;
114                if (gene[z] == '"')
115                {
116                        z--;
117                        if (!getNextCharId(gene, z))
118                        {
119                                delete handle;
120                                ParamObject::freeObject(obj);
121                                return "";
122                        }
123                }
124                endoffset = 0;
125                if (gene.indexOf("zz", 0) != -1) endoffset = 2;
126                int nclassdefcount = 1;
127                while (z < gene.length() - endoffset)
128                {
129                        if (processNextLetter(creature, handle, par, gene, propindex, z, ranges, nclassdefcount) == -1)
130                        {
131                                logMessage("GenoConv_fBH", "convert", LOG_ERROR, "Property of fH could not be parsed");
132                                delete handle;
133                                ParamObject::freeObject(obj);
134                                return "";
135                        }
136                }
137                if (handle->type == fHBodyType::NEURON && propindex < par.getPropCount())
138                {
139                        SString nclass;
140                        if (!getNeuroClass(gene, nclass, nclassdefcount))
141                        {
142                                delete handle;
143                                ParamObject::freeObject(obj);
144                                return "";
145                        }
146                        par.setStringById(FH_PE_NEURO_DET, nclass);
147                }
148                handle->loadProperties(par);
149                creature.addHandle(handle);
150        }
151
152        SString fHgenotype = creature.toString();
153
154        if (NULL != map)
155        {
156                int fHpos = 0;
157                SString line;
158                fHgenotype.getNextToken(fHpos, line, '\n');
159                int lastpos = fHpos;
160                for (int t = 0; t < 3; t++)
161                {
162                        for (unsigned int q = 0; q < ranges[t].size(); q++)
163                        {
164                                fHgenotype.getNextToken(fHpos, line, '\n');
165                                map->add(ranges[t][q].begin, ranges[t][q].end, lastpos, fHpos - 1);
166                                lastpos = fHpos;
167                        }
168                }
169        }
170
171        return fHgenotype;
172}
173
174bool GenoConv_fBH::getNextCharId(const SString& genotype, int &i)
175{
176        i++;
177        if (genotype[i] == '"')
178        {
179                int nextid = i + 1;
180                do
181                {
182                        nextid = genotype.indexOf('"', nextid);
183                        if (nextid == -1)
184                        {
185                                return false;
186                        }
187                        nextid++;
188                } while (genotype[nextid] == '"');
189                i = nextid;
190        }
191        return true;
192}
193
194bool GenoConv_fBH::getNeuroClass(const SString& gene, SString &def, int nclassdefcount)
195{
196        SString lastdef = "N";
197        int nclass = 0;
198        int pos = 0;
199        while (nclass < nclassdefcount)
200        {
201                pos = gene.indexOf('\"', pos);
202                if (pos == -1)
203                {
204                        def = lastdef;
205                        return true;
206                }
207                pos++;
208                SString currdef;
209                if (gene.indexOf('\"', pos) == -1 || !gene.getNextToken(pos, currdef, '\"'))
210                {
211                        def = lastdef;
212                        return false;
213                }
214                lastdef = currdef;
215                nclass++;
216        }
217        def = lastdef;
218        return true;
219}
220
221int GenoConv_fBH::processNextLetter(fH_Builder &creature, fH_Handle *&currhandle, Param &par, const SString& gene, int &propindex, int &i, std::vector<IRange> ranges[3], int &nclassdefcount)
222{
223        if (propindex >= par.getPropCount())
224        {
225                int tmpend = currhandle->end;
226                currhandle->end = i - 1;
227                currhandle->loadProperties(par);
228                creature.addHandle(currhandle);
229                currhandle = convertCharacterToHandle(gene[i], currhandle->getDimensions(), currhandle->begin + i, tmpend, ranges);
230                ParamEntry *tab = creature.getParamTab(currhandle->type);
231                par.setParamTab(tab);
232                void *obj = ParamObject::makeObject(tab);
233                par.select(obj);
234                par.setDefault();
235                propindex = 0;
236                if (!getNextCharId(gene, i))
237                        return -1;
238                return 0;
239        }
240        else
241        {
242                if (*par.type(propindex) == 'f')
243                {
244                        if (currhandle->type == fHBodyType::CONNECTION && *par.id(propindex) == 'w')
245                        {
246                                par.setDouble(propindex, convertCharacterToWeight(gene[i]));
247                        }
248                        else
249                        {
250                                double val = convertCharacterTo01(gene[i]);
251                                double mn, mx, def;
252                                par.getMinMaxDouble(propindex, mn, mx, def);
253                                par.setDouble(propindex, std::min(mx, std::max(mn, (mx - mn) * val + mn)));
254                        }
255                        propindex++;
256                        if (!getNextCharId(gene, i))
257                                return -1;
258                        return 0;
259                }
260                else if (currhandle->type == fHBodyType::NEURON && *par.id(propindex) == 'd')
261                {
262                        //When 'd' property appears for i-th element in gene, the method
263                        //looks for i-th neuron definition
264                        SString nclass;
265                        if (!getNeuroClass(gene, nclass, nclassdefcount)) return -1;
266                        par.setString(propindex, nclass);
267                        propindex++;
268                        nclassdefcount++;
269                        if (!getNextCharId(gene, i))
270                                return -1;
271                        return 0;
272                }
273                // other property types are not available in this encoding
274                return -1;
275        }
276}
Note: See TracBrowser for help on using the repository browser.