[Avida-SVN] r2189 - in branches/dkdev/source: actions main

dknoester at myxo.css.msu.edu dknoester at myxo.css.msu.edu
Sat Nov 10 14:16:45 PST 2007


Author: dknoester
Date: 2007-11-10 17:16:44 -0500 (Sat, 10 Nov 2007)
New Revision: 2189

Modified:
   branches/dkdev/source/actions/PopulationActions.cc
   branches/dkdev/source/main/cAvidaConfig.h
   branches/dkdev/source/main/cDeme.cc
   branches/dkdev/source/main/cDeme.h
   branches/dkdev/source/main/cOrganism.cc
   branches/dkdev/source/main/cOrganism.h
   branches/dkdev/source/main/cPopulation.cc
   branches/dkdev/source/main/cPopulation.h
   branches/dkdev/source/main/cStats.cc
   branches/dkdev/source/main/cStats.h
Log:
Added "trials" framework for demes, refactored replicate demes into two parts, one that determines if replication should proceed, and another that handles the replication itself.  Added NewDemeTrial event, and config options for the number of trials, and whether or not a new trial reseeds the deme.



Modified: branches/dkdev/source/actions/PopulationActions.cc
===================================================================
--- branches/dkdev/source/actions/PopulationActions.cc	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/actions/PopulationActions.cc	2007-11-10 22:16:44 UTC (rev 2189)
@@ -445,6 +445,19 @@
 };
 
 
