[Avida-SVN] r2501 - in development/source: . cpu main

barrick at myxo.css.msu.edu barrick at myxo.css.msu.edu
Wed Mar 26 18:29:48 PDT 2008


Author: barrick
Date: 2008-03-26 21:29:48 -0400 (Wed, 26 Mar 2008)
New Revision: 2501

Modified:
   development/source/cpu/cHardwareBase.h
   development/source/cpu/cHardwareCPU.cc
   development/source/cpu/cHardwareCPU.h
   development/source/defs.h
   development/source/main/cAvidaConfig.h
   development/source/main/cDeme.cc
   development/source/main/cDeme.h
   development/source/main/cPhenotype.cc
   development/source/main/cPopulation.cc
   development/source/main/cStats.cc
   development/source/main/cStats.h
Log:

Added new SEED_DEME_METHODs that correctly track genotypes (making organism generations, phylogenetic depth, etc work in demes). Unfortunately, they break consistency, so they are off by default. SEED_DEME_METHOD 1 uses InjectClone to create offspring, therefore the offspring get exact copies of the parent organism's phenotype -- importantly, they start with its merit like a normal offspring would. SEED_DEME_METHOD 2 uses InjectGenotype to create offspring, so the offspring get phenotypes with default values. 

Cleaned up how demes are reset, and added a cPhenotype-like DivideReset function.

Added additional stats to PrintDemeAverages, including some experimental "deme gestation time" measures, with the idea that we should be able to define a "deme fitness".

Added some experimental DIVIDE_METHODs that allow state information (register, stack, head values) to be inhertied by the offspring from the mother. The idea is that this could help demes orgs to  differentiate.

Removed some old promoter model junk from cPhenotype.



Modified: development/source/cpu/cHardwareBase.h
===================================================================
--- development/source/cpu/cHardwareBase.h	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/cpu/cHardwareBase.h	2008-03-27 01:29:48 UTC (rev 2501)
@@ -187,6 +187,9 @@
   virtual tBuffer<int>& GetInputBuf();
   virtual tBuffer<int>& GetOutputBuf();
   
+  // --------  State Transfer  --------
+  virtual void InheritState(cHardwareBase& in_hardware){ ; }
+  
 protected:
   // --------  No-Operation Instruction --------
   bool Inst_Nop(cAvidaContext& ctx);  // A no-operation instruction that does nothing! 

Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/cpu/cHardwareCPU.cc	2008-03-27 01:29:48 UTC (rev 2501)
@@ -1631,7 +1631,17 @@
   return true;
 }
 
+void cHardwareCPU::InheritState(cHardwareBase& in_hardware)
+{ 
+  cHardwareCPU& in_h = (cHardwareCPU&)in_hardware; 
+  const cLocalThread& thread = in_h.GetThread(in_h.GetCurThread());
+  m_threads[m_cur_thread].stack = thread.stack;
+  for (int i=0; i<NUM_REGISTERS; i++) {
+    m_threads[m_cur_thread].reg[i] = thread.reg[i];
+  }
+}
 
+
 //////////////////////////
 // And the instructions...
 //////////////////////////

Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/cpu/cHardwareCPU.h	2008-03-27 01:29:48 UTC (rev 2501)
@@ -118,6 +118,7 @@
     int GetPromoterInstExecuted() { return m_promoter_inst_executed; }
     void IncPromoterInstExecuted() { m_promoter_inst_executed++; }
     void ResetPromoterInstExecuted() { m_promoter_inst_executed = 0; }
+    
   };
 
     
@@ -294,8 +295,8 @@
   int GetNumThreads() const     { return m_threads.GetSize(); }
   int GetCurThread() const      { return m_cur_thread; }
   int GetCurThreadID() const    { return m_threads[m_cur_thread].GetID(); }
+  const cLocalThread& GetThread(int _index) const { return m_threads[_index]; }
   
-  
   // --------  Parasite Stuff  --------
   bool InjectHost(const cCodeLabel& in_label, const cGenome& injection);
 
@@ -305,6 +306,10 @@
   int GetActiveStack() const { return m_threads[m_cur_thread].cur_stack; }
   bool GetMalActive() const   { return m_mal_active; }
   
+  // --------  Inherit State  --------
+  void InheritState(cHardwareBase& in_hardware);
+
+  
 private:
   // ---------- Instruction Library -----------
 

