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

barrick at myxo.css.msu.edu barrick at myxo.css.msu.edu
Tue Apr 1 13:45:48 PDT 2008


Author: barrick
Date: 2008-04-01 16:45:48 -0400 (Tue, 01 Apr 2008)
New Revision: 2512

Modified:
   development/source/actions/PrintActions.cc
   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/cPopulation.h
   development/source/main/cStats.cc
   development/source/main/cStats.h
Log:
Pulled a few parts out of cPopulation::PositionChild() into separate functions. Split my deme migration code from Art's so that I can PREFER_EMPTY in the deme being migrated to. Mine uses DEMES_MIGRATION_RATE, Art's uses MIGRATION_RATE. 

New stat files for tracking tasks and reactions done in a deme's lifetime  (basically a deme-wide phenotype).

Option to replicate demes on a number of orgs (b/c you can't tell from your birth count how many orgs you have when migration is happening).



Modified: development/source/actions/PrintActions.cc
===================================================================
--- development/source/actions/PrintActions.cc	2008-04-01 20:20:46 UTC (rev 2511)
+++ development/source/actions/PrintActions.cc	2008-04-01 20:45:48 UTC (rev 2512)
@@ -96,6 +96,9 @@
 STATS_OUT_FILE(PrintCompetitionData,        competition.dat     );
 STATS_OUT_FILE(PrintDemeReplicationData,    deme_repl.dat       );
 STATS_OUT_FILE(PrintDemeFounders,           deme_founders.dat   );
+STATS_OUT_FILE(PrintDemeTasks,              deme_tasks.dat      );
+STATS_OUT_FILE(PrintDemeTasksExe,           deme_tasks_exe.dat  );
+STATS_OUT_FILE(PrintDemeReactions,          deme_reactions.dat  );
 STATS_OUT_FILE(PrintGermlineData,           germline.dat        );
 // @WRE: Added output event for collected visit counts
 STATS_OUT_FILE(PrintCellVisitsData,         visits.dat			);
@@ -2681,7 +2684,10 @@
   action_lib->Register<cActionPrintDemeFounders>("PrintDemeFounders");
   action_lib->Register<cActionPrintGermlineData>("PrintGermlineData");
   action_lib->Register<cActionSaveDemeFounders>("SaveDemeFounders");
-  
+  action_lib->Register<cActionPrintDemeTasks>("PrintDemeTasksData");
+  action_lib->Register<cActionPrintDemeTasksExe>("PrintDemeTasksExeData");
+  action_lib->Register<cActionPrintDemeReactions>("PrintDemeReactionData");
+
   //Coalescence Clade Actions
   action_lib->Register<cActionPrintCCladeCounts>("PrintCCladeCounts");
   action_lib->Register<cActionPrintCCladeFitnessHistogram>("PrintCCladeFitnessHistogram");

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2008-04-01 20:20:46 UTC (rev 2511)
+++ development/source/main/cAvidaConfig.h	2008-04-01 20:45:48 UTC (rev 2512)
@@ -310,8 +310,10 @@
   CONFIG_ADD_VAR(GERMLINE_DEL_MUT, double, 0.05, "Prob. of a deletion mutation occuring\nduring germline replication (default=0.05).");
   CONFIG_ADD_VAR(DEMES_REPLICATE_CPU_CYCLES, double, 0.0, "Replicate a deme immediately after it has used\nthis number of cpu cycles, normalized\nby number of orgs in deme (0 = OFF).");
   CONFIG_ADD_VAR(DEMES_REPLICATE_BIRTHS, int, 0, "Replicate a deme immediately after it has \nproduced this many offspring (0 = OFF).");
+  CONFIG_ADD_VAR(DEMES_REPLICATE_ORGS, int, 0, "Replicate a deme immediately once it reaches a\ncertain number of organisms (0 = OFF).");
   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_MIGRATION_RATE, double, 0.0, "Probability of an offspring being born in a different deme.");