+class cActionNewDemeTrial : public cAction
+{
+public:
+  cActionNewDemeTrial(cWorld* world, const cString& args) : cAction(world, args) { }
+  static const cString GetDescription() { return "Move all demes on to their next trial; no arguments."; }
+  void Process(cAvidaContext& ctx) {
+    for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+      m_world->GetPopulation().GetDeme(i).NewTrial();
+    }
+  }    
+};
+
+
 /*
  Randomly removes a certain proportion of the population.
  
@@ -911,7 +924,8 @@
     else if (in_trigger == "two-cells-region-latched") m_rep_trigger = 19;
     else if (in_trigger == "two-cells-germline-region") m_rep_trigger = 20;
     else if (in_trigger == "two-cells-germline-region-count") m_rep_trigger = 21;
-    else if (in_trigger == "two-cells-germline-bounded-region") m_rep_trigger = 22;
+    else if (in_trigger == "two-cells-germline-region-reverse") m_rep_trigger = 22;
+    else if (in_trigger == "two-cells-germline-bounded-region") m_rep_trigger = 23;
         //    else if (in_trigger == "topo-2cells-path-merit") m_rep_trigger = 8;
 //    else if (in_trigger == "message-collection") m_rep_trigger = 9;
     else {
@@ -1311,7 +1325,8 @@
   action_lib->Register<cActionInjectRange>("InjectRange");
   action_lib->Register<cActionInjectSequence>("InjectSequence");
   action_lib->Register<cActionInjectDemes>("InjectDemes");
-
+  action_lib->Register<cActionNewDemeTrial>("NewDemeTrial");
+  
   action_lib->Register<cActionInjectParasite>("InjectParasite");
   action_lib->Register<cActionInjectParasitePair>("InjectParasitePair");
 
@@ -1336,7 +1351,8 @@
 
   action_lib->Register<cActionConnectCells>("ConnectCells");
   action_lib->Register<cActionDisconnectCells>("DisconnectCells");
-
+  
+  
   // @DMB - The following actions are DEPRECATED aliases - These will be removed in 2.7.
   action_lib->Register<cActionInject>("inject");
   action_lib->Register<cActionInjectRandom>("inject_random");

Modified: branches/dkdev/source/main/cAvidaConfig.h
===================================================================
--- branches/dkdev/source/main/cAvidaConfig.h	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/main/cAvidaConfig.h	2007-11-10 22:16:44 UTC (rev 2189)
@@ -163,10 +163,12 @@
   CONFIG_ADD_VAR(NUM_DEMES, int, 0, "Number of independed groups in the population; 0=off");
   CONFIG_ADD_VAR(DEMES_USE_GERMLINE, int, 0, "Whether or not demes use a distinct germline; 0=off");
   CONFIG_ADD_VAR(DEMES_HAVE_MERIT, int, 0, "Whether or not demes apply a merit to their members; 0=off");
+  CONFIG_ADD_VAR(DEME_REPLICATION_TRIALS, int, 1, "The number of trials that a deme must go through before replication is allowed.");
+  CONFIG_ADD_VAR(DEME_RESEED_ON_NEW_TRIAL, int, 0, "Whether to reseed the deme from the germline on a new trial; 0=no");
+  CONFIG_ADD_VAR(GERMLINE_RANDOM_PLACEMENT, int, 0, "Whether the seed for a germline is placed randomly within the deme; 0=no.");
   CONFIG_ADD_VAR(GERMLINE_COPY_MUT, double, 0.0075, "Probability of copy mutations occuring during germline replication.");
   CONFIG_ADD_VAR(FILL_DEME_ON_REPLICATE, int, 0, "Whether to fill the source and target demes upon replication.");
-  CONFIG_ADD_VAR(GERMLINE_REPLACES_SOURCE, int, 0, "Whether the source germline is updated on replication; 0=no.");
-  CONFIG_ADD_VAR(GERMLINE_RANDOM_PLACEMENT, int, 0, "Whether the seed for a germline is placed randomly within the deme; 0=no.");
+
   CONFIG_ADD_VAR(MAX_DEME_AGE, int, 500, "The maximum age of a deme (in updates) to be used for age-based replication (default=500).");
   CONFIG_ADD_VAR(TRACK_GENOTYPES, int, 0, "Whether genotypes are tracked graphically.");
   CONFIG_ADD_VAR(TWOCELLS_MIN_REGION_RATIO, double, 0.2, "Ratio of size of two-cells region to environment size.");

Modified: branches/dkdev/source/main/cDeme.cc
===================================================================
--- branches/dkdev/source/main/cDeme.cc	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/main/cDeme.cc	2007-11-10 22:16:44 UTC (rev 2189)
@@ -28,9 +28,10 @@
 {
 }
 
-void cDeme::Setup(const tArray<int> & in_cells, int in_width, cWorld* world, cPopulation* pop)
+void cDeme::Setup(const tArray<int> & in_cells, int in_width, cWorld* world, cPopulation* pop, int deme_id)
 {
   _world = world;
+  _deme_id = deme_id;
   cell_ids = in_cells;
   birth_count = 0;
   org_count = 0;
@@ -45,7 +46,7 @@
       _cellsToMsgCount[pop->GetCell(cell_ids[i]).GetRandomCellID()] = 0;
     }  
   }  
-  Reset();
+  NewTrial();
 }
 
 int cDeme::GetCellID(int x, int y) const
@@ -72,22 +73,13 @@
   birth_count = 0;
   m_network = Network();
   m_cvMap = CellVertexMap();
+  _trial_merits.clear();
   _age = 0;
   _links = 20; // Start with extra.
   _collect_count = 0;
   for(CellCountMap::iterator i=_cellsToMsgCount.begin(); i!=_cellsToMsgCount.end(); ++i) {
     i->second = 0;
   }
-  if(cell_ids.GetSize() > 0) {
-    _cellsToLink = std::make_pair(GetCellID(_world->GetRandom().GetInt(GetWidth()), _world->GetRandom().GetInt(GetHeight()-2)+1),
-                                  cell_ids[_world->GetRandom().GetInt(cell_ids.GetSize())]);
-    
-    while((_cellsToLink.second == _cellsToLink.first) 
-          || (((double)region_size(GetCellPosition(_cellsToLink.first), GetCellPosition(_cellsToLink.second))
-               / GetSize()) < _world->GetConfig().TWOCELLS_MIN_REGION_RATIO.Get())) {
-      _cellsToLink.second = cell_ids[_world->GetRandom().GetInt(cell_ids.GetSize())];
-    }  
-  }
 }
 
 
@@ -124,6 +116,28 @@
 }
 
 
+void cDeme::NewTrial() {
+  // (0-6, (0-5)+1
+  _cellsToLink = std::make_pair(GetCellID(_world->GetRandom().GetInt(GetWidth()), _world->GetRandom().GetInt(GetHeight()-1)+1),
+                                cell_ids[_world->GetRandom().GetInt(cell_ids.GetSize())]);
+    
+  while((_cellsToLink.second == _cellsToLink.first) 
+        || (((double)region_size(GetCellPosition(_cellsToLink.first), GetCellPosition(_cellsToLink.second))
+             / GetSize()) < _world->GetConfig().TWOCELLS_MIN_REGION_RATIO.Get())) {
+    _cellsToLink.second = cell_ids[_world->GetRandom().GetInt(cell_ids.GetSize())];
+  }
+  
+  // Do we need to recycle the deme on a new trial?  This is a little different than 
+  // a reset, not sure if this should be a reset or if a reseed is sufficient...
+  if(_world->GetConfig().DEME_RESEED_ON_NEW_TRIAL.Get() 
+     && _world->GetConfig().DEMES_USE_GERMLINE.Get()
+     && (GetGermline().Size()>0)) {
+    //re-seed this deme from its germline
+    _world->GetPopulation().SeedDeme(*this, GetGermline().GetLatest());
+  }
+}
+
+
 bool network_is_connected(cDeme::Network& network) {
   // Do we have a connected graph?
   std::vector<int> components(boost::num_vertices(network));
@@ -250,4 +264,3 @@
     * (std::max(one_xy.second, two_xy.second) - std::min(one_xy.second, two_xy.second)+1);
 }
 
-

Modified: branches/dkdev/source/main/cDeme.h
===================================================================
--- branches/dkdev/source/main/cDeme.h	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/main/cDeme.h	2007-11-10 22:16:44 UTC (rev 2189)
@@ -19,6 +19,7 @@
 #include <boost/graph/visitors.hpp>
 #include <map>
 #include <utility>
+#include <vector>
 
 #include "tArray.h"
 #include "cGermline.h"
@@ -60,8 +61,8 @@
   cDeme();
   ~cDeme();
 
-  void Setup(const tArray<int> & in_cells, int in_width, cWorld* world, cPopulation* pop);
-
+  void Setup(const tArray<int> & in_cells, int in_width, cWorld* world, cPopulation* pop, int deme_id);
+  int GetID() { return _deme_id; }
   int GetSize() const { return cell_ids.GetSize(); }
   int GetCellID(int pos) const { return cell_ids[pos]; }
   int GetCellID(int x, int y) const;
@@ -107,11 +108,18 @@
   const CellCountMap& GetMessageCollection() const { return _cellsToMsgCount; }
   unsigned int GetMessageCollectionCount() const { return _collect_count; }
   
+  // -= Trial support =-
+  std::vector<double>& GetTrials() { return _trial_merits; }
+  void AddTrial(double merit) { _trial_merits.push_back(merit); }
+  void NewTrial();
+  
 private:
   tArray<int> cell_ids;
   int width;        // How wide is the deme?
   int birth_count;  // How many organisms have been born into deme since reset?
   int org_count;    // How many organisms are currently in the deme?
+  int _deme_id; // This deme's id.
+  std::vector<double> _trial_merits; // What are the associated per-trial merits for this deme?
 
   Network m_network; //!< The network associated with this deme.
   CellVertexMap m_cvMap; //!< A map of cell IDs to vertex descriptors.

Modified: branches/dkdev/source/main/cOrganism.cc
===================================================================
--- branches/dkdev/source/main/cOrganism.cc	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/main/cOrganism.cc	2007-11-10 22:16:44 UTC (rev 2189)
@@ -651,4 +651,5 @@
     _region_latched = true;
   }
   _region_count += region;
+  _region_latest = region;
 }

Modified: branches/dkdev/source/main/cOrganism.h
===================================================================
--- branches/dkdev/source/main/cOrganism.h	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/main/cOrganism.h	2007-11-10 22:16:44 UTC (rev 2189)
@@ -284,10 +284,12 @@
   bool _region_latched;
   int _region;
   int _region_count;
+  int _region_latest;
 public:
   void SetRegion(int region);
   int GetRegion() const { return _region; }
   int GetRegionCount() const { return _region_count; }
+  int GetLatestRegion() const { return _region_latest; }
   bool IsRegionLatched() const { return _region_latched; }
 };
 

Modified: branches/dkdev/source/main/cPopulation.cc
===================================================================
--- branches/dkdev/source/main/cPopulation.cc	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/main/cPopulation.cc	2007-11-10 22:16:44 UTC (rev 2189)
@@ -55,8 +55,8 @@
 /*! This is an accumulator type for adding up the number of organisms that have their
 region correct within a deme.
 */