Modified: development/source/defs.h
===================================================================
--- development/source/defs.h	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/defs.h	2008-03-27 01:29:48 UTC (rev 2501)
@@ -135,7 +135,9 @@
 {
   DIVIDE_METHOD_OFFSPRING = 0,
   DIVIDE_METHOD_SPLIT,
-  DIVIDE_METHOD_BIRTH
+  DIVIDE_METHOD_BIRTH,
+  DIVIDE_METHOD_KEEP_STATE,
+  DIVIDE_METHOD_KEEP_STATE_EPIGENETIC
 };
 
 enum eINJECT_METHOD

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/main/cAvidaConfig.h	2008-03-27 01:29:48 UTC (rev 2501)
@@ -313,6 +313,7 @@
   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_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");
@@ -322,7 +323,7 @@
   CONFIG_ADD_VAR(AGE_LIMIT, int, 20, "Modifies DEATH_METHOD");
   CONFIG_ADD_VAR(AGE_DEVIATION, int, 0, "Creates a distribution around AGE_LIMIT");
   CONFIG_ADD_VAR(ALLOC_METHOD, int, 0, "(Orignal CPU Only)\n0 = Allocated space is set to default instruction.\n1 = Set to section of dead genome (Necrophilia)\n2 = Allocated space is set to random instruction.");
-  CONFIG_ADD_VAR(DIVIDE_METHOD, int, 1, "0 = Divide leaves state of mother untouched.\n1 = Divide resets state of mother\n    (after the divide, we have 2 children)\n2 = Divide resets state of current thread only\n    (does not touch possible parasite threads)");
+  CONFIG_ADD_VAR(DIVIDE_METHOD, int, 1, "0 = Divide leaves state of mother untouched.\n1 = Divide resets state of mother\n    (after the divide, we have 2 children)\n2 = Divide resets state of current thread only\n    (does not touch possible parasite threads)\n3 = Divide resets mother stats, but not state.\n4 = 3 + child inherits mother registers and stack values.");
   CONFIG_ADD_VAR(INJECT_METHOD, int, 0, "0 = Leaves the parasite thread state untouched.\n1 = Resets the calling thread state on inject");
   CONFIG_ADD_VAR(GENERATION_INC_METHOD, int, 1, "0 = Only the generation of the child is\n    increased on divide.\n1 = Both the generation of the mother and child are\n    increased on divide (good with DIVIDE_METHOD 1).");
   CONFIG_ADD_VAR(RESET_INPUTS_ON_DIVIDE, int, 0, "Reset environment inputs of parent upon successful divide.");

Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/main/cDeme.cc	2008-03-27 01:29:48 UTC (rev 2501)
@@ -99,37 +99,48 @@
   ++_age;
 }
 
-void cDeme::Reset(int previous_generation, bool resetResources)
+void cDeme::Reset(bool resetResources, double deme_energy)
 {
-  deme_time_used = 0;
+  // Handle energy model
+  if (m_world->GetConfig().ENERGY_ENABLED.Get())
+  {
+    assert(org_count>0);
+    
+    total_org_energy = deme_energy;
+    if(total_org_energy < 0.0)
+      total_org_energy = 0.0;
+    
+    // split deme energy evenly between organisms in deme
+    for (int i=0; i<GetSize(); i++) {
+      int cellid = GetCellID(i);
+      cPopulationCell& cell = m_world->GetPopulation().GetCell(cellid);
+      if(cell.IsOccupied()) {
+        cOrganism* organism = cell.GetOrganism();
+        cPhenotype& phenotype = organism->GetPhenotype();
+        phenotype.SetEnergy(phenotype.GetStoredEnergy() + total_org_energy/static_cast<double>(org_count));
+        phenotype.SetMerit(cMerit(cMerit::EnergyToMerit(phenotype.GetStoredEnergy() * phenotype.GetEnergyUsageRatio(), m_world)));
+      }
+    }
+  }
+  
+  // Handle stat and resource resets
+  _age = 0;
+  time_used = 0;
   birth_count = 0;
-  _age = 0;
-  generation = previous_generation + 1;
-  if(resetResources)
-    deme_resource_count.ReinitializeResources();
+  cur_normalized_time_used = 0;
+
+  if(resetResources) deme_resource_count.ReinitializeResources();
 }
 
