[Avida-SVN] r2503 - in development/source: actions classification main

barrick at myxo.css.msu.edu barrick at myxo.css.msu.edu
Thu Mar 27 21:08:19 PDT 2008


Author: barrick
Date: 2008-03-28 00:08:18 -0400 (Fri, 28 Mar 2008)
New Revision: 2503

Modified:
   development/source/actions/PrintActions.cc
   development/source/classification/cClassificationManager.cc
   development/source/classification/cClassificationManager.h
   development/source/classification/cGenotypeControl.cc
   development/source/classification/cGenotypeControl.h
   development/source/main/cAvidaConfig.h
   development/source/main/cDeme.cc
   development/source/main/cDeme.h
   development/source/main/cPopulation.cc
   development/source/main/cPopulation.h
Log:
Added founder genotype tracking to demes. New DEMES_DIVIDE_METHOD configuration option to allow demes to be reset to their exact founding organisms upon replication, to leave the source deme untouched, or to replace both source and target demes. These only work with SEED_DEME_METHOD 1. New action SaveDemeFounders outputs a single file, like "deme_founders-10000.dat" that can be used at the same time as a saved population file to reconstruct demes for testing.




Modified: development/source/actions/PrintActions.cc
===================================================================
--- development/source/actions/PrintActions.cc	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/actions/PrintActions.cc	2008-03-28 04:08:18 UTC (rev 2503)
@@ -2565,6 +2565,29 @@
   }
 };
 
+class cActionSaveDemeFounders : public cAction
+{
+private:
+  cString m_filename;
+  
+public:
+  cActionSaveDemeFounders(cWorld* world, const cString& args) : cAction(world, args), m_filename("")
+  {
+    cString largs(args);
+    if (largs.GetSize()) m_filename = largs.PopWord();
+  }
+  
+  static const cString GetDescription() { return "Arguments: [string fname='']"; }
+  
+  void Process(cAvidaContext& ctx)
+  {
+    cString filename(m_filename);
+    if (filename == "") filename.Set("deme_founders-%d.dat", m_world->GetStats().GetUpdate());
+    m_world->GetPopulation().DumpDemeFounders(m_world->GetDataFileOFStream(filename));
+    m_world->GetDataFileManager().Remove(filename);
+  }
+};
+
 class cActionSetVerbose : public cAction
 {
 private:
@@ -2657,8 +2680,8 @@
   action_lib->Register<cActionPrintDemeReplicationData>("PrintDemeReplicationData");
   action_lib->Register<cActionPrintDemeFounders>("PrintDemeFounders");
   action_lib->Register<cActionPrintGermlineData>("PrintGermlineData");
+  action_lib->Register<cActionSaveDemeFounders>("SaveDemeFounders");
   
-  
   //Coalescence Clade Actions
   action_lib->Register<cActionPrintCCladeCounts>("PrintCCladeCounts");
   action_lib->Register<cActionPrintCCladeFitnessHistogram>("PrintCCladeFitnessHistogram");

Modified: development/source/classification/cClassificationManager.cc
===================================================================
--- development/source/classification/cClassificationManager.cc	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/classification/cClassificationManager.cc	2008-03-28 04:08:18 UTC (rev 2503)
@@ -732,7 +732,7 @@
   << "#  1: ID" << endl
   << "#  2: parent ID" << endl
   << "#  3: parent distance" << endl
-  << "#  4: number of orgranisms currently alive" << endl
+  << "#  4: number of organisms currently alive" << endl
   << "#  5: total number of organisms that ever existed" << endl
   << "#  6: length of genome" << endl
   << "#  7: merit" << endl

Modified: development/source/classification/cClassificationManager.h
===================================================================
--- development/source/classification/cClassificationManager.h	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/classification/cClassificationManager.h	2008-03-28 04:08:18 UTC (rev 2503)
@@ -132,6 +132,8 @@
   cGenotype* GetGenotypeLoaded(const cGenome& in_genome, int update_born = 0, int id_num = -1);
   const cGenotype* FindGenotype(const cGenome& in_genome, int lineage_label, int list_num = -1) const;
   cGenotype* FindGenotype(const cGenome& in_genome, int lineage_label, int list_num = -1);
+  cGenotype* FindGenotype(const int _in_genotype_id) { return m_genotype_ctl->Find(_in_genotype_id); }
+
   void RemoveGenotype(cGenotype& in_genotype);
   void ThresholdGenotype(cGenotype& in_genotype);
   bool AdjustGenotype(cGenotype& in_genotype);

Modified: development/source/classification/cGenotypeControl.cc
===================================================================
--- development/source/classification/cGenotypeControl.cc	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/classification/cGenotypeControl.cc	2008-03-28 04:08:18 UTC (rev 2503)
@@ -258,6 +258,21 @@
   return NULL;
 }
 