+  CONFIG_ADD_VAR(DEMES_MIGRATION_METHOD, 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=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");

Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc	2008-04-01 20:20:46 UTC (rev 2511)
+++ development/source/main/cDeme.cc	2008-04-01 20:45:48 UTC (rev 2512)
@@ -23,6 +23,7 @@
 
 #include "cDeme.h"
 #include "cClassificationManager.h"
+#include "cEnvironment.h"
 #include "cGenotype.h"
 #include "cOrganism.h"
 #include "cPhenotype.h"
@@ -42,6 +43,17 @@
   _current_merit = 1.0;
   _next_merit = 1.0;
   
+  const int num_tasks = m_world->GetEnvironment().GetNumTasks();
+  const int num_reactions = m_world->GetNumReactions();  
+  cur_task_count.Resize(num_tasks);
+  cur_task_count.SetAll(0);
+  cur_reaction_count.ResizeClear(num_reactions);
+  cur_reaction_count.SetAll(0);
+  last_task_count.ResizeClear(num_tasks);
+  last_task_count.SetAll(0);
+  last_reaction_count.ResizeClear(num_reactions);
+  last_reaction_count.SetAll(0);
+
   // If width is negative, set it to the full number of cells.
   width = in_width;
   if (width < 1) width = cell_ids.GetSize();
@@ -130,6 +142,9 @@
   time_used = 0;
   birth_count = 0;
   cur_normalized_time_used = 0;
+  
+  cur_task_count.SetAll(0);
+  cur_reaction_count.SetAll(0);
 
   if(resetResources) deme_resource_count.ReinitializeResources();
 }
@@ -142,6 +157,9 @@
   gestation_time = parent_deme.GetTimeUsed();
   last_normalized_time_used = parent_deme.GetNormalizedTimeUsed();
   
+  last_task_count = cur_task_count;
+  last_reaction_count = cur_reaction_count;
+
   Reset(resetResources, deme_energy);
 }
 

Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h	2008-04-01 20:20:46 UTC (rev 2511)
+++ development/source/main/cDeme.h	2008-04-01 20:45:48 UTC (rev 2512)
@@ -48,7 +48,7 @@
   tArray<int> cell_ids;
   int width; //!< Width of this deme.
 
-// The following should be moved to cDemePhenotype
+// The following should be moved to cDemePhenotype / cPopulationPhenotype
   int birth_count; //!< Number of organisms that have been born into this deme since reset.
   int org_count; //!< Number of organisms are currently in this deme.
   int _age; //!< Age of this deme, in updates.
@@ -59,6 +59,11 @@
   double cur_normalized_time_used; // normalized by merit and number of orgs
   double last_normalized_time_used; 
   
+  tArray<int> cur_task_count;
+  tArray<int> cur_reaction_count;
+  tArray<int> last_task_count;
+  tArray<int> last_reaction_count;
+  
   // End of phenotypic traits
   
   cGermline _germline; //!< The germline for this deme, if used.
@@ -98,7 +103,7 @@
 
   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; }
@@ -129,7 +134,14 @@
   const cMerit& GetDemeMerit() const { return _current_merit; }
   //! Retrieve this deme's heritable merit.
   const cMerit& GetHeritableDemeMerit() const { return _next_merit; }
-  
+
+
+  void AddCurTask(int task_num) { cur_task_count[task_num]++; }
+  void AddCurReaction (int reaction_num) { cur_reaction_count[reaction_num]++; }
+
+  const tArray<int>& GetLastTaskCount() const { return last_task_count; }
+  const tArray<int>& GetLastReactionCount() const { return last_reaction_count; }
+
   bool HasDemeMerit() const { return _current_merit.GetDouble() != 1.0; }
 
   // -= Update support =-

Modified: development/source/main/cPhenotype.cc
===================================================================
--- development/source/main/cPhenotype.cc	2008-04-01 20:20:46 UTC (rev 2511)
+++ development/source/main/cPhenotype.cc	2008-04-01 20:45:48 UTC (rev 2512)
@@ -1011,6 +1011,14 @@
     deme_bonus *= result.GetMultDemeBonus();
     deme_bonus += result.GetAddDemeBonus();
     deme->UpdateHeritableDemeMerit(deme_bonus);
+    
+    //also count tasks/reactions
+    for (int i = 0; i < num_tasks; i++) {
+      if (result.TaskDone(i) == true) deme->AddCurTask(i);
+    }
+    for (int i = 0; i < num_reactions; i++) {
+      if (result.ReactionTriggered(i) == true) deme->AddCurReaction(i);
+    }
   }
     
   // Update the energy bonus

Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc	2008-04-01 20:20:46 UTC (rev 2511)
+++ development/source/main/cPopulation.cc	2008-04-01 20:45:48 UTC (rev 2512)
@@ -2002,7 +2002,9 @@
   if (m_world->GetConfig().DEMES_REPLICATE_CPU_CYCLES.Get() 
     && (deme.GetTimeUsed() >= m_world->GetConfig().DEMES_REPLICATE_CPU_CYCLES.Get())) ReplicateDeme(deme);
   else if (m_world->GetConfig().DEMES_REPLICATE_BIRTHS.Get() 
-    && (deme.GetBirthCount() >= m_world->GetConfig().DEMES_REPLICATE_BIRTHS.Get())) ReplicateDeme(deme);      
+    && (deme.GetBirthCount() >= m_world->GetConfig().DEMES_REPLICATE_BIRTHS.Get())) ReplicateDeme(deme); 
+  else if (m_world->GetConfig().DEMES_REPLICATE_ORGS.Get() 
+    && (deme.GetOrgCount() >= m_world->GetConfig().DEMES_REPLICATE_ORGS.Get())) ReplicateDeme(deme);      
 }
 
 // Print out all statistics about individual demes
