[Avida-SVN] r3298 - in development: . Avida.xcodeproj source source/actions source/main
dk at myxo.css.msu.edu
dk at myxo.css.msu.edu
Sun Jun 7 09:52:15 PDT 2009
Author: dk
Date: 2009-06-07 12:52:14 -0400 (Sun, 07 Jun 2009)
New Revision: 3298
Added:
development/source/main/cDemeNetwork.cc
development/source/main/cDemeNetwork.h
development/source/main/cDemeNetworkUtils.h
development/source/main/cDemeTopologyNetwork.cc
development/source/main/cDemeTopologyNetwork.h
Modified:
development/Avida.xcodeproj/project.pbxproj
development/CMakeLists.txt
development/source/actions/PopulationActions.cc
development/source/actions/PrintActions.cc
development/source/defs.h
development/source/main/cAvidaConfig.h
development/source/main/cDeme.cc
development/source/main/cDeme.h
development/source/main/cPopulation.cc
development/source/main/cStats.cc
development/source/main/cStats.h
Log:
Added macro magic for conditional compilation of Boost in Avida proper, merged in the beginnings of support for cooperative construction of networks by demes.
Modified: development/Avida.xcodeproj/project.pbxproj
===================================================================
--- development/Avida.xcodeproj/project.pbxproj 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/Avida.xcodeproj/project.pbxproj 2009-06-07 16:52:14 UTC (rev 3298)
@@ -26,6 +26,8 @@
10479F2E0F1BC54B00AF9F6A /* cMutationSteps.cc in Sources */ = {isa = PBXBuildFile; fileRef = 10479F2C0F1BC54B00AF9F6A /* cMutationSteps.cc */; };
2A57A3FF0D6B954D00FC54C7 /* cProbDemeProbSchedule.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A57A3FD0D6B954D00FC54C7 /* cProbDemeProbSchedule.cc */; };
2A57A4000D6B954D00FC54C7 /* cProbDemeProbSchedule.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A57A3FE0D6B954D00FC54C7 /* cProbDemeProbSchedule.h */; };
+ 42C27C840FDC22AC00C45B78 /* cDemeNetwork.cc in Sources */ = {isa = PBXBuildFile; fileRef = 42C27C7F0FDC22AC00C45B78 /* cDemeNetwork.cc */; };
+ 42C27C870FDC22AC00C45B78 /* cDemeTopologyNetwork.cc in Sources */ = {isa = PBXBuildFile; fileRef = 42C27C820FDC22AC00C45B78 /* cDemeTopologyNetwork.cc */; };
5629D8110C3EE14800C5F152 /* cTextWindow.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5629D80D0C3EE13500C5F152 /* cTextWindow.cc */; };
5629D8180C3EE20C00C5F152 /* libncurses.5.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 70658C59085DF67D00486BED /* libncurses.5.4.dylib */; };
5629D8190C3EE21300C5F152 /* libavida-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7023EC330C0A426900362B9C /* libavida-core.a */; };
@@ -400,6 +402,11 @@
423335890BC067E3000DF681 /* cHardwareGX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cHardwareGX.h; sourceTree = "<group>"; };
42490EFE0BE2472800318058 /* cGermline.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cGermline.h; sourceTree = "<group>"; };
42777E5B0C7F123600AFA4ED /* cOrgMessage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cOrgMessage.h; sourceTree = "<group>"; };
+ 42C27C7F0FDC22AC00C45B78 /* cDemeNetwork.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cDemeNetwork.cc; sourceTree = "<group>"; };
+ 42C27C800FDC22AC00C45B78 /* cDemeNetwork.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cDemeNetwork.h; sourceTree = "<group>"; };
+ 42C27C810FDC22AC00C45B78 /* cDemeNetworkUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cDemeNetworkUtils.h; sourceTree = "<group>"; };
+ 42C27C820FDC22AC00C45B78 /* cDemeTopologyNetwork.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cDemeTopologyNetwork.cc; sourceTree = "<group>"; };
+ 42C27C830FDC22AC00C45B78 /* cDemeTopologyNetwork.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cDemeTopologyNetwork.h; sourceTree = "<group>"; };
5629D80D0C3EE13500C5F152 /* cTextWindow.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cTextWindow.cc; sourceTree = "<group>"; };
5629D80E0C3EE13500C5F152 /* cTextWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cTextWindow.h; sourceTree = "<group>"; };
5629D80F0C3EE13500C5F152 /* ncurses-defs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "ncurses-defs.h"; sourceTree = "<group>"; };
@@ -1525,6 +1532,11 @@
702D4F3908DA61E2007BA469 /* cBirthChamber.h */,
1097463D0AE9606E00929ED6 /* cDeme.cc */,
1097463E0AE9606E00929ED6 /* cDeme.h */,
+ 42C27C7F0FDC22AC00C45B78 /* cDemeNetwork.cc */,
+ 42C27C800FDC22AC00C45B78 /* cDemeNetwork.h */,
+ 42C27C810FDC22AC00C45B78 /* cDemeNetworkUtils.h */,
+ 42C27C820FDC22AC00C45B78 /* cDemeTopologyNetwork.cc */,
+ 42C27C830FDC22AC00C45B78 /* cDemeTopologyNetwork.h */,
702D4EFC08DA5341007BA469 /* cEnvironment.cc */,
702D4EF508DA5328007BA469 /* cEnvironment.h */,
70CA6EB208DB7F8200068AC2 /* cFitnessMatrix.cc */,
@@ -2180,6 +2192,8 @@
70447CA80F83DB5600E1BF72 /* cBirthMateSelectHandler.cc in Sources */,
70447CAC0F83DBC100E1BF72 /* cBirthDemeHandler.cc in Sources */,
7020828F0FB9F2DF00637AD6 /* cBitArray.cc in Sources */,
+ 42C27C840FDC22AC00C45B78 /* cDemeNetwork.cc in Sources */,
+ 42C27C870FDC22AC00C45B78 /* cDemeTopologyNetwork.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: development/CMakeLists.txt
===================================================================
--- development/CMakeLists.txt 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/CMakeLists.txt 2009-06-07 16:52:14 UTC (rev 3298)
@@ -239,6 +239,8 @@
${MAIN_DIR}/cBirthNeighborhoodHandler.cc
${MAIN_DIR}/cBirthSelectionHandler.cc
${MAIN_DIR}/cDeme.cc
+ ${MAIN_DIR}/cDemeNetwork.cc
+ ${MAIN_DIR}/cDemeTopologyNetwork.cc
${MAIN_DIR}/cDemeCellEvent.cc
${MAIN_DIR}/cEnvironment.cc
${MAIN_DIR}/cEventList.cc
Modified: development/source/actions/PopulationActions.cc
===================================================================
--- development/source/actions/PopulationActions.cc 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/source/actions/PopulationActions.cc 2009-06-07 16:52:14 UTC (rev 3298)
@@ -1863,7 +1863,7 @@
/*! Deme fitness function, to be overriden by specific types of deme competition.
*/
- virtual double Fitness(const cDeme& deme) = 0;
+ virtual double Fitness(cDeme& deme) = 0;
};
@@ -1929,6 +1929,27 @@
};
+/*! Competes demes based on the networks they've constructed.
+ */
+class cActionCompeteDemesByNetwork : public cAbstractCompeteDemes {
+public:
+ //! Constructor.
+ cActionCompeteDemesByNetwork(cWorld* world, const cString& args) : cAbstractCompeteDemes(world, args) {
+ }
+
+ //! Destructor.
+ virtual ~cActionCompeteDemesByNetwork() { }
+
+ //! Retrieve this class's description.
+ static const cString GetDescription() { return "No arguments."; }
+
+ //! Calculate the current fitness of this deme.
+ virtual double Fitness(cDeme& deme) {
+ return deme.GetNetwork().Fitness();
+ }
+};
+
+
/*! This class contains methods that are useful for consensus-related problems.
*/
class ConsensusSupport {
@@ -1999,7 +2020,7 @@
static const cString GetDescription() { return "Arguments: [int compete_period=100 [int replace_number=0]]"; }
//! Calculate the current fitness of this deme.
- virtual double Fitness(const cDeme& deme) {
+ virtual double Fitness(cDeme& deme) {
return max_support(deme).first + 1;
}
@@ -2070,7 +2091,7 @@
return "Competes demes according to the number of times a given task has been completed within that deme";
}
- virtual double Fitness(const cDeme& deme) {
+ virtual double Fitness(cDeme& deme) {
double fitness = pow(deme.GetCurTaskExeCount()[_task_num], 2.0);///deme.GetInjectedCount());
if (fitness == 0.0) fitness = 0.1;
return fitness;
@@ -2109,7 +2130,7 @@
return "Competes demes according to the number of times a given task has been completed within that deme and the efficiency with which it was done";
}
- virtual double Fitness(const cDeme& deme) {
+ virtual double Fitness(cDeme& deme) {
double energy_used = _initial_deme_energy - deme.CalculateTotalEnergy();
double fitness =
pow(deme.GetCurTaskExeCount()[_task_num] * (_initial_deme_energy/energy_used),2);
@@ -2132,7 +2153,7 @@
return "Competes demes according to the distribution of energy among the organisms";
}
- virtual double Fitness(const cDeme& deme) {
+ virtual double Fitness(cDeme& deme) {
const int numcells = deme.GetSize();
double min_energy = -1;
@@ -2224,7 +2245,7 @@
/*! Calculate the fitness based on how well the organisms in this deme have
synchronized their flashes.
*/
- virtual double Fitness(const cDeme& deme) {
+ virtual double Fitness(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.
@@ -2295,7 +2316,7 @@
static const cString GetDescription() { return "No Arguments"; }
//! Calculate fitness based on how well organisms have spread throughout phase-space.
- virtual double Fitness(const cDeme& deme) {
+ virtual double Fitness(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.
@@ -2330,7 +2351,7 @@
static const cString GetDescription() { return "No Arguments"; }
- double Fitness(const cDeme& deme) {
+ double Fitness(cDeme& deme) {
double eventsKilled = static_cast<double>(deme.GetEventsKilled());
double totalEvents = static_cast<double>(deme.GetEventsTotal());
double energyRemaining = deme.CalculateTotalEnergy();
@@ -3300,6 +3321,7 @@
action_lib->Register<cAbstractCompeteDemes_AttackKillAndEnergyConserve>("CompeteDemes_AttackKillAndEnergyConserve");
action_lib->Register<cAssignRandomCellData>("AssignRandomCellData");
+ action_lib->Register<cActionCompeteDemesByNetwork>("CompeteDemesByNetwork");
action_lib->Register<cActionIteratedConsensus>("IteratedConsensus");
action_lib->Register<cActionSynchronization>("Synchronization");
action_lib->Register<cActionDesynchronization>("Desynchronization");
Modified: development/source/actions/PrintActions.cc
===================================================================
--- development/source/actions/PrintActions.cc 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/source/actions/PrintActions.cc 2009-06-07 16:52:14 UTC (rev 3298)
@@ -107,6 +107,7 @@
STATS_OUT_FILE(PrintDemeTreatableCount, deme_treatable.dat );
STATS_OUT_FILE(PrintDemeCompetitionData, deme_compete.dat);
+STATS_OUT_FILE(PrintDemeNetworkData, deme_network.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 );
Modified: development/source/defs.h
===================================================================
--- development/source/defs.h 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/source/defs.h 2009-06-07 16:52:14 UTC (rev 3298)
@@ -46,6 +46,12 @@
#ifndef FATAL_WARNINGS
#define FATAL_WARNINGS 0
#endif
+/* By default, Boost is not available. To enable Boost, either modify your environment,
+ alter your build settings, or change this value -- BUT BE CAREFUL NOT TO CHECK IT IN LIKE THAT!
+ */
+#ifndef BOOST_IS_AVAILABLE
+#define BOOST_IS_AVAILABLE 0
+#endif
// #define SPECIES_TEST
Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/source/main/cAvidaConfig.h 2009-06-07 16:52:14 UTC (rev 3298)
@@ -334,8 +334,6 @@
CONFIG_ADD_VAR(DEMES_PROTECTION_POINTS, int, 0, "The number of points a deme receives for each suicide.");
CONFIG_ADD_VAR(POINT_DECAY_PERCENT, int, 0, "The percentage of points decayed each time cActionDecayPoints is called.");
-
-
CONFIG_ADD_GROUP(REPRODUCTION_GROUP, "Birth and Death");
CONFIG_ADD_VAR(BIRTH_METHOD, int, 0, "Which organism should be replaced on birth?\n0 = Random organism in neighborhood\n1 = Oldest in neighborhood\n2 = Largest Age/Merit in neighborhood\n3 = None (use only empty cells in neighborhood)\n4 = Random from population (Mass Action)\n5 = Oldest in entire population\n6 = Random within deme\n7 = Organism faced by parent\n8 = Next grid cell (id+1)\n9 = Largest energy used in entire population\n10 = Largest energy used in neighborhood");
CONFIG_ADD_VAR(PREFER_EMPTY, int, 1, "Give empty cells preference in offsping placement?");
@@ -642,11 +640,15 @@
CONFIG_ADD_VAR(SPECIALISTS, int, 0, "0=generalists allowed\n1=only specialists");
CONFIG_ADD_VAR(STRING_AMOUNT_CAP, int, -1, "-1=no cap on string amounts\n#=CAP");
CONFIG_ADD_VAR(MATCH_ALREADY_PRODUCED, int, 0, "0=off\n1=on");
-
CONFIG_ADD_GROUP(GROUP_FORMATION_GROUP, "Group Formation Settings");
CONFIG_ADD_VAR(USE_FORM_GROUPS, bool, 0, "Enable organisms to form groups. 0/1 (off/on)");
-
+
+ // -------- Deme network config options --------
+ CONFIG_ADD_VAR(DEME_NETWORK_TYPE, int, 0, "0=topology, structure of network determines fitness.");
+ CONFIG_ADD_VAR(DEME_NETWORK_REQUIRES_CONNECTEDNESS, int, 1, "Whether the deme's network must be connected before an actual fitness is calculated.");
+ CONFIG_ADD_VAR(DEME_NETWORK_TOPOLOGY_FITNESS, int, 0, "Network measure used to determine fitness; see cDemeTopologyNetwork.h.");
+
#endif
inline void Load(const cString& filename) { Load(filename, false); }
Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/source/main/cDeme.cc 2009-06-07 16:52:14 UTC (rev 3298)
@@ -36,6 +36,22 @@
#include "cOrgMovementPredicate.h"
#include "cDemePredicate.h"
+/*! Constructor
+ */
+cDeme::cDeme() : _id(0), width(0), replicateDeme(false), treatable(false), cur_birth_count(0), last_birth_count(0), cur_org_count(0), last_org_count(0), injected_count(0), birth_count_perslot(0),
+_age(0), generation(0), total_org_energy(0.0),
+time_used(0), gestation_time(0), cur_normalized_time_used(0.0), last_normalized_time_used(0.0),
+MSG_sendFailed(0), MSG_dropped(0), MSG_SuccessfullySent(0), MSG_sent(0), energyInjectedIntoOrganisms(0.0), energyRemainingInDemeAtReplication(0.0), total_energy_testament(0.0),
+eventsTotal(0), eventsKilled(0), eventsKilledThisSlot(0), eventKillAttempts(0), eventKillAttemptsThisSlot(0),
+consecutiveSuccessfulEventPeriods(0), sleeping_count(0),
+avg_founder_generation(0.0), generations_per_lifetime(0.0),
+deme_resource_count(0), m_germline_genotype_id(0), points(0), migrations_out(0), migrations_in(0), suicides(0), m_network(0) {
+}
+
+cDeme::~cDeme() {
+ if(m_network) delete m_network;
+}
+
void cDeme::Setup(int id, const tArray<int> & in_cells, int in_width, cWorld* world)
{
_id = id;
@@ -236,6 +252,17 @@
++_age;
}
+
+/*! Called when an organism living in a cell in this deme is about to be killed.
+
+ This method is called from cPopulation::KillOrganism().
+ */
+void cDeme::OrganismDeath(cPopulationCell& cell) {
+ // Clean up this deme's network, if we have one.
+ if(IsNetworkInitialized()) { m_network->OrganismDeath(cell); }
+}
+
+
void cDeme::Reset(bool resetResources, double deme_energy)
{
double additional_resource = 0.0;
@@ -295,6 +322,11 @@
if (resetResources) {
deme_resource_count.ReinitializeResources(additional_resource);
}
+ // Instead of polluting cDemeNetwork with Resets, we're just going to delete it,
+ // and go ahead and rely on lazy initialization to fill this back in.
+ if(m_network) {
+ delete m_network;
+ }
}
@@ -904,3 +936,11 @@
return false;
} //End cDeme::IsTreatableAtAge()
+
+
+/*! Retrieve the network object, initializing it as needed.
+ */
+cDemeNetwork& cDeme::GetNetwork() {
+ InitNetworkCreation();
+ return *m_network;
+}
Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/source/main/cDeme.h 2009-06-07 16:52:14 UTC (rev 3298)
@@ -31,6 +31,7 @@
#include "cGermline.h"
#include "cPhenotype.h"
#include "cMerit.h"
+#include "cDemeNetwork.h"
#include "tArray.h"
#include "tVector.h"
#include "cResourceCount.h"
@@ -141,17 +142,12 @@
unsigned int migrations_in;
unsigned int suicides;
-
public:
- cDeme() : _id(0), width(0), replicateDeme(false), treatable(false), cur_birth_count(0), last_birth_count(0), cur_org_count(0), last_org_count(0), injected_count(0), birth_count_perslot(0),
- _age(0), generation(0), total_org_energy(0.0),
- time_used(0), gestation_time(0), cur_normalized_time_used(0.0), last_normalized_time_used(0.0),
- MSG_sendFailed(0), MSG_dropped(0), MSG_SuccessfullySent(0), MSG_sent(0), energyInjectedIntoOrganisms(0.0), energyRemainingInDemeAtReplication(0.0), total_energy_testament(0.0),
- eventsTotal(0), eventsKilled(0), eventsKilledThisSlot(0), eventKillAttempts(0), eventKillAttemptsThisSlot(0),
- consecutiveSuccessfulEventPeriods(0), sleeping_count(0),
- avg_founder_generation(0.0), generations_per_lifetime(0.0),
- deme_resource_count(0), m_germline_genotype_id(0), points(0), migrations_out(0), migrations_in(0), suicides(0){ ; }
- ~cDeme() { ; }
+ //! Constructor.
+ cDeme();
+
+ //! Destructor.
+ ~cDeme();
void Setup(int id, const tArray<int>& in_cells, int in_width = -1, cWorld* world = NULL);
@@ -255,9 +251,10 @@
// -= Update support =-
//! Called once, at the end of every update.
void ProcessUpdate();
- /*! Returns the age of this deme, updates. Age is defined as the number of
- updates since the last time Reset() was called. */
+ //! Returns the age of this deme in updates, where age is defined as the number of updates since the last time Reset() was called.
int GetAge() const { return _age; }
+ //! Called when an organism living in a cell in this deme is about to be killed.
+ void OrganismDeath(cPopulationCell& cell);
const cResourceCount& GetDemeResourceCount() const { return deme_resource_count; }
double GetSpatialResource(int rel_cellid, int resource_id) const;
@@ -367,6 +364,19 @@
void IncreaseEnergyDonated(double amount) { assert(amount >=0); total_energy_donated += amount; }
void IncreaseEnergyReceived(double amount) { assert(amount >=0); total_energy_received += amount; }
void IncreaseEnergyApplied(double amount) { assert(amount >=0); total_energy_applied += amount; }
+
+ // -= Network creation support =-
+private:
+ //! Lazily-initialized pointer to the network creation support struct.
+ cDemeNetwork* m_network;
+
+ //! Initialize network creation support.
+ inline void InitNetworkCreation() { if(!m_network) m_network = cDemeNetwork::DemeNetworkFactory(m_world, *this); }
+ //! Test for initialization of the network.
+ inline bool IsNetworkInitialized() { return m_network != 0; }
+public:
+ //! Retrieve this deme's network.
+ cDemeNetwork& GetNetwork();
};
#endif
Added: development/source/main/cDemeNetwork.cc
===================================================================
--- development/source/main/cDemeNetwork.cc (rev 0)
+++ development/source/main/cDemeNetwork.cc 2009-06-07 16:52:14 UTC (rev 3298)
@@ -0,0 +1,60 @@
+/*
+ * cDemeNetwork.cpp
+ * Avida
+ *
+ * Copyright 1999-2009 Michigan State University. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "defs.h" // Must be first.
+#include "cDeme.h"
+#include "cDemeNetwork.h"
+#include "cWorld.h"
+#include "cWorldDriver.h"
+// Conditional includes (these use the BGL).
+#if BOOST_IS_AVAILABLE
+#include "cDemeTopologyNetwork.h"
+#endif
+
+/*! Creates a cDemeNetwork object.
+
+ WARNING: This method throws an exception if BOOST_IS_AVAILABLE is not 1, as this
+ indicates at *least* a configuration error.
+
+ WARNING: The returned pointer is owned by the caller (you're responsible for deleting it)!
+ */
+cDemeNetwork* cDemeNetwork::DemeNetworkFactory(cWorld* world, cDeme& deme) {
+#if BOOST_IS_AVAILABLE
+ switch(world->GetConfig().DEME_NETWORK_TYPE.Get()) {
+ case cDemeNetwork::TOPOLOGY: {
+ return new cDemeTopologyNetwork(world, deme);
+ }
+ default: {
+ world->GetDriver().RaiseFatalException(-1, "Unrecognized network type in cDemeNetwork::DemeNetworkFactory().");
+ }
+ }
+#else
+ world->GetDriver().RaiseFatalException(-1, "cDemeNetwork requires Boost; if Boost *is* available, #define BOOST_IS_AVAILABLE in defs.h, and (possibly) update your include path.");
+#endif
+ return 0; // never reached, to quell warnings only.
+}
+
+/*! Constructor.
+ */
+cDemeNetwork::cDemeNetwork(cWorld* world, cDeme& deme) : m_world(world), m_deme(deme) {
+}
Added: development/source/main/cDemeNetwork.h
===================================================================
--- development/source/main/cDemeNetwork.h (rev 0)
+++ development/source/main/cDemeNetwork.h 2009-06-07 16:52:14 UTC (rev 3298)
@@ -0,0 +1,84 @@
+/*
+ * cDemeNetwork.h
+ * Avida
+ *
+ * Copyright 1999-2009 Michigan State University. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef cDemeNetwork_h
+#define cDemeNetwork_h
+
+class cDeme;
+class cWorld;
+class cPopulationCell;
+
+/*! Provides the organisms in a deme with a shared network object.
+
+ The idea here is that the organisms in a deme cooperate to construct a network that
+ meets certain criteria. As of this writing, there's only a single "type" of network
+ that can be manipulated in this way, but others are in the works.
+
+ This can be loosely described as "cooperative construction," but the term "network
+ creation" also applies. See~\cite{knoester2008cooperative} for more details.
+
+ Oh - Because this abstraction relies heavily upon the Boost Graph Library (BGL), we play
+ some tricks so that we don't require that all Avida developers have Boost. If
+ you want to use cDemeNetwork, either change the #define for #define BOOST_IS_AVAILABLE over in
+ defs.h, alter your environment, or change your build settings. And you actually need
+ Boost installed, of course (you'll probably also need to update your include path).
+
+ Because of the different types of networks that are available, there's a factory
+ method, cDemeNetwork::DemeNetworkFactory() that creates cDemeNetworks.
+ */
+class cDemeNetwork {
+public:
+ /*! Available network types.
+
+ TOPOLOGY: Original network-creation approach; each cell is a node, organisms connect to
+ neighboring cells. The network's performance is based on its structure (evaluated as a graph).
+ */
+ enum NetworkType { TOPOLOGY };
+
+ //! Factory method, the only way to create a deme network (pointer is owned by the caller).
+ static cDemeNetwork* DemeNetworkFactory(cWorld* world, cDeme& deme);
+
+ //! Destructor.
+ virtual ~cDemeNetwork() { }
+
+ //! Called at the end of every update.
+ virtual void ProcessUpdate() = 0;
+
+ //! Connect u->v with weight w.
+ virtual void Connect(cPopulationCell& u, cPopulationCell& v, double w=0.0) = 0;
+
+ //! Called when the organism living in cell u dies.
+ virtual void OrganismDeath(cPopulationCell& u) = 0;
+
+ //! Returns a network-defined fitness.
+ virtual double Fitness() const = 0;
+
+protected:
+ //! Constructor, called by derived classes only.
+ cDemeNetwork(cWorld* world, cDeme& deme);
+
+ cWorld* m_world; //!< The world.
+ cDeme& m_deme; //!< The owning deme.
+};
+
+#endif
Added: development/source/main/cDemeNetworkUtils.h
===================================================================
--- development/source/main/cDemeNetworkUtils.h (rev 0)
+++ development/source/main/cDemeNetworkUtils.h 2009-06-07 16:52:14 UTC (rev 3298)
@@ -0,0 +1,172 @@
+/*
+ * cDemeNetworkUtils.h
+ * Avida
+ *
+ * Copyright 1999-2009 Michigan State University. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef cDemeNetworkUtils_h
+#define cDemeNetworkUtils_h
+
+#include <boost/graph/breadth_first_search.hpp>
+#include <boost/graph/connected_components.hpp>
+#include <boost/graph/visitors.hpp>
+#include <numeric>
+#include <vector>
+
+
+//! A BGL breadth-first visitor to calculate distances between vertices.
+template <class Distance>
+class NetworkDistanceVisitor : public boost::bfs_visitor< > {
+public:
+ NetworkDistanceVisitor(Distance d) : distance(d) { }
+ template <class Graph>
+ void tree_edge(typename boost::graph_traits<Graph>::edge_descriptor e, Graph& g) {
+ typename boost::graph_traits<Graph>::vertex_descriptor u, v;
+ u = boost::source(e, g);
+ v = boost::target(e, g);
+ distance[v] = distance[u] + 1;
+ }
+
+private:
+ Distance distance;
+};
+
+//! An ease-of-use typedef to support distance calculations.
+typedef std::vector<size_t> NetworkDistanceVector;
+
+//! An ease-of-use typedef to support distance matrices.
+typedef std::vector<NetworkDistanceVector> NetworkDistanceMatrix;
+
+
+/*! Is the passed-in network connected?
+ */
+template <typename Network>
+bool network_is_connected(const Network& network) {
+ std::vector<int> components(boost::num_vertices(network));
+ return boost::connected_components(network, &components[0]) == 1;
+}
+
+
+/*! Are the two passed-in vertices connected?
+ */
+template <typename Network>
+bool network_2cells_connected(typename Network::vertex_descriptor u, typename Network::vertex_descriptor v, Network& network) {
+ NetworkDistanceVector dv(boost::num_vertices(network),0);
+ NetworkDistanceVisitor<size_t*> visitor(&dv[0]);
+ boost::breadth_first_search(network, u, boost::visitor(visitor));
+
+ // If the distance from u to v is 0, there is no path.
+ return dv[v] != 0;
+}
+
+
+/*! Calculate the distances between each pair of nodes; 0 == not connected.
+ */
+template <typename Network>
+NetworkDistanceMatrix all_pairs_distances(const Network& network) {
+ NetworkDistanceMatrix distance_matrix(boost::num_vertices(network),
+ NetworkDistanceVector(boost::num_vertices(network), 0));
+
+ for(size_t i=0; i<boost::num_vertices(network); ++i) {
+ NetworkDistanceVisitor<size_t*> visitor(&distance_matrix[i][0]);
+ typename Network::vertex_descriptor src = boost::vertices(network).first[i];
+ boost::breadth_first_search(network, src, boost::visitor(visitor));
+ }
+
+ return distance_matrix;
+}
+
+
+/*! Calculate the characteristic path length of the passed-in network. CPL is the
+ mean distance between all pairs of vertices.
+ */
+template <typename Network>
+double characteristic_path_length(const Network& network) {
+ NetworkDistanceMatrix distance_matrix = all_pairs_distances(network);
+
+ // Mean path length from v to v'.
+ double cpl_sum=0.0;
+ for(size_t i=0; i<boost::num_vertices(network); ++i) {
+ cpl_sum += std::accumulate(distance_matrix[i].begin(), distance_matrix[i].end(), 0.0) / (boost::num_vertices(network)-1);
+ }
+
+ return cpl_sum / boost::num_vertices(network);
+}
+
+
+/*! Calculate the diameter of the passed-in network.
+ */
+template <typename Network>
+size_t diameter(const Network& network) {
+ NetworkDistanceMatrix distance_matrix = all_pairs_distances(network);
+
+ // Mean path length from v to v'.
+ NetworkDistanceVector max_distances;
+ for(size_t i=0; i<boost::num_vertices(network); ++i) {
+ max_distances.push_back(*std::max_element(distance_matrix[i].begin(), distance_matrix[i].end()));
+ }
+
+ return *std::max_element(max_distances.begin(), max_distances.end());
+}
+
+
+/*! Calculate the clustering coefficient of the passed-in network. Clustering coefficient
+ is roughly a measure of "how many of my friends are themselves friends?"
+ */
+template <typename Network>
+double clustering_coefficient(const Network& network) {
+ // For each vertex in the graph, calculate the number of edges between vertices in the neighborhood.
+ typename Network::vertex_iterator vi, vi_end;
+ std::vector<double> cluster_coeffs;
+ for(tie(vi,vi_end)=vertices(network); vi!=vi_end; ++vi) {
+ // Get the list of vertices which are in the neighborhood of vi.
+ typedef typename Network::adjacency_iterator adjacency_iterator;
+ std::pair<adjacency_iterator, adjacency_iterator> adjacent = boost::adjacent_vertices(*vi, network);
+ typedef std::set<typename Network::vertex_descriptor> neighborhood;
+ neighborhood neighbors;
+ for(; adjacent.first!=adjacent.second; ++adjacent.first) {
+ neighbors.insert(*adjacent.first);
+ }
+
+ if(neighbors.size() > 1) {
+ // Now, count the edges between vertices in the neighborhood.
+ unsigned int neighborhood_edge_count=0;
+ for(typename neighborhood::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) {
+ typedef typename Network::out_edge_iterator out_edge_iterator;
+ std::pair<out_edge_iterator,out_edge_iterator> oe = out_edges(*i,network);
+ for(; oe.first!=oe.second; ++oe.first) {
+ if(neighbors.find(target(*oe.first,network))!=neighbors.end()) {
+ ++neighborhood_edge_count;
+ }
+ }
+ }
+ neighborhood_edge_count /= 2;
+ cluster_coeffs.push_back((double)neighborhood_edge_count / (neighbors.size()*(neighbors.size()-1)/2));
+ } else {
+ // This used to be 1.0... but, if our neighborhood size is <1, there are zero edges out of a possible 0.
+ cluster_coeffs.push_back(0.0);
+ }
+ }
+
+ // Clustering coefficient:
+ return std::accumulate(cluster_coeffs.begin(), cluster_coeffs.end(), 0.0) / cluster_coeffs.size();
+}
+
+#endif
Added: development/source/main/cDemeTopologyNetwork.cc
===================================================================
--- development/source/main/cDemeTopologyNetwork.cc (rev 0)
+++ development/source/main/cDemeTopologyNetwork.cc 2009-06-07 16:52:14 UTC (rev 3298)
@@ -0,0 +1,141 @@
+/*
+ * cDemeTopologyNetwork.cc
+ * Avida
+ *
+ * Copyright 1999-2009 Michigan State University. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "defs.h" // Must be first.
+#if BOOST_IS_AVAILABLE
+#include "cDemeTopologyNetwork.h"
+#include "cDemeNetworkUtils.h"
+#include "cDeme.h"
+#include "cStats.h"
+#include "cWorld.h"
+#include "cWorldDriver.h"
+
+/*! Constructor.
+ */
+cDemeTopologyNetwork::cDemeTopologyNetwork(cWorld* world, cDeme& deme) : cDemeNetwork(world, deme) {
+}
+
+/*! Connect u->v with weight w.
+ */
+void cDemeTopologyNetwork::Connect(cPopulationCell& u, cPopulationCell& v, double w) {
+}
+
+/*! Returns the fitness of the network, as determined by the DEME_NETWORK_TOPOLOGY_FITNESS config option.
+ */
+double cDemeTopologyNetwork::Fitness() const {
+ // Yay, stats tracking.
+ m_world->GetStats().NetworkTopology(m_network);
+
+ // Are we requiring connectedness before fitness is calculated?
+ if(m_world->GetConfig().DEME_NETWORK_REQUIRES_CONNECTEDNESS.Get()) {
+ // Short-circuit if we don't have all the vertices (cheap!):
+ if((boost::num_vertices(m_network) < (size_t)m_deme.GetSize())
+ // and then check for connectedness:
+ || !network_is_connected(m_network)) {
+ return 0.0;
+ }
+ }
+
+ // We're going to arbitrarily define the maximum number of edges that can exist
+ // in this network to be the number of edges that would be in a fully-connected
+ // network of m_deme.GetSize() number of vertices (Euler's formula).
+ double max_edges = m_deme.GetSize() * (m_deme.GetSize()-1) / 2;
+
+ // Ok, calculate fitness.
+ switch(m_world->GetConfig().DEME_NETWORK_TOPOLOGY_FITNESS.Get()) {
+ case MIN_SIZE: {
+ return pow(max_edges - boost::num_edges(m_network) + 1, 2);
+ }
+ case MIN_DIAMETER: {
+ // Note: we don't need a +1 here (max diameter is less than num_vertices).
+ return pow((double)boost::num_vertices(m_network) - diameter(m_network), 2);
+ }
+ case MIN_CPL: {
+ return pow(0.75*boost::num_vertices(m_network) - characteristic_path_length(m_network) + 1, 2);
+ }
+ case MAX_CC: {
+ return pow(100.0*clustering_coefficient(m_network) + 1, 2);
+ }
+ case MIN_CC: {
+ return pow(100.0 - 100.0*clustering_coefficient(m_network) + 1, 2);
+ }
+ case TGT_CC: {
+ double coeff = clustering_coefficient(m_network);
+ double target_coeff = 0.5;
+
+ // 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)
+ return pow(pow(0.01, abs(target_coeff - coeff))*100, 2);
+ }
+ case CPL_AND_EDGES_1: {
+ // Replicate demes that are connected, and set the merit based on a combination of
+ // characteristic path length and edge count (1):
+ // \[Merit=\Big((CPL_{max}-CPL_{mean}+1) * (L_{max}-L(G)+1)\Big)^2\]
+ return pow((0.75*boost::num_vertices(m_network) - characteristic_path_length(m_network) + 1)
+ * (max_edges - boost::num_edges(m_network) + 1), 2);
+ }
+ case CPL_AND_EDGES_2: {
+ // Replicate demes that are connected, and set the merit based on a combination of
+ // characteristic path length and edge count (2):
+ // \[Merit=(CPL_{max}-CPL_{mean}+1)^2 + (L_{max}-L(G)+1)^2\]
+ return pow(0.75*boost::num_vertices(m_network) - characteristic_path_length(m_network) + 1, 2)
+ + pow(max_edges - boost::num_edges(m_network) + 1.0, 2);
+ }
+ case CPL_AND_EDGES_3: {
+ // Replicate demes that are connected, and set the merit based on a combination of
+ // characteristic path length and edge count, where each is normalized (3):
+ // \[Merit=\Big(100*\frac{CPL_{max}-CPL_{mean}}{CPL_{max}} + 100*\frac{L_{max}-L(G)}{L_{max}}+1\Big)^2\]
+ return pow(100*(0.75*boost::num_vertices(m_network)
+ - characteristic_path_length(m_network)) / (0.75*boost::num_vertices(m_network))
+ + 100*((max_edges - boost::num_edges(m_network)) / max_edges)
+ + 1
+ , 2);
+ }
+ case CPL_AND_EDGES_LADDER_1: {
+ // Replicate demes that are connected, and set the merit to a ladder fitness function
+ // based on CPL and edge count (min edges -> CPL) (~5% error):
+ double source_germline_merit = pow(max_edges - boost::num_edges(m_network) + 1.0, 2);
+ // ~5% error margin...
+ if(boost::num_edges(m_network) <= (boost::num_vertices(m_network) + 2)) {
+ source_germline_merit += pow(0.75*boost::num_vertices(m_network) - characteristic_path_length(m_network) + 1, 2);
+ }
+ return source_germline_merit;
+ }
+ case CPL_AND_EDGES_LADDER_2: {
+ // Replicate demes that are connected, and set the merit to a ladder fitness function
+ // based on CPL and edge count (min CPL -> edges) (error margin):
+ double cpl = characteristic_path_length(m_network);
+ double source_germline_merit = pow(0.75*boost::num_vertices(m_network) - cpl + 1, 2);
+ if((cpl > 3.25) && (cpl < 3.75)) {
+ source_germline_merit += pow(max_edges - boost::num_edges(m_network) + 1.0, 2);
+ }
+ return source_germline_merit;
+ }
+ default: {
+ m_world->GetDriver().RaiseFatalException(-1, "Unrecognized network fitness type in cDemeTopologyNetwork::Fitness().");
+ }
+ }
+ return 0.0;
+}
+
+#endif
Added: development/source/main/cDemeTopologyNetwork.h
===================================================================
--- development/source/main/cDemeTopologyNetwork.h (rev 0)
+++ development/source/main/cDemeTopologyNetwork.h 2009-06-07 16:52:14 UTC (rev 3298)
@@ -0,0 +1,94 @@
+/*
+ * cDemeTopologyNetwork.h
+ * Avida
+ *
+ * Copyright 1999-2009 Michigan State University. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef cDemeTopologyNetwork_h
+#define cDemeTopologyNetwork_h
+
+/* THIS HEADER REQUIRES BOOST */
+#include <boost/graph/adjacency_list.hpp>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cDemeNetwork.h"
+
+class cDeme;
+class cWorld;
+class cPopulationCell;
+
+/*!
+ */
+class cDemeTopologyNetwork : public cDemeNetwork {
+public:
+ enum FitnessType {
+ MIN_SIZE,
+ MIN_DIAMETER,
+ MIN_CPL,
+ MAX_CC,
+ MIN_CC,
+ TGT_CC,
+ CPL_AND_EDGES_1,
+ CPL_AND_EDGES_2,
+ CPL_AND_EDGES_3,
+ CPL_AND_EDGES_LADDER_1,
+ CPL_AND_EDGES_LADDER_2
+ };
+
+ //! The internal vertex properties.
+ struct vertex_properties {
+ vertex_properties() { }
+ vertex_properties(std::pair<int,int> pos, int cell_id) : _x(pos.first), _y(pos.second), _cell_id(cell_id) { }
+ int _x, _y, _cell_id;
+ };
+
+ //! An ease-of-use typedef to support the distributed construction of a network.
+ typedef boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS, vertex_properties> Network;
+
+ //! A map of cell IDs to vertex descriptors.
+ typedef std::map<int, Network::vertex_descriptor> CellVertexMap;
+
+ //! Map of cell IDs to counts.
+ typedef std::map<int, unsigned int> CellCountMap;
+
+ //! Constructor.
+ cDemeTopologyNetwork(cWorld* world, cDeme& deme);
+
+ //! Called at the end of every update.
+ virtual void ProcessUpdate() { }
+
+ //! Connect u->v with weight w.
+ virtual void Connect(cPopulationCell& u, cPopulationCell& v, double w=0.0);
+
+ //! Called when the organism living in cell u dies.
+ virtual void OrganismDeath(cPopulationCell& u) { }
+
+ //! Returns a network-defined fitness.
+ virtual double Fitness() const;
+
+protected:
+ Network m_network; //!< Underlying network model.
+ CellVertexMap m_cv; //!< Map of cell ids to vertex descriptors.
+};
+
+#endif
Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/source/main/cPopulation.cc 2009-06-07 16:52:14 UTC (rev 3298)
@@ -786,8 +786,10 @@
// Update count statistics...
num_organisms--;
- if (deme_array.GetSize() > 0) {
+ // Handle deme updates.
+ if(deme_array.GetSize() > 0) {
deme_array[in_cell.GetDemeID()].DecOrgCount();
+ deme_array[in_cell.GetDemeID()].OrganismDeath(in_cell);
}
genotype->RemoveOrganism();
Modified: development/source/main/cStats.cc
===================================================================
--- development/source/main/cStats.cc 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/source/main/cStats.cc 2009-06-07 16:52:14 UTC (rev 3298)
@@ -2589,3 +2589,11 @@
}
+/*! Print and reset network statistics.
+ */
+void cStats::PrintDemeNetworkData(const cString& filename) {
+ cDataFile& df = m_world->GetDataFile(filename);
+
+ df.WriteComment("Deme network statistics");
+ df.WriteTimeStamp();
+}
Modified: development/source/main/cStats.h
===================================================================
--- development/source/main/cStats.h 2009-06-07 15:51:08 UTC (rev 3297)
+++ development/source/main/cStats.h 2009-06-07 16:52:14 UTC (rev 3298)
@@ -954,7 +954,18 @@
cDoubleSum m_perfect_match_org;
std::map <int, int> m_tags;
-
+// -------- Deme network support --------
+private:
+public:
+ template <typename Network>
+ void NetworkTopology(const Network& network) {
+#if BOOST_IS_AVAILABLE
+#else
+// world->GetDriver().RaiseFatalException(-1, "Cannot track network statistics without Boost in cStats::NetworkTopology().");
+#endif
+ }
+ //! Print network statistics.
+ void PrintDemeNetworkData(const cString& filename);
};
More information about the Avida-cvs
mailing list