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

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

Fixed genotype returned on conversion error

File size: 6.5 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2018  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.len() - 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.len() - 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                }
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, min(mx, 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.