@@ -2492,70 +2494,19 @@
 
     //cerr << "Attempting to migrate with rate " << m_world->GetConfig().MIGRATION_RATE.Get() << "!" << endl;
     int deme_id = parent_cell.GetDemeID();
+         
+    //get another -unadjusted- deme id
+    int rnd_deme_id = m_world->GetRandom().GetInt(deme_array.GetSize()-1);
     
-    //@JEB - Different target modes
-    //Original (random OTHER deme) by @AWC
-    if (m_world->GetConfig().DEMES_MIGRATION_TARGET_MODE.Get() == 0) {  
-     
-      //get another -unadjusted- deme id
-      int rnd_deme_id = m_world->GetRandom().GetInt(deme_array.GetSize()-1);
-      
-      //if the -unadjusted- id is above the excluded id, bump it up one
-      //insures uniform prob of landing in any deme but the parent's
-      if(rnd_deme_id >= deme_id) rnd_deme_id++;
-      
-      //set the new deme_id
-      deme_id = rnd_deme_id;
-    }
+    //if the -unadjusted- id is above the excluded id, bump it up one
+    //insures uniform prob of landing in any deme but the parent's
+    if(rnd_deme_id >= deme_id) rnd_deme_id++;
     
-    //@JEB - random OTHER deme in neighborhood (assuming torus)
-    //Extremely hacked, temporary until demes fixed
-    else if (m_world->GetConfig().DEMES_MIGRATION_TARGET_MODE.Get() == 1) {
+    //set the new deme_id
+    deme_id = rnd_deme_id;
     
-      //get a random eight-neighbor
-      int dir = m_world->GetRandom().GetInt(8);
-      
-      // 0 = NW, 1=N, continuing clockwise....
-    
-      // Up one row
-      int x_size = m_world->GetConfig().DEMES_NUM_X.Get();
-      int y_size = (int) (m_world->GetConfig().NUM_DEMES.Get() / x_size);
-
-      assert(y_size * x_size == m_world->GetConfig().NUM_DEMES.Get());
-
-      int x = deme_id % x_size;
-      int y = (int) (deme_id / x_size);
-
-      if ( (dir == 0) || (dir == 1) || (dir == 2) ) y--;
-      if ( (dir == 5) || (dir == 6) || (dir == 7) ) y++;
-      if ( (dir == 0) || (dir == 3) || (dir == 5) ) x--;
-      if ( (dir == 2) || (dir == 4) || (dir == 7) ) x++;
-      
-      //handle boundary conditions...
-      
-      x = (x + x_size) % x_size;
-      y = (y + y_size) % y_size;
-
-      //set the new deme_id
-      deme_id = x + x_size * y;
-
-      assert(deme_id > 0);
-      assert(deme_id > 0);
-    }
-    
-    //@JEB - random deme adjacent in list
-    else if (m_world->GetConfig().DEMES_MIGRATION_TARGET_MODE.Get() == 2) {
-
-      //get a random direction to move in deme list
-      int rnd_deme_id = m_world->GetRandom().GetInt(1);
-      if (rnd_deme_id == 0) rnd_deme_id = -1;
-      
-      //set the new deme_id
-      deme_id = (deme_id + rnd_deme_id + deme_array.GetSize()) % deme_array.GetSize();
-    }
-    
-    
     //The rest of this is essentially POSITION_CHILD_DEME_RANDOM
+    //@JEB: But note that this will not honor PREFER_EMPTY in the new deme.
     const int deme_size = deme_array[deme_id].GetSize();
     
     int out_pos = m_world->GetRandom().GetUInt(deme_size);
@@ -2569,26 +2520,29 @@
     GetCell(out_cell_id).SetMigrant();
     return GetCell(out_cell_id);    
   }
-  
   // Fix so range can be arbitrary and we won't accidentally include ourself as a target
+  // @AWC If not migrating try out global/full-deme birth methods first...
   
