[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