+cGenotype * cGenotypeControl::Find(const int in_genotype_id) const
+{
+  int i;
+  cGenotype * cur_genotype = best;
+
+  for (i = 0; i < size; i++) {
+    if (in_genotype_id == cur_genotype->GetID()) {
+      return cur_genotype;
+    }
+    cur_genotype = cur_genotype->GetNext();
+  }
+
+  return NULL;
+}
+
 int cGenotypeControl::FindPos(cGenotype & in_genotype, int max_depth)
 {
   cGenotype * temp_genotype = best;

Modified: development/source/classification/cGenotypeControl.h
===================================================================
--- development/source/classification/cGenotypeControl.h	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/classification/cGenotypeControl.h	2008-03-28 04:08:18 UTC (rev 2503)
@@ -72,6 +72,7 @@
   inline cGenotype * GetCoalescent() const { return coalescent; }
 
   cGenotype * Find(const cGenome & in_genome) const;
+  cGenotype * Find(const int in_genotype_id) const;
   int FindPos(cGenotype & in_genotype, int max_depth = -1);
 
   inline cGenotype * Get(int thread) const { return threads[thread]; }

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/main/cAvidaConfig.h	2008-03-28 04:08:18 UTC (rev 2503)
@@ -313,7 +313,8 @@
   CONFIG_ADD_VAR(DEMES_REPLICATION_ONLY_RESETS, int, 0, "Kin selection mode. Deme replication really:\n1=resets deme resources\n2=rests deme resources and re-injects organisms");
   CONFIG_ADD_VAR(DEMES_MIGRATION_TARGET_MODE, int, 0, "How do we choose what demes an org may land in when it migrates?\n0=all other demes\n1=eight adjacent neighbors\n2=two adjacent demes in list");
   CONFIG_ADD_VAR(DEMES_NUM_X, int, 0, "Simulated number of demes in X dimension. Only used for migration. ");
-  CONFIG_ADD_VAR(DEMES_SEED_METHOD, int, 0, "Deme seeding method.\n0=maintain old consistency\n1=full genotype and phenotype inheritance\n2=genotype inheritance, phenotype reset");
+  CONFIG_ADD_VAR(DEMES_SEED_METHOD, int, 0, "Deme seeding method.\n0=maintain old consistency\n1=new method using genotypes");
+  CONFIG_ADD_VAR(DEMES_DIVIDE_METHOD, int, 0, "Deme divide method. Only works with DEMES_SEED_METHOD 1\n0=replace and target demes\n1= replace target deme, reset source deme to founders\n2=replace target deme, leave source deme unchanged");
 
   CONFIG_ADD_GROUP(REPRODUCTION_GROUP, "Birth and Death");
   CONFIG_ADD_VAR(BIRTH_METHOD, int, 0, "Which organism should be replaced on birth?\n0 = Random organism in neighborhood\n1 = Oldest in neighborhood\n2 = Largest Age/Merit in neighborhood\n3 = None (use only empty cells in neighborhood)\n4 = Random from population (Mass Action)\n5 = Oldest in entire population\n6 = Random within deme\n7 = Organism faced by parent\n8 = Next grid cell (id+1)\n9 = Largest energy used in entire population\n10 = Largest energy used in neighborhood");

Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/main/cDeme.cc	2008-03-28 04:08:18 UTC (rev 2503)
@@ -22,6 +22,8 @@
  */
 
 #include "cDeme.h"
+#include "cClassificationManager.h"
+#include "cGenotype.h"
 #include "cOrganism.h"
 #include "cPhenotype.h"
 #include "cPopulation.h"
@@ -266,3 +268,26 @@
   }
   return energy_sum;
 }
