source: cpp/frams/genetics/genoconv.cpp @ 1101

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

Building a Model from Geno now fails when Model.shape is incompatible with Geno.format; renamed enum constants for genetic formats: xxx_FORMAT => FORMAT_xxx

  • Property svn:eol-style set to native
File size: 5.3 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 <common/nonstd.h>
6
7#include <stdlib.h>
8#include <math.h>
9#include <stdio.h>
10#include <string.h>
11#include <ctype.h>
12#include <time.h>
13#include <errno.h>
14
15#include "genoconv.h"
16#include <frams/util/multimap.h>
17#include <common/util-string.h>
18
19///////////////////////////////////////////////////////////////////////////
20
21GenoConvParam::GenoConvParam(GenoConvManager *g) :Param(0), gcm(g)
22{
23        updatetab();
24}
25
26void GenoConvParam::freetab()
27{
28        if (tab) free(tab);
29        tab = 0;
30}
31
32const char *GenoConvParam::id(int i)
33{
34        if (i >= gcm->converters.size()) return 0;
35        sprintf(tmp_id, "genkonw%d", i);
36        return tmp_id;
37}
38
39void GenoConvParam::updatetab()
40{
41        int i;
42        GenoConverter *gk;
43        ParamEntry *pe;
44        int ile = gcm->converters.size();
45        freetab();
46        tab = (ParamEntry*)calloc(2 + ile, sizeof(ParamEntry));
47        tab[0].id = "Genetics: Conversions";
48        tab[0].group = 1;
49        tab[0].flags = (paInt)ile;
50        tab[0].name = "gkparam:";
51        gcnames.clear();
52        gcnames.reserve(gcm->converters.size()); //avoid reallocations in the loop below, since we externally store pointers to objects saved in this vector
53        for (i = 0, pe = tab + 1; gk = (GenoConverter *)gcm->converters(i); pe++, i++)
54        {
55                pe->id = "?";
56                pe->group = 0;
57                pe->flags = 0;
58                std::string descr = "f";
59                descr += gk->in_format.c_str();
60                descr += " --> f";
61                descr += gk->out_format.c_str();
62                descr += "  :  ";
63                descr += gk->name;
64                gcnames.push_back(descr);
65                pe->name = gcnames.back().c_str(); //externally store a pointer to the object just saved in the vector
66                pe->type = "d 0 1";
67        }
68        pe->id = 0;
69}
70
71GenoConvParam::~GenoConvParam()
72{
73        freetab();
74}
75
76void *GenoConvParam::getTarget(int i)
77{
78        GenoConverter *gk = (GenoConverter *)gcm->converters(i);
79        return &gk->enabled;
80}
81
82GenoConvManager::GenoConvManager()
83        :param(this)
84{
85}
86
87GenoConvManager::~GenoConvManager()
88{
89        FOREACH(GenoConverter*, gc, converters) delete gc;
90}
91
92void GenoConvManager::addConverter(GenoConverter *gc)
93{
94        converters += gc;
95        param.updatetab();
96}
97void GenoConvManager::removeConverter(GenoConverter *gc)
98{
99        converters -= gc;
100        param.updatetab();
101}
102
103GenoConverter *GenoConvManager::findConverters(SListTempl<GenoConverter*>* result, const SString& in, const SString& out, int enabled, char* name)
104{
105        GenoConverter *gk, *retval = 0;
106        int i = 0;
107        for (; gk = (GenoConverter*)converters(i); i++)
108        {
109                if ((in != Geno::FORMAT_UNKNOWN) && (in != gk->in_format)) continue;
110                if ((out != Geno::FORMAT_UNKNOWN) && (out != gk->out_format)) continue;
111                if ((enabled != -1) && (enabled != gk->enabled)) continue;
112                if ((name) && (strcmp(name, gk->name))) continue;
113                if (!retval) { retval = gk; if (!result) break; }
114                if (result) result->append(gk);
115        }
116        return retval;
117}
118
119/// Writes path into 'path'.
120/// return the last path element (return >= path)
121/// null -> path not found
122/// @param mapavailable will receive 1 if conversion map is supported by all converters in path
123/// (can be NULL if you don't need this information)
124
125GenoConverter **GenoConvManager::getPath(const SString& in_format, const SString& out_format_list, GenoConverter **path, int maxlen, int *mapavailable)
126{
127        if (!maxlen) return 0;
128        GenoConverter *gk;
129        int i = 0;
130        for (; gk = (GenoConverter*)converters(i); i++)
131        {
132                if ((gk->enabled) && (gk->in_format == in_format))
133                {
134                        *path = gk;
135                        if (Geno::formatIsOneOf(gk->out_format, out_format_list))
136                        {
137                                if (mapavailable)
138                                        *mapavailable = gk->mapsupport;
139                                return path;
140                        }
141                        else
142                        {
143                                int mapavail;
144                                GenoConverter **ret = getPath(gk->out_format, out_format_list, path + 1, maxlen - 1, &mapavail);
145                                if (ret)
146                                {
147                                        if (mapavailable)
148                                                *mapavailable = gk->mapsupport && mapavail;
149                                        return ret;
150                                }
151                        }
152                }
153        }
154        return 0;
155}
156
157Geno GenoConvManager::convert(Geno &in, SString format_list, MultiMap *map, bool using_checkpoints, bool *converter_missing)
158{
159        if (Geno::formatIsOneOf(in.getFormat(), format_list))
160        {
161                if (converter_missing) *converter_missing = false;
162                return in;
163        }
164        GenoConverter *path[10];
165        int dep;
166        GenoConverter **ret;
167        if (in.isInvalid())
168        {
169                if (converter_missing) *converter_missing = false;
170                return Geno("", Geno::FORMAT_INVALID, "", "Invalid genotype cannot be converted");
171        }
172        int mapavail;
173        for (dep = 1; dep < (int)sizeof(path); dep++) //iterative deepening
174                if (ret = getPath(in.getFormat(), format_list, path, dep, &mapavail)) break;
175        if (!ret)
176        {
177                if (converter_missing) *converter_missing = true;
178                return Geno("", Geno::FORMAT_INVALID, "", "Converter not found");
179        }
180        if (converter_missing) *converter_missing = false;
181        if (!map) mapavail = 0;
182        GenoConverter **t = path;
183        SString tmp, out_format;
184        tmp = in.getGenes();
185        MultiMap lastmap, tmpmap;
186        int firstmap = 1;
187        for (; t <= ret; t++)
188        {
189                GenoConverter *gk = *t;
190                tmp = gk->convert(tmp, mapavail ? &tmpmap : 0, using_checkpoints);
191                out_format = gk->out_format;
192                if (!tmp.length())
193                {
194                        string t = ssprintf("f%s->f%s conversion failed (%s)", gk->in_format.c_str(), gk->out_format.c_str(), gk->name);
195                        return Geno("", Geno::FORMAT_INVALID, "", t.c_str());
196                }
197                if (mapavail)
198                {
199                        if (firstmap)
200                        {
201                                lastmap = tmpmap;
202                                firstmap = 0;
203                        }
204                        else
205                        {
206                                MultiMap m;
207                                m.addCombined(lastmap, tmpmap);
208                                lastmap = m;
209                        }
210                        tmpmap.clear();
211                }
212        }
213        if (map)
214                *map = lastmap;
215        return Geno(tmp, out_format, in.getName(), in.getComment());
216}
Note: See TracBrowser for help on using the repository browser.