-void cDeme::Reset(double deme_energy, int previous_generation, bool resetResources)
+
+void cDeme::DivideReset(cDeme& parent_deme, bool resetResources, double deme_energy)
 {
-  assert(m_world->GetConfig().ENERGY_ENABLED.Get());
-  assert(org_count>0);
+  //Save statistics according to parent before reset.
+  generation = parent_deme.GetGeneration() + 1;
+  gestation_time = parent_deme.GetTimeUsed();
+  last_normalized_time_used = parent_deme.GetNormalizedTimeUsed();
   
-  total_org_energy = deme_energy;
-  if(total_org_energy < 0.0)
-    total_org_energy = 0.0;
-  
-  // split deme energy evenly between organisms in deme
-  for (int i=0; i<GetSize(); i++) {
-    int cellid = GetCellID(i);
-    cPopulationCell& cell = m_world->GetPopulation().GetCell(cellid);
-    if(cell.IsOccupied()) {
-      cOrganism* organism = cell.GetOrganism();
-      cPhenotype& phenotype = organism->GetPhenotype();
-      phenotype.SetEnergy(phenotype.GetStoredEnergy() + total_org_energy/static_cast<double>(org_count));
-      phenotype.SetMerit(cMerit(cMerit::EnergyToMerit(phenotype.GetStoredEnergy() * phenotype.GetEnergyUsageRatio(), m_world)));
-    }
-  }
-  Reset(previous_generation, resetResources);
+  Reset(resetResources, deme_energy);
 }
 
 

Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/main/cDeme.h	2008-03-27 01:29:48 UTC (rev 2501)
@@ -53,9 +53,13 @@
   int _age; //!< Age of this deme, in updates.
   int generation; //!< Generation of this deme
   double total_org_energy; //! total amount of energy in organisms in this deme
-  double deme_time_used; //!< number of cpu cycles, normalized by current orgs, this deme has used
-// End of phenotypic traits
+  int time_used; //!< number of cpu cycles this deme has used
+  int gestation_time; // Time used during last generation
+  double cur_normalized_time_used; // normalized by merit and number of orgs
+  double last_normalized_time_used; 
   
+  // End of phenotypic traits
+  
   cGermline _germline; //!< The germline for this deme, if used.
 
   cDeme(const cDeme&); // @not_implemented
@@ -69,7 +73,9 @@
   cMerit _next_merit; //!< Deme merit that will be inherited upon deme replication.
   
 public:
-  cDeme() : _id(0), width(0), birth_count(0), org_count(0), _age(0), generation(0), total_org_energy(0.0), deme_time_used(0.0), deme_resource_count(0) { ; }
+  cDeme() : _id(0), width(0), birth_count(0), org_count(0), _age(0), generation(0), total_org_energy(0.0),
+            time_used(0), gestation_time(0), cur_normalized_time_used(0.0), last_normalized_time_used(0.0), 
+            deme_resource_count(0) { ; }
   ~cDeme() { ; }
 
   void Setup(int id, const tArray<int>& in_cells, int in_width = -1, cWorld* world = NULL);
@@ -85,8 +91,9 @@
   int GetWidth() const { return width; }
   int GetHeight() const { return cell_ids.GetSize() / width; }
 
-  void Reset(int previous_generation, bool resetResources = true);
-  void Reset(double deme_energy, int previous_generation, bool resetResources = true); //! used to pass energy to offspring deme
+  void Reset(bool resetResources = true, double deme_energy = 0.0); //! used to pass energy to offspring deme
+  void DivideReset(cDeme& parent_deme, bool resetResources = true, double deme_energy = 0.0);
+  
   //! Kills all organisms currently in this deme.
   void KillAll();
   int GetBirthCount() const { return birth_count; }
@@ -142,8 +149,13 @@
   
   double CalculateTotalEnergy();
   
-  void IncTimeUsed() { deme_time_used += 1.0/(double)org_count; }
-  double GetTimeUsed() { return deme_time_used; }
+  void IncTimeUsed(double merit) 
+    { time_used++; cur_normalized_time_used += 1.0/merit/(double)org_count; }
+  int GetTimeUsed() { return time_used; }
+  int GetGestationTime() { return gestation_time; }
+  double GetNormalizedTimeUsed() { return cur_normalized_time_used; }
+  double GetLastNormalizedTimeUsed() { return last_normalized_time_used; }
+
 };
 
 #endif

