Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

genetics.cc

Go to the documentation of this file.
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 //       |   |                     o            ----                        //
00044 //       |\ /|        |   ___   |           _   |   )  ___   |   ___        //
00045 //       | V | |   | -+-  ___| -+- |  __  |/ \  |---   ___| -+- /   )       //
00046 //       | | | |   |  |  (   |  |  | /  \ |   | | \   (   |  |  |---        //
00047 //       |   |  \__!   \  \__|   \ | \__/ |   | |  \   \__|   \  \__        //
00048 //                                                                          //
00050 
00051 MutationRate::MutationRate (const Gentainer& g) {
00052     mBinaryRate = static_cast<const FloatGene&> (*g.getGene ("Rb")).getvalue();
00053     mFloatRate      = 1;//static_cast<FloatGene&> (*g.getGene ("Rf")).getvalue();
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     //g.add (&(new FloatGene ("Vf", 0, 1, 10.0))->setMutator(&mutmut));
00067     g.add (&(new FloatGene ("Vf", 0, 1, 10.0))->setMutator(&mutmut));
00068     //g.add (new FloatGene ("Vf", 0, 1, 10.0));
00069     g.add (&(new FloatGene ("Ri", low, 1, 10.0))->setMutator(&mutmut));
00070 
00071     // Set them hidden by default
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 //                ----                       o                               //
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     // Replicate all the other's substructures
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     // Spread the initialization message to all substructures
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     // Propability of crossovers
00165     if (isnull(params))
00166         add (new FloatGene ("Px", 0, 1, 0.1)); // Same as below!
00167     else  {
00168         params.failByNullOnce ();
00169         if (isnull (params["Gentainer.recombFreq"]))
00170             add (new FloatGene ("Px", 0, 1, 0.1)); // Same as above!
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));    // Recombination method (1=crossover, 2=uniform)
00179     add (new IntGene ("Nx", 1, 4, 1.0));    // Number of crossovers
00180 
00181     // Hide 'em
00182     //(*this)["RM"].hide ();
00183     //(*this)["Nx"].hide ();
00184     //(*this)["Px"].hide ();
00185 
00186     MutationRate::addGenesTo (*this, params);
00187 
00188     // Also add private genes for contained genes
00189     for (int i=0; i<substructs.size(); i++)
00190         substructs[i].addPrivateGenes (*this, params);
00191 
00192     // (Well, most of them don't propably exist at this time yet)
00193 }
00194 
00195 const Genstruct* Gentainer::getGene (const GeneticID& cc_name) const
00196 {
00197     try {
00198         // First seek this gentainer width-first
00199         for (int i=0; i<substructs.size(); i++) {
00200             if (substructs[i].getID() == cc_name)
00201                 return &substructs[i];
00202         }
00203 
00204         // The gene might be somewhere below, so now we seek recursively
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         // Forward any exceptions
00211         throw invalid_gene_name (format ("Error while seeking gene '%s':\n%s",
00212                                          (CONSTR)cc_name, e.what()));
00213     }
00214 
00215     // Gene really not found
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         // No self-adjustment
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     // Currently the genomes have to have equal length
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     // Make an array of cross-over position marks
00253     bool crosspos [substructs.size()-1];
00254     for (int i=0; i<substructs.size()-1; i++)
00255         crosspos [i] = false;
00256     
00257     // Mark the cross-over points
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     // And copy the parents, switching at the marks...
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         // If at crossover mark
00272         if (i>0 && crosspos [i-1]) {
00273             // Switch order
00274             whichpar = 1-whichpar;
00275             
00276             // recurse the crossover
00277             substructs[i].recombine (whichpar? a[i]:b[i], (1-whichpar)? a[i]:b[i]);
00278         } else
00279             // otherwise just copy as is
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     // For each gene
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         // Let gene compare itself to the other
00296         tot += substructs[i].equality (other.substructs[i]);
00297     }
00298 
00299     // Return difference
00300     return tot;
00301 }
00302 
00303 Genstruct* Gentainer::replicate () const {
00304     // Create a gentainer of the same class. Using this scheme we
00305     // don't have to implement a replication operation for all
00306     // different gentainers. Hmm. This might be a wrong approach.
00307     Gentainer* cln = static_cast<Gentainer*> (dyncreate (this->getclassname())); 
00308 
00309     // There's definitely something missing right here
00310     
00311     // Replicate all substructures
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         // Copy all substructures
00331         for (int i=0; i<substructs.size(); i++)
00332             substructs[i].copy (other.substructs[i]);
00333     } else {
00334         // Can't copy, so clone
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     // For all contained genstructs
00349     for (int i=0; i<substructs.size(); i++) {
00350         // Print genstruct, if visible
00351         if (!substructs[i].isHidden()) {
00352             substructs[i].print (out);
00353             
00354             // Print whitespace, but not at end of list, and not for bits.
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     // Send the message to the named receiver
00381     for (int i=0; i<substructs.size(); i++)
00382         if (substructs[i].getID() == msg.receiver)
00383             return substructs[i].execute (msg);
00384 
00385     // KLUDGE
00386     /*
00387     if (msg.receiver != "init")
00388         throw exception (format ("Receiver '%s' not found in gentainer %s '%s'",
00389                                  (CONSTR) msg.receiver, (CONSTR) getclassname(),
00390                                  (CONSTR) id));
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 void Genome::recombine (const Genstruct& as, const Genstruct& bs) {
00458     Gentainer::recombine (as, bs);
00459 }
00460 */
00461 
00462 
00464 //                                                                          //
00465 //      ___   o      |      o     |  ----                                   //
00466 //      |  \     --  |            | |      ___    _               ___       //
00467 //      |   | | |  ) |  __  |  ---| | --- /   ) |/ \   __  |/|/| /   )      //
00468 //      |   | | |--  | /  \ | (   | |   \ |---  |   | /  \ | | | |---       //
00469 //      |__/  | |    | \__/ |  ---| |___/  \__  |   | \__/ | | |  \__       //
00470 //                                                                          //
00472 
00473 

Generated on Thu Feb 10 20:12:00 2005 for NeHeP by doxygen1.2.18