-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGABin2DecGenome.C
More file actions
306 lines (251 loc) · 8.72 KB
/
GABin2DecGenome.C
File metadata and controls
306 lines (251 loc) · 8.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
// $Header$
/* ----------------------------------------------------------------------------
bin2dec.C
mbwall 19apr95
Copyright (c) 1995 Massachusetts Institute of Technology
all rights reserved
DESCRIPTION:
Source file for the binary-to-decimal genome.
This is the phenotype for converting binary strings to decimal values. There
are limits to the size of the numbers you can use (ie you're limited to the
number of bits that can represent a float - see the converters file for more
information).
---------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <ga/gaerror.h>
#include <ga/GABin2DecGenome.h>
/* ----------------------------------------------------------------------------
Phenotype class definitions
---------------------------------------------------------------------------- */
#define GA_B2D_CHUNKSIZE 20
GABin2DecPhenotypeCore::GABin2DecPhenotypeCore() :
csz(GA_B2D_CHUNKSIZE), n(0), N(0), sz(0) {
nbits = oset = 0;
minval = maxval = 0;
cnt = 1;
}
GABin2DecPhenotypeCore::
GABin2DecPhenotypeCore(const GABin2DecPhenotypeCore& p) :
csz(p.csz), n(p.n), N(p.N), sz(p.sz) {
nbits = new unsigned short[N];
oset = new unsigned short[N];
minval = new float[N];
maxval = new float[N];
memcpy(nbits, p.nbits, n*sizeof(unsigned short));
memcpy(oset, p.oset, n*sizeof(unsigned short));
memcpy(minval, p.minval, n*sizeof(float));
memcpy(maxval, p.maxval, n*sizeof(float));
cnt = 1;
}
GABin2DecPhenotypeCore::~GABin2DecPhenotypeCore(){
if(cnt > 0)
GAErr(GA_LOC, "GABin2DecPhenotypeCore", "destructor", gaErrRefsRemain);
delete [] nbits;
delete [] oset;
delete [] minval;
delete [] maxval;
}
GABin2DecPhenotypeCore&
GABin2DecPhenotypeCore::operator=(const GABin2DecPhenotypeCore& p){
if(&p == this) return *this;
delete [] nbits;
delete [] oset;
delete [] minval;
delete [] maxval;
n = p.n;
sz = p.sz;
N = p.N;
csz = p.csz;
nbits = new unsigned short[N];
oset = new unsigned short[N];
minval = new float[N];
maxval = new float[N];
memcpy(nbits, p.nbits, n*sizeof(unsigned short));
memcpy(oset, p.oset, n*sizeof(unsigned short));
memcpy(minval, p.minval, n*sizeof(float));
memcpy(maxval, p.maxval, n*sizeof(float));
return *this;
}
// Add another phenotype to this phenotype object. If needed, we allocate more
// space, otherwise just tag the new on then end. We allocate space in chunks
// so we don't spend too much time doing memory allocation stuff.
void
GABin2DecPhenotype::add(unsigned int nb, float min, float max){
if(core->n + 1 > core->N){
core->N += core->csz;
unsigned short *nbtmp = core->nbits;
core->nbits = new unsigned short[core->N];
memcpy(core->nbits, nbtmp, core->n*sizeof(unsigned short));
delete [] nbtmp;
unsigned short *ostmp = core->oset;
core->oset = new unsigned short[core->N];
memcpy(core->oset, ostmp, core->n*sizeof(unsigned short));
delete [] ostmp;
float *mintmp = core->minval;
core->minval = new float[core->N];
memcpy(core->minval, mintmp, core->n*sizeof(float));
delete [] mintmp;
float *maxtmp = core->maxval;
core->maxval = new float[core->N];
memcpy(core->maxval, maxtmp, core->n*sizeof(float));
delete [] maxtmp;
}
core->nbits[core->n] = nb;
if(core->n > 0)
core->oset[core->n] = core->oset[core->n-1] + core->nbits[core->n-1];
else
core->oset[core->n] = 0;
core->minval[core->n] = min;
core->maxval[core->n] = max;
core->n++;
core->sz += nb;
}
void
GABin2DecPhenotype::remove(unsigned int x){
if(x >= core->n) return;
memmove(&(core->nbits[x]), &(core->nbits[x+1]),
(core->n - x - 1)*sizeof(unsigned short));
memmove(&(core->oset[x]), &(core->oset[x+1]),
(core->n - x - 1)*sizeof(unsigned short));
memmove(&(core->minval[x]), &(core->minval[x+1]),
(core->n - x - 1)*sizeof(float));
memmove(&(core->maxval[x]), &(core->maxval[x+1]),
(core->n - x - 1)*sizeof(float));
core->n -= 1;
}
int
GABin2DecPhenotype::equal(const GABin2DecPhenotype & b) const {
if(core->sz != b.core->sz || core->n != b.core->n) return gaFalse;
if(memcmp(core->nbits,b.core->nbits,core->n*sizeof(unsigned short))!=0 ||
memcmp(core->oset, b.core->oset, core->n*sizeof(unsigned short))!=0 ||
memcmp(core->minval, b.core->minval, core->n*sizeof(float)) != 0 ||
memcmp(core->maxval, b.core->maxval, core->n*sizeof(float)))
return gaFalse;
return(gaTrue);
}
/* ----------------------------------------------------------------------------
Genome class definition
---------------------------------------------------------------------------- */
void
GABin2DecGenome::copy(const GAGenome & orig)
{
if(&orig == this) return;
const GABin2DecGenome* c = DYN_CAST(const GABin2DecGenome*, &orig);
if(c) {
GA1DBinaryStringGenome::copy(*c);
encode = c->encode;
decode = c->decode;
if(ptype) *ptype = *(c->ptype);
else ptype = new GABin2DecPhenotype(*(c->ptype));
}
}
// We shouldn't have to worry about our superclass's data members for the
// attributes part here, but there is no 'copy attributes' function, so we
// end up doing it. bummer.
GAGenome *
GABin2DecGenome::clone(GAGenome::CloneMethod flag) const {
GABin2DecGenome *cpy = new GABin2DecGenome(*ptype);
if(flag == CONTENTS){ cpy->copy(*this); }
else{
cpy->GAGenome::copy(*this);
cpy->maxX = maxX; cpy->minX = minX;
*(cpy->ptype) = *ptype;
cpy->encode = encode;
cpy->decode = decode;
}
return cpy;
}
// The phenotype does reference counting, so its ok to keep our own copy of
// the phenotype. So all we have to do here is copy the one that is passed
// to us, then modify the bit string to accomodate the new mapping.
const GABin2DecPhenotype &
GABin2DecGenome::phenotypes(const GABin2DecPhenotype & p)
{
*ptype = p;
GA1DBinaryStringGenome::resize(p.size());
return *ptype;
}
// We access the data string directly here. This could be dangerous (if the
// bitstream ever changes on us it will affect the way this method sees the
// data string).
// Eventually we may need to cache the decimal values in an array of floats,
// but for now we call the converter routine every time each phenotype is
// requested.
float
GABin2DecGenome::phenotype(unsigned int n) const
{
if(n >= ptype->nPhenotypes()){
GAErr(GA_LOC, className(), "phenotype", gaErrBadPhenotypeID);
return(0.0);
}
float val=0.0;
decode(val,
&(data[ptype->offset(n)]), ptype->length(n),
ptype->min(n), ptype->max(n));
return val;
}
// Set the bits of the binary string based on the decimal value that is passed
// to us. Notice that the number you pass may or may not be set properly. It
// depends on the resolution defined in the phenotype. If you didn't define
// enough resolution, then there may be no way to represent the number.
// We round off to the closest representable value, then return the number
// that we actually entered (the rounded value).
// *** this is dangerous! we're accessing the superclass' data representation
// directly, so if the representation changes to a bit stream, this will break.
// If someone tries to set the phenotype beyond the bounds, we post an error
// then set the bits to the closer bound.
float
GABin2DecGenome::phenotype(unsigned int n, float val)
{
if(n >= ptype->nPhenotypes()){
GAErr(GA_LOC, className(), "phenotype", gaErrBadPhenotypeID);
return val;
}
if(val < ptype->min(n) || val > ptype->max(n)){
GAErr(GA_LOC, className(), "phenotype", gaErrBadPhenotypeValue);
val = ((val < ptype->min(n)) ? ptype->min(n) : ptype->max(n));
}
encode(val,
&(data[ptype->offset(n)]), ptype->length(n),
ptype->min(n), ptype->max(n));
return val;
}
#ifdef GALIB_USE_STREAMS
// Read the incoming data as a list of phenotype values. It would be nice to
// do this either as binary or decimal read, but oh well... not much need.
int
GABin2DecGenome::read(STD_ISTREAM & is)
{
float value;
for(unsigned int i=0; i<phenotypes().nPhenotypes(); i++){
is >> value;
if(is.fail() || is.eof()) return 1;
phenotype(i, value);
}
return 0;
}
int
GABin2DecGenome::write(STD_OSTREAM & os) const
{
for(unsigned int i=0; i<phenotypes().nPhenotypes(); i++)
os << phenotype(i) << " ";
return 0;
}
#endif
// For two bin2dec genomes to be equal they must have the same bits AND the
// same phenotypes.
int
GABin2DecGenome::equal(const GAGenome& g) const {
GABin2DecGenome & b = (GABin2DecGenome&)g;
return((GA1DBinaryStringGenome::equal(b) && *ptype == *(b.ptype)) ?
gaTrue : gaFalse);
}
int
GABin2DecGenome::notequal(const GAGenome& g) const {
GABin2DecGenome & b = (GABin2DecGenome&)g;
return((GA1DBinaryStringGenome::notequal(b) || *ptype != *(b.ptype)) ?
gaTrue : gaFalse);
}