Modified: development/source/main/cPhenotype.cc
===================================================================
--- development/source/main/cPhenotype.cc	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/main/cPhenotype.cc	2008-03-27 01:29:48 UTC (rev 2501)
@@ -290,7 +290,6 @@
   cur_task_time.SetAll(0.0);  // Added for time tracking; WRE 03-18-07
   for (int j = 0; j < sensed_resources.GetSize(); j++)
 	      sensed_resources[j] =  parent_phenotype.sensed_resources[j];
-  //SetupPromoterWeights(_genome, true);
   cur_trial_fitnesses.Resize(0); 
   cur_trial_bonuses.Resize(0); 
   cur_trial_times_used.Resize(0); 
@@ -425,7 +424,6 @@
   sensed_resources.SetAll(0);
   cur_sense_count.SetAll(0);
   cur_task_time.SetAll(0.0);
-  //SetupPromoterWeights(_genome, true);
   cur_trial_fitnesses.Resize(0);
   cur_trial_bonuses.Resize(0); 
   cur_trial_times_used.Resize(0); 
@@ -648,12 +646,13 @@
 
   // A few final changes if the parent was supposed to be be considered
   // a second child on the divide.
-  if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
+  if ( (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT)
+    || (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE)
+    || (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE_EPIGENETIC) ) {
     gestation_start = 0;
     cpu_cycles_used = 0;
     time_used = 0;
     neutral_metric += m_world->GetRandom().GetRandNormal();
-    //SetupPromoterWeights(_genome, true);
   }
 
   if (m_world->GetConfig().GENERATION_INC_METHOD.Get() == GENERATION_INC_BOTH) generation++;
@@ -721,7 +720,6 @@
   cur_sense_count.SetAll(0); 
   cur_task_time.SetAll(0.0);
   sensed_resources.SetAll(-1.0);
- //SetupPromoterWeights(_genome, true);
   cur_trial_fitnesses.Resize(0); 
   cur_trial_bonuses.Resize(0); 
   cur_trial_times_used.Resize(0); 
@@ -843,7 +841,6 @@
   cur_task_time.SetAll(0.0);
   for (int j = 0; j < sensed_resources.GetSize(); j++)
 	      sensed_resources[j] =  clone_phenotype.sensed_resources[j];
-  //SetupPromoterWeights(_genome); Do we reset here? @JEB
   cur_trial_fitnesses.Resize(0); 
   cur_trial_bonuses.Resize(0); 
   cur_trial_times_used.Resize(0); 
@@ -1609,12 +1606,13 @@
 
   // A few final changes if the parent was supposed to be be considered
   // a second child on the divide.
-  if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
+  if ( (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT)
+    || (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE)
+    || (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE_EPIGENETIC) ) {    
     gestation_start = 0;
     cpu_cycles_used = 0;
     time_used = 0;
     neutral_metric += m_world->GetRandom().GetRandNormal();
-    //SetupPromoterWeights(_genome, true);
   }
 
   if (m_world->GetConfig().GENERATION_INC_METHOD.Get() == GENERATION_INC_BOTH) generation++;

Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/main/cPopulation.cc	2008-03-27 01:29:48 UTC (rev 2501)
@@ -396,6 +396,13 @@
   // Place all of the offspring...
   for (int i = 0; i < child_array.GetSize(); i++) {
     ActivateOrganism(ctx, child_array[i], GetCell(target_cells[i]));
+    
+    //@JEB - we may want to pass along some state information from parent to child
+    if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE_EPIGENETIC)
+    {
+      child_array[i]->GetHardware().InheritState(parent_organism.GetHardware());
+    }
+    
     cGenotype* child_genotype = child_array[i]->GetGenotype();
     child_genotype->DecDeferAdjust();
     m_world->GetClassificationManager().AdjustGenotype(*child_genotype);
@@ -1162,9 +1169,8 @@
     if (m_world->GetConfig().DEMES_REPLICATION_ONLY_RESETS.Get())
     {
       //Reset deme (resources and births, among other things)
-      int source_deme_generation = source_deme.GetGeneration();
       bool source_deme_resource_reset = m_world->GetConfig().DEMES_RESET_RESOURCES.Get() == 0;
-      source_deme.Reset(source_deme_generation, source_deme_resource_reset);
+      source_deme.DivideReset(source_deme, source_deme_resource_reset);
       
       //Reset all organisms in deme, by re-injecting them?
       if (m_world->GetConfig().DEMES_REPLICATION_ONLY_RESETS.Get() == 2) {
@@ -1282,16 +1288,16 @@
   }
   
   // Reset both demes, in case they have any cleanup work to do.
-  int source_deme_generation = source_deme.GetGeneration();
   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_generation, source_deme_resource_reset);