-struct correct_region_accumulator : std::binary_function<double, cPopulationCell, double> {
-  correct_region_accumulator(cDeme& deme) : _deme(deme) { }
+struct correct_region_latching_accumulator : std::binary_function<double, cPopulationCell, double> {
+  correct_region_latching_accumulator(cDeme& deme) : _deme(deme) { }
   double operator()(double result, cPopulationCell& cell) {
     // What are the deme dimensions, and where is the organism located?
     assert(cell.IsOccupied());
@@ -75,7 +75,7 @@
     if((self_xy.second >= (cell1_xy.second)) && (organism->GetRegion()==1)) {
       result += 1.0;
 //      std::cout << " up.";
-    } else if((self_xy.second <= (cell1_xy.second)) && (organism->GetRegion()==-1)) {
+    } else if((self_xy.second < (cell1_xy.second)) && (organism->GetRegion()==-1)) {
       result += 1.0;
 //      std::cout << " down.";
     }
@@ -89,6 +89,43 @@
 };
 
 
+/*! This is an accumulator type for adding up the number of organisms that have their
+region correct within a deme.
+*/
+struct correct_region_reversible_accumulator : std::binary_function<double, cPopulationCell, double> {
+  correct_region_reversible_accumulator(cDeme& deme) : _deme(deme) { }
+  double operator()(double result, cPopulationCell& cell) {
+    // What are the deme dimensions, and where is the organism located?
+    assert(cell.IsOccupied());
+    cOrganism* organism = cell.GetOrganism();
+    assert(organism != 0);
+    //std::pair<int,int> deme_xy = std::make_pair(_deme.GetWidth(), _deme.GetHeight());
+    
+    std::pair<int,int> cells = _deme.GetCellsToLink();
+    std::pair<int,int> cell1_xy = _deme.GetCellPosition(cells.first);    
+    std::pair<int,int> self_xy = _deme.GetCellPosition(organism->GetCellID());
+    
+    //    std::cout << "Organism " << organism->GetCellID() << " @ (" << self_xy.first << "," << self_xy.second << ") declares "
+    //      << organism->GetRegion() << " for cell1 @ (" << cell1_xy.first << "," << cell1_xy.second << ");";
+    
+    // Has the organism declared correctly or not?  If so, increment result.
+    if((self_xy.second >= (cell1_xy.second)) && (organism->GetLatestRegion()==1)) {
+      result += 1.0;
+      //      std::cout << " up.";
+    } else if((self_xy.second < (cell1_xy.second)) && (organism->GetLatestRegion()==-1)) {
+      result += 1.0;
+      //      std::cout << " down.";
+    }
+    //    std::cout << endl;
+    
+    // All done.
+    return result;
+  }
+  
+  cDeme& _deme;
+};
+
+
 /*! As above, this is an accumulator type for adding up the number of organisms that have their
 region correct within a deme.  However, this one is based on the number of times that
 an Organism has called the correct region function, as opposed to the *first* one that 
@@ -114,7 +151,7 @@
     if((self_xy.second >= (cell1_xy.second)) && (organism->GetRegionCount() > 0)) {
       result += 1.0;
 //      std::cout << " up.";
-    } else if((self_xy.second <= (cell1_xy.second)) && (organism->GetRegionCount() < 0)) {
+    } else if((self_xy.second < (cell1_xy.second)) && (organism->GetRegionCount() < 0)) {
       result += 1.0;
 //      std::cout << " down.";
     }
@@ -229,7 +266,7 @@
 			deme_cells[offset] = cell_id;
 			cell_array[cell_id].SetDemeID(deme_id);
 		}
-		deme_array[deme_id].Setup(deme_cells, deme_size_x, m_world, this);
+		deme_array[deme_id].Setup(deme_cells, deme_size_x, m_world, this, deme_id);
 	}
 	
 	
@@ -932,8 +969,6 @@
 	for (int deme_id = 0; deme_id < num_demes; deme_id++) {
 		cDeme& source_deme = deme_array[deme_id];
     cDeme::Network& network = source_deme.GetNetwork();
-    double source_germline_merit = 0.0;
-    bool record_replication = true;
 
     // Doesn't make sense to try and replicate a deme that *has no organisms*.
     if(source_deme.IsEmpty()) continue;
@@ -944,11 +979,13 @@
 			case 0: {
         // Replicate non-empty demes.
 				if(source_deme.IsEmpty()) continue;
+        source_deme.AddTrial(0.0);
 				break;
       }
 			case 1: {
         // Replicate full demes.
 				if(source_deme.IsFull() == false) continue;
+        source_deme.AddTrial(0.0);
 				break;
       }
 			case 2: {
@@ -958,6 +995,7 @@
 				const int id2 = source_deme.GetCellID(source_deme.GetSize() - 1);
 				if (cell_array[id1].IsOccupied() == false ||
             cell_array[id2].IsOccupied() == false) continue;
+        source_deme.AddTrial(0.0);
 				break;
 			}
       case 3: {
@@ -966,7 +1004,7 @@
            || (source_deme.GetBirthCount() < source_deme.GetSize())) {
           continue;
         }
-        record_replication = false;
+        source_deme.AddTrial(0.0);
         break;
       }			
       case 4: {
@@ -975,6 +1013,7 @@
         if(boost::num_vertices(network) < (unsigned int)source_deme.GetSize()) continue;
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
+        source_deme.AddTrial(0.0);
         break;
       }
       case 5: {
@@ -983,8 +1022,7 @@
         if(boost::num_vertices(network) < (unsigned int)source_deme.GetSize()) continue;
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
-        
-        source_germline_merit = pow((double)boost::num_edges(network), 2);
+        source_deme.AddTrial(pow((double)boost::num_edges(network), 2));
 				break;
       }
       case 6: {
@@ -994,7 +1032,7 @@
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
 
-        source_germline_merit = pow((double)max_edges(source_deme) - boost::num_edges(network) + 1, 2);
+        source_deme.AddTrial(pow((double)max_edges(source_deme) - boost::num_edges(network) + 1, 2));
 				break;
       }
       case 7: {
@@ -1004,7 +1042,7 @@
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
 
-        source_germline_merit = pow((double)diameter(network), 2);
+        source_deme.AddTrial(pow((double)diameter(network), 2));
         break;
       }
       case 8: {
@@ -1016,7 +1054,7 @@
         m_world->GetStats().TopologyReplication(network);
 
         // Note: we don't need a +1 here (max diameter is less than num_vertices).
-        source_germline_merit = pow((double)boost::num_vertices(network) - diameter(network), 2);
+        source_deme.AddTrial(pow((double)boost::num_vertices(network) - diameter(network), 2));
         break;
       }
       case 9: {
@@ -1027,7 +1065,7 @@
         m_world->GetStats().TopologyReplication(network);
         
         // What is the maximum possible CPL?
-        source_germline_merit = pow(characteristic_path_length(network), 2);
+        source_deme.AddTrial(pow(characteristic_path_length(network), 2));
         break;
       }        
       case 10: {
@@ -1037,8 +1075,8 @@
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
 
-        source_germline_merit = pow(0.75*boost::num_vertices(network) 
-                                    - characteristic_path_length(network) + 1, 2);
+        source_deme.AddTrial(pow(0.75*boost::num_vertices(network) 
+                                 - characteristic_path_length(network) + 1, 2));
         break;
       }        
       case 11: {
@@ -1048,7 +1086,7 @@
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
 
-        source_germline_merit = pow(100.0*clustering_coefficient(network) + 1, 2);
+        source_deme.AddTrial(pow(100.0*clustering_coefficient(network) + 1, 2));
         break;
       }
       case 12: {
@@ -1059,7 +1097,7 @@
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
 
-        source_germline_merit = pow(100.0 - 100.0*clustering_coefficient(network) + 1, 2);
+        source_deme.AddTrial(pow(100.0 - 100.0*clustering_coefficient(network) + 1, 2));
         break;
       }
       case 13: {
@@ -1075,7 +1113,7 @@
 
         // Want to reward for absolute "closeness" to target.
         // matlab: x=0:0.001:1; target=0.5; plot(x, (power(1/100,abs(target-x))*100).^2)
-        source_germline_merit = pow(pow(0.01, abs(target_coeff - coeff))*100, 2);
+        source_deme.AddTrial(pow(pow(0.01, abs(target_coeff - coeff))*100, 2));
         break;
       }
       case 14: {
@@ -1087,8 +1125,8 @@
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
         
-        source_germline_merit = pow((0.75*boost::num_vertices(network) - characteristic_path_length(network) + 1)
-                                    * (max_edges(source_deme) - boost::num_edges(network) + 1), 2);
+        source_deme.AddTrial(pow((0.75*boost::num_vertices(network) - characteristic_path_length(network) + 1)
+                                 * (max_edges(source_deme) - boost::num_edges(network) + 1), 2));
         break;
       }
       case 15: {
@@ -1100,8 +1138,8 @@
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
         
-        source_germline_merit = pow(0.75*boost::num_vertices(network) - characteristic_path_length(network) + 1, 2)
-                                    + pow(max_edges(source_deme) - boost::num_edges(network) + 1.0, 2);
+        source_deme.AddTrial(pow(0.75*boost::num_vertices(network) - characteristic_path_length(network) + 1, 2)
+                             + pow(max_edges(source_deme) - boost::num_edges(network) + 1.0, 2));
         break;
       }
       case 16: {
@@ -1113,12 +1151,12 @@
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
 
-        source_germline_merit = pow(
-                                    100*(0.75*boost::num_vertices(network) 
-                                         - characteristic_path_length(network)) / (0.75*boost::num_vertices(network))
-                                    + 100*((max_edges(source_deme) - boost::num_edges(network)) / max_edges(source_deme))
-                                    + 1
-                                    , 2);
+        source_deme.AddTrial(pow(
+                                 100*(0.75*boost::num_vertices(network) 
+                                      - characteristic_path_length(network)) / (0.75*boost::num_vertices(network))
+                                 + 100*((max_edges(source_deme) - boost::num_edges(network)) / max_edges(source_deme))
+                                 + 1
+                                 , 2));
         break;
       }
       case 17: {
@@ -1129,11 +1167,12 @@
         if(!network_is_connected(network)) continue;
         m_world->GetStats().TopologyReplication(network);
 
-        source_germline_merit = pow(max_edges(source_deme) - boost::num_edges(network) + 1.0, 2);
+        double source_germline_merit = pow(max_edges(source_deme) - boost::num_edges(network) + 1.0, 2);
         // ~5% error margin...
         if(boost::num_edges(network) <= (boost::num_vertices(network) + 2)) {
           source_germline_merit += pow(0.75*boost::num_vertices(network) - characteristic_path_length(network) + 1, 2);
         }
+        source_deme.AddTrial(source_germline_merit);
         break;
       }
       case 18: {
@@ -1145,10 +1184,11 @@
         m_world->GetStats().TopologyReplication(network);
         
         double cpl = characteristic_path_length(network);
-        source_germline_merit = pow(0.75*boost::num_vertices(network) - cpl + 1, 2);
+        double source_germline_merit = pow(0.75*boost::num_vertices(network) - cpl + 1, 2);
         if((cpl > 3.25) && (cpl < 3.75)) {
           source_germline_merit += pow(max_edges(source_deme) - boost::num_edges(network) + 1.0, 2);
         }
+        source_deme.AddTrial(source_germline_merit);
         break;
       }
       case 19: {
@@ -1161,7 +1201,7 @@
           all_latched = all_latched && cell_array[source_deme.GetCellID(i)].GetOrganism()->IsRegionLatched();
         }
         if(!all_latched) continue;
-        
+        source_deme.AddTrial(0.0);
         break;
       }
       case 20: {
@@ -1175,10 +1215,10 @@
         }
         if(!all_latched) continue;
         
-        source_germline_merit = pow(std::accumulate(&cell_array.begin()[source_deme.GetCellID(0)],
-                                                    &cell_array.begin()[source_deme.GetCellID(source_deme.GetSize()-1)+1],
-                                                    0.0, correct_region_accumulator(source_deme)),
-                                    2);
+        source_deme.AddTrial(pow(std::accumulate(&cell_array.begin()[source_deme.GetCellID(0)],
+                                                 &cell_array.begin()[source_deme.GetCellID(source_deme.GetSize()-1)+1],
+                                                 0.0, correct_region_latching_accumulator(source_deme)),
+                                 2));
         break;
       }
       case 21: {
@@ -1194,13 +1234,31 @@
         }
         if(!all_latched) continue;
         
-        source_germline_merit = pow(std::accumulate(&cell_array.begin()[source_deme.GetCellID(0)],
-                                                    &cell_array.begin()[source_deme.GetCellID(source_deme.GetSize()-1)+1],
-                                                    0.0, correct_region_count_accumulator(source_deme)),
-                                    2);
+        source_deme.AddTrial(pow(std::accumulate(&cell_array.begin()[source_deme.GetCellID(0)],
+                                                 &cell_array.begin()[source_deme.GetCellID(source_deme.GetSize()-1)+1],
+                                                 0.0, correct_region_count_accumulator(source_deme)),
+                                 2));
         break;
       }        
       case 22: {
+        // Replicate demes where all organisms in the deme have decided on a region.
+        // Merit is proportional to the number of organisms that have correctly decided.
+        // In this case, their decision is based on the last region instruction they have called.
+        if(!source_deme.IsFull()) continue;
+        
+        bool all_latched=true;
+        for(int i=0; i<source_deme.GetSize() && all_latched; ++i) {
+          all_latched = all_latched && (cell_array[source_deme.GetCellID(i)].GetOrganism()->IsRegionLatched() != 0);
+        }
+        if(!all_latched) continue;
+        
+        source_deme.AddTrial(pow(std::accumulate(&cell_array.begin()[source_deme.GetCellID(0)],
+                                                 &cell_array.begin()[source_deme.GetCellID(source_deme.GetSize()-1)+1],
+                                                 0.0, correct_region_reversible_accumulator(source_deme)),
+                                 2));
+        break;
+      }        
+      case 23: {
         // Replicate demes where all organisms have decided on a region, and set
         // merit proportional to the number of organisms that have correctly identified
         // the region in which they reside.
@@ -1211,231 +1269,141 @@
           all_latched = all_latched && cell_array[source_deme.GetCellID(i)].GetOrganism()->IsRegionLatched();
         }
         if(!all_latched) continue;
-
-        source_germline_merit = pow(std::accumulate(&cell_array.begin()[source_deme.GetCellID(0)],
-                                                    &cell_array.begin()[source_deme.GetCellID(source_deme.GetSize()-1)+1],
-                                                    0.0, bounded_region_accumulator(source_deme)),
-                                    2);
+        
+        source_deme.AddTrial(pow(std::accumulate(&cell_array.begin()[source_deme.GetCellID(0)],
+                                                 &cell_array.begin()[source_deme.GetCellID(source_deme.GetSize()-1)+1],
+                                                 0.0, bounded_region_accumulator(source_deme)),
+                                 2));
         break;
       }
-//      case 19: {
-//        // Replicate demes that have connected two randomly-selected cells.
-//        // Merit is the inverse of edge count.
-//        cDeme::Network& network = source_deme.GetNetwork();
-//        m_world->GetStats().Topology(network);
-//        
-//        cDeme::CellVertexMap& vertex_map = source_deme.GetCellVertexMap();        
-//        std::pair<int,int> cells = source_deme.GetCellsToLink();
-//
-//        // First verify that both of the cells in question are in the network.
-//        if(vertex_map.find(cells.first)==vertex_map.end()
-//           || vertex_map.find(cells.second)==vertex_map.end()) {
-//          continue;
-//        }
-//        
-//        // Ok, they're both in the network.  From the src, get the distance to
-//        // all other vertices.
-//        typedef cDeme::Network::vertices_size_type size_type;
-//        typedef std::vector<size_type> DistanceVector;
-//        DistanceVector dv(boost::num_vertices(network),0);
-//        DistanceVisitor<size_type*> visitor(&dv[0]);
-//        cDeme::Network::vertex_descriptor src = vertex_map[cells.first];
-//        cDeme::Network::vertex_descriptor dst = vertex_map[cells.second];
-//        boost::breadth_first_search(network, src, boost::visitor(visitor));
-//        
-//        // Now, if the distance from src to dst is 0, we know there is no path.
-//        if(dv[dst]==0) continue;
-//        
-//        // We've determined that there is a path; replication will proceed.
-//        m_world->GetStats().TopologyReplication(network);
-//        source_germline_merit = pow((double)(max_edges(source_deme) - boost::num_edges(network)+1), 2);
-//        break;
-//      }
-//      case 8: {
-//        // Replicate demes that have connected two randomly-selected cells.
-//        // Merit is the inverse of (max(e(N))-e(N)+1) + 
-//        cDeme::Network& network = source_deme.GetNetwork();
-//        m_world->GetStats().Topology(network);
-//        
-//        cDeme::CellVertexMap& vertex_map = source_deme.GetCellVertexMap();        
-//        std::pair<int,int> cells = source_deme.GetCellsToLink();
-//        
-//        // First verify that both of the cells in question are in the network.
-//        if(vertex_map.find(cells.first)==vertex_map.end()
-//           || vertex_map.find(cells.second)==vertex_map.end()) {
-//          continue;
-//        }
-//        
-//        // We're also going to make sure that the network has a chance to fill up.
-//        // This is to discourage extra work.
-//        if(boost::num_vertices(network) < (unsigned)source_deme.GetSize()) {
-//          continue;
-//        }
-//        
-//        // Ok, they're both in the network.  From the src, get the distance to
-//        // all other vertices.
-//        typedef cDeme::Network::vertices_size_type size_type;
-//        typedef std::vector<size_type> DistanceVector;
-//        DistanceVector dv(boost::num_vertices(network),0);
-//        DistanceVisitor<size_type*> visitor(&dv[0]);
-//        cDeme::Network::vertex_descriptor src = vertex_map[cells.first];
-//        cDeme::Network::vertex_descriptor dst = vertex_map[cells.second];
-//        boost::breadth_first_search(network, src, boost::visitor(visitor));
-//        
-//        // Now, if the distance from src to dst is 0, we know there is no path.
-//        if(dv[dst]==0) continue;
-//        
-//        // We've determined that there is a path; replication will proceed.
-//        m_world->GetStats().TopologyReplication(network);
-//        source_germline_merit = pow((double)boost::num_vertices(network) - 1 - dv[dst], 2);
-//        break;
-//      }       
-//      case 9: {
-//        // Replicate demes that have managed to collect all their constituent ids.
-//        // The merit of the deme is in inverse proportion to the number of messages used.
-//        
-//        // Have we collected each id?
-//        const cDeme::CellCountMap& ccmap = source_deme.GetMessageCollection();
-//        bool replicate=true;
-//        for(cDeme::CellCountMap::const_iterator i=ccmap.begin(); i!=ccmap.end(); ++i) {
-//          replicate = replicate && (i->second>0);
-//        }
-//        if(!replicate) continue;
-//        
-//        // Merit in inverse proportion to the number of messages used.
-//        // Merit will be in the range [1,deme size).
-//        source_germline_merit = pow(1+
-//                                    (double)source_deme.GetSize() - 
-//                                    std::min((int)source_deme.GetMessageCollectionCount(), source_deme.GetSize())
-//                                    , 2);
-//        
-//        break;
-//      }
-        default: {
-          cerr << "ERROR: Invalid replication trigger " << rep_trigger << " in cPopulation::ReplicateDemes()" << endl;
-          assert(false);
-        }
+      default: {
+        cerr << "ERROR: Invalid replication trigger " << rep_trigger << " in cPopulation::ReplicateDemes()" << endl;
+        assert(false);
+      }
     }
-		
-		// -- If we made it this far, we should replicate this deme. --
     
-    // Check to see if we should update the source deme's germline merit.
-    if(m_world->GetConfig().DEMES_USE_GERMLINE.Get() && m_world->GetConfig().DEMES_HAVE_MERIT.Get()) {
-      source_deme.GetGermline().UpdateMerit(source_germline_merit);
+    // Check to see if this deme has undergone enough trials to warrant replication.
+    assert(m_world->GetConfig().DEME_REPLICATION_TRIALS.Get() > 0);
+    assert(source_deme.GetTrials().size() > 0);
+    if(((int)source_deme.GetTrials().size()) < m_world->GetConfig().DEME_REPLICATION_TRIALS.Get()) {
+      // Not yet; need a new trial.
+      source_deme.NewTrial();
+      continue;
     }
-    if(record_replication) {
-      m_world->GetStats().DemeReplication(source_deme, rep_trigger);
-    }
-		cRandom& random = m_world->GetRandom();
-		
-		// Choose a random target deme to replicate to, and kill all the organisms
-		// in that deme.
-		int target_id = deme_id;
-		while(target_id == deme_id) {
-			target_id = random.GetUInt(num_demes);
-		}
-		cDeme& target_deme = deme_array[target_id];
-		for (int i=0; i<target_deme.GetSize(); i++) {
-			KillOrganism(cell_array[target_deme.GetCellID(i)]);
-		}
-		
-		// Ok, there are two potential places where the seed for the target deme can
-		// come from.  First, it could be a random organism in the source deme.
-		// Second, it could be an offspring of the source deme's germline, if the config
-		// option DEMES_USE_GERMLINE is set.
-		if(m_world->GetConfig().DEMES_USE_GERMLINE.Get()) {
-			// Get the latest germ from the source deme.
-			cGermline& source_germline = source_deme.GetGermline();
-			cGenome& source_germ = source_germline.GetLatest();
 
-      // Now create the next germ by manually mutating the source.
-      // @refactor (strategy pattern)
-      cGenome next_germ(source_germ);
-      if(m_world->GetConfig().GERMLINE_COPY_MUT.Get() > 0) {
-        const cInstSet& instset = m_world->GetHardwareManager().GetInstSet();
-        cAvidaContext ctx(m_world->GetRandom());        
-        for(int i=0; i<next_germ.GetSize(); ++i) {
-          if(m_world->GetRandom().P(m_world->GetConfig().GERMLINE_COPY_MUT.Get())) {
-            next_germ[i] = instset.GetRandomInst(ctx);
-          }
-        }
-      }
-      
-			// Here we're adding the next_germ to the germline(s).  Note the
-      // config option to determine if we should update the source_germline
-      // as well.
-			target_deme.ReplaceGermline(source_germline);
-      cGermline& target_germline = target_deme.GetGermline();
-      target_germline.Add(next_germ);
-      if(m_world->GetConfig().GERMLINE_REPLACES_SOURCE.Get()) {
-        source_germline.Add(next_germ);
-      }
+    // If we made it here, the source_deme should be replicated.  Do so now.
+    ReplicateDeme(source_deme);
+  } // And loop around to check other demes.
+}
 
-      // Kill all the organisms in the source deme.
-			for (int i=0; i<source_deme.GetSize(); i++) {
-				KillOrganism(cell_array[source_deme.GetCellID(i)]);
-			}
-      
-      // And inject the genomes into the source and target demes.  There are a
-      // couple of different ways we can do this:
-      if(m_world->GetConfig().FILL_DEME_ON_REPLICATE.Get()) {
-        // Fill each deme with copies of the new organism:
-        for(int i=0; i<source_deme.GetSize(); ++i) {
-          InjectGenome(source_deme.GetCellID(i), source_germline.GetLatest(), 0);
+
+/*! Replicate a single deme, overwriting a randomly-selected target deme.
+Handles both germline and non-germline replications. */
+void cPopulation::ReplicateDeme(cDeme& source_deme) 
+{
+  // Select a deme to replace, making sure that we don't try to replace the source deme.
+  cRandom& random = m_world->GetRandom();
+		
+  int target_id = source_deme.GetID();
+  while(target_id == source_deme.GetID()) { target_id = random.GetUInt(GetNumDemes()); }
+  cDeme& target_deme = deme_array[target_id];  
+    
+  // Are we using germlines?
+  if(m_world->GetConfig().DEMES_USE_GERMLINE.Get()) {
+    // Yes, we're using germlines.  Check to see if we need to do anything with 
+    // germline merit.
+    if(m_world->GetConfig().DEMES_HAVE_MERIT.Get()) {
+      source_deme.GetGermline().UpdateMerit((double)std::accumulate(source_deme.GetTrials().begin(),
+                                                                    source_deme.GetTrials().end(), 0.0)
+                                            / m_world->GetConfig().DEME_REPLICATION_TRIALS.Get());
+      m_world->GetStats().DemeReplication(source_deme);
+    }
+    
+    // Yes; get the latest germ from the source, and mutate it.
+    // @refactor (strategy pattern)
+    cGenome next_germ(source_deme.GetGermline().GetLatest());
+    if(m_world->GetConfig().GERMLINE_COPY_MUT.Get() > 0) {
+      const cInstSet& instset = m_world->GetHardwareManager().GetInstSet();
+      cAvidaContext ctx(m_world->GetRandom());        
+      for(int i=0; i<next_germ.GetSize(); ++i) {
+        if(m_world->GetRandom().P(m_world->GetConfig().GERMLINE_COPY_MUT.Get())) {
+          next_germ[i] = instset.GetRandomInst(ctx);
         }
-        for(int i=0; i<target_deme.GetSize(); ++i) {
-          InjectGenome(target_deme.GetCellID(i), target_germline.GetLatest(), 0);
-        }
-      } else {
-        if(m_world->GetConfig().GERMLINE_RANDOM_PLACEMENT.Get()) {
-          // Place the new organisms randomly:
-          InjectGenome(source_deme.GetCellID(m_world->GetRandom().GetInt(0, source_deme.GetSize()-1)),
-                       source_germline.GetLatest(), 0);
-          InjectGenome(target_deme.GetCellID(m_world->GetRandom().GetInt(0, target_deme.GetSize()-1)),
-                       target_germline.GetLatest(), 0);
-        } else {
-          // Place the new organisms in the 'middle' of the demes:
-          InjectGenome(source_deme.GetCellID(source_deme.GetSize()/2), source_germline.GetLatest(), 0);
-          InjectGenome(target_deme.GetCellID(target_deme.GetSize()/2), target_germline.GetLatest(), 0);
-        }
       }
+    }
+    
+    // Replace the target deme's germline with the source deme's, and add the newly-
+    // mutated germ to ONLY the target's germline.
+    target_deme.ReplaceGermline(source_deme.GetGermline());
+    target_deme.GetGermline().Add(next_germ);
+    
+    // All done with the germline manipulation, so go ahead and seed each deme.
+    SeedDeme(source_deme, source_deme.GetGermline().GetLatest());
+    SeedDeme(target_deme, target_deme.GetGermline().GetLatest());
+  } else {
+    // Not using germlines; choose a random organism from this deme.
+    int cell1_id = -1;
+    while (cell1_id == -1 || cell_array[cell1_id].IsOccupied() == false) {
+      cell1_id = source_deme.GetCellID(random.GetUInt(source_deme.GetSize()));
+    }
 			
-			// Note: not rotating the clones.
-		} else {
-			// Not using germline; choose a random organism from this deme.
-			int cell1_id = -1;
-			while (cell1_id == -1 || cell_array[cell1_id].IsOccupied() == false) {
-				cell1_id = source_deme.GetCellID(random.GetUInt(source_deme.GetSize()));
-			}
-			
-			cOrganism* seed = cell_array[cell1_id].GetOrganism();
-			
-			// And do the replication into the central cell of the target deme...
-			const int cell2_id = target_deme.GetCellID(target_deme.GetSize()/2);
-			InjectClone(cell2_id, *seed);
-
-			// Kill all the organisms in the source deme.
-			seed = 0; // Note that we're killing the organism that seed points to.
-			for (int i=0; i<source_deme.GetSize(); i++) {
-				KillOrganism(cell_array[source_deme.GetCellID(i)]);
-			}
-			
-			// Inject the target offspring back into the source ID.
-			const int cell3_id = source_deme.GetCellID( source_deme.GetSize()/2 );
-			InjectClone(cell3_id, *cell_array[cell2_id].GetOrganism());
+    cOrganism* seed = cell_array[cell1_id].GetOrganism();
+    
+    // And do the replication into the central cell of the target deme...
+    const int cell2_id = target_deme.GetCellID(target_deme.GetSize()/2);
+    InjectClone(cell2_id, *seed);
+    
+    // Kill all the organisms in the source deme.
+    seed = 0; // Note that we're killing the organism that seed points to.
+    for (int i=0; i<source_deme.GetSize(); i++) {
+      KillOrganism(cell_array[source_deme.GetCellID(i)]);
+    }
+    
+    // Inject the target offspring back into the source ID.
+    const int cell3_id = source_deme.GetCellID( source_deme.GetSize()/2 );
+    InjectClone(cell3_id, *cell_array[cell2_id].GetOrganism());
 		
-			// Rotate both injected cells to face northwest.
-			cell_array[cell2_id].Rotate(cell_array[GridNeighbor(cell2_id, world_x, world_y, -1, -1)] );
-			cell_array[cell3_id].Rotate(cell_array[GridNeighbor(cell3_id, world_x, world_y, -1, -1)] );
-		}
+    // Rotate both injected cells to face northwest.
+    cell_array[cell2_id].Rotate(cell_array[GridNeighbor(cell2_id, world_x, world_y, -1, -1)] );
+    cell_array[cell3_id].Rotate(cell_array[GridNeighbor(cell3_id, world_x, world_y, -1, -1)] );
+  }
 		
-		// And reset both demes, in case they have any cleanup work to do.
-		source_deme.Reset();
-		target_deme.Reset();
-	}
+  // And reset both demes, in case they have any cleanup work to do.
+  source_deme.Reset();
+  target_deme.Reset();
 }
 
 
