[Avida-SVN] r2425 - development/source/main

dknoester at myxo.css.msu.edu dknoester at myxo.css.msu.edu
Tue Mar 4 18:45:28 PST 2008


Author: dknoester
Date: 2008-03-04 21:45:27 -0500 (Tue, 04 Mar 2008)
New Revision: 2425

Modified:
   development/source/main/cAvidaConfig.h
   development/source/main/cDeme.cc
   development/source/main/cDeme.h
   development/source/main/cEnvironment.cc
   development/source/main/cPopulation.cc
Log:
Updates to deme replication strategies.

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cAvidaConfig.h	2008-03-05 02:45:27 UTC (rev 2425)
@@ -300,7 +300,8 @@
   CONFIG_ADD_VAR(DEMES_RESET_RESOURCES, int, 0, "Reset resources in demes on replication. \n0 = reset both demes \n1 = reset target deme \n2 = deme resources remain unchanged\n");
   CONFIG_ADD_VAR(DEMES_REPLICATE_SIZE, int, 1, "Number of identical organisms to create or copy from the\nsource deme to the target deme (default=1).");
   CONFIG_ADD_VAR(DEMES_PROB_ORG_TRANSFER, double, 0.0, "Probablity of an organism being transferred from the\nsource deme to the target deme (default=0.0).");
-  CONFIG_ADD_VAR(DEMES_ORGANISM_PLACEMENT, int, 0, "How organisms are placed during deme replication.\n0=cell-array middle (default).\n1=deme center.\n2=random placement.");
+  CONFIG_ADD_VAR(DEMES_ORGANISM_SELECTION, int, 0, "How organisms are selected for transfer from\nsource to target during deme replication.\n0=random with replacement (default).\n2=sequential.");
+  CONFIG_ADD_VAR(DEMES_ORGANISM_PLACEMENT, int, 0, "How organisms are placed during deme replication.\n0=cell-array middle (default).\n1=deme center.\n2=random placement.\n3=sequential.");
   CONFIG_ADD_VAR(DEMES_ORGANISM_FACING, int, 0, "How organisms are facing during deme replication.\n0=unchanged (default).\n1=northwest.\n2=random.");
   CONFIG_ADD_VAR(DEMES_MAX_AGE, int, 500, "The maximum age of a deme (in updates) to be\nused for age-based replication (default=500).");
   CONFIG_ADD_VAR(DEMES_MAX_BIRTHS, int, 100, "The maximum number of births that can occur\nwithin a deme; used with birth-count\nreplication (default=100).");

Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc	2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cDeme.cc	2008-03-05 02:45:27 UTC (rev 2425)
@@ -126,6 +126,18 @@
 }
 
 