-  // @AWC If not migrating try out global/full-deme birth methods first...
-  else if (birth_method == POSITION_CHILD_FULL_SOUP_RANDOM) {
+  // Similar to MIGRATION_RATE code above but allows for a bit more flexibility
+  // in how migration between demes works. Also, respects PREFER_EMPTY in new deme.
+  // Temporary until Deme 
+  if ((m_world->GetConfig().DEMES_MIGRATION_RATE.Get() > 0.0)
+      && m_world->GetRandom().P(m_world->GetConfig().DEMES_MIGRATION_RATE.Get())) 
+  {
+    deme_array[parent_cell.GetDemeID()].IncBirthCount();
+    return PositionDemeMigration(parent_cell, parent_ok);
+  }
+  
+  // This block should be changed to a switch statment with functions handling 
+  // the cases. For now, a bunch of if's that return if they handle.
+  
+  if (birth_method == POSITION_CHILD_FULL_SOUP_RANDOM) {
    
-    // @JEB Look randomly within empty cells, if requested
+    // Look randomly within empty cells first, if requested
     if (m_world->GetConfig().PREFER_EMPTY.Get()) {
       
-      // Note: empty_cell_id_array was resized to be large enough to hold
-      // all cells in the cPopulation when it was created. Using functions
-      // that resize it (like Push) will slow this code down considerably.
-      // Instead, we keep track of how much of this memory we are using.
-      
-      int num_empty_cells = 0;      
-      for (int i=0; i<cell_array.GetSize(); i++) {
-        if (GetCell(i).IsOccupied() == false) empty_cell_id_array[num_empty_cells++] = i;
-      }
-     
-       if (num_empty_cells > 0) {
+      int num_empty_cells = UpdateEmptyCellIDArray();
+      if (num_empty_cells > 0) {
         int out_pos = m_world->GetRandom().GetUInt(num_empty_cells);
         return GetCell(empty_cell_id_array[out_pos]);
       } 
@@ -2600,7 +2554,8 @@
     }
     return GetCell(out_pos);
   }
-  else if (birth_method == POSITION_CHILD_FULL_SOUP_ELDEST) {
+  
+  if (birth_method == POSITION_CHILD_FULL_SOUP_ELDEST) {
     cPopulationCell * out_cell = reaper_queue.PopRear();
     if (parent_ok == false && out_cell->GetID() == parent_cell.GetID()) {
       out_cell = reaper_queue.PopRear();
@@ -2608,41 +2563,10 @@
     }
     return *out_cell;
   }
-  else if (birth_method == POSITION_CHILD_DEME_RANDOM) {
-    const int deme_id = parent_cell.GetDemeID();    
-    const int deme_size = deme_array[deme_id].GetSize();
-    
-    deme_array[deme_id].IncBirthCount();
-
-    // @JEB Look randomly within empty cells, if requested
-    if (m_world->GetConfig().PREFER_EMPTY.Get()) {
-      
-      // Note: empty_cell_id_array was resized to be large enough to hold
-      // all cells in the cPopulation when it was created. Using functions
-      // that resize it (like Push) will slow this code down considerably.
-      // Instead, we keep track of how much of this memory we are using.
-      
-      int num_empty_cells = 0; 
-      for (int i=0; i<deme_array[deme_id].GetSize(); i++) {
-        int cell_id = deme_array[deme_id].GetCellID(i);
-        if (!GetCell(cell_id).IsOccupied()) /*return cell;*/ empty_cell_id_array[num_empty_cells++] = cell_id;
-      }
-     
-      if (num_empty_cells > 0) {
-        int out_pos = m_world->GetRandom().GetUInt(num_empty_cells);
-        return GetCell(empty_cell_id_array[out_pos]);
-      } 
-    }
-
-    int out_pos = m_world->GetRandom().GetUInt(deme_size);
-    int out_cell_id = deme_array[deme_id].GetCellID(out_pos);
-    
-    while (parent_ok == false && out_cell_id == parent_cell.GetID()) {
-      out_pos = m_world->GetRandom().GetUInt(deme_size);
-      out_cell_id = deme_array[deme_id].GetCellID(out_pos);
-    }
-    
-    return GetCell(out_cell_id);    
+  
+  if (birth_method == POSITION_CHILD_DEME_RANDOM) {
+    deme_array[parent_cell.GetDemeID()].IncBirthCount();
+    return PositionDemeRandom(parent_cell.GetDemeID(), parent_cell, parent_ok);
   }
   else if (birth_method == POSITION_CHILD_PARENT_FACING) {
     return parent_cell.GetCellFaced();
@@ -2724,7 +2648,227 @@
   return *( found_list.GetPos(choice) );
 }
 
+void cPopulation::PositionAge(cPopulationCell & parent_cell,
+                              tList<cPopulationCell> & found_list,
+                              bool parent_ok)
+{
+  // Start with the parent organism as the replacement, and see if we can find
+  // anything equivilent or better.
+  
+  found_list.Push(&parent_cell);
+  int max_age = parent_cell.GetOrganism()->GetPhenotype().GetAge();
+  if (parent_ok == false) max_age = -1;
+  
+  // Now look at all of the neighbors.
+  tListIterator<cPopulationCell> conn_it( parent_cell.ConnectionList() );
+  
+  cPopulationCell * test_cell;
+  while ( (test_cell = conn_it.Next()) != NULL) {
+    const int cur_age = test_cell->GetOrganism()->GetPhenotype().GetAge();
+    if (cur_age > max_age) {
+      max_age = cur_age;
+      found_list.Clear();
+      found_list.Push(test_cell);
+    }
+    else if (cur_age == max_age) {
+      found_list.Push(test_cell);
+    }
+  }
+}
 
+void cPopulation::PositionMerit(cPopulationCell & parent_cell,
+                                tList<cPopulationCell> & found_list,
+                                bool parent_ok)
+{
+  // Start with the parent organism as the replacement, and see if we can find
+  // anything equivilent or better.
+  
+  found_list.Push(&parent_cell);
+  double max_ratio = parent_cell.GetOrganism()->CalcMeritRatio();
+  if (parent_ok == false) max_ratio = -1;
+  
+  // Now look at all of the neighbors.
+  tListIterator<cPopulationCell> conn_it( parent_cell.ConnectionList() );
+  
+  cPopulationCell * test_cell;
+  while ( (test_cell = conn_it.Next()) != NULL) {
+    const double cur_ratio = test_cell->GetOrganism()->CalcMeritRatio();
+    if (cur_ratio > max_ratio) {
+      max_ratio = cur_ratio;
+      found_list.Clear();
+      found_list.Push(test_cell);
+    }
+    else if (cur_ratio == max_ratio) {
+      found_list.Push(test_cell);
+    }
+  }
+}
+
+void cPopulation::PositionEnergyUsed(cPopulationCell & parent_cell,
+                                tList<cPopulationCell> & found_list,
+                                bool parent_ok)
+{
+  // Start with the parent organism as the replacement, and see if we can find
+  // anything equivilent or better.
+  
+  found_list.Push(&parent_cell);
+  int max_energy_used = parent_cell.GetOrganism()->GetPhenotype().GetTimeUsed();
+  if (parent_ok == false) max_energy_used = -1;
+  
+  // Now look at all of the neighbors.
+  tListIterator<cPopulationCell> conn_it( parent_cell.ConnectionList() );
+  
+  cPopulationCell * test_cell;
+  while ( (test_cell = conn_it.Next()) != NULL) {
+    const int cur_energy_used = test_cell->GetOrganism()->GetPhenotype().GetTimeUsed();
+    if (cur_energy_used > max_energy_used) {
+      max_energy_used = cur_energy_used;
+      found_list.Clear();
+      found_list.Push(test_cell);
+    }
+    else if (cur_energy_used == max_energy_used) {
+      found_list.Push(test_cell);
+    }
+  }
+}
+
+// This function handles PositionChild() when there is migration between demes
+cPopulationCell& cPopulation::PositionDemeMigration(cPopulationCell& parent_cell, bool parent_ok)
+{
+    //cerr << "Attempting to migrate with rate " << m_world->GetConfig().MIGRATION_RATE.Get() << "!" << endl;
+    int deme_id = parent_cell.GetDemeID();
+    
+    // Position randomly in any other deme
+    if (m_world->GetConfig().DEMES_MIGRATION_METHOD.Get() == 0) {  
+                    
+      //get another -unadjusted- deme id
+      int rnd_deme_id = m_world->GetRandom().GetInt(deme_array.GetSize()-1);
+      
+      //if the -unadjusted- id is above the excluded id, bump it up one
+      //insures uniform prob of landing in any deme but the parent's
+      if(rnd_deme_id >= deme_id) rnd_deme_id++;
+      
+      //set the new deme_id
+      deme_id = rnd_deme_id;
+    }
+    
+    //Position randomly in an adjacent deme in neighborhood (assuming torus)
+    //Extremely hacked DEMES_NUM_X config setting simulates grid
+    else if (m_world->GetConfig().DEMES_MIGRATION_METHOD.Get() == 1) {
+    
+      //get a random eight-neighbor
+      int dir = m_world->GetRandom().GetInt(8);
+      
+      // 0 = NW, 1=N, continuing clockwise....
+    
+      // Up one row
+      if (m_world->GetConfig().DEMES_NUM_X.Get() == 0) {
+          m_world->GetDriver().RaiseFatalException(1, "DEMES_NUM_X must be non-zero if DEMES_MIGRATION_METHOD 1 used.");
+      }
+      int x_size = m_world->GetConfig().DEMES_NUM_X.Get();
+      int y_size = (int) (m_world->GetConfig().NUM_DEMES.Get() / x_size);
+
+      assert(y_size * x_size == m_world->GetConfig().NUM_DEMES.Get());
+
+      int x = deme_id % x_size;
+      int y = (int) (deme_id / x_size);
+
+      if ( (dir == 0) || (dir == 1) || (dir == 2) ) y--;
+      if ( (dir == 5) || (dir == 6) || (dir == 7) ) y++;
+      if ( (dir == 0) || (dir == 3) || (dir == 5) ) x--;
+      if ( (dir == 2) || (dir == 4) || (dir == 7) ) x++;
+      
+      //handle boundary conditions...
+      
+      x = (x + x_size) % x_size;
+      y = (y + y_size) % y_size;
+
+      //set the new deme_id
+      deme_id = x + x_size * y;
+
+      assert(deme_id > 0);
+      assert(deme_id > 0);
+    }
+    
+    //Random deme adjacent in list
+    else if (m_world->GetConfig().DEMES_MIGRATION_METHOD.Get() == 2) {
+
+      //get a random direction to move in deme list
+      int rnd_deme_id = m_world->GetRandom().GetInt(1);
+      if (rnd_deme_id == 0) rnd_deme_id = -1;
+      
+      //set the new deme_id
+      deme_id = (deme_id + rnd_deme_id + GetNumDemes()) % GetNumDemes();
+    }
+    
+    // TODO the above choice of deme does not respect PREFER_EMPTY
+    // i.e., it does not preferentially pick a deme with empty cells if they are 
+    // it might make sense for that to happen...
+    
+    // Now return an empty cell from the chosen deme
+    return PositionDemeRandom(deme_id, parent_cell, parent_ok); 
+}
+
+// This function handles PositionChild() by returning a random cell from the entire deme.
+cPopulationCell& cPopulation::PositionDemeRandom(int deme_id, cPopulationCell& parent_cell, bool parent_ok)
+{
+  assert((deme_id >=0) && (deme_id < deme_array.GetSize()));
+  
+  const int deme_size = deme_array[deme_id].GetSize();
+  cDeme& deme = deme_array[deme_id];
+
+  // Look randomly within empty cells first, if requested
+  if (m_world->GetConfig().PREFER_EMPTY.Get()) {
+    
+    int num_empty_cells = UpdateEmptyCellIDArray(deme_id);
+    if (num_empty_cells > 0) {
+      int out_pos = m_world->GetRandom().GetUInt(num_empty_cells);
+      return GetCell(empty_cell_id_array[out_pos]);
+    } 
+  }
+
+  int out_pos = m_world->GetRandom().GetUInt(deme_size);
+  int out_cell_id = deme.GetCellID(out_pos);
+  
+  while (parent_ok == false && out_cell_id == parent_cell.GetID()) {
+    out_pos = m_world->GetRandom().GetUInt(deme_size);
+    out_cell_id = deme.GetCellID(out_pos);
+  }
+  
+  return GetCell(out_cell_id); 
+}
+
+
+// This function updates the list of empty cell ids in the population
+// and returns the number of empty cells found. Used by global PREFER_EMPTY
+// PositionChild() methods. If deme_id is -1 (the default), then operates
+// on the entire population. 
+int cPopulation::UpdateEmptyCellIDArray(int deme_id)
+{
+  int num_empty_cells = 0;  
+  cDeme& deme = deme_array[deme_id];
+  // Note: empty_cell_id_array was resized to be large enough to hold
+  // all cells in the cPopulation when it was created. Using functions
+  // that resize it (like Push) will slow this code down considerably.
+  // Instead, we keep track of how much of this memory we are using.
+      
+  // Look at all cells
+  if (deme_id == -1) { 
+    for (int i=0; i<cell_array.GetSize(); i++) {
+      if (GetCell(i).IsOccupied() == false) empty_cell_id_array[num_empty_cells++] = i;
+    }
+  }
+  // Look at a specific deme
+  else {
+    for (int i=0; i<deme.GetSize(); i++) {
+      if (GetCell(deme.GetCellID(i)).IsOccupied() == false) empty_cell_id_array[num_empty_cells++] = deme.GetCellID(i);
+    }
+  }
+  
+  return num_empty_cells;
+}
+
+
 int cPopulation::ScheduleOrganism()
 {
   return schedule->GetNextID();
@@ -2813,6 +2957,10 @@
 // Loop through all the demes getting stats and doing calculations
 // which must be done on a deme by deme basis.
 void cPopulation::UpdateDemeStats() {
+
+  // bail early to save time if there are no demes
+  if (GetNumDemes() == 1) return ;
+
   cStats& stats = m_world->GetStats();
 
   stats.SumDemeAge().Clear();
@@ -2823,11 +2971,13 @@
   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
+    if(!deme.IsEmpty())  // ignore empty demes
+    { 
       continue;
+    }
     stats.SumDemeAge().Add(deme.GetAge());
     stats.SumDemeBirthCount().Add(deme.GetBirthCount());
     stats.SumDemeOrgCount().Add(deme.GetOrgCount());
@@ -3583,90 +3733,6 @@
 }
 
 
-void cPopulation::PositionAge(cPopulationCell & parent_cell,
-                              tList<cPopulationCell> & found_list,
-                              bool parent_ok)
-{
-  // Start with the parent organism as the replacement, and see if we can find
-  // anything equivilent or better.
-  
-  found_list.Push(&parent_cell);
-  int max_age = parent_cell.GetOrganism()->GetPhenotype().GetAge();
-  if (parent_ok == false) max_age = -1;
-  
-  // Now look at all of the neighbors.
-  tListIterator<cPopulationCell> conn_it( parent_cell.ConnectionList() );
-  
-  cPopulationCell * test_cell;
-  while ( (test_cell = conn_it.Next()) != NULL) {
-    const int cur_age = test_cell->GetOrganism()->GetPhenotype().GetAge();
-    if (cur_age > max_age) {
-      max_age = cur_age;
-      found_list.Clear();
-      found_list.Push(test_cell);
-    }
-    else if (cur_age == max_age) {
-      found_list.Push(test_cell);
-    }
-  }
-}
-
-void cPopulation::PositionMerit(cPopulationCell & parent_cell,
-                                tList<cPopulationCell> & found_list,
-                                bool parent_ok)
-{
-  // Start with the parent organism as the replacement, and see if we can find
-  // anything equivilent or better.
-  
-  found_list.Push(&parent_cell);
-  double max_ratio = parent_cell.GetOrganism()->CalcMeritRatio();
-  if (parent_ok == false) max_ratio = -1;
-  
-  // Now look at all of the neighbors.
-  tListIterator<cPopulationCell> conn_it( parent_cell.ConnectionList() );
-  
-  cPopulationCell * test_cell;
-  while ( (test_cell = conn_it.Next()) != NULL) {
-    const double cur_ratio = test_cell->GetOrganism()->CalcMeritRatio();
-    if (cur_ratio > max_ratio) {
-      max_ratio = cur_ratio;
-      found_list.Clear();
-      found_list.Push(test_cell);
-    }
-    else if (cur_ratio == max_ratio) {
-      found_list.Push(test_cell);
-    }
-  }
-}
-
-void cPopulation::PositionEnergyUsed(cPopulationCell & parent_cell,
-                                tList<cPopulationCell> & found_list,
-                                bool parent_ok)
-{
-  // Start with the parent organism as the replacement, and see if we can find
-  // anything equivilent or better.
-  
-  found_list.Push(&parent_cell);
-  int max_energy_used = parent_cell.GetOrganism()->GetPhenotype().GetTimeUsed();
-  if (parent_ok == false) max_energy_used = -1;
-  
-  // Now look at all of the neighbors.
-  tListIterator<cPopulationCell> conn_it( parent_cell.ConnectionList() );
-  
-  cPopulationCell * test_cell;
-  while ( (test_cell = conn_it.Next()) != NULL) {
-    const int cur_energy_used = test_cell->GetOrganism()->GetPhenotype().GetTimeUsed();
-    if (cur_energy_used > max_energy_used) {
-      max_energy_used = cur_energy_used;
-      found_list.Clear();
-      found_list.Push(test_cell);
-    }
-    else if (cur_energy_used == max_energy_used) {
-      found_list.Push(test_cell);
-    }
-  }
-}
-
 void cPopulation::FindEmptyCell(tList<cPopulationCell> & cell_list,
                                 tList<cPopulationCell> & found_list)
 {

Modified: development/source/main/cPopulation.h
===================================================================
--- development/source/main/cPopulation.h	2008-04-01 20:20:46 UTC (rev 2511)
+++ development/source/main/cPopulation.h	2008-04-01 20:45:48 UTC (rev 2512)
@@ -120,6 +120,9 @@
   void PositionAge(cPopulationCell& parent_cell, tList<cPopulationCell>& found_list, bool parent_ok);
   void PositionMerit(cPopulationCell & parent_cell, tList<cPopulationCell>& found_list, bool parent_ok);
   void PositionEnergyUsed(cPopulationCell & parent_cell, tList<cPopulationCell>& found_list, bool parent_ok);
+  cPopulationCell& PositionDemeMigration(cPopulationCell& parent_cell, bool parent_ok = true);
+  cPopulationCell& PositionDemeRandom(int deme_id, cPopulationCell& parent_cell, bool parent_ok = true);
+  int UpdateEmptyCellIDArray(int deme_id = -1);
   void FindEmptyCell(tList<cPopulationCell>& cell_list, tList<cPopulationCell>& found_list);
 
   // Update statistics collecting...

Modified: development/source/main/cStats.cc
===================================================================
--- development/source/main/cStats.cc	2008-04-01 20:20:46 UTC (rev 2511)
+++ development/source/main/cStats.cc	2008-04-01 20:45:48 UTC (rev 2512)
@@ -1327,3 +1327,63 @@
   }
   m_deme_founders.clear();
 }
+
+void cStats::PrintDemeTasks(const cString& filename){
+  cDataFile& df = m_world->GetDataFile(filename);
+	df.WriteComment("Avida deme tasks data");
+	df.WriteTimeStamp();
+	df.WriteComment("First column gives the current update, next columns give the number");
+	df.WriteComment("of organisms that have the particular task as a component of their merit");
+	df.WriteComment("in a particular deme");
+
+  const int num_tasks = m_world->GetEnvironment().GetNumTasks();
+
+	df.Write(m_update,   "Update");
+  for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+    cDeme& deme = m_world->GetPopulation().GetDeme(i);
+    for(int j = 0; j < num_tasks; j++) {
+      df.Write( (deme.GetLastTaskCount()[j] > 0), cStringUtil::Stringf("%i.", i) + task_names[j] );
+    }
+	}
+  df.Endl();
+}
+
+void cStats::PrintDemeTasksExe(const cString& filename){
+  cDataFile& df = m_world->GetDataFile(filename);
+	df.WriteComment("Avida deme tasks exe data");
+	df.WriteTimeStamp();
+	df.WriteComment("First column gives the current update, next columns give the number");
+	df.WriteComment("of times a task has contributed to the merit of all organisms");
+	df.WriteComment("in a particular deme");
+
+  const int num_tasks = m_world->GetEnvironment().GetNumTasks();
+
+	df.Write(m_update,   "Update");
+  for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+    cDeme& deme = m_world->GetPopulation().GetDeme(i);
+    for(int j = 0; j < num_tasks; j++) {
+      df.Write( deme.GetLastTaskCount()[j], cStringUtil::Stringf("%i.", i) + task_names[j] );
+    }
+	}
+  df.Endl();
+}
+
+void cStats::PrintDemeReactions(const cString& filename){
+  cDataFile& df = m_world->GetDataFile(filename);
+	df.WriteComment("Avida deme reactions data");
+	df.WriteTimeStamp();
+  df.WriteComment("First column gives the current update, all further columns give the number");
+  df.WriteComment("of currently living organisms each reaction has affected.");
+
+  const int num_reactions = m_world->GetEnvironment().GetReactionLib().GetSize();
+
+	df.Write(m_update,   "Update");
+  for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+    cDeme& deme = m_world->GetPopulation().GetDeme(i);
+    for(int j = 0; j < num_reactions; j++) {
+      df.Write( deme.GetLastReactionCount()[j], cStringUtil::Stringf("%i.", i) + m_world->GetEnvironment().GetReactionLib().GetReaction(j)->GetName()  );
+    }
+  }
+  df.Endl();
+}
+

Modified: development/source/main/cStats.h
===================================================================
--- development/source/main/cStats.h	2008-04-01 20:20:46 UTC (rev 2511)
+++ development/source/main/cStats.h	2008-04-01 20:45:48 UTC (rev 2512)
@@ -418,7 +418,7 @@
   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
@@ -719,6 +719,11 @@
   //! Print the genotype IDs for the founders of demes that have recently been "born."
   void PrintDemeFounders(const cString& filename);
 
+  void PrintDemeTasks(const cString& filename);
+  void PrintDemeTasksExe(const cString& filename);
+  void PrintDemeReactions(const cString& filename);
+
+
 protected:
   int m_deme_num_repls; //!< Number of deme replications since last PrintDemeReplicationData.
   cDoubleSum m_deme_gestation_time; //!< Gestation time for demes - mean age at deme replication.




More information about the Avida-cvs mailing list