+/*! Helper function to seed a deme from the given genome.
+If the passed-in deme is populated, all resident organisms are terminated.  The
+deme's germline is left unchanged.
+*/
+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)]);
+  }
+  
+  // Inject the given genome into the demes.  There are some options we have to deal
+  // with here:
+  if(m_world->GetConfig().FILL_DEME_ON_REPLICATE.Get()) {
+    // Fill the deme with copies of the new organism:
+    for(int i=0; i<deme.GetSize(); ++i) {
+      InjectGenome(deme.GetCellID(i), genome, 0);
+    }
+  } else {
+    if(m_world->GetConfig().GERMLINE_RANDOM_PLACEMENT.Get()) {
+      // Place the new organisms randomly:
+      InjectGenome(deme.GetCellID(m_world->GetRandom().GetInt(0, deme.GetSize()-1)),
+                   genome, 0);
+    } else {
+      // Place the new organism in the 'middle' of the deme:
+      InjectGenome(deme.GetCellID(deme.GetSize()/2), genome, 0);
+    }
+  }  
+}
+
+
 // Reset Demes goes through each deme and resets the individual organisms as
 // if they were just injected into the population.
 void cPopulation::ResetDemes()

Modified: branches/dkdev/source/main/cPopulation.h
===================================================================
--- branches/dkdev/source/main/cPopulation.h	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/main/cPopulation.h	2007-11-10 22:16:44 UTC (rev 2189)
@@ -117,6 +117,8 @@
   // Deme-related methods
   void CompeteDemes(int competition_type);
   void ReplicateDemes(int rep_trigger);