+/*! Check every cell in this deme for a living organism.  If found, kill it. */
+void cDeme::KillAll()
+{
+  for (int i=0; i<GetSize(); ++i) {
+    cPopulationCell& cell = m_world->GetPopulation().GetCell(cell_ids[i]);
+    if(cell.IsOccupied()) {
+      m_world->GetPopulation().KillOrganism(cell);
+    }
+  }
+}
+
+
 /*! Replacing this deme's germline has the effect of changing the deme's lineage.
 There's still some work to do here; the lineage labels of the Genomes in the germline
 are all messed up.

Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h	2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cDeme.h	2008-03-05 02:45:27 UTC (rev 2425)
@@ -80,6 +80,8 @@
 
   void Reset(bool resetResources = true);
   void Reset(double deme_energy, bool resetResources = true); //! used to pass energy to offspring deme
+  //! Kills all organisms currently in this deme.
+  void KillAll();
   int GetBirthCount() const { return birth_count; }
   void IncBirthCount() { birth_count++; }
 

Modified: development/source/main/cEnvironment.cc
===================================================================
--- development/source/main/cEnvironment.cc	2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cEnvironment.cc	2008-03-05 02:45:27 UTC (rev 2425)
@@ -1032,7 +1032,7 @@
         break;
       case nReaction::PROCTYPE_MULT:
         result.MultBonus(bonus);
-        // Not quite sure what to do to the deme_bonus for this process:type.
+        // @todo Not quite sure what to do to the deme_bonus for this process:type.
         break;
       case nReaction::PROCTYPE_POW:
         result.MultBonus(pow(2.0, bonus));

Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc	2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cPopulation.cc	2008-03-05 02:45:27 UTC (rev 2425)
@@ -113,15 +113,18 @@
     num_demes = 1; // One population == one deme.
   }
 
-  // Error checking for demes vs. non-demes setup.
-
-  // The following combination of options creates an infinite rotate-loop.
+  // The following combination of options creates an infinite rotate-loop:
   assert(!((m_world->GetConfig().DEMES_ORGANISM_PLACEMENT.Get()==0)
            && (m_world->GetConfig().DEMES_ORGANISM_FACING.Get()==1)
            && (m_world->GetConfig().WORLD_GEOMETRY.Get()==1)));
   
-  // Not yet supported:
-  assert(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()==1);
+  // Incompatible deme replication strategies:
+  assert(!(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()
+           && (m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get()>0.0)));
+  assert(!(m_world->GetConfig().DEMES_USE_GERMLINE.Get()
+           && (m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get()>0.0)));
+  assert(!(m_world->GetConfig().DEMES_USE_GERMLINE.Get()
+           && (m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()>1)));
   
 #ifdef DEBUG
   const int birth_method = m_world->GetConfig().BIRTH_METHOD.Get();
@@ -151,6 +154,9 @@
   const int deme_size = deme_size_x * deme_size_y;
   deme_array.Resize(num_demes);
   
+  // Broken setting:
+  assert(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get() <= deme_size);         
+  
   // Setup the deme structures.
   tArray<int> deme_cells(deme_size);
   for (int deme_id = 0; deme_id < num_demes; deme_id++) {
@@ -1221,7 +1227,7 @@
   }
 
   // The source's merit must be transferred to the target, and then the source has
-  // rotate its merits.
+  // to rotate its heritable merit to its current merit.
   target_deme.UpdateDemeMerit(source_deme);
   source_deme.UpdateDemeMerit();
   
@@ -1247,9 +1253,11 @@
   
   // Reset both demes, in case they have any cleanup work to do.
   if(m_world->GetConfig().ENERGY_ENABLED.Get()) {
+    // Transfer energy from source to target if we're using the energy model.
     source_deme.Reset(parent_deme_energy, source_deme_resource_reset);
     target_deme.Reset(offspring_deme_energy, target_deme_resource_reset);
   } else {
+    // Default; reset both source and target.
     source_deme.Reset(source_deme_resource_reset);
     target_deme.Reset(target_deme_resource_reset);
   }
@@ -1268,13 +1276,7 @@
 */
 void cPopulation::SeedDeme(cDeme& deme, cGenome& genome) {
   // Kill all the organisms in the deme.
-  for (int i=0; i<deme.GetSize(); i++) {
-    KillOrganism(cell_array[deme.GetCellID(i)]);
-  }
-
-  // Sanity.
-  assert(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get() < deme.GetSize());
-  assert(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get() > 0);
+  deme.KillAll();
   
   // Create the specified number of organisms in the deme.
   for(int i=0; i< m_world->GetConfig().DEMES_REPLICATE_SIZE.Get(); ++i) {
@@ -1290,97 +1292,118 @@
 */
 void cPopulation::SeedDeme(cDeme& source_deme, cDeme& target_deme) {
   cRandom& random = m_world->GetRandom();
-
+  
+  // Check to see if we're doing probabilistic organism replication from source
+  // to target deme.
   if(m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get() == 0.0) {
-    // Select a random organism from the source.  All we need to do here is get a
-    // genome and a lineage label.
-    cOrganism* seed = 0;
-    while(seed == 0) {
-      int cellid = source_deme.GetCellID(random.GetUInt(source_deme.GetSize()));
-      if(cell_array[cellid].IsOccupied()) {
-        seed = cell_array[cellid].GetOrganism();
+    // Here's the idea: store up a list of the genotypes from the source that we
+    // need to copy to the target. Then clear both the source and target demes, 
+    // and finally inject organisms from the saved genotypes into both the source 
+    // and target.
+    //
+    // This is a little ugly - Note that if you're trying to get something a little
+    // more random, there's also the "fruiting body" option (DEMES_PROB_ORG_TRANSFER),
+    // and the even less contrived MIGRATION_RATE.
+    //
+    // @todo In order to get lineage tracking to work again, we need to change this
+    //       from tracking cGenomes to tracking cGenotypes.  But that's a pain,
+    //       because the cGenotype* from cOrganism::GetGenotype may not live after
+    //       a call to cDeme::KillAll.
+    std::vector<std::pair<cGenome,int> > xfer; // List of genomes we're going to transfer.
+  
+    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((int)xfer.size() < m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()) {
+          int cellid = source_deme.GetCellID(random.GetUInt(source_deme.GetSize()));
+          if(cell_array[cellid].IsOccupied()) {
+            xfer.push_back(std::make_pair(cell_array[cellid].GetOrganism()->GetGenome(),
+                                          cell_array[cellid].GetOrganism()->GetLineageLabel()));
+          }
+        }
+        break;
       }
+      case 1: { // Sequential selection, from the beginning.  Good with DEMES_ORGANISM_PLACEMENT=3.
+        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_back(std::make_pair(cell_array[cellid].GetOrganism()->GetGenome(),
+                                          cell_array[cellid].GetOrganism()->GetLineageLabel()));
+          }
+        }
+        break;
+      }
+      default: {
+        cout << "Undefined value (" << m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get()
+          << ") for DEMES_ORGANISM_SELECTION." << endl;
+        exit(1);
+      }
     }
+        
+    // We'd better have at *least* one genome.
+    assert(xfer.size()>0);
     
-    cGenome genome = seed->GetGenome();
-    int lineage = seed->GetLineageLabel();
-    seed = 0; // We're done with the seed organism.
+    // Clear the demes.
+    source_deme.KillAll();
+    target_deme.KillAll();
     
-    // Kill all the organisms in the source and target demes.
-    for (int i=0; i<target_deme.GetSize(); i++) {
-      KillOrganism(cell_array[target_deme.GetCellID(i)]);
-    }
-    for (int i=0; i<source_deme.GetSize(); i++) {
-      KillOrganism(cell_array[source_deme.GetCellID(i)]);
-    }
+    // And now populate the source and target.
+    int j=0;
+    for(std::vector<std::pair<cGenome,int> >::iterator i=xfer.begin(); i!=xfer.end(); ++i, ++j) {
+      int cellid = DemeSelectInjectionCell(source_deme, j);
+      InjectGenome(cellid, i->first, i->second);
+      DemePostInjection(source_deme, cell_array[cellid]);
 
-    // Repopulation the source.
-    for(int i=0; i< m_world->GetConfig().DEMES_REPLICATE_SIZE.Get(); ++i) {
-      int cellid = DemeSelectInjectionCell(source_deme, i);
-      InjectGenome(cellid, genome, lineage);
-      DemePostInjection(source_deme, cell_array[cellid]);
+      cellid = DemeSelectInjectionCell(target_deme, j);
+      InjectGenome(cellid, i->first, i->second);
+      DemePostInjection(target_deme, cell_array[cellid]);      
     }
+  } else {
+    // Probabilistic organism replication -- aka "fruiting body."
+    //
+    // This is a little different than the other deme replication styles.  First,
+    // in a fruiting body we don't reset the individuals in the source deme; we
+    // leave them unchanged.  The idea is that we're pulling random organisms
+    // out, and letting the source continue.
     
-    // And repopulate the target.
-    for(int i=0; i< m_world->GetConfig().DEMES_REPLICATE_SIZE.Get(); ++i) {
-      int cellid = DemeSelectInjectionCell(target_deme, i);
-      InjectGenome(cellid, genome, lineage);
-      DemePostInjection(target_deme, cell_array[cellid]);
-    }
-  } else {
-    assert(m_world->GetConfig().DEMES_USE_GERMLINE.Get() != 1);
-    vector< pair<cGenome, int> > fruiting_body;
-
     // Kill all the organisms in the target deme.
-    for (int i=0; i<target_deme.GetSize(); i++) {
-      KillOrganism(cell_array[target_deme.GetCellID(i)]);
-    }
+    target_deme.KillAll();
 
-    for(int i = 0; i < source_deme.GetSize(); i++) {
+    // Check all the organisms in the source deme to see if they get transferred
+    // to the target.
+    for(int i=0,j=0; i<source_deme.GetSize(); ++i) {
       int source_cellid = source_deme.GetCellID(i);
       
-      if(cell_array[source_cellid].IsOccupied() && random.GetDouble(0.0, 1.0) < m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get()) {
-        // save genome and lineage label of organism being transfered
+      // Does this organism stay with the source or move to the target?
+      if(cell_array[source_cellid].IsOccupied() && random.P(m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get())) {
+        // Moves to the target; save the genome and lineage label of organism being transfered.
         cOrganism* seed = cell_array[source_cellid].GetOrganism();
         cGenome genome = seed->GetGenome();
         int lineage = seed->GetLineageLabel();
         seed = 0; // We're done with the seed organism.
         
-        // remove organism from source deme
+        // Remove this organism from the source.
         KillOrganism(cell_array[source_cellid]);
         
-        // inject into target deme
-        int target_cellid = DemeSelectInjectionCell(target_deme, i);
+        // And inject it into target deme.
+        int target_cellid = DemeSelectInjectionCell(target_deme, j++);
         InjectGenome(target_cellid, genome, lineage);
         DemePostInjection(target_deme, cell_array[target_cellid]);
-      }
-      
-      // collect genome and lineage label of organisms that remain in source deme
-      if(cell_array[source_cellid].IsOccupied()) {
-        cOrganism* seed = cell_array[source_cellid].GetOrganism();
-        fruiting_body.push_back(make_pair(seed->GetGenome(), seed->GetLineageLabel()));
-        seed = 0;
-
-        // kill remaining organisms
-        KillOrganism(cell_array[source_cellid]);
-      }
+      } 
+      //else {
+      // Stays with the source.  Nothing to do here yet.
+      //}
     }
-    
-    int i = 0;
-    // reseed source deme
-    for(vector< pair<cGenome, int> >::iterator iter = fruiting_body.begin(); iter < fruiting_body.end(); iter++) {
-      // inject back into source deme
-      int source_offspring_cellid = DemeSelectInjectionCell(source_deme, i);
-      InjectGenome(source_offspring_cellid, (*iter).first, (*iter).second);
-      DemePostInjection(source_deme, cell_array[source_offspring_cellid]);
-      i++;
-    }
   }
 }
 
 
 /*! Helper method that determines the cell into which an organism will be placed.
 Respects all of the different placement options that are relevant for deme replication.
+
+ at param sequence The number of times DemeSelectInjectionCell has been called on this deme
+                already.  Used for replicating multiple organisms from the source to the
+                target deme in a sensible fashion.
 */
 int cPopulation::DemeSelectInjectionCell(cDeme& deme, int sequence) {
   int cellid = -1;
@@ -1403,7 +1426,11 @@
         cellid = deme.GetCellID(m_world->GetRandom().GetInt(0, deme.GetSize()-1));
       }
       break;
-    }      
+    }
+    case 3: { // Sequential.
+      cellid = deme.GetCellID(sequence);
+      break;
+    }
     default: {
       assert(false); // Shouldn't ever reach here.
     }




More information about the Avida-cvs mailing list