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

dk at myxo.css.msu.edu dk at myxo.css.msu.edu
Fri Jun 6 10:55:51 PDT 2008


Author: dk
Date: 2008-06-06 13:55:51 -0400 (Fri, 06 Jun 2008)
New Revision: 2612

Modified:
   development/source/actions/PopulationActions.cc
   development/source/actions/PrintActions.cc
   development/source/main/cPopulation.cc
   development/source/main/cPopulation.h
   development/source/main/cStats.cc
   development/source/main/cStats.h
Log:
Added an upated form of CompeteDemes that integrates with the ReplicateDemes framework.

Modified: development/source/actions/PopulationActions.cc
===================================================================
--- development/source/actions/PopulationActions.cc	2008-06-06 16:01:21 UTC (rev 2611)
+++ development/source/actions/PopulationActions.cc	2008-06-06 17:55:51 UTC (rev 2612)
@@ -1068,6 +1068,41 @@
 };
 
 
+
+/*! An abstract base class to ease the development of new deme competition fitness functions.
+ */
+class cAbstractCompeteDemes : public cAction {
+public:
+  //! Constructor.
+  cAbstractCompeteDemes(cWorld* world, const cString& args) : cAction(world, args) { }
+  //! Destructor.
+  virtual ~cAbstractCompeteDemes() { }
+  
+  /*! Compete all demes with each other.
+   
+   For deme competition, what we do here is iterate over every deme and calculate its 
+   fitness according to the subclass-defined fitness function.  The resulting vector of
+   fitness values is then passed to cPopulation::CompeteDemes for fitness-proportional
+   selection, and then each deme is piped through the standard battery of config options.
+   
+   Note that each fitness value must be >= 0.0, and the sum of all fitnesses must 
+   be > 0.0.
+   */
+  virtual void Process(cAvidaContext& ctx) {
+    std::vector<double> fitness;
+    for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+      fitness.push_back(Fitness(m_world->GetPopulation().GetDeme(i)));
+      assert(fitness.back() >= 0.0);
+    }
+    m_world->GetPopulation().CompeteDemes(fitness);
+  }
+
+  /*! Deme fitness function, to be overriden by specific types of deme competition.
+   */
+  virtual double Fitness(const cDeme& deme) = 0;
+};
+
+
 /* This Action will check if any demes have met the critera to be replicated
    and do so.  There are several bases this can be checked on:
 

Modified: development/source/actions/PrintActions.cc
===================================================================
--- development/source/actions/PrintActions.cc	2008-06-06 16:01:21 UTC (rev 2611)
+++ development/source/actions/PrintActions.cc	2008-06-06 17:55:51 UTC (rev 2612)
@@ -95,6 +95,7 @@
 STATS_OUT_FILE(PrintSleepData,              sleep.dat           );
 STATS_OUT_FILE(PrintCompetitionData,        competition.dat     );
 STATS_OUT_FILE(PrintDemeReplicationData,    deme_repl.dat       );
+STATS_OUT_FILE(PrintDemeCompetitionData,    deme_compete.dat);
 STATS_OUT_FILE(PrintDemeFoundersData,       deme_founders.dat   );
 STATS_OUT_FILE(PrintPerDemeTasksData,       per_deme_tasks.dat      );
 STATS_OUT_FILE(PrintPerDemeTasksExeData,    per_deme_tasks_exe.dat  );
@@ -2688,6 +2689,7 @@
   action_lib->Register<cActionPrintDemeSpacialSleep>("PrintDemeSpacialSleepStats");
   action_lib->Register<cActionPrintDemeResources>("PrintDemeResourceStats");
   action_lib->Register<cActionPrintDemeReplicationData>("PrintDemeReplicationData");
+  action_lib->Register<cActionPrintDemeCompetitionData>("PrintDemeCompetitionData");
   action_lib->Register<cActionPrintDemeFoundersData>("PrintDemeFoundersData");
   action_lib->Register<cActionPrintGermlineData>("PrintGermlineData");
   action_lib->Register<cActionSaveDemeFounders>("SaveDemeFounders");

Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc	2008-06-06 16:01:21 UTC (rev 2611)
+++ development/source/main/cPopulation.cc	2008-06-06 17:55:51 UTC (rev 2612)
@@ -64,6 +64,7 @@
 #include <fstream>
 #include <vector>
 #include <algorithm>
+#include <numeric>
 #include <set>
 #include <cfloat>
 #include <cmath>
@@ -1096,6 +1097,81 @@
 }
 
 
+/*! Compete all demes with each other based on the given vector of fitness values.
+ 
+ This form of compete demes uses fitness-proportional selection on a vector of deme
+ fitnesses for group selection.  It integrates with the various deme replication options
+ used in ReplicateDemes.
+ 
+ Note: New deme competition fitness functions are added in PopulationActions.cc by subclassing
+ cActionAbstractCompeteDemes and overriding cActionAbstractCompeteDemes::Fitness(cDeme&).  (Don't forget
+ to register the action and add it to the events file).
+ 
+ Another note: To mimic the behavior of the other version of CompeteDemes (which is kept around
+ for backwards compatibility), change the config option DEMES_REPLICATE_SIZE to be the size of 
+ each deme.
+ */
+void cPopulation::CompeteDemes(const std::vector<double>& fitness) {
+  // Each deme must have a fitness:
+  assert((int)fitness.size() == deme_array.GetSize());
+  
+  // Stat-tracking:
+  m_world->GetStats().CompeteDemes(fitness);
+  
+  // Now, select the demes to live.  Each deme has a probability to replicate that is
+  // equal to its fitness / total fitness.
+  const double total_fitness = std::accumulate(fitness.begin(), fitness.end(), 0.0);
+  assert(total_fitness > 0.0); // Must have *some* positive fitnesses...
+  std::vector<unsigned int> deme_counts(deme_array.GetSize(), 0); // Number of demes (at index) which should wind up in the next generation.
+  
+  // What we're doing here is summing up the fitnesses until we reach or exceed the target fitness.
+  // Then we're marking that deme as being part of the next generation.
+  for(int i=0; i<deme_array.GetSize(); ++i) {
+    double running_sum = 0.0;
+    double target_sum = m_world->GetRandom().GetDouble(total_fitness);
+    for(int j=0; j<deme_array.GetSize(); ++j) {
+      running_sum += fitness[j];
+      if(running_sum >= target_sum) {
+        // j'th deme will be replicated.
+        ++deme_counts[j];
+        break;
+      }
+    }
+  }
+  
+  // Now, while we can find both a source deme (one with a count greater than 1)
+  // and a target deme (one with a count of 0), replace the target with the source.
+  while(true) {
+    int source_id=0;
+    for(; source_id<(int)deme_counts.size(); ++source_id) {
+      if(deme_counts[source_id] > 1) {
+        --deme_counts[source_id];
+        break;
+      }
+    }
+    
+    if(source_id == (int)deme_counts.size()) {
+      break; // All done.
+    }
+    
+    int target_id=0;
+    for(; target_id<(int)deme_counts.size(); ++target_id) {
+      if(deme_counts[target_id] == 0) {
+        ++deme_counts[target_id];
+        break;
+      }
+    }
+    
+    assert(source_id < deme_array.GetSize());
+    assert(target_id < deme_array.GetSize());
+    assert(source_id != target_id);
+    
+    // Replace the target with a copy of the source:
+    ReplaceDeme(deme_array[source_id], deme_array[target_id]);
+  }  
+}
+
+
 /* Check if any demes have met the critera to be replicated and do so.
 There are several bases this can be checked on:
 

Modified: development/source/main/cPopulation.h
===================================================================
--- development/source/main/cPopulation.h	2008-06-06 16:01:21 UTC (rev 2611)
+++ development/source/main/cPopulation.h	2008-06-06 17:55:51 UTC (rev 2612)
@@ -186,6 +186,9 @@
   // Deme-related methods
   //! Compete all demes with each other based on the given competition type.
   void CompeteDemes(int competition_type);
+  
+  //! Compete all demes with each other based on the given vector of fitness values.
+  void CompeteDemes(const std::vector<double>& fitness);
 
   //! Replicate all demes based on the given replication trigger.
   void ReplicateDemes(int rep_trigger);

Modified: development/source/main/cStats.cc
===================================================================
--- development/source/main/cStats.cc	2008-06-06 16:01:21 UTC (rev 2611)
+++ development/source/main/cStats.cc	2008-06-06 17:55:51 UTC (rev 2612)
@@ -43,6 +43,7 @@
 #include "functions.h"
 
 #include <cfloat>
+#include <numeric>
 #include <cmath>
 
 
@@ -1568,3 +1569,25 @@
   df.Endl();
 }
 
+
+void cStats::CompeteDemes(const std::vector<double>& fitness) {
+  m_deme_fitness = fitness;
+}
+
+
+void cStats::PrintDemeCompetitionData(const cString& filename) {
+  cDataFile& df = m_world->GetDataFile(filename);
+  
+  df.WriteComment("Avida compete demes data");
+  df.WriteTimeStamp();
+  df.Write(m_update, "Update [update]");
+  
+  double avg = std::accumulate(m_deme_fitness.begin(), m_deme_fitness.end(), 0.0);
+  if(avg > 0.0) {
+    avg /= m_deme_fitness.size();
+  }
+  df.Write(avg, "Avg. deme fitness [avgfit]");
+  df.Endl();
+  
+  m_deme_fitness.clear();
+}

Modified: development/source/main/cStats.h
===================================================================
--- development/source/main/cStats.h	2008-06-06 16:01:21 UTC (rev 2611)
+++ development/source/main/cStats.h	2008-06-06 17:55:51 UTC (rev 2612)
@@ -751,6 +751,17 @@
   cDoubleSum m_deme_generation; //!< Mean generation of replicated demes.
   cDoubleSum m_germline_generation; //!< "Generation" accumulator of replicated germlines.
   t_founder_map m_deme_founders; //!< Data structure to track the founders of demes.
+  
+  
+  // -------- Deme competition support --------
+public:
+  //! Called immediately prior to deme competition.
+  void CompeteDemes(const std::vector<double>& fitness);
+  //! Print data regarding deme competition.
+  void PrintDemeCompetitionData(const cString& filename);
+  
+private:
+  std::vector<double> m_deme_fitness; //!< Fitness of each deme during last deme competition.
 };
 
 




More information about the Avida-cvs mailing list