[Avida-SVN] r2806 - development/source/actions
dk at myxo.css.msu.edu
dk at myxo.css.msu.edu
Mon Sep 29 09:15:55 PDT 2008
Author: dk
Date: 2008-09-29 12:15:54 -0400 (Mon, 29 Sep 2008)
New Revision: 2806
Modified:
development/source/actions/PopulationActions.cc
Log:
Final(?) merge of synchronization-related population actions.
Modified: development/source/actions/PopulationActions.cc
===================================================================
--- development/source/actions/PopulationActions.cc 2008-09-29 16:04:08 UTC (rev 2805)
+++ development/source/actions/PopulationActions.cc 2008-09-29 16:15:54 UTC (rev 2806)
@@ -39,6 +39,7 @@
#include <map>
#include <set>
+#include <numeric>
/*
@@ -1525,110 +1526,153 @@
};
-/**** The below are merges-in-progress. ****/
-
-/*! Action to send an artificial flash to each deme in the population at a specified period.
-class cActionPacecarFlash : public cAction {
+/*! Send an artificial flash to a single organism in each deme in the population
+ at a specified period.
+
+ This action sends a single flash to the organism in the center of each deme. It
+ is meant to be sort of a "pacecar" flash, and is useful for analysis. This action
+ is also capable of having a per-deme flash period, which should assist in evolving
+ organisms that can adapt their flash period.
+ */
+class cActionFlash : public cAction {
public:
- cActionPacecarFlash(cWorld* world, const cString& args): cAction(world, args), _pacecar(80) {
- if(args.GetSize()) {
- cString largs(args);
- _pacecar = largs.PopWord().AsInt();
- }
- }
+ cActionFlash(cWorld* world, const cString& args): cAction(world, args) { }
//! Destructor.
- virtual ~cActionPacecarFlash() { }
+ virtual ~cActionFlash() { }
- static const cString GetDescription() { return "Arguments: [pacecar=80]"; }
+ static const cString GetDescription() { return "No arguments"; }
- //! Send a flash
+ //! Process this event, sending a flash to each deme.
virtual void Process(cAvidaContext& ctx) {
+ for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+ SendFlash(m_world->GetPopulation().GetDeme(i));
+ }
}
-
-private:
- int _pacecar; //!< Period for artificial flashes that will be sent to each deme.
+
+ //! Send a flash to a single organism in the given deme.
+ void SendFlash(cDeme& deme) {
+ cOrganism* org = deme.GetOrganism(deme.GetSize()/2);
+ if(org != 0) {
+ org->ReceiveFlash();
+ }
+ }
};
- */
/*! Compete demes based on the ability of their constituent organisms
to synchronize their flashes to a common phase and period.
-class cActionSynchronization : public cAbstractMonitoringCompeteDemes {
+ */
+class cActionSynchronization : public cAbstractCompeteDemes {
public:
//! Constructor.
- cActionSynchronization(cWorld* world, const cString& args) : cAbstractMonitoringCompeteDemes(world, args), _pacecar(0) {
- if(args.GetSize()) {
- cString largs(args);
- _pacecar = largs.PopWord().AsInt();
- }
- }
+ cActionSynchronization(cWorld* world, const cString& args) : cAbstractCompeteDemes(world, args) { }
+ //! Destructor.
+ virtual ~cActionSynchronization() { }
+
//! Description of this event.
static const cString GetDescription() { return "No Arguments"; }
-
- //! Run this event on the population.
- virtual void Process(cAvidaContext& ctx) {
- std::vector<double> fitness;
- for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
- fitness.push_back(fitness_function(m_world->GetPopulation().GetDeme(i)));
- }
- m_world->GetPopulation().CompeteDemes(fitness);
- }
-
- //! Calculate the fitness of a deme (must return > 0.0).
- virtual double fitness_function(const cDeme& deme) {
- // How many unique organisms have flashed in the last SYNC_FITNESS_WINDOW updates?
- int total_flashed = deme.GetUniqueFlashes();
+
+ /*! Calculate the fitness based on how well the organisms in this deme have
+ synchronized their flashes.
+ */
+ virtual double Fitness(const cDeme& deme) {
+ cStats::PopulationFlashes::const_iterator deme_flashes = m_world->GetStats().GetFlashTimes().find(deme.GetID());
+ if(deme_flashes == m_world->GetStats().GetFlashTimes().end()) {
+ // Hm, nothing to see here. We're done.
+ return 1.0;
+ }
- // If not everyone has flashed, fitness is just the number that have flashed:
- if(total_flashed < deme.GetSize()) {
- return 1.0 + total_flashed;
- }
+ // Now, chop off all flashes that are outside of the SYNC_FITNESS_WINDOW:
+ cStats::DemeFlashes window_flashes;
+ copy_flashes(window_flashes, deme_flashes->second, m_world->GetConfig().SYNC_FITNESS_WINDOW.Get());
+
+ // Make sure that everyone's flashed:
+ if(window_flashes.size() < (unsigned int)deme.GetSize()) {
+ return 1.0 + window_flashes.size();
+ }
- // If everyone has flashed, fitness is the difference between max and average
- // squared, added to the size of the deme.
- const cDeme::flash_row& fr = deme.GetFlashRollingSum();
- double avg = std::accumulate(fr.begin(), fr.end(), 0.0) / fr.size();
- double max = *std::max_element(fr.begin(), fr.end());
-
- return 1.0 + deme.GetSize() + pow(max-avg, 2.0);
+ // Since everyone has flashed, fitness is the difference between max and average
+ // number of flashes that occurred during the same update squared, added to
+ // the size of the deme.
+ std::vector<unsigned int> flash_counts;
+ count_flashes(window_flashes, flash_counts);
+
+ double max = *std::max_element(flash_counts.begin(), flash_counts.end());
+ double mean = std::accumulate(flash_counts.begin(), flash_counts.end(), 0.0) / flash_counts.size();
+
+ return 1.0 + deme.GetSize() + max - mean;
}
+
+protected:
+ //! Copy flashes that occured in the last window updates from source to target.
+ void copy_flashes(cStats::DemeFlashes& target, const cStats::DemeFlashes& source, int window) {
+ for(cStats::DemeFlashes::const_iterator i=source.begin(); i!=source.end(); ++i) {
+ for(cStats::CellFlashes::const_iterator j=i->second.begin(); j!=i->second.end(); ++j) {
+ if(*j > (m_world->GetStats().GetUpdate() - window)) {
+ target[i->first].push_back(*j);
+ }
+ }
+ }
+ }
+
+ //! Calculate the number of flashes that have occurred during each update.
+ void count_flashes(const cStats::DemeFlashes& flashes, std::vector<unsigned int>& flash_count) {
+ flash_count.clear();
+ flash_count.resize((unsigned int)m_world->GetConfig().SYNC_FITNESS_WINDOW.Get(), 0);
+ for(cStats::DemeFlashes::const_iterator i=flashes.begin(); i!=flashes.end(); ++i) {
+ for(cStats::CellFlashes::const_iterator j=i->second.begin(); j!=i->second.end(); ++j) {
+ ++flash_count[m_world->GetStats().GetUpdate()-*j];
+ }
+ }
+ }
};
- */
/*! Compete demes based on the ability of their constituent organisms
to synchronize their flashes to a common period, and yet distribute themselves
throughout phase-space (phase desynchronization).
-class cActionDesynchronization : public cActionCompeteDemesFlashTiming {
+ */
+class cActionDesynchronization : public cActionSynchronization {
public:
//! Constructor.
- cActionCompeteDemesFlashTimingDesync(cWorld* world, const cString& args) : cActionCompeteDemesFlashTiming(world, args) {
+ cActionDesynchronization(cWorld* world, const cString& args) : cActionSynchronization(world, args) {
}
+ //! Destructor.
+ virtual ~cActionDesynchronization() { }
+
//! Description of this event.
static const cString GetDescription() { return "No Arguments"; }
- //! Calculate the fitness of a deme (must return > 0.0).
- virtual double fitness_function(const cDeme& deme) {
- // How many unique organisms have flashed in the last SYNC_FITNESS_WINDOW updates?
- int total_flashed = deme.GetUniqueFlashes();
-
- // If not everyone has flashed, fitness is just the number that have flashed:
- if(total_flashed < deme.GetSize()) {
- return total_flashed + 1.0;
- }
-
- // Let's find out the max number of flashes in any update:
- const cDeme::flash_row& fr = deme.GetFlashRollingSum();
- double max = *std::max_element(fr.begin(), fr.end());
-
- // And reward based on the difference:
- return 1.0 + deme.GetSize() + pow(deme.GetSize()-max, 2.0);
+ //! Calculate fitness based on how well organisms have spread throughout phase-space.
+ virtual double Fitness(const cDeme& deme) {
+ cStats::PopulationFlashes::const_iterator deme_flashes = m_world->GetStats().GetFlashTimes().find(deme.GetID());
+ if(deme_flashes == m_world->GetStats().GetFlashTimes().end()) {
+ // Hm, nothing to see here. We're done.
+ return 1.0;
+ }
+
+ // Now, chop off all flashes that are outside of the SYNC_FITNESS_WINDOW:
+ cStats::DemeFlashes window_flashes;
+ copy_flashes(window_flashes, deme_flashes->second, m_world->GetConfig().SYNC_FITNESS_WINDOW.Get());
+
+ // Make sure that everyone's flashed:
+ if(window_flashes.size() < (unsigned int)deme.GetSize()) {
+ return 1.0 + window_flashes.size();
+ }
+
+ // Since everyone has flashed, fitness is the size of the deme minus the max
+ // number of organisms that have flashed during the same update.
+ std::vector<unsigned int> flash_counts;
+ count_flashes(window_flashes, flash_counts);
+
+ double max = *std::max_element(flash_counts.begin(), flash_counts.end());
+
+ return 1.0 + 2*deme.GetSize() - max;
}
};
- */
class cAbstractCompeteDemes_AttackKillAndEnergyConserve : public cAbstractCompeteDemes {
@@ -2339,10 +2383,15 @@
action_lib->Register<cActionResetDemes>("ResetDemes");
action_lib->Register<cActionCopyDeme>("CopyDeme");
+ action_lib->Register<cActionFlash>("Flash");
+
/****AbstractCompeteDemes sub-classes****/
+
action_lib->Register<cAbstractCompeteDemes_AttackKillAndEnergyConserve>("CompeteDemes_AttackKillAndEnergyConserve");
action_lib->Register<cAssignRandomCellData>("AssignRandomCellData");
action_lib->Register<cActionIteratedConsensus>("IteratedConsensus");
+ action_lib->Register<cActionSynchronization>("Synchronization");
+ action_lib->Register<cActionDesynchronization>("Desynchronization");
action_lib->Register<cActionNewTrial>("NewTrial");
action_lib->Register<cActionCompeteOrganisms>("CompeteOrganisms");
More information about the Avida-cvs
mailing list