-    target_deme.Reset(offspring_deme_energy, source_deme_generation, target_deme_resource_reset);
+    target_deme.DivideReset(source_deme, target_deme_resource_reset, offspring_deme_energy);
+    source_deme.DivideReset(source_deme, source_deme_resource_reset, parent_deme_energy);
   } else {
     // Default; reset both source and target.
-    source_deme.Reset(source_deme_generation, source_deme_resource_reset);
-    target_deme.Reset(source_deme_generation, target_deme_resource_reset);
+    target_deme.DivideReset(source_deme, target_deme_resource_reset);
+    source_deme.DivideReset(source_deme, source_deme_resource_reset);
   }
+
   
   // do our post-replication stats tracking.
   m_world->GetStats().DemePostReplication(source_deme, target_deme);
@@ -1328,68 +1334,167 @@
   // to target deme.
   if(m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get() == 0.0) {
   
-    // 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()));
+    //@JEB -- old method is default for consistency! 
+    if (m_world->GetConfig().DEMES_SEED_METHOD.Get() == 0) {
+      // 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;
         }
-        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);
+      
+      // Clear the demes.
+      source_deme.KillAll();
+      target_deme.KillAll();
+      
+      // 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]);
+
+        cellid = DemeSelectInjectionCell(target_deme, j);
+        InjectGenome(cellid, i->first, i->second);
+        DemePostInjection(target_deme, cell_array[cellid]);      
       }
-      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()));
+    } else /* if (m_world->GetConfig().DEMES_SEED_METHOD.Get() != 0) */{
+    
+      // @JEB
+      // Updated seed deme method that maintains genotype inheritance.
+      
+      tArray<cOrganism*> xfer; // List of organisms 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(xfer.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());
+            }
           }
+          break;
         }
-        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(cell_array[cellid].GetOrganism());
+            }
+          }
+          break;
+        }
+        default: {
+          cout << "Undefined value (" << m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get()
+            << ") for DEMES_ORGANISM_SELECTION." << endl;
+          exit(1);
+        }
       }
-      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.GetSize()>0);
+      
+      // We clear the deme, but trick cPopulation::KillOrganism
+      // to NOT delete the organisms, by pretending 
+      // the orgs are running. This way we can still create 
+      // clones of them that will track stats correctly.
+      // We also need to defer adjusting the genotype
+      // or it will be prematurely deleted before we are done!
+      
+      tArray<cOrganism*> old_deme_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);
+          org->SetRunning(true);
+          org->GetGenotype()->IncDeferAdjust();
+        }
+      }  
+      
+      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);
+          org->SetRunning(true);
+          org->GetGenotype()->IncDeferAdjust();
+        }
       }
-    }
-        
-    // We'd better have at *least* one genome.
-    assert(xfer.size()>0);
-    
-    // Clear the demes.
-    source_deme.KillAll();
-    target_deme.KillAll();
-    
-    // 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]);
+      
+      // Clear the demes.
+      source_deme.KillAll();
+      target_deme.KillAll();
+      
+      // 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);
-      InjectGenome(cellid, i->first, i->second);
-      DemePostInjection(target_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]);      
+      }
+      
+      // 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();
+        genotype->DecDeferAdjust();
+        m_world->GetClassificationManager().AdjustGenotype(*genotype);
+        delete old_deme_organisms[i];
+      }
+    } //End DEMES_PROB_ORG_TRANSFER > 0 methods
   } else {
     // Probabilistic organism replication -- aka "fruiting body."
     //
@@ -2486,7 +2591,7 @@
     for(int i = 0; i < GetNumDemes(); i++) GetDeme(i).Update(step_size);
   
     cDeme & deme = GetDeme(GetCell(cell_id).GetDemeID());
-    deme.IncTimeUsed();
+    deme.IncTimeUsed(cur_org->GetPhenotype().GetMerit().GetDouble());
     CheckImplicitDemeRepro(deme);
   }
 }
