[Avida-SVN] r2425 - development/source/main
dknoester at myxo.css.msu.edu
dknoester at myxo.css.msu.edu
Tue Mar 4 18:45:28 PST 2008
Author: dknoester
Date: 2008-03-04 21:45:27 -0500 (Tue, 04 Mar 2008)
New Revision: 2425
Modified:
development/source/main/cAvidaConfig.h
development/source/main/cDeme.cc
development/source/main/cDeme.h
development/source/main/cEnvironment.cc
development/source/main/cPopulation.cc
Log:
Updates to deme replication strategies.
Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h 2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cAvidaConfig.h 2008-03-05 02:45:27 UTC (rev 2425)
@@ -300,7 +300,8 @@
CONFIG_ADD_VAR(DEMES_RESET_RESOURCES, int, 0, "Reset resources in demes on replication. \n0 = reset both demes \n1 = reset target deme \n2 = deme resources remain unchanged\n");
CONFIG_ADD_VAR(DEMES_REPLICATE_SIZE, int, 1, "Number of identical organisms to create or copy from the\nsource deme to the target deme (default=1).");
CONFIG_ADD_VAR(DEMES_PROB_ORG_TRANSFER, double, 0.0, "Probablity of an organism being transferred from the\nsource deme to the target deme (default=0.0).");
- CONFIG_ADD_VAR(DEMES_ORGANISM_PLACEMENT, int, 0, "How organisms are placed during deme replication.\n0=cell-array middle (default).\n1=deme center.\n2=random placement.");
+ CONFIG_ADD_VAR(DEMES_ORGANISM_SELECTION, int, 0, "How organisms are selected for transfer from\nsource to target during deme replication.\n0=random with replacement (default).\n2=sequential.");
+ CONFIG_ADD_VAR(DEMES_ORGANISM_PLACEMENT, int, 0, "How organisms are placed during deme replication.\n0=cell-array middle (default).\n1=deme center.\n2=random placement.\n3=sequential.");
CONFIG_ADD_VAR(DEMES_ORGANISM_FACING, int, 0, "How organisms are facing during deme replication.\n0=unchanged (default).\n1=northwest.\n2=random.");
CONFIG_ADD_VAR(DEMES_MAX_AGE, int, 500, "The maximum age of a deme (in updates) to be\nused for age-based replication (default=500).");
CONFIG_ADD_VAR(DEMES_MAX_BIRTHS, int, 100, "The maximum number of births that can occur\nwithin a deme; used with birth-count\nreplication (default=100).");
Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc 2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cDeme.cc 2008-03-05 02:45:27 UTC (rev 2425)
@@ -126,6 +126,18 @@
}
+/*! Check every cell in this deme for a living organism. If found, kill it. */
+void cDeme::KillAll()
+{
+ for (int i=0; i<GetSize(); ++i) {
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(cell_ids[i]);
+ if(cell.IsOccupied()) {
+ m_world->GetPopulation().KillOrganism(cell);
+ }
+ }
+}
+
+
/*! Replacing this deme's germline has the effect of changing the deme's lineage.
There's still some work to do here; the lineage labels of the Genomes in the germline
are all messed up.
Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h 2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cDeme.h 2008-03-05 02:45:27 UTC (rev 2425)
@@ -80,6 +80,8 @@
void Reset(bool resetResources = true);
void Reset(double deme_energy, bool resetResources = true); //! used to pass energy to offspring deme
+ //! Kills all organisms currently in this deme.
+ void KillAll();
int GetBirthCount() const { return birth_count; }
void IncBirthCount() { birth_count++; }
Modified: development/source/main/cEnvironment.cc
===================================================================
--- development/source/main/cEnvironment.cc 2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cEnvironment.cc 2008-03-05 02:45:27 UTC (rev 2425)
@@ -1032,7 +1032,7 @@
break;
case nReaction::PROCTYPE_MULT:
result.MultBonus(bonus);
- // Not quite sure what to do to the deme_bonus for this process:type.
+ // @todo Not quite sure what to do to the deme_bonus for this process:type.
break;
case nReaction::PROCTYPE_POW:
result.MultBonus(pow(2.0, bonus));
Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc 2008-03-05 00:35:05 UTC (rev 2424)
+++ development/source/main/cPopulation.cc 2008-03-05 02:45:27 UTC (rev 2425)
@@ -113,15 +113,18 @@
num_demes = 1; // One population == one deme.
}
- // Error checking for demes vs. non-demes setup.
-
- // The following combination of options creates an infinite rotate-loop.
+ // The following combination of options creates an infinite rotate-loop:
assert(!((m_world->GetConfig().DEMES_ORGANISM_PLACEMENT.Get()==0)
&& (m_world->GetConfig().DEMES_ORGANISM_FACING.Get()==1)
&& (m_world->GetConfig().WORLD_GEOMETRY.Get()==1)));
- // Not yet supported:
- assert(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()==1);
+ // Incompatible deme replication strategies:
+ assert(!(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()
+ && (m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get()>0.0)));
+ assert(!(m_world->GetConfig().DEMES_USE_GERMLINE.Get()
+ && (m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get()>0.0)));
+ assert(!(m_world->GetConfig().DEMES_USE_GERMLINE.Get()
+ && (m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()>1)));
#ifdef DEBUG
const int birth_method = m_world->GetConfig().BIRTH_METHOD.Get();
@@ -151,6 +154,9 @@
const int deme_size = deme_size_x * deme_size_y;
deme_array.Resize(num_demes);
+ // Broken setting:
+ assert(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get() <= deme_size);
+
// Setup the deme structures.
tArray<int> deme_cells(deme_size);
for (int deme_id = 0; deme_id < num_demes; deme_id++) {
@@ -1221,7 +1227,7 @@
}
// The source's merit must be transferred to the target, and then the source has
- // rotate its merits.
+ // to rotate its heritable merit to its current merit.
target_deme.UpdateDemeMerit(source_deme);
source_deme.UpdateDemeMerit();
@@ -1247,9 +1253,11 @@
// Reset both demes, in case they have any cleanup work to do.
if(m_world->GetConfig().ENERGY_ENABLED.Get()) {
+ // Transfer energy from source to target if we're using the energy model.
source_deme.Reset(parent_deme_energy, source_deme_resource_reset);
target_deme.Reset(offspring_deme_energy, target_deme_resource_reset);
} else {
+ // Default; reset both source and target.
source_deme.Reset(source_deme_resource_reset);
target_deme.Reset(target_deme_resource_reset);
}
@@ -1268,13 +1276,7 @@
*/
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)]);
- }
-
- // Sanity.
- assert(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get() < deme.GetSize());
- assert(m_world->GetConfig().DEMES_REPLICATE_SIZE.Get() > 0);
+ deme.KillAll();
// Create the specified number of organisms in the deme.
for(int i=0; i< m_world->GetConfig().DEMES_REPLICATE_SIZE.Get(); ++i) {
@@ -1290,97 +1292,118 @@
*/
void cPopulation::SeedDeme(cDeme& source_deme, cDeme& target_deme) {
cRandom& random = m_world->GetRandom();
-
+
+ // Check to see if we're doing probabilistic organism replication from source
+ // to target deme.
if(m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get() == 0.0) {
- // Select a random organism from the source. All we need to do here is get a
- // genome and a lineage label.
- cOrganism* seed = 0;
- while(seed == 0) {
- int cellid = source_deme.GetCellID(random.GetUInt(source_deme.GetSize()));
- if(cell_array[cellid].IsOccupied()) {
- seed = cell_array[cellid].GetOrganism();
+ // Here's the idea: store up a list of the genotypes from the source that we
+ // need to copy to the target. Then clear both the source and target demes,
+ // and finally inject organisms from the saved genotypes into both the source
+ // and target.
+ //
+ // This is a little ugly - Note that if you're trying to get something a little
+ // more random, there's also the "fruiting body" option (DEMES_PROB_ORG_TRANSFER),
+ // and the even less contrived MIGRATION_RATE.
+ //
+ // @todo In order to get lineage tracking to work again, we need to change this
+ // from tracking cGenomes to tracking cGenotypes. But that's a pain,
+ // because the cGenotype* from cOrganism::GetGenotype may not live after
+ // a call to cDeme::KillAll.
+ std::vector<std::pair<cGenome,int> > xfer; // List of genomes we're going to transfer.
+
+ switch(m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get()) {
+ case 0: { // Random w/ replacement (meaning, we don't prevent the same genotype from
+ // being selected more than once).
+ while((int)xfer.size() < m_world->GetConfig().DEMES_REPLICATE_SIZE.Get()) {
+ int cellid = source_deme.GetCellID(random.GetUInt(source_deme.GetSize()));
+ if(cell_array[cellid].IsOccupied()) {
+ xfer.push_back(std::make_pair(cell_array[cellid].GetOrganism()->GetGenome(),
+ cell_array[cellid].GetOrganism()->GetLineageLabel()));
+ }
+ }
+ break;
}
+ case 1: { // Sequential selection, from the beginning. Good with DEMES_ORGANISM_PLACEMENT=3.
+ for(int i=0; i<m_world->GetConfig().DEMES_REPLICATE_SIZE.Get(); ++i) {
+ int cellid = source_deme.GetCellID(i);
+ if(cell_array[cellid].IsOccupied()) {
+ xfer.push_back(std::make_pair(cell_array[cellid].GetOrganism()->GetGenome(),
+ cell_array[cellid].GetOrganism()->GetLineageLabel()));
+ }
+ }
+ break;
+ }
+ default: {
+ cout << "Undefined value (" << m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get()
+ << ") for DEMES_ORGANISM_SELECTION." << endl;
+ exit(1);
+ }
}
+
+ // We'd better have at *least* one genome.
+ assert(xfer.size()>0);
- cGenome genome = seed->GetGenome();
- int lineage = seed->GetLineageLabel();
- seed = 0; // We're done with the seed organism.
+ // Clear the demes.
+ source_deme.KillAll();
+ target_deme.KillAll();
- // Kill all the organisms in the source and target demes.
- for (int i=0; i<target_deme.GetSize(); i++) {
- KillOrganism(cell_array[target_deme.GetCellID(i)]);
- }
- for (int i=0; i<source_deme.GetSize(); i++) {
- KillOrganism(cell_array[source_deme.GetCellID(i)]);
- }
+ // And now populate the source and target.
+ int j=0;
+ for(std::vector<std::pair<cGenome,int> >::iterator i=xfer.begin(); i!=xfer.end(); ++i, ++j) {
+ int cellid = DemeSelectInjectionCell(source_deme, j);
+ InjectGenome(cellid, i->first, i->second);
+ DemePostInjection(source_deme, cell_array[cellid]);
- // Repopulation the source.
- for(int i=0; i< m_world->GetConfig().DEMES_REPLICATE_SIZE.Get(); ++i) {
- int cellid = DemeSelectInjectionCell(source_deme, i);
- InjectGenome(cellid, genome, lineage);
- DemePostInjection(source_deme, cell_array[cellid]);
+ cellid = DemeSelectInjectionCell(target_deme, j);
+ InjectGenome(cellid, i->first, i->second);
+ DemePostInjection(target_deme, cell_array[cellid]);
}
+ } else {
+ // Probabilistic organism replication -- aka "fruiting body."
+ //
+ // This is a little different than the other deme replication styles. First,
+ // in a fruiting body we don't reset the individuals in the source deme; we
+ // leave them unchanged. The idea is that we're pulling random organisms
+ // out, and letting the source continue.
- // And repopulate the target.
- for(int i=0; i< m_world->GetConfig().DEMES_REPLICATE_SIZE.Get(); ++i) {
- int cellid = DemeSelectInjectionCell(target_deme, i);
- InjectGenome(cellid, genome, lineage);
- DemePostInjection(target_deme, cell_array[cellid]);
- }
- } else {
- assert(m_world->GetConfig().DEMES_USE_GERMLINE.Get() != 1);
- vector< pair<cGenome, int> > fruiting_body;
-
// Kill all the organisms in the target deme.
- for (int i=0; i<target_deme.GetSize(); i++) {
- KillOrganism(cell_array[target_deme.GetCellID(i)]);
- }
+ target_deme.KillAll();
- for(int i = 0; i < source_deme.GetSize(); i++) {
+ // Check all the organisms in the source deme to see if they get transferred
+ // to the target.
+ for(int i=0,j=0; i<source_deme.GetSize(); ++i) {
int source_cellid = source_deme.GetCellID(i);
- if(cell_array[source_cellid].IsOccupied() && random.GetDouble(0.0, 1.0) < m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get()) {
- // save genome and lineage label of organism being transfered
+ // Does this organism stay with the source or move to the target?
+ if(cell_array[source_cellid].IsOccupied() && random.P(m_world->GetConfig().DEMES_PROB_ORG_TRANSFER.Get())) {
+ // Moves to the target; save the genome and lineage label of organism being transfered.
cOrganism* seed = cell_array[source_cellid].GetOrganism();
cGenome genome = seed->GetGenome();
int lineage = seed->GetLineageLabel();
seed = 0; // We're done with the seed organism.
- // remove organism from source deme
+ // Remove this organism from the source.
KillOrganism(cell_array[source_cellid]);
- // inject into target deme
- int target_cellid = DemeSelectInjectionCell(target_deme, i);
+ // And inject it into target deme.
+ int target_cellid = DemeSelectInjectionCell(target_deme, j++);
InjectGenome(target_cellid, genome, lineage);
DemePostInjection(target_deme, cell_array[target_cellid]);
- }
-
- // collect genome and lineage label of organisms that remain in source deme
- if(cell_array[source_cellid].IsOccupied()) {
- cOrganism* seed = cell_array[source_cellid].GetOrganism();
- fruiting_body.push_back(make_pair(seed->GetGenome(), seed->GetLineageLabel()));
- seed = 0;
-
- // kill remaining organisms
- KillOrganism(cell_array[source_cellid]);
- }
+ }
+ //else {
+ // Stays with the source. Nothing to do here yet.
+ //}
}
-
- int i = 0;
- // reseed source deme
- for(vector< pair<cGenome, int> >::iterator iter = fruiting_body.begin(); iter < fruiting_body.end(); iter++) {
- // inject back into source deme
- int source_offspring_cellid = DemeSelectInjectionCell(source_deme, i);
- InjectGenome(source_offspring_cellid, (*iter).first, (*iter).second);
- DemePostInjection(source_deme, cell_array[source_offspring_cellid]);
- i++;
- }
}
}
/*! Helper method that determines the cell into which an organism will be placed.
Respects all of the different placement options that are relevant for deme replication.
+
+ at param sequence The number of times DemeSelectInjectionCell has been called on this deme
+ already. Used for replicating multiple organisms from the source to the
+ target deme in a sensible fashion.
*/
int cPopulation::DemeSelectInjectionCell(cDeme& deme, int sequence) {
int cellid = -1;
@@ -1403,7 +1426,11 @@
cellid = deme.GetCellID(m_world->GetRandom().GetInt(0, deme.GetSize()-1));
}
break;
- }
+ }
+ case 3: { // Sequential.
+ cellid = deme.GetCellID(sequence);
+ break;
+ }
default: {
assert(false); // Shouldn't ever reach here.
}
More information about the Avida-cvs
mailing list