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

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

Increased SString and std::string compatibility: introduced length(), size(), and capacity(), and removed legacy methods that have std::string equivalents

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