@@ -2535,7 +2640,7 @@
     for(int i = 0; i < GetNumDemes(); i++) GetDeme(i).Update(step_size);
   
     cDeme & deme = GetDeme(GetCell(cell_id).GetDemeID());
-    deme.IncTimeUsed();
+    deme.IncTimeUsed(cur_org->GetPhenotype().GetMerit().GetDouble());
     CheckImplicitDemeRepro(deme);
   }
   
@@ -2551,6 +2656,10 @@
   stats.SumDemeOrgCount().Clear();
   stats.SumDemeGeneration().Clear();
   
+  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
@@ -2559,6 +2668,10 @@
     stats.SumDemeBirthCount().Add(deme.GetBirthCount());
     stats.SumDemeOrgCount().Add(deme.GetOrgCount());
     stats.SumDemeGeneration().Add(deme.GetGeneration());
+
+    stats.SumDemeGestationTime().Add(deme.GetGestationTime());
+    stats.SumDemeNormalizedTimeUsed().Add(deme.GetLastNormalizedTimeUsed());
+    stats.SumDemeMerit().Add(deme.GetDemeMerit().GetDouble());
   }
 }
 

Modified: development/source/main/cStats.cc
===================================================================
--- development/source/main/cStats.cc	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/main/cStats.cc	2008-03-27 01:29:48 UTC (rev 2501)
@@ -576,11 +576,15 @@
   df.WriteComment("Avida Average Deme Data");
   df.WriteTimeStamp();
 
-  df.Write(m_update,                        "Update");
-  df.Write(sum_deme_age.Average(),          "Age");
-  df.Write(sum_deme_birth_count.Average(),  "Births");
-  df.Write(sum_deme_org_count.Average(),    "Organisms");
-  df.Write(sum_deme_generation.Average(),   "Generation");
+  df.Write(m_update,                                        "Update");
+  df.Write(sum_deme_age.Average(),                          "Age");
+  df.Write(sum_deme_birth_count.Average(),                  "Births");
+  df.Write(sum_deme_org_count.Average(),                    "Organisms");
+  df.Write(sum_deme_generation.Average(),                   "Generation");
+  df.Write(sum_deme_merit.Average(),                        "Merit");
+  df.Write(sum_deme_gestation_time.Average(),               "Gestation Time");
+  df.Write(sum_deme_normalized_time_used.Average(),         "Time Used (normalized by org fitness)");
+
   df.Endl();
 }
 

Modified: development/source/main/cStats.h
===================================================================
--- development/source/main/cStats.h	2008-03-26 20:02:30 UTC (rev 2500)
+++ development/source/main/cStats.h	2008-03-27 01:29:48 UTC (rev 2501)
@@ -272,6 +272,9 @@
   cIntSum sum_deme_birth_count;
   cIntSum sum_deme_org_count;
   cIntSum sum_deme_generation;
+  cIntSum sum_deme_gestation_time;
+  cDoubleSum sum_deme_normalized_time_used;
+  cDoubleSum sum_deme_merit;
 
   // Speculative Execution Stats
   int m_spec_total;
@@ -413,8 +416,10 @@
   cIntSum& SumDemeBirthCount()   { return sum_deme_birth_count; }
   cIntSum& SumDemeOrgCount()     { return sum_deme_org_count; }
   cIntSum& SumDemeGeneration()   { return sum_deme_generation; }
+  cIntSum& SumDemeGestationTime()   { return sum_deme_gestation_time; }
+  cDoubleSum& SumDemeNormalizedTimeUsed()   { return sum_deme_normalized_time_used; }
+  cDoubleSum& SumDemeMerit()   { return sum_deme_merit; }
 
-
 #if INSTRUCTION_COUNT
   void ZeroInst();
 #endif
@@ -451,6 +456,9 @@
   const cIntSum& SumDemeBirthCount() const   { return sum_deme_birth_count; }
   const cIntSum& SumDemeOrgCount() const     { return sum_deme_org_count; }
   const cIntSum& SumDemeGeneration() const   { return sum_deme_generation; }
+  const cIntSum& SumDemeGestationTime() const  { return sum_deme_generation; }
+  const cDoubleSum& SumDemeNormalizedTimeUsed() const  { return sum_deme_normalized_time_used; }
+  const cDoubleSum& SumDemeMerit()  const  { return sum_deme_merit; }
 
 
   void IncResamplings() { ++num_resamplings; }  // @AWC 06/29/06




More information about the Avida-cvs mailing list