00001
00025 #include <magic/mmath.h>
00026 #include <magic/mstream.h>
00027 #include <magic/mclass.h>
00028 #include <magic/mtextstream.h>
00029
00030 #include "nhp/genetics.h"
00031 #include "nhp/genes.h"
00032 #include "nhp/mutrecord.h"
00033 #include "nhp/mutator.h"
00034
00035 impl_dynamic (Genstruct, {Object});
00036 impl_dynamic (Gentainer, {Genstruct});
00037 impl_dynamic (Genome, {Gentainer});
00038
00039
00040
00042
00043
00044
00045
00046
00047
00048
00050
00051 MutationRate::MutationRate (const Gentainer& g) {
00052 mBinaryRate = static_cast<const FloatGene&> (*g.getGene ("Rb")).getvalue();
00053 mFloatRate = 1;
00054 mFloatVariance = static_cast<const FloatGene&> (*g.getGene ("Vf")).getvalue();
00055 mIntRate = static_cast<const FloatGene&> (*g.getGene ("Ri")).getvalue();
00056 mOneBitMutation = false;
00057 }
00058
00059 MutationSimpleMutator mutmut (30);
00060
00061 void MutationRate::addGenesTo (Gentainer& g, const StringMap& params)
00062 {
00063 double low = isnull(params)? 0.01 : getOrDefault (params, "MutationRate.lowBound", String(0.01)).toDouble ();
00064 g.add (&(new FloatGene ("Rb", low, 1, 10.0))->setMutator(&mutmut));
00065 g.add (&(new FloatGene ("Rf", low, 1, 10.0))->setMutator(&mutmut));
00066
00067 g.add (&(new FloatGene ("Vf", 0, 1, 10.0))->setMutator(&mutmut));
00068
00069 g.add (&(new FloatGene ("Ri", low, 1, 10.0))->setMutator(&mutmut));
00070
00071
00072 g["Rb"].hide ();
00073 g["Rf"].hide ();
00074 g["Vf"].hide ();
00075 g["Ri"].hide ();
00076 }
00077
00078
00079
00081
00082
00083
00084
00085
00086
00087
00089
00090 Genstruct::Genstruct (const GeneticID& nam) {
00091 size = 0;
00092 id = nam;
00093 mHidden = false;
00094 }
00095
00096 Genstruct::Genstruct (const Genstruct& orig) {
00097 size = orig.size;
00098 id = orig.id;
00099 mHidden = orig.mHidden;
00100 }
00101
00102 int Genstruct::length () const {
00103 if (!size)
00104 size = calc_len ();
00105
00106 return size;
00107 }
00108
00109 void Genstruct::print (TextOStream& out) const {
00110 if (!mHidden)
00111 out.printf ("%s", (CONSTR) id);
00112 }
00113
00114 DataOStream& Genstruct::operator>> (DataOStream& out) const {
00115 out.name ("size") << size;
00116 out.name ("id") << id;
00117 out.name ("mHidden") << int(mHidden);
00118 return out;
00119 }
00120
00121 void Genstruct::check () const {
00122 ASSERT (size>=0);
00123 ASSERTWITH (size<1000000, "A sensible upper limit for error checking");
00124 }
00125
00126
00127
00129
00130
00131
00132
00133
00134
00135
00137
00138 Gentainer::Gentainer (const GeneticID& iid) : Genstruct (iid) {
00139 self_adjust = false;
00140 mRecombRate = 1.0;
00141 }
00142
00143 Gentainer::Gentainer (const Gentainer& orig) : Genstruct (orig) {
00144
00145 for (int i=0; i<orig.substructs.size(); i++)
00146 substructs.add (orig.substructs[i].replicate ());
00147
00148 self_adjust = orig.self_adjust;
00149 mRecombRate = orig.mRecombRate;
00150 }
00151
00152 void Gentainer::add (Genstruct* genestr) {
00153 ASSERTWITH (genestr, "Genstruct to be added to Gentainer must not be null pointer.");
00154 substructs.add (genestr);
00155 }
00156
00157 void Gentainer::init () {
00158
00159 for (int i=0; i<substructs.size(); i++)
00160 substructs[i].init ();
00161 }
00162
00163 void Gentainer::addPrivateGenes (Gentainer& parent, const StringMap& params) {
00164
00165 if (isnull(params))
00166 add (new FloatGene ("Px", 0, 1, 0.1));
00167 else {
00168 params.failByNullOnce ();
00169 if (isnull (params["Gentainer.recombFreq"]))
00170 add (new FloatGene ("Px", 0, 1, 0.1));
00171 else {
00172 params.failByNullOnce ();
00173 double value = params["Gentainer.recombFreq"].toDouble ();
00174 add (new FloatGene ("Px", value, value, 0.0));
00175 }
00176 }
00177
00178 add (new IntGene ("RM", 1, 2, 1.0));
00179 add (new IntGene ("Nx", 1, 4, 1.0));
00180
00181
00182
00183
00184
00185
00186 MutationRate::addGenesTo (*this, params);
00187
00188
00189 for (int i=0; i<substructs.size(); i++)
00190 substructs[i].addPrivateGenes (*this, params);
00191
00192
00193 }
00194
00195 const Genstruct* Gentainer::getGene (const GeneticID& cc_name) const
00196 {
00197 try {
00198
00199 for (int i=0; i<substructs.size(); i++) {
00200 if (substructs[i].getID() == cc_name)
00201 return &substructs[i];
00202 }
00203
00204
00205 for (int i=0; i<substructs.size(); i++)
00206 if (const Genstruct* gotten = substructs[i].getGene (cc_name))
00207 return gotten;
00208
00209 } catch (exception e) {
00210
00211 throw invalid_gene_name (format ("Error while seeking gene '%s':\n%s",
00212 (CONSTR)cc_name, e.what()));
00213 }
00214
00215
00216 return NULL;
00217 }
00218
00219 bool Gentainer::pointMutate (const MutationRate& k) {
00220 bool mutated = false;
00221
00222 if (self_adjust) {
00223 MutationRate mult (*this);
00224 MutationRate combined (k, mult);
00225
00226 MutabilityRecord::addBoolMutability (combined.binaryRate());
00227 MutabilityRecord::addFloatMutability (combined.doubleRate());
00228 MutabilityRecord::addFloatVariance (combined.doubleVariance());
00229
00230 for (int i=0; i<substructs.size(); i++)
00231 if (substructs[i].pointMutate (combined))
00232 mutated = true;
00233 } else {
00234
00235 for (int i=0; i<substructs.size(); i++)
00236 if (substructs[i].pointMutate (k))
00237 mutated = true;
00238 }
00239
00240 return mutated;
00241 }
00242
00243 void Gentainer::recombine (const Genstruct& as, const Genstruct& bs) {
00244 const Gentainer& a = static_cast<const Gentainer&> (as);
00245 const Gentainer& b = static_cast<const Gentainer&> (bs);
00246
00247
00248 ASSERTWITH (a.length() == length() && b.length() == length(),
00249 format ("Parameter error, len=%d, a.len=%d, b.len=%d",
00250 length(), a.length(), b.length()));
00251
00252
00253 bool crosspos [substructs.size()-1];
00254 for (int i=0; i<substructs.size()-1; i++)
00255 crosspos [i] = false;
00256
00257
00258 int n = static_cast<const AnyIntGene&> (*getGene ("Nx")).getvalue();
00259 double pX = static_cast<const AnyFloatGene&> (*getGene ("Px")).getvalue();
00260 for (int i=0; i<n; i++)
00261 if (frnd ()<pX)
00262 crosspos [rnd (substructs.size())] = true;
00263
00264
00265 int whichpar = 0;
00266 for (int i=0; i<substructs.size(); i++) {
00267 ASSERTWITH (substructs[i].getID() == a[i].getID() &&
00268 substructs[i].getID() == b[i].getID(),
00269 "Chromosomes must be in equal order to be crossed");
00270
00271
00272 if (i>0 && crosspos [i-1]) {
00273
00274 whichpar = 1-whichpar;
00275
00276
00277 substructs[i].recombine (whichpar? a[i]:b[i], (1-whichpar)? a[i]:b[i]);
00278 } else
00279
00280 substructs[i].copy (whichpar? a[i] : b[i]);
00281 }
00282 }
00283
00284 double Gentainer::equality (const Genstruct& o) const {
00285 const Gentainer& other = static_cast<const Gentainer&> (o);
00286
00287 ASSERT (length() == other.length());
00288
00289
00290 double tot=0.0;
00291 for (int i=0; i<substructs.size(); i++) {
00292 ASSERTWITH (substructs[i].getID() == other[i].getID(),
00293 "Chromosomes must be in equal order to be compared");
00294
00295
00296 tot += substructs[i].equality (other.substructs[i]);
00297 }
00298
00299
00300 return tot;
00301 }
00302
00303 Genstruct* Gentainer::replicate () const {
00304
00305
00306
00307 Gentainer* cln = static_cast<Gentainer*> (dyncreate (this->getclassname()));
00308
00309
00310
00311
00312 for (int i=0; i<substructs.size(); i++)
00313 cln->add (substructs[i].replicate ());
00314
00315 return cln;
00316 }
00317
00318 void Gentainer::copy (const Genstruct& o) {
00319 copyGenstr (o);
00320 const Gentainer& other = static_cast<const Gentainer&> (o);
00321
00322 ASSERTWITH (length()==o.length() || length()==0,
00323 format ("Cannot copy structure of differing dimension (this=%d, other=%d)"
00324 , length(), o.length()));
00325 ASSERTWITH (substructs.size()==other.substructs.size() || substructs.size()==0,
00326 format ("Cannot copy structure of differing dimension (this=%d, other=%d)"
00327 , substructs.size(), other.substructs.size()));
00328
00329 if (substructs.size()>0) {
00330
00331 for (int i=0; i<substructs.size(); i++)
00332 substructs[i].copy (other.substructs[i]);
00333 } else {
00334
00335 for (int i=0; i<other.substructs.size(); i++)
00336 substructs.add (other.substructs[i].replicate());
00337 }
00338
00339 self_adjust = other.self_adjust;
00340 }
00341
00342 void Gentainer::print (TextOStream& out) const
00343 {
00344 if (!isempty(id))
00345 out.printf ("%s=", (CONSTR) id);
00346 out.printf ("%s {", (CONSTR) getclassname());
00347
00348
00349 for (int i=0; i<substructs.size(); i++) {
00350
00351 if (!substructs[i].isHidden()) {
00352 substructs[i].print (out);
00353
00354
00355 if (i<substructs.size()-1 && !substructs[i].is_a("BinaryGene") && !substructs[i+1].is_a("BinaryGene"))
00356 out << ' ';
00357 }
00358 }
00359 out.flush ();
00360 out << '}';
00361 }
00362
00363 int Gentainer::calc_len () const {
00364 int sum=0;
00365 for (int i=0; i<substructs.size(); i++)
00366 sum += substructs[i].length ();
00367 return sum;
00368 }
00369
00376 bool Gentainer::execute (const GeneticMsg& msg) const
00377 {
00378 FUNCTION_BEGIN;
00379
00380
00381 for (int i=0; i<substructs.size(); i++)
00382 if (substructs[i].getID() == msg.receiver)
00383 return substructs[i].execute (msg);
00384
00385
00386
00387
00388
00389
00390
00391
00392 if (msg.receiver == "init")
00393 return true;
00394
00395 return false;
00396 FUNCTION_END;
00397 }
00398
00399 void Gentainer::check () const {
00400 Genstruct::check ();
00401 ASSERT (mRecombRate>=0 && mRecombRate<=1);
00402 substructs.check();
00403 }
00404
00405 DataOStream& Gentainer::operator>> (DataOStream& out) const {
00406 Genstruct::operator>> (out);
00407 out.name ("substructs") << substructs;
00408 return out;
00409 }
00410
00411
00412
00414
00415
00416
00417
00418
00419
00420
00422
00423 Genome::Genome () {
00424 kings = 0;
00425 }
00426
00427 Genome::Genome (const Genome& other) : Gentainer (other) {
00428 kings = other.kings;
00429 }
00430
00431 void Genome::init () {
00432 kings = 0;
00433 Gentainer::init ();
00434 }
00435
00436 void Genome::addPrivateGenes (Gentainer& parent, const StringMap& pars) {
00437 Gentainer::addPrivateGenes (*this, pars);
00438 }
00439
00440 void Genome::print (TextOStream& out) const {
00441 Gentainer::print (out);
00442 }
00443
00444 DataOStream& Genome::operator>> (DataOStream& out) const {
00445 Gentainer::operator>> (out);
00446 out.name ("kings") << kings;
00447 return out;
00448 }
00449
00450 void Genome::check () const {
00451 Gentainer::check ();
00452 ASSERT (kings>=0);
00453 ASSERTWITH (kings<100000, "Reasonable upper limit");
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00464
00465
00466
00467
00468
00469
00470
00472
00473