+  void ReplicateDeme(cDeme& source_deme);
+  void SeedDeme(cDeme& deme, cGenome& genome);
   void ResetDemes();
   void CopyDeme(int deme1_id, int deme2_id);
   void SpawnDeme(int deme1_id, int deme2_id=-1);

Modified: branches/dkdev/source/main/cStats.cc
===================================================================
--- branches/dkdev/source/main/cStats.cc	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/main/cStats.cc	2007-11-10 22:16:44 UTC (rev 2189)
@@ -995,7 +995,7 @@
 }
 
 
-void cStats::DemeReplication(cDeme& deme, int replication_trigger) {
+void cStats::DemeReplication(cDeme& deme) {
   // Common deme statistics.
   ++_deme_repl_count;
   _deme_age.Add(deme.GetAge());

Modified: branches/dkdev/source/main/cStats.h
===================================================================
--- branches/dkdev/source/main/cStats.h	2007-11-09 00:33:08 UTC (rev 2188)
+++ branches/dkdev/source/main/cStats.h	2007-11-10 22:16:44 UTC (rev 2189)
@@ -577,7 +577,7 @@
   // Deme-related statistics.
   //
 public:
-  void DemeReplication(cDeme& deme, int replication_trigger);
+  void DemeReplication(cDeme& deme);
   void PrintDemeData(const cString& filename);
   void PrintGermlineData(const cString& filename);
   void PrintDominantGermlineData(const cString& filename);
@@ -585,6 +585,7 @@
 private:
   int _deme_repl_count; //!< Number of deme replications since the last stats output.
   cDoubleSum _deme_merit; //!< Deme merits, upon replication.
+  cDoubleSum _deme_merit_nonzero; //!< Deme merits, upon replication, not counting zeroes.
   cDoubleSum _deme_age; //!< Deme ages, upon replication.
   cGermline _deme_last_germline; //!< The last germline to cause a deme replication.  
   double _deme_max_germline_merit; //!< The maximum germline merit since the last stat output.




More information about the Avida-cvs mailing list