+
+// --- Founder list management --- //
+
+void cDeme::AddFounder(cGenotype& _in_genotype) {
+  // save genotype id
+  m_founder_genotype_ids.Push( _in_genotype.GetID() );
+
+  // defer adjusting this genotype until we are done with it
+  _in_genotype.IncDeferAdjust();
+}
+
+void cDeme::ClearFounders() {
+  // check for unused genotypes, now that we're done with these
+  for (int i=0; i<m_founder_genotype_ids.GetSize(); i++) {
+    cGenotype * genotype = m_world->GetClassificationManager().FindGenotype(m_founder_genotype_ids[i]);
+    assert(genotype);
+    genotype->DecDeferAdjust();
+    m_world->GetClassificationManager().AdjustGenotype(*genotype);
+  }
+  
+  // empty our list
+  m_founder_genotype_ids.ResizeClear(0);
+}

Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/main/cDeme.h	2008-03-28 04:08:18 UTC (rev 2503)
@@ -34,6 +34,7 @@
 class cResource;
 class cWorld;
 class cPopulationCell;
+class cGenotype;
 
 /*! Demes are groups of cells in the population that are somehow bound together
 as a unit.  The deme object is used from within cPopulation to manage these 
@@ -69,6 +70,9 @@
   
   tArray<cDemeCellEvent> cell_events;
   
+  tArray<int> m_founder_genotype_ids; // List of genotype ids used to found deme.
+                                      // Keep a lease on these genotypes for the deme's lifetime.
+                                      
   cMerit _current_merit; //!< Deme merit applied to all organisms living in this deme.
   cMerit _next_merit; //!< Deme merit that will be inherited upon deme replication.
   
@@ -156,6 +160,10 @@
   double GetNormalizedTimeUsed() { return cur_normalized_time_used; }
   double GetLastNormalizedTimeUsed() { return last_normalized_time_used; }
 
+  // --- Founder list management --- //
+  void ClearFounders();
+  void AddFounder(cGenotype& _in_genotype);
+  tArray<int>& GetFounders() { return m_founder_genotype_ids; }
 };
 
 #endif

Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/main/cPopulation.cc	2008-03-28 04:08:18 UTC (rev 2503)
@@ -1402,15 +1402,32 @@
       // @JEB
       // Updated seed deme method that maintains genotype inheritance.
       
-      tArray<cOrganism*> xfer; // List of organisms we're going to transfer.
-    
+      tArray<cOrganism*> founders; // List of organisms we're going to transfer.
+
+      /*
+      // Debug
+      tArray<int>& source_founders = source_deme.GetFounders();
+      cerr << "Original source genotype ids:" << endl;
+      for(int i=0; i<source_founders.GetSize(); i++) {
+        cerr << source_founders[i] << " ";
+      }
+      cerr << endl;
+  
+      tArray<int>& target_founders = target_deme.GetFounders();
+      cerr << "Original target genotype ids:" << endl;
+      for(int i=0; i<target_founders.GetSize(); i++) {
+        cerr << target_founders[i] << " ";
+      }
+      cerr << endl;
+      */
+      
       switch(m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get()) {
         case 0: { // Random w/ replacement (meaning, we don't prevent the same genotype from
           // being selected more than once).
-          while(xfer.GetSize() < m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()) {
+          while(founders.GetSize() < m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()) {
             int cellid = source_deme.GetCellID(random.GetUInt(source_deme.GetSize()));
             if(cell_array[cellid].IsOccupied()) {
-              xfer.Push(cell_array[cellid].GetOrganism());
+              founders.Push(cell_array[cellid].GetOrganism());
             }
           }
           break;
@@ -1419,7 +1436,7 @@
           for(int i=0; i<m_world->GetConfig().DEMES_REPLICATE_SIZE.Get(); ++i) {
             int cellid = source_deme.GetCellID(i);
             if(cell_array[cellid].IsOccupied()) {
-              xfer.Push(cell_array[cellid].GetOrganism());
+              founders.Push(cell_array[cellid].GetOrganism());
             }
           }
           break;
@@ -1432,7 +1449,7 @@
       }
           
       // We'd better have at *least* one genome.
-      assert(xfer.GetSize()>0);
+      assert(founders.GetSize()>0);
       
       // We clear the deme, but trick cPopulation::KillOrganism
       // to NOT delete the organisms, by pretending 
@@ -1441,59 +1458,123 @@
       // We also need to defer adjusting the genotype
       // or it will be prematurely deleted before we are done!
       
-      tArray<cOrganism*> old_deme_organisms;
-    
+      tArray<cOrganism*> old_source_organisms;
       for(int i=0; i<source_deme.GetSize(); ++i) {
         int cell_id = source_deme.GetCellID(i);
           
         if(cell_array[cell_id].IsOccupied()) {
           cOrganism * org = cell_array[cell_id].GetOrganism();
-          old_deme_organisms.Push(org);
+          old_source_organisms.Push(org);
           org->SetRunning(true);
           org->GetGenotype()->IncDeferAdjust();
         }
       }  
       
+      tArray<cOrganism*> old_target_organisms;
       for(int i=0; i<target_deme.GetSize(); ++i) {
         int cell_id = target_deme.GetCellID(i);
           
         if(cell_array[cell_id].IsOccupied()) {
           cOrganism * org = cell_array[cell_id].GetOrganism();
-          old_deme_organisms.Push(org);
+          old_target_organisms.Push(org);
           org->SetRunning(true);
           org->GetGenotype()->IncDeferAdjust();
         }
       }
       
       // Clear the demes.
-      source_deme.KillAll();
       target_deme.KillAll();
+      target_deme.ClearFounders();
       
-      // And now populate the source and target.
-      // We have a choice here between using InjectClone and InjectGenotype
-      // The first maintains the phenotype of the organism, i.e. its merit!
-      // The latter sets the phenotype to injected defaults.
-      int j=0;
-      for(int i=0; i<xfer.GetSize(); i++) {
-        int cellid = DemeSelectInjectionCell(source_deme, j);
-        if (m_world->GetConfig().DEMES_SEED_METHOD.Get() == 1) InjectClone(cellid, *xfer[i]);
-        else InjectGenotype(cellid, xfer[i]->GetGenotype());
-        DemePostInjection(source_deme, cell_array[cellid]);
-
-        cellid = DemeSelectInjectionCell(target_deme, j);
-        if (m_world->GetConfig().DEMES_SEED_METHOD.Get() == 1) InjectClone(cellid, *xfer[i]);
-        else InjectGenotype(cellid, xfer[i]->GetGenotype());        
-        DemePostInjection(target_deme, cell_array[cellid]);      
+      // Now populate the target (and optionally the source) using InjectGenotype.
+      // In the future InjectClone could be used, but this would require the 
+      // deme keeping complete copies of the founder organisms when
+      // we wanted to re-seed from the original founders.
+      for(int i=0; i<founders.GetSize(); i++) {
+          int cellid = DemeSelectInjectionCell(target_deme, i);
+          InjectGenotype(cellid, founders[i]->GetGenotype());        
+          DemePostInjection(target_deme, cell_array[cellid]);  
+          target_deme.AddFounder(*founders[i]->GetGenotype());          
       }
       
-      // remember to delete the old organisms and adjust their genotypes
-      for(int i=0; i<old_deme_organisms.GetSize(); ++i) {
-        old_deme_organisms[i]->SetRunning(false);
-        cGenotype * genotype = old_deme_organisms[i]->GetGenotype();
+      // We either repeat this procedure in the source deme,
+      // restart the source deme from its old founders, 
+      // or do nothing to the source deme...
+      
+      // source deme is replaced in the same way as the target
+      if (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() == 0) {
+        source_deme.KillAll();
+        source_deme.ClearFounders();
+        
+        for(int i=0; i<founders.GetSize(); i++) {
+          int cellid = DemeSelectInjectionCell(source_deme, i);
+          InjectGenotype(cellid, founders[i]->GetGenotype());
+          DemePostInjection(source_deme, cell_array[cellid]);
+          source_deme.AddFounder(*founders[i]->GetGenotype());          
+        }
+      }
+      // source deme is "reset" by re-injecting founder genotypes
+      else if (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() == 1) {
+          
+        source_deme.KillAll();
+        // do not clear or change founder list
+        
+        // use it to recreate ancestral state of genotypes
+        tArray<int>& source_founders = source_deme.GetFounders();
+        for(int i=0; i<source_founders.GetSize(); i++) {
+          int cellid = DemeSelectInjectionCell(source_deme, i);
+          cGenotype * genotype = m_world->GetClassificationManager().FindGenotype(source_founders[i]);
+          assert(genotype);
+          InjectGenotype(cellid, genotype);
+          DemePostInjection(source_deme, cell_array[cellid]); 
+        }
+      }
+      // source deme is left untouched
+      else if (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() == 2) {
+      }
+      else {
+        m_world->GetDriver().RaiseFatalException(1, "Unknown DEMES_DIVIDE_METHOD");
+      }
+      
+      /*
+      // Debug
+      tArray<int>& new_source_founders = source_deme.GetFounders();
+      cerr << "New source genotype ids:" << endl;
+      for(int i=0; i<new_source_founders.GetSize(); i++) {
+        cerr << new_source_founders[i] << " ";
+      }
+      cerr << endl;
+  
+      tArray<int>& new_target_founders = target_deme.GetFounders();
+      cerr << "New target genotype ids:" << endl;
+      for(int i=0; i<new_target_founders.GetSize(); i++) {
+        cerr << new_target_founders[i] << " ";
+      }
+      cerr << endl;
+      */
+              
+      // remember to delete the old target organisms and adjust their genotypes
+      for(int i=0; i<old_target_organisms.GetSize(); ++i) {
+        old_target_organisms[i]->SetRunning(false);
+        cGenotype * genotype = old_target_organisms[i]->GetGenotype();
         genotype->DecDeferAdjust();
         m_world->GetClassificationManager().AdjustGenotype(*genotype);
-        delete old_deme_organisms[i];
+        delete old_target_organisms[i];
       }
+      
+      for(int i=0; i<old_source_organisms.GetSize(); ++i) {
+        old_source_organisms[i]->SetRunning(false);
+        cGenotype * genotype = old_source_organisms[i]->GetGenotype();
+        genotype->DecDeferAdjust();
+        m_world->GetClassificationManager().AdjustGenotype(*genotype);
+        
+        // delete old source organisms ONLY if source was replaced
+        if ( (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() == 0)
+          || (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() == 1) ) {
+        delete old_source_organisms[i];
+        }
+      }
+      
     } //End DEMES_PROB_ORG_TRANSFER > 0 methods
   } else {
     // Probabilistic organism replication -- aka "fruiting body."
@@ -2237,6 +2318,34 @@
   df_task.Endl();
 }
 
+void cPopulation::DumpDemeFounders(ofstream& fp) {
+  fp << "#filetype deme_founders" << endl
+  << "#format deme_id num_founders genotype_ids" << endl
+  << endl
+  << "#  1: Deme ID" << endl
+  << "#  2: Number of founders" << endl
+  << "#  3+: founder genotype ids" << endl << endl;
+  
+  for(int i=0; i<deme_array.GetSize(); i++) {
+  
+    if(deme_array[i].IsEmpty()) continue;
+    
+    tArray<int>& deme_founders = deme_array[i].GetFounders();   
+    
+    // this case really shouldn't happen, but starting
+    // orgs don't count as founders currently...
+    if (deme_founders.GetSize() == 0) continue;
+      
+    fp << i << " " << deme_founders.GetSize();    
+    for(int j=0; j<deme_founders.GetSize(); j++) {  
+      fp << " " << deme_founders[j];
+    }
+  
+    fp << endl;
+  }
+}
+
+
 /**
 * This function is responsible for adding an organism to a given lineage,
  * and setting the organism's lineage label and the lineage pointer.
@@ -2659,7 +2768,7 @@
   stats.SumDemeGestationTime().Clear();
   stats.SumDemeNormalizedTimeUsed().Clear();
   stats.SumDemeMerit().Clear();
-  
+
   for(int i = 0; i < GetNumDemes(); i++) {
     cDeme& deme = GetDeme(i);
     if(deme.IsEmpty())  // ignore empty demes
@@ -3512,6 +3621,9 @@
 void cPopulation::InjectGenotype(int cell_id, cGenotype *new_genotype)
 {
   assert(cell_id >= 0 && cell_id < cell_array.GetSize());
+  if (cell_id < 0 || cell_id >= cell_array.GetSize()) {
+    m_world->GetDriver().RaiseFatalException(1, "InjectGenotype into nonexistant cell");
+  }
   
   cAvidaContext& ctx = m_world->GetDefaultContext();
   

Modified: development/source/main/cPopulation.h
===================================================================
--- development/source/main/cPopulation.h	2008-03-27 11:56:05 UTC (rev 2502)
+++ development/source/main/cPopulation.h	2008-03-28 04:08:18 UTC (rev 2503)
@@ -227,8 +227,10 @@
   void PrintDemeSpatialEnergyData() const;
   void PrintDemeSpatialSleepData() const;
   void PrintDemeTasks();
-
   
+  // Print deme founders
+  void DumpDemeFounders(ofstream& fp);
+  
   // Print donation stats
   void PrintDonationStats();
 




More information about the Avida-cvs mailing list