[Avida-SVN] r2804 - in branches/movement/source: actions analyze cpu main script
grabow38 at myxo.css.msu.edu
grabow38 at myxo.css.msu.edu
Mon Sep 29 05:20:09 PDT 2008
Author: grabow38
Date: 2008-09-29 08:20:07 -0400 (Mon, 29 Sep 2008)
New Revision: 2804
Modified:
branches/movement/source/actions/EnvironmentActions.cc
branches/movement/source/actions/PopulationActions.cc
branches/movement/source/actions/PrintActions.cc
branches/movement/source/analyze/cAnalyze.cc
branches/movement/source/analyze/cAnalyze.h
branches/movement/source/analyze/cAnalyzeGenotype.h
branches/movement/source/cpu/cHardwareBase.cc
branches/movement/source/cpu/cHardwareBase.h
branches/movement/source/cpu/cHardwareCPU.cc
branches/movement/source/cpu/cHardwareCPU.h
branches/movement/source/cpu/cHardwareManager.cc
branches/movement/source/cpu/cInstSet.h
branches/movement/source/cpu/cTestCPUInterface.h
branches/movement/source/main/cAvidaConfig.h
branches/movement/source/main/cDeme.h
branches/movement/source/main/cOrgInterface.h
branches/movement/source/main/cOrgMessagePredicate.h
branches/movement/source/main/cOrganism.cc
branches/movement/source/main/cOrganism.h
branches/movement/source/main/cPopulation.cc
branches/movement/source/main/cPopulationInterface.cc
branches/movement/source/main/cPopulationInterface.h
branches/movement/source/main/cStats.cc
branches/movement/source/main/cStats.h
branches/movement/source/script/AvidaScript.h
branches/movement/source/script/cASNativeObject.h
branches/movement/source/script/cDirectInterpretASTVisitor.cc
branches/movement/source/script/cDirectInterpretASTVisitor.h
Log:
Merged development changes r2771:2803 into branches/movement.
Modified: branches/movement/source/actions/EnvironmentActions.cc
===================================================================
--- branches/movement/source/actions/EnvironmentActions.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/actions/EnvironmentActions.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -582,9 +582,11 @@
void Process(cAvidaContext& ctx)
{
int time = m_world->GetStats().GetUpdate();
- double m_res_count = -1*(tanh((time-182500)/50000)+1)*(0.5*sin(time/58.091)+0.5)+1;
+ double m_res_count = -m_scale*(tanh((time-182500)/50000)+1)*(0.5*sin(time/58.091)+0.5)+1;
if(m_res_count < 0.0)
m_res_count = 0.0;
+ if(m_res_count < 0.0)
+ m_res_count = 0.0;
cResource* res = m_world->GetEnvironment().GetResourceLib().GetResource(m_res_name);
if (res != NULL)
m_world->GetPopulation().SetResource(res->GetID(), m_res_count * m_scale);
@@ -614,9 +616,11 @@
void Process(cAvidaContext& ctx)
{
int time = m_world->GetStats().GetUpdate();
- double m_res_count = -1*(tanh((time-1825000)/500000)+1)*(0.5*sin(time/58.091)+0.5)+1;
+ double m_res_count = -m_scale*(tanh((time-1825000)/500000)+1)*(0.5*sin(time/58.091)+0.5)+1;
if(m_res_count < 0.0)
m_res_count = 0.0;
+ if(m_res_count < 0.0)
+ m_res_count = 0.0;
cResource* res = m_world->GetEnvironment().GetResourceLib().GetResource(m_res_name);
if (res != NULL)
m_world->GetPopulation().SetResource(res->GetID(), m_res_count* m_scale);
Modified: branches/movement/source/actions/PopulationActions.cc
===================================================================
--- branches/movement/source/actions/PopulationActions.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/actions/PopulationActions.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -30,13 +30,17 @@
#include "cGenome.h"
#include "cGenomeUtil.h"
#include "cHardwareManager.h"
+#include "cOrgMessagePredicate.h"
#include "cPopulation.h"
#include "cPopulationCell.h"
#include "cStats.h"
#include "cWorld.h"
#include "cOrganism.h"
+#include <map>
+#include <set>
+
/*
Injects a single organism into the population.
@@ -1197,6 +1201,25 @@
};
+/*! This action enables the tracking of all messages that are sent in each deme. */
+class cActionTrackAllMessages : public cAction {
+public:
+ cActionTrackAllMessages(cWorld* world, const cString& args) : cAction(world, args) { }
+
+ static const cString GetDescription() { return "No Arguments"; }
+
+ void Process(cAvidaContext& ctx) {
+ s_pred = new cOrgMessagePred_AllData(m_world);
+ m_world->GetStats().AddMessagePredicate(s_pred);
+ }
+
+private:
+ static cOrgMessagePred_AllData* s_pred;
+};
+
+cOrgMessagePred_AllData* cActionTrackAllMessages::s_pred=0;
+
+
/*
Compete all of the demes using a basic genetic algorithm approach. Fitness
of each deme is determined differently depending on the competition_type:
@@ -1230,8 +1253,70 @@
};
+/*! Assign a random identifier to the data for each cell and save those IDs for later
+ use, respecting deme boundaries.
+
+ This is a little hackish; feel free to modify.
+ */
+class cAssignRandomCellData : public cAction {
+public:
+ typedef std::map<int, std::set<int> > DataMap;
+
+ cAssignRandomCellData(cWorld* world, const cString& args) : cAction(world, args) { }
+
+ virtual ~cAssignRandomCellData() { }
+
+ static const cString GetDescription() { return "No Arguments"; }
+
+ virtual void Process(cAvidaContext& ctx) {
+ deme_to_id.clear();
+ for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+ cDeme& deme = m_world->GetPopulation().GetDeme(i);
+ for(int j=0; j<deme.GetSize(); ++j) {
+ // Assign random data to each cell:
+ int d = m_world->GetRandom().GetInt(INT_MAX);
+ deme.GetCell(j).SetCellData(d);
+ // Save that data by deme in the map:
+ deme_to_id[deme.GetID()].insert(d);
+ }
+ }
+ }
+
+ static bool IsCellDataInDeme(int data, const cDeme& deme) {
+ DataMap::iterator i = deme_to_id.find(deme.GetID());
+ return i->second.find(data) != i->second.end();
+ }
+
+ static void ReplaceCellData(int old_data, int new_data, const cDeme& deme) {
+ // Find all cells in the deme that hold the old data, and replace it with the new.
+ for(int i=0; i<deme.GetSize(); ++i) {
+ if(deme.GetCell(i).GetCellData() == old_data) {
+ deme.GetCell(i).SetCellData(new_data);
+ }
+ }
+ // Update the data map.
+ DataMap::iterator i = deme_to_id.find(deme.GetID());
+ i->second.erase(old_data);
+ i->second.insert(new_data);
+ }
+
+ static const std::set<int>& GetDataInDeme(const cDeme& deme) {
+ return deme_to_id[deme.GetID()];
+ }
+
+protected:
+ static std::map<int, std::set<int> > deme_to_id; //!< Map of deme ID -> set of all cell data in that deme.
+};
+//! Definition for static data.
+cAssignRandomCellData::DataMap cAssignRandomCellData::deme_to_id;
+
+
/*! An abstract base class to ease the development of new deme competition fitness functions.
+
+ This base class does the bookkeeping associated with deme competitions, including calling a virtual
+ function to calculate the fitness of each deme at the right time, collecting those fitness values in
+ a vector, and finally invoking the deme competition.
*/
class cAbstractCompeteDemes : public cAction {
public:
@@ -1264,6 +1349,288 @@
virtual double Fitness(const cDeme& deme) = 0;
};
+
+/*! An abstract base class to ease the development of new deme competition fitness functions
+ that require a per-update monitoring of each deme.
+
+ The idea here is that in addition to normal deme competition, we also have periodic housekeeping to do.
+ This housekeeping may or may not influence the final fitness value (once deme competition is triggered).
+
+ In the events file, when using any deme competition strategy that uses cAbstractMonitoringCompeteDemes,
+ the execution of the event corresponds to when the Update(...) method will be called, while the integer parameter
+ to the event is the period (in updates) of deme competition. So this:
+
+ u 1:1:end SomeFormOfCompeteDemes 400
+
+ will call Update(...) every update, but only calls Fitness(...) every 400 updates.
+
+ WARNING: The compete_period argument MUST be an even multiple of the update period!
+ If it isn't, competition won't ever be triggered. We're not preventing this, 'cause
+ there might be good reasons you'd want that...
+ */
+class cAbstractMonitoringCompeteDemes : public cAbstractCompeteDemes {
+public:
+ //! Constructor.
+ cAbstractMonitoringCompeteDemes(cWorld* world, const cString& args) : cAbstractCompeteDemes(world, args), _compete_period(100) {
+ if(args.GetSize()) {
+ cString largs(args);
+ _compete_period = largs.PopWord().AsInt();
+ }
+ }
+
+ //! Destructor.
+ virtual ~cAbstractMonitoringCompeteDemes() { }
+
+ /*! Update each deme, and possibly compete them.
+
+ Calls Update(...) on every execution, but only calls Fitness(...) when the current
+ update is an even multiple of the competition period.
+ */
+ virtual void Process(cAvidaContext& ctx) {
+ _update_fitness.resize(m_world->GetPopulation().GetNumDemes());
+ for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+ _update_fitness[i] += Update(m_world->GetPopulation().GetDeme(i));
+ }
+
+ if((m_world->GetStats().GetUpdate() % _compete_period) == 0) {
+ std::vector<double> fitness;
+ for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+ fitness.push_back(pow(_update_fitness[i] + Fitness(m_world->GetPopulation().GetDeme(i)), 2.0));
+ assert(fitness.back() >= 0.0);
+ }
+ m_world->GetPopulation().CompeteDemes(fitness);
+ _update_fitness.clear();
+ }
+ }
+
+ //! Called on each action invocation, *including* immediately prior to fitness calculation.
+ virtual double Update(cDeme& deme) = 0;
+
+protected:
+ int _compete_period; //!< Period at which demes compete.
+ std::vector<double> _update_fitness; //!< Running sum of returns from Update(cDeme).
+};
+
+
+/*! This class contains methods that are useful for consensus-related problems.
+ */
+class ConsensusSupport {
+public:
+ ConsensusSupport() { }
+ virtual ~ConsensusSupport() { }
+
+ /*! Returns a pair (support, opinion), where support is equal to the maximum
+ number of organisms within the deme that have set their opinion to the same value,
+ and opinion is the value that they have set their (shared) opinion to.
+ */
+ virtual std::pair<unsigned int, cOrganism::Opinion> max_support(const cDeme& deme) {
+ typedef std::vector<cOrganism::Opinion> OpinionList;
+ OpinionList opinions;
+ // For each organism in the deme:
+ for(int i=0; i<deme.GetSize(); ++i) {
+ cOrganism* org = deme.GetOrganism(i);
+ if((org != 0) && org->HasOpinion()) {
+ // Get its current opinion (we don't care about the date here):
+ opinions.push_back(org->GetOpinion().first);
+ }
+ }
+
+ // Go through the list of opinions, count & filter:
+ typedef std::map<cOrganism::Opinion, unsigned int> OpinionMap;
+ unsigned int support=0;
+ cOrganism::Opinion opinion=0;
+ OpinionMap opinion_counts;
+ for(OpinionList::iterator i=opinions.begin(); i!=opinions.end(); ++i) {
+ // filter:
+ if(cAssignRandomCellData::IsCellDataInDeme(*i, deme)) {
+ // count:
+ ++opinion_counts[*i];
+ // find support:
+ if(opinion_counts[*i] > support) {
+ support = opinion_counts[*i];
+ opinion = *i;
+ }
+ }
+ }
+ return std::make_pair(support, opinion);
+ }
+};
+
+
+/*! This class rewards for solving the Iterated Consensus Dilemma, where organisms
+ are to repeatedly reach consensus on one of a set of values.
+
+ Each organism is initialized with access to a single value, so the first part of
+ the ICD is to distribute knowledge of all possible values. The second part of
+ the ICD is to determine which of the possible values should be selected by the
+ group. The third, and final, part of the ICD is for the group to iterate this
+ problem, so that consensus on as many values as possible is reached in the shortest
+ amount of time.
+ */
+class cActionIteratedConsensus : public cAbstractMonitoringCompeteDemes, ConsensusSupport {
+public:
+ cActionIteratedConsensus(cWorld* world, const cString& args) : cAbstractMonitoringCompeteDemes(world, args), _replace(0) {
+ if(args.GetSize()) {
+ cString largs(args);
+ _replace = largs.PopWord().AsInt();
+ }
+ }
+
+ //! Destructor.
+ virtual ~cActionIteratedConsensus() { }
+
+ 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) {
+ return max_support(deme).first + 1;
+ }
+
+ /*! Determine if the organisms in this deme have reached consensus, and if so,
+ record that fact and reset so that they can "iterate" (try to reach consensus
+ again). This version includes protection against resetting to an "easy" value,
+ removing the ability for organisms to continually filter in one direction to
+ solve ICD.
+
+ Resets always reset the cell data of the agreed-upon value, and if _replace is
+ greater than zero, we also reset the cell data of other cells, which are
+ selected at random with replacement.
+
+ Called during every update (depending on configuration). Return values are
+ summed and included in final fitness calculation. */
+ virtual double Update(cDeme& deme) {
+ std::pair<unsigned int, cOrganism::Opinion> support = max_support(deme);
+
+ // Have all organisms in this deme reached consensus?
+ if(support.first == static_cast<unsigned int>(deme.GetSize())) {
+ // Yes; change the cell data for the value that was agreed upon:
+ int min_data = *cAssignRandomCellData::GetDataInDeme(deme).begin();
+ int max_data = *cAssignRandomCellData::GetDataInDeme(deme).rbegin();
+ cAssignRandomCellData::ReplaceCellData(support.second, m_world->GetRandom().GetInt(min_data+1, max_data-1), deme);
+
+ // Now reset the others:
+ for(int i=0; i<_replace; ++i) {
+ int cell_id = m_world->GetRandom().GetInt(deme.GetSize());
+ int cell_data = deme.GetCell(cell_id).GetCellData();
+ cAssignRandomCellData::ReplaceCellData(cell_data, m_world->GetRandom().GetInt(min_data+1, max_data-1), deme);
+ }
+
+ return deme.GetSize();
+ }
+ return 0.0;
+ }
+
+private:
+ int _replace; //!< Number of cell datas that will be replaced on successful consensus.
+};
+
+
+/**** 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 {
+public:
+ cActionPacecarFlash(cWorld* world, const cString& args): cAction(world, args), _pacecar(80) {
+ if(args.GetSize()) {
+ cString largs(args);
+ _pacecar = largs.PopWord().AsInt();
+ }
+ }
+
+ //! Destructor.
+ virtual ~cActionPacecarFlash() { }
+
+ static const cString GetDescription() { return "Arguments: [pacecar=80]"; }
+
+ //! Send a flash
+ virtual void Process(cAvidaContext& ctx) {
+ }
+
+private:
+ int _pacecar; //!< Period for artificial flashes that will be sent to each deme.
+};
+ */
+
+
+/*! Compete demes based on the ability of their constituent organisms
+ to synchronize their flashes to a common phase and period.
+class cActionSynchronization : public cAbstractMonitoringCompeteDemes {
+public:
+ //! Constructor.
+ cActionSynchronization(cWorld* world, const cString& args) : cAbstractMonitoringCompeteDemes(world, args), _pacecar(0) {
+ if(args.GetSize()) {
+ cString largs(args);
+ _pacecar = largs.PopWord().AsInt();
+ }
+ }
+
+ //! 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();
+
+ // If not everyone has flashed, fitness is just the number that have flashed:
+ if(total_flashed < deme.GetSize()) {
+ return 1.0 + total_flashed;
+ }
+
+ // 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);
+ }
+};
+ */
+
+
+/*! 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 {
+public:
+ //! Constructor.
+ cActionCompeteDemesFlashTimingDesync(cWorld* world, const cString& args) : cActionCompeteDemesFlashTiming(world, args) {
+ }
+
+ //! 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);
+ }
+};
+ */
+
+
class cAbstractCompeteDemes_AttackKillAndEnergyConserve : public cAbstractCompeteDemes {
public:
@@ -1964,15 +2331,19 @@
action_lib->Register<cActionModMutProb>("ModMutProb");
action_lib->Register<cActionZeroMuts>("ZeroMuts");
+ action_lib->Register<cActionTrackAllMessages>("TrackAllMessages");
+
action_lib->Register<cActionCompeteDemes>("CompeteDemes");
action_lib->Register<cActionReplicateDemes>("ReplicateDemes");
action_lib->Register<cActionDivideDemes>("DivideDemes");
action_lib->Register<cActionResetDemes>("ResetDemes");
action_lib->Register<cActionCopyDeme>("CopyDeme");
-/****AbstractCompeteDemes sub-classes****/
+ /****AbstractCompeteDemes sub-classes****/
action_lib->Register<cAbstractCompeteDemes_AttackKillAndEnergyConserve>("CompeteDemes_AttackKillAndEnergyConserve");
-
+ action_lib->Register<cAssignRandomCellData>("AssignRandomCellData");
+ action_lib->Register<cActionIteratedConsensus>("IteratedConsensus");
+
action_lib->Register<cActionNewTrial>("NewTrial");
action_lib->Register<cActionCompeteOrganisms>("CompeteOrganisms");
Modified: branches/movement/source/actions/PrintActions.cc
===================================================================
--- branches/movement/source/actions/PrintActions.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/actions/PrintActions.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -107,7 +107,12 @@
STATS_OUT_FILE(PrintDemeOrgTasksExeData, deme_org_tasks_exe.dat );
STATS_OUT_FILE(PrintDemeOrgReactionData, deme_org_reactions.dat );
STATS_OUT_FILE(PrintGermlineData, germline.dat );
+STATS_OUT_FILE(PrintPredicatedMessages, messages.dat );
+STATS_OUT_FILE(PrintCellData, cell_data.dat );
+STATS_OUT_FILE(PrintCurrentOpinions, opinions.dat );
STATS_OUT_FILE(PrintPerDemeGenPerFounderData, deme_gen_between_founders.dat );
+STATS_OUT_FILE(PrintSynchronizationData, sync.dat );
+STATS_OUT_FILE(PrintDetailedSynchronizationData, sync-detail.dat);
// @WRE: Added output event for collected visit counts
STATS_OUT_FILE(PrintCellVisitsData, visits.dat );
STATS_OUT_FILE(PrintFlowRateTuples, flow_rate_tuples.dat);
@@ -2692,6 +2697,12 @@
action_lib->Register<cActionPrintDemeTestamentStats>("PrintDemeTestamentStats");
+ action_lib->Register<cActionPrintPredicatedMessages>("PrintPredicatedMessages");
+ action_lib->Register<cActionPrintCellData>("PrintCellData");
+ action_lib->Register<cActionPrintCurrentOpinions>("PrintCurrentOpinions");
+ action_lib->Register<cActionPrintSynchronizationData>("PrintSynchronizationData");
+ action_lib->Register<cActionPrintDetailedSynchronizationData>("PrintDetailedSynchronizationData");
+
// deme output files
action_lib->Register<cActionPrintDemeAllStats>("PrintDemeAllStats");
action_lib->Register<cActionPrintDemeAllStats>("PrintDemeStats"); //duplicate of previous
Modified: branches/movement/source/analyze/cAnalyze.cc
===================================================================
--- branches/movement/source/analyze/cAnalyze.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/analyze/cAnalyze.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -1265,6 +1265,7 @@
batch[cur_batch].SetAligned(false);
}
+
void cAnalyze::FindSexLineage(cString cur_string)
{
@@ -1493,6 +1494,146 @@
batch[cur_batch].SetAligned(false);
}
+// @JEB 9-25-2008
+void cAnalyze::FindLastCommonAncestor(cString cur_string)
+{
+
+/*
+ // Assumes that the current batch contains a population and all of its common ancestors
+ // Finds the last common ancestor among all current organisms that are still alive,
+ // i.e. have an update_died of -1.
+
+ cout << "Finding last common ancestor of batch " << cur_batch << endl;
+
+ // Make a list of alive organisms
+ tListPlus<cAnalyzeGenotype> alive_list;
+ {
+ tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+ cAnalyzeGenotype * test_genotype = NULL;
+ while ((test_genotype = batch_it.Next()) != NULL) {
+ if (test_genotype->GetUpdateDead() == -1) {
+ alive_list.Push(test_genotype);
+ }
+ }
+ }
+
+ if (m_world->GetVerbosity() >= VERBOSE_ON) {
+ cout << " Number of genotypes that are alive: " << alive_list.GetSize() << endl;
+ cout << " Number of ancestor genotypes: " << batch[cur_batch].List().GetSize() << endl;
+ }
+
+ // Extract the lineage of the first alive organism.
+ // The LCA must be among these genotypes. The approach is to step back one ancestor
+ // at a time, collect all of its descendants, and then check to see if there are
+ // andy alive organisms that have not been collected yet.
+
+ // find the lineage of the first genotype...
+ cAnalyzeGenotype * first_alive_genotype = alive_list.Pop();
+ tListPlus<cAnalyzeGenotype> master_lineage;
+ {
+ master_lineage.Push(first_alive_genotype);
+ int next_id = first_alive_genotype->GetParentID();
+ bool found = true;
+ while (found == true) {
+ found = false;
+
+ tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+ cAnalyzeGenotype * found_gen = NULL;
+ while ((found_gen = batch_it.Next()) != NULL) {
+ if (found_gen->GetID() == next_id) {
+ master_lineage.Push(found_gen);
+ next_id = found_gen->GetParentID();
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (m_world->GetVerbosity() >= VERBOSE_ON) {
+ cout << " Size of master lineage: " << master_lineage.GetSize() << endl;
+ }
+
+ tListIterator<cAnalyzeGenotype> master_lineage_batch_it(master_lineage);
+
+ while ((collect_genotype = master_lineage_batch_it.Next()) != NULL) {
+
+ // collect all children of the current lineage genotype
+ tListPlus<cAnalyzeGenotype> collect_genotype_list;
+ collect_genotype_list.PushRear(collect_genotype);
+ tListIterator<cAnalyzeGenotype> collect_batch_it(collect_genotype_list);
+
+ next_collect_genotype_list;
+
+ int current_id = alive_genotype->GetID();
+ int parent_id = alive_genotype->GetParentID();
+ bool found_parent = true;
+ bool found_in_master_lineage = false;
+ while (found_parent == true) {
+
+ // Check to see if this id is among those in the first lineage.
+ tListIterator<cAnalyzeGenotype> master_lineage_batch_it(master_lineage);
+ cAnalyzeGenotype * master_lineage_genotype;
+ while ((master_lineage_genotype = master_lineage_batch_it.Next()) != NULL) {
+ if (master_lineage_genotype->GetID() == current_id) break;
+ }
+
+ found_in_master_lineage = master_lineage_genotype != NULL;
+ if (found_in_master_lineage) {
+
+ // Remove anything in the master lineage that is past this point.
+ // as it is younger than the new most recent common ancestor
+ while ((master_lineage_genotype = master_lineage_batch_it.Next()) != NULL) {
+ master_lineage_batch_it.Remove();
+ }
+
+ // We can also stop looking at ancestors of the current alive_genotype
+ if (found_in_master_lineage) break;
+ }
+
+ // Find the ancestor of the current organism in the alive_genotype lineage
+ found_parent = false;
+ tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+ cAnalyzeGenotype * test_genotype = NULL;
+ while ((test_genotype = batch_it.Next()) != NULL) {
+ if (test_genotype->GetID() == parent_id) {
+ parent_id = test_genotype->GetParentID();
+ current_id = test_genotype->GetID();
+ found_parent = true;
+ break;
+ }
+ }
+ }
+
+ // Warn if we did not find a common ancestor at all.
+ if (!found_in_master_lineage) {
+ cout << " Warning! Did not find common ancestor between two organisms. " << endl;
+ }
+
+ if (m_world->GetVerbosity() >= VERBOSE_ON) {
+ cout << " Size of master lineage: " << master_lineage.GetSize() << endl;
+ }
+ }
+
+ // The first one left in this lineage is the one we want to save.
+ cAnalyzeGenotype * last_common_ancestor = master_lineage.Pop();
+
+ // Delete everything else.
+ tListIterator<cAnalyzeGenotype> delete_batch_it(batch[cur_batch].List());
+ cAnalyzeGenotype * delete_genotype = NULL;
+ while ((delete_genotype = delete_batch_it.Next()) != NULL) {
+ if (delete_genotype->GetID() != last_common_ancestor->GetID()) {
+ delete batch[cur_batch].List().Pop();
+ }
+ }
+
+ // And fill it back in with the good stuff.
+ batch[cur_batch].List().PushRear(last_common_ancestor);
+
+ */
+}
+
+
void cAnalyze::SampleOrganisms(cString cur_string)
{
double fraction = cur_string.PopWord().AsDouble();
@@ -5388,6 +5529,87 @@
}
+// Determine redundancy by calculating the percentage of the lifetimes
+// where fitness is decreased over a range of instruction failure probabilities.
+// @JEB 9-24-2008
+void cAnalyze::CommandAnalyzeRedundancyByInstFailure(cString cur_string)
+{
+ cString filename("analyze_redundancy_by_inst_failure.dat");
+ if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
+ int replicates = 1000;
+ if (cur_string.GetSize() != 0) replicates = cur_string.PopWord().AsInt();
+
+ // Output is one line per organism in the current batch with columns.
+ cDataFile & df = m_world->GetDataFile(filename);
+ df.WriteComment( "Redundancy calculated by changing the probability of instruction failure" );
+ cString s;
+ s.Set("%i replicates at each chance of instruction failure", replicates);
+ df.WriteComment(s);
+ df.WriteTimeStamp();
+
+ // Loop through all of the genotypes in this batch...
+
+ tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
+ cAnalyzeGenotype * genotype = NULL;
+ while ((genotype = batch_it.Next()) != NULL) {
+
+ if (m_world->GetVerbosity() >= VERBOSE_ON) {
+ cout << " Determining redundancy by instruction failure for " << genotype->GetName() << endl;
+ }
+
+ cInstSet modify_inst_set = genotype->GetInstructionSet();
+
+ // Modify the instruction set to include the current probability of failure.
+ for (int j=0; j<modify_inst_set.GetSize(); j++)
+ {
+ cString inst_name = modify_inst_set.GetName(j);
+ cInstruction inst = modify_inst_set.GetInst(inst_name);
+ modify_inst_set.SetProbFail(inst, 0);
+ }
+ genotype->SetInstructionSet(modify_inst_set);
+
+ // Recalculate the baseline fitness
+ // May need to calculate multiple times to check for stochastic behavior....
+ genotype->Recalculate(m_ctx);
+ double baseline_fitness = genotype->GetFitness();
+
+ if (baseline_fitness>0)
+ {
+ // Write information for this
+ df.Write(genotype->GetName(), "genotype name");
+ df.Write(genotype->GetID(), "genotype id");
+ df.Write(baseline_fitness, "fitness");
+
+ // Run the organism the specified number of replicates
+
+ for (double log10_fc=-4.0; log10_fc<=0.0; log10_fc+=0.1)
+ {
+ double fc = exp(log10_fc*log(10));
+
+ // Modify the instruction set to include the current probability of failure.
+ for (int j=0; j<modify_inst_set.GetSize(); j++)
+ {
+ cString inst_name = modify_inst_set.GetName(j);
+ cInstruction inst = modify_inst_set.GetInst(inst_name);
+ modify_inst_set.SetProbFail(inst, fc);
+ }
+ genotype->SetInstructionSet(modify_inst_set);
+
+ // Recalculate the requested number of times
+ double chance = 0;
+ for (int i=0; i<replicates; i++)
+ {
+ genotype->Recalculate(m_ctx);
+ if (genotype->GetFitness() < baseline_fitness) chance++;
+ }
+ s.Set("Inst prob fail %.3g", fc);
+ df.Write(chance/replicates, s);
+ }
+ df.Endl();
+ }
+ }
+}
+
void cAnalyze::CommandMapMutations(cString cur_string)
{
cout << "Constructing genome mutations maps..." << endl;
@@ -9254,6 +9476,7 @@
AddLibraryDef("FIND_LINEAGE", &cAnalyze::FindLineage);
AddLibraryDef("FIND_SEX_LINEAGE", &cAnalyze::FindSexLineage);
AddLibraryDef("FIND_CLADE", &cAnalyze::FindClade);
+ AddLibraryDef("FIND_LAST_COMMON_ANCESTOR", &cAnalyze::FindLastCommonAncestor);
AddLibraryDef("SAMPLE_ORGANISMS", &cAnalyze::SampleOrganisms);
AddLibraryDef("SAMPLE_GENOTYPES", &cAnalyze::SampleGenotypes);
AddLibraryDef("KEEP_TOP", &cAnalyze::KeepTopGenotypes);
@@ -9286,6 +9509,7 @@
AddLibraryDef("MAP", &cAnalyze::CommandMapTasks); // Deprecated...
AddLibraryDef("MAP_TASKS", &cAnalyze::CommandMapTasks);
AddLibraryDef("AVERAGE_MODULARITY", &cAnalyze::CommandAverageModularity);
+ AddLibraryDef("ANALYZE_REDUNDANCY_BY_INST_FAILURE", &cAnalyze::CommandAnalyzeRedundancyByInstFailure);
AddLibraryDef("MAP_MUTATIONS", &cAnalyze::CommandMapMutations);
AddLibraryDef("ANALYZE_COMPLEXITY", &cAnalyze::AnalyzeComplexity);
AddLibraryDef("ANALYZE_FITNESS_TWO_SITES", &cAnalyze::AnalyzeFitnessLandscapeTwoSites);
Modified: branches/movement/source/analyze/cAnalyze.h
===================================================================
--- branches/movement/source/analyze/cAnalyze.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/analyze/cAnalyze.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -234,6 +234,7 @@
void FindLineage(cString cur_string);
void FindSexLineage(cString cur_string);
void FindClade(cString cur_string);
+ void FindLastCommonAncestor(cString cur_string);
void SampleOrganisms(cString cur_string);
void SampleGenotypes(cString cur_string);
void KeepTopGenotypes(cString cur_string);
@@ -268,6 +269,7 @@
void CommandMapTasks(cString cur_string);
void CommandAverageModularity(cString cur_string);
void CommandAnalyzeModularity(cString cur_string);
+ void CommandAnalyzeRedundancyByInstFailure(cString cur_string);
void CommandMapMutations(cString cur_string);
void CommandMapDepth(cString cur_string);
void CommandPairwiseEntropy(cString cur_string);
Modified: branches/movement/source/analyze/cAnalyzeGenotype.h
===================================================================
--- branches/movement/source/analyze/cAnalyzeGenotype.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/analyze/cAnalyzeGenotype.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -37,6 +37,9 @@
#ifndef cGenome_h
#include "cGenome.h"
#endif
+#ifndef cInstSet_h
+#include "cInstSet.h"
+#endif
#ifndef cLandscape_h
#include "cLandscape.h"
#endif
@@ -241,6 +244,7 @@
// Set...
void SetSequence(cString _sequence);
void SetName(const cString & _name) { name = _name; }
+ void SetInstructionSet(cInstSet& _inst_set) { m_inst_set = _inst_set; }
void SetAlignedSequence(const cString & _seq) { aligned_sequence = _seq; }
void SetTag(const cString & _tag) { tag = _tag; }
@@ -285,6 +289,7 @@
// Accessors...
const cGenome & GetGenome() const { return genome; }
const cString & GetName() const { return name; }
+ const cInstSet & GetInstructionSet() const { return m_inst_set; }
const cString & GetAlignedSequence() const { return aligned_sequence; }
cString GetExecutedFlags() const { return executed_flags; }
cString GetAlignmentExecutedFlags() const;
Modified: branches/movement/source/cpu/cHardwareBase.cc
===================================================================
--- branches/movement/source/cpu/cHardwareBase.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/cpu/cHardwareBase.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -913,3 +913,8 @@
for (int i = 0; i < num_inst_cost; i++) inst_energy_cost[i] = m_inst_set->GetEnergyCost(cInstruction(i));
}
}
+
+//! Called when the organism that owns this CPU has received a flash from a neighbor.
+void cHardwareBase::ReceiveFlash() {
+ m_world->GetDriver().RaiseFatalException(1, "Method cHardwareBase::ReceiveFlash must be overriden.");
+}
Modified: branches/movement/source/cpu/cHardwareBase.h
===================================================================
--- branches/movement/source/cpu/cHardwareBase.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/cpu/cHardwareBase.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -204,6 +204,11 @@
bool Inst_DoubleEnergyUsage(cAvidaContext& ctx);
bool Inst_HalfEnergyUsage(cAvidaContext& ctx);
bool Inst_DefaultEnergyUsage(cAvidaContext& ctx);
+
+ // -------- Synchronization --------
+public:
+ //! Called when the organism that owns this CPU has received a flash from a neighbor.
+ virtual void ReceiveFlash();
};
Modified: branches/movement/source/cpu/cHardwareCPU.cc
===================================================================
--- branches/movement/source/cpu/cHardwareCPU.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/cpu/cHardwareCPU.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -210,11 +210,6 @@
tInstLibEntry<tMethod>("sense-m100", &cHardwareCPU::Inst_SenseMult100, nInstFlag::STALL), // the names to cStats::cStats() @JEB
tInstLibEntry<tMethod>("sense-diff-facing", &cHardwareCPU::Inst_SenseDiffFacing, nInstFlag::STALL),
tInstLibEntry<tMethod>("if-resources", &cHardwareCPU::Inst_IfResources, nInstFlag::STALL),
- // Data collection
- tInstLibEntry<tMethod>("collect-cell-data", &cHardwareCPU::Inst_CollectCellData, nInstFlag::STALL),
- tInstLibEntry<tMethod>("kill-cell-event", &cHardwareCPU::Inst_KillCellEvent, nInstFlag::STALL),
- tInstLibEntry<tMethod>("kill-faced-cell-event", &cHardwareCPU::Inst_KillFacedCellEvent, nInstFlag::STALL),
- tInstLibEntry<tMethod>("collect-cell-data-and-kill-event", &cHardwareCPU::Inst_CollectCellDataAndKillEvent, nInstFlag::STALL),
tInstLibEntry<tMethod>("donate-rnd", &cHardwareCPU::Inst_DonateRandom, nInstFlag::STALL),
tInstLibEntry<tMethod>("donate-kin", &cHardwareCPU::Inst_DonateKin, nInstFlag::STALL),
@@ -466,6 +461,22 @@
// These are STALLs because opinions are only relevant with respect to time.
tInstLibEntry<tMethod>("set-opinion", &cHardwareCPU::Inst_SetOpinion, nInstFlag::STALL),
tInstLibEntry<tMethod>("get-opinion", &cHardwareCPU::Inst_GetOpinion, nInstFlag::STALL),
+
+ // Data collection
+ tInstLibEntry<tMethod>("if-cell-data-changed", &cHardwareCPU::Inst_IfCellDataChanged, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("collect-cell-data", &cHardwareCPU::Inst_CollectCellData, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("kill-cell-event", &cHardwareCPU::Inst_KillCellEvent, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("kill-faced-cell-event", &cHardwareCPU::Inst_KillFacedCellEvent, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("collect-cell-data-and-kill-event", &cHardwareCPU::Inst_CollectCellDataAndKillEvent, nInstFlag::STALL),
+
+ // Synchronization
+ tInstLibEntry<tMethod>("flash", &cHardwareCPU::Inst_Flash, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("if-recvd-flash", &cHardwareCPU::Inst_IfRecvdFlash, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("flash-info", &cHardwareCPU::Inst_FlashInfo, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("flash-info-b", &cHardwareCPU::Inst_FlashInfoB, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("reset-flash-info", &cHardwareCPU::Inst_ResetFlashInfo, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("hard-reset", &cHardwareCPU::Inst_HardReset, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("get-cycles", &cHardwareCPU::Inst_GetCycles, nInstFlag::STALL),
// Must always be the last instruction in the array
tInstLibEntry<tMethod>("NULL", &cHardwareCPU::Inst_Nop, 0, "True no-operation instruction: does nothing"),
@@ -492,6 +503,7 @@
cHardwareCPU::cHardwareCPU(cWorld* world, cOrganism* in_organism, cInstSet* in_m_inst_set)
: cHardwareBase(world, in_organism, in_m_inst_set)
+, m_last_cell_data(false, 0)
{
/* FIXME: reorganize storage of m_functions. -- kgn */
m_functions = s_inst_slib->GetFunctions();
@@ -523,6 +535,7 @@
, m_advance_ip(hardware_cpu.m_advance_ip)
, m_executedmatchstrings(hardware_cpu.m_executedmatchstrings)
, m_epigenetic_state(hardware_cpu.m_epigenetic_state)
+, m_last_cell_data(false, 0)
{
#if INSTRUCTION_COSTS
m_inst_cost = hardware_cpu.m_inst_cost;
@@ -581,6 +594,7 @@
}
}
}
+ m_last_cell_data = std::make_pair(false, 0);
}
void cHardwareCPU::cLocalThread::operator=(const cLocalThread& in_thread)
@@ -693,6 +707,12 @@
exec = !( ctx.GetRandom().P(m_inst_set->GetProbFail(cur_inst)) );
}
+ // Flag instruction as executed even if it failed (moved from SingleProcess_ExecuteInst)
+ // this allows division conditions to be met even if most instruction executions failed. @JEB
+
+ // Mark the instruction as executed
+ IP().SetFlagExecuted();
+
// Add to the promoter inst executed count before executing the inst (in case it is a terminator)
if (m_promoters_enabled) m_threads[m_cur_thread].IncPromoterInstExecuted();
@@ -748,10 +768,6 @@
// Get a pointer to the corresponding method...
int inst_idx = m_inst_set->GetLibFunctionIndex(actual_inst);
- // Mark the instruction as executed
- IP().SetFlagExecuted();
-
-
#if INSTRUCTION_COUNT
// instruction execution count incremented
organism->GetPhenotype().IncCurInstCount(actual_inst.GetOp());
@@ -2166,6 +2182,7 @@
GetRegister(REG_BX) = 0;
GetRegister(REG_CX) = 0;
StackClear();
+ m_last_cell_data = std::make_pair(false, 0);
return true;
}
@@ -3464,51 +3481,6 @@
}
-bool cHardwareCPU::Inst_CollectCellData(cAvidaContext& ctx) {
- const int out_reg = FindModifiedRegister(REG_BX);
- GetRegister(out_reg) = organism->GetCellData();
- return true;
-}
-
-bool cHardwareCPU::Inst_KillCellEvent(cAvidaContext& ctx) {
- // Fail if we're running in the test CPU.
- if((organism->GetOrgInterface().GetDemeID() < 0) || (organism->GetCellID() < 0))
- return false;
-
- const int reg = FindModifiedRegister(REG_BX);
- int eventID = organism->GetCellData();
- GetRegister(reg) = organism->GetOrgInterface().GetDeme()->KillCellEvent(eventID);
- return true;
-}
-
-bool cHardwareCPU::Inst_KillFacedCellEvent(cAvidaContext& ctx) {
- // Fail if we're running in the test CPU.
- if((organism->GetOrgInterface().GetDemeID() < 0) || (organism->GetCellID() < 0))
- return false;
-
- const int reg = FindModifiedRegister(REG_BX);
- int eventID = organism->GetNeighborCellContents();
- GetRegister(reg) = organism->GetOrgInterface().GetDeme()->KillCellEvent(eventID);
-
- if(GetRegister(reg))
- organism->SetEventKilled();
-
- return true;
-}
-
-bool cHardwareCPU::Inst_CollectCellDataAndKillEvent(cAvidaContext& ctx) {
- // Fail if we're running in the test CPU.
- if((organism->GetOrgInterface().GetDemeID() < 0) || (organism->GetCellID() < 0))
- return false;
-
- const int out_reg = FindModifiedRegister(REG_BX);
- int eventID = organism->GetCellData();
- GetRegister(out_reg) = eventID;
-
- organism->GetOrgInterface().GetDeme()->KillCellEvent(eventID);
- return true;
-}
-
void cHardwareCPU::DoDonate(cOrganism* to_org)
{
assert(to_org != NULL);
@@ -7451,6 +7423,7 @@
*/
bool cHardwareCPU::Inst_SetOpinion(cAvidaContext& ctx)
{
+ assert(organism != 0);
organism->SetOpinion(GetRegister(FindModifiedRegister(REG_BX)));
return true;
}
@@ -7462,6 +7435,7 @@
*/
bool cHardwareCPU::Inst_GetOpinion(cAvidaContext& ctx)
{
+ assert(organism != 0);
if(organism->HasOpinion()) {
const int opinion_reg = FindModifiedRegister(REG_BX);
const int age_reg = FindNextRegister(opinion_reg);
@@ -7471,3 +7445,158 @@
}
return true;
}
+
+
+/*! Collect this cell's data, and place it in ?BX?. Set the flag indicating that
+ this organism has collected cell data to true, and set the last collected cell data
+ as well.
+ */
+bool cHardwareCPU::Inst_CollectCellData(cAvidaContext& ctx)
+{
+ assert(organism != 0);
+ const int out_reg = FindModifiedRegister(REG_BX);
+ GetRegister(out_reg) = organism->GetCellData();
+ // Update last collected cell data:
+ m_last_cell_data = std::make_pair(true, GetRegister(out_reg));
+ return true;
+}
+
+
+/*! Detect if the cell data in which this organism lives has changed since the
+ last time that this organism has collected cell data. Note that this process
+ DOES NOT take into account organism movement, and it only works with explicit
+ collection of cell data.
+ */
+bool cHardwareCPU::Inst_IfCellDataChanged(cAvidaContext& ctx)
+{
+ assert(organism != 0);
+ // If we haven't collected cell data yet, or it's the same as the current cell data, advance
+ // the IP:
+ if(!m_last_cell_data.first || (m_last_cell_data.second == organism->GetCellData())) {
+ IP().Advance();
+ }
+
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_KillCellEvent(cAvidaContext& ctx) {
+ // Fail if we're running in the test CPU.
+ if((organism->GetOrgInterface().GetDemeID() < 0) || (organism->GetCellID() < 0))
+ return false;
+
+ const int reg = FindModifiedRegister(REG_BX);
+ int eventID = organism->GetCellData();
+ GetRegister(reg) = organism->GetOrgInterface().GetDeme()->KillCellEvent(eventID);
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_KillFacedCellEvent(cAvidaContext& ctx) {
+ // Fail if we're running in the test CPU.
+ if((organism->GetOrgInterface().GetDemeID() < 0) || (organism->GetCellID() < 0))
+ return false;
+
+ const int reg = FindModifiedRegister(REG_BX);
+ int eventID = organism->GetNeighborCellContents();
+ GetRegister(reg) = organism->GetOrgInterface().GetDeme()->KillCellEvent(eventID);
+
+ if(GetRegister(reg))
+ organism->SetEventKilled();
+
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_CollectCellDataAndKillEvent(cAvidaContext& ctx) {
+ // Fail if we're running in the test CPU.
+ if((organism->GetOrgInterface().GetDemeID() < 0) || (organism->GetCellID() < 0))
+ return false;
+
+ const int out_reg = FindModifiedRegister(REG_BX);
+ int eventID = organism->GetCellData();
+ GetRegister(out_reg) = eventID;
+
+ organism->GetOrgInterface().GetDeme()->KillCellEvent(eventID);
+ return true;
+}
+
+
+/*! Called when the organism that owns this CPU has received a flash from a neighbor. */
+void cHardwareCPU::ReceiveFlash() {
+ m_flash_info.first = 1; // Yes, we've received a flash.
+ m_flash_info.second = m_cycle_counter; // When we received it.
+}
+
+
+/*! Send a "flash" event to all neighboring organisms. */
+bool cHardwareCPU::Inst_Flash(cAvidaContext& ctx) {
+ assert(organism != 0);
+ organism->SendFlash(ctx);
+ return true;
+}
+
+
+/*! Test if this organism has ever recieved a flash event. */
+bool cHardwareCPU::Inst_IfRecvdFlash(cAvidaContext& ctx) {
+ assert(organism != 0);
+ if(m_flash_info.first == 0) {
+ IP().Advance();
+ }
+ return true;
+}
+
+
+/*! Retrieve if & when this organism has last received a flash. */
+bool cHardwareCPU::Inst_FlashInfo(cAvidaContext& ctx) {
+ assert(organism != 0);
+ const int bx = FindModifiedRegister(REG_BX);
+ const int cx = FindNextRegister(bx);
+
+ if(m_flash_info.first > 0) {
+ assert(m_cycle_counter >= m_flash_info.second);
+ GetRegister(bx) = m_flash_info.first;
+ GetRegister(cx) = m_cycle_counter - m_flash_info.second;
+ } else {
+ GetRegister(bx) = 0;
+ GetRegister(cx) = 0;
+ }
+ return true;
+}
+
+
+/*! Retrieve if (but not when) this organism has last received a flash. */
+bool cHardwareCPU::Inst_FlashInfoB(cAvidaContext& ctx) {
+ assert(organism != 0);
+ const int bx = FindModifiedRegister(REG_BX);
+
+ if(m_flash_info.first > 0) {
+ assert(m_cycle_counter >= m_flash_info.second);
+ GetRegister(bx) = m_flash_info.first;
+ } else {
+ GetRegister(bx) = 0;
+ }
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_ResetFlashInfo(cAvidaContext& ctx) {
+ assert(organism != 0);
+ m_flash_info.first = 0;
+ m_flash_info.second = 0;
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_HardReset(cAvidaContext& ctx) {
+ Reset();
+ m_advance_ip = false;
+ return true;
+}
+
+
+//! Current "time": the number of cycles this CPU has been "alive."
+bool cHardwareCPU::Inst_GetCycles(cAvidaContext& ctx) {
+ GetRegister(FindModifiedRegister(REG_BX)) = m_cycle_counter;
+ return true;
+}
Modified: branches/movement/source/cpu/cHardwareCPU.h
===================================================================
--- branches/movement/source/cpu/cHardwareCPU.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/cpu/cHardwareCPU.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -469,10 +469,6 @@
bool DoSenseDiffFacing(cAvidaContext& ctx, int conversion_method, double base);
//! Execute the following instruction if all resources are above their min level.
bool Inst_IfResources(cAvidaContext& ctx);
- bool Inst_CollectCellData(cAvidaContext& ctx);
- bool Inst_KillCellEvent(cAvidaContext& ctx);
- bool Inst_KillFacedCellEvent(cAvidaContext& ctx);
- bool Inst_CollectCellDataAndKillEvent(cAvidaContext& ctx);
void DoDonate(cOrganism * to_org);
void DoEnergyDonate(cOrganism* to_org);
@@ -674,6 +670,7 @@
bool Inst_DropPheromone(cAvidaContext& ctx);
// -------- Opinion support --------
+public:
/* These instructions interact with the "opinion" support in cOrganism.h. The
idea is that we're enabling organisms to express an opinion about *something*,
where that something is defined by the particular tasks and/or (deme) fitness function
@@ -685,6 +682,45 @@
bool Inst_SetOpinion(cAvidaContext& ctx);
//! Retrieve this organism's current opinion.
bool Inst_GetOpinion(cAvidaContext& ctx);
+
+ // -------- Cell Data Support --------
+public:
+ //! Collect this cell's data, and place it in a register.
+ bool Inst_CollectCellData(cAvidaContext& ctx);
+ //! Detect if this cell's data has changed since the last collection.
+ bool Inst_IfCellDataChanged(cAvidaContext& ctx);
+ bool Inst_KillCellEvent(cAvidaContext& ctx);
+ bool Inst_KillFacedCellEvent(cAvidaContext& ctx);
+ bool Inst_CollectCellDataAndKillEvent(cAvidaContext& ctx);
+
+private:
+ std::pair<bool, int> m_last_cell_data; //<! If cell data has been previously collected, and it's value.
+
+ // -------- Synchronization primitives --------
+public:
+ //! Called when the owning organism receives a flash from a neighbor.
+ virtual void ReceiveFlash();
+ //! Sends a "flash" to all neighboring organisms.
+ bool Inst_Flash(cAvidaContext& ctx);
+ //! Test if this organism has ever received a flash.
+ bool Inst_IfRecvdFlash(cAvidaContext& ctx);
+ //! Get if & when this organism last received a flash.
+ bool Inst_FlashInfo(cAvidaContext& ctx);
+ //! Get if (but not when) this organism last received a flash.
+ bool Inst_FlashInfoB(cAvidaContext& ctx);
+ //! Reset the information this organism has regarding receiving a flash.
+ bool Inst_ResetFlashInfo(cAvidaContext& ctx);
+ //! Reset the entire CPU.
+ bool Inst_HardReset(cAvidaContext& ctx);
+ //! Current "time": the number of cycles this CPU has been "alive."
+ bool Inst_GetCycles(cAvidaContext& ctx);
+
+private:
+ /*! Used to track the last flash received; first=whether we've received a flash,
+ second= #cycles since we've received a flash, or 0 if we haven't. */
+ std::pair<unsigned int, unsigned int> m_flash_info;
+ //! Cycle timer; counts the number of cycles this virtual CPU has executed.
+ unsigned int m_cycle_counter;
};
Modified: branches/movement/source/cpu/cHardwareManager.cc
===================================================================
--- branches/movement/source/cpu/cHardwareManager.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/cpu/cHardwareManager.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -29,6 +29,7 @@
#include "cHardwareSMT.h"
#include "cHardwareTransSMT.h"
#include "cHardwareGX.h"
+#include "cHardwareStatusPrinter.h"
#include "cInitFile.h"
#include "cInstSet.h"
#include "cWorld.h"
@@ -67,40 +68,56 @@
default:
m_world->GetDriver().RaiseFatalException(1, "Unknown/Unsupported HARDWARE_TYPE specified");
}
-
+
if (filename == "" || filename == "-") {
filename = default_filename;
m_world->GetDriver().NotifyComment(cString("Using default instruction set: ") + filename);
}
-
if (m_world->GetConfig().INST_SET_FORMAT.Get()) {
m_inst_set->LoadFromConfig();
} else {
m_inst_set->LoadFromLegacyFile(filename);
}
-
}
cHardwareBase* cHardwareManager::Create(cOrganism* in_org, cInstSet* inst_set)
{
+ static unsigned int cpu=0;
assert(in_org != NULL);
-
- switch (m_type)
- {
+
+ cHardwareBase* hw=0;
+
+ switch (m_type) {
case HARDWARE_TYPE_CPU_ORIGINAL:
- return new cHardwareCPU(m_world, in_org, inst_set);
+ hw = new cHardwareCPU(m_world, in_org, m_inst_set);
+ break;
case HARDWARE_TYPE_CPU_SMT:
- return new cHardwareSMT(m_world, in_org, inst_set);
+ hw = new cHardwareSMT(m_world, in_org, m_inst_set);
+ break;
case HARDWARE_TYPE_CPU_TRANSSMT:
- return new cHardwareTransSMT(m_world, in_org, inst_set);
+ hw = new cHardwareTransSMT(m_world, in_org, m_inst_set);
+ break;
case HARDWARE_TYPE_CPU_EXPERIMENTAL:
- return new cHardwareExperimental(m_world, in_org, inst_set);
+ hw = new cHardwareExperimental(m_world, in_org, m_inst_set);
+ break;
case HARDWARE_TYPE_CPU_GX:
- return new cHardwareGX(m_world, in_org, inst_set);
+ hw = new cHardwareGX(m_world, in_org, m_inst_set);
+ break;
default:
- return NULL;
+ m_world->GetDriver().RaiseFatalException(-1, "Unrecognized hardware type.");
+ break;
}
+
+ // Are we tracing the execution of this cpu?
+ if(m_world->GetConfig().TRACE_EXECUTION.Get()) {
+ std::ostringstream filename;
+ filename << "trace-" << cpu++ << ".trace";
+ hw->SetTrace(new cHardwareStatusPrinter(m_world->GetDataFileOFStream(filename.str().c_str())));
+ }
+
+ assert(hw != 0);
+ return hw;
}
bool cHardwareManager::SupportsSpeculative()
Modified: branches/movement/source/cpu/cInstSet.h
===================================================================
--- branches/movement/source/cpu/cInstSet.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/cpu/cInstSet.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -138,6 +138,9 @@
// Insertion of new instructions...
cInstruction ActivateNullInst();
+
+ // Modification of instructions during run.
+ void SetProbFail(const cInstruction& inst, double _prob_fail) { m_lib_name_map[inst.GetOp()].prob_fail = _prob_fail; }
// accessors for instruction library
cInstLib* GetInstLib() { return m_inst_lib; }
Modified: branches/movement/source/cpu/cTestCPUInterface.h
===================================================================
--- branches/movement/source/cpu/cTestCPUInterface.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/cpu/cTestCPUInterface.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -88,10 +88,9 @@
bool TestOnDivide() { return false; }
int GetFacing() { return 0; }
bool SendMessage(cOrgMessage& msg) { return false; }
-
- bool BcastAlarm(int jump_label, int bcast_range) { return false; }
-
+ bool BcastAlarm(int jump_label, int bcast_range) { return false; }
void DivideOrgTestamentAmongDeme(double value) {;}
+ void SendFlash() { }
};
Modified: branches/movement/source/main/cAvidaConfig.h
===================================================================
--- branches/movement/source/main/cAvidaConfig.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cAvidaConfig.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -283,6 +283,7 @@
CONFIG_ADD_VAR(RANDOM_SEED, int, 0, "Random number seed (0 for based on time)");
CONFIG_ADD_VAR(HARDWARE_TYPE, int, 0, "0 = Original CPUs\n1 = New SMT CPUs\n2 = Transitional SMT\n3 = Experimental CPU\n4 = Gene Expression CPU");
CONFIG_ADD_VAR(SPECULATIVE, bool, 1, "Enable speculative execution");
+ CONFIG_ADD_VAR(TRACE_EXECUTION, bool, 0, "Trace the execution of all organisms in the population (default=off,SLOW!)");
CONFIG_ADD_VAR(BCAST_HOPS, int, 1, "Number of hops to broadcast an alarm");
CONFIG_ADD_VAR(ALARM_SELF, bool, 0, "Does sending an alarm move sender IP to alarm label?\n0=no\n1=yes");
@@ -475,8 +476,8 @@
CONFIG_ADD_VAR(ENERGY_ENABLED, bool, 0, "Enable Energy Model. 0/1 (off/on)");
CONFIG_ADD_VAR(ENERGY_GIVEN_ON_INJECT, int, 0, "Energy given to organism upon injection.");
CONFIG_ADD_VAR(ENERGY_GIVEN_AT_BIRTH, int, 0, "Energy given to offspring upon birth.");
- CONFIG_ADD_VAR(FRAC_PARENT_ENERGY_GIVEN_TO_ORG_AT_BIRTH, double, 0.5, "Fraction of perent's energy given to offspring organism.");
- CONFIG_ADD_VAR(FRAC_PARENT_ENERGY_GIVEN_TO_DEME_AT_BIRTH, double, 0.5, "Fraction of perent's energy given to offspring deme.");
+ CONFIG_ADD_VAR(FRAC_PARENT_ENERGY_GIVEN_TO_ORG_AT_BIRTH, double, 0.5, "Fraction of parent's energy given to offspring organism.");
+ CONFIG_ADD_VAR(FRAC_PARENT_ENERGY_GIVEN_TO_DEME_AT_BIRTH, double, 0.5, "Fraction of parent's energy given to offspring deme.");
CONFIG_ADD_VAR(FRAC_ENERGY_DECAY_AT_ORG_BIRTH, double, 0.0, "Fraction of energy lost due to decay during organism reproduction.");
CONFIG_ADD_VAR(FRAC_ENERGY_DECAY_AT_DEME_BIRTH, double, 0.0, "Fraction of energy lost due to decay during deme reproduction.");
CONFIG_ADD_VAR(NUM_INST_EXC_BEFORE_0_ENERGY, int, 0, "Number of instructions executed before energy is exhausted.");
@@ -563,6 +564,12 @@
CONFIG_ADD_VAR(LOG_INJECT, bool, 0, "Log injection of organisms. 0/1 (off/on)");
CONFIG_ADD_VAR(INJECT_LOG_START, int, 0, "Update at which to start logging injection of\norganisms");
+ // -------- Synchronization config options --------
+ CONFIG_ADD_GROUP(SYNCHRONIZATION_GROUP, "Synchronization settings");
+ CONFIG_ADD_VAR(SYNC_FITNESS_WINDOW, int, 100, "Number of updates over which to calculate fitness (default=100).");
+ CONFIG_ADD_VAR(SYNC_FLASH_LOSSRATE, double, 0.0, "P() to lose a flash send (0.0==off).");
+ CONFIG_ADD_VAR(SYNC_TEST_FLASH_ARRIVAL, int, -1, "CPU cycle at which an organism will receive a flash (off=-1, default=-1, analyze mode only.)");
+
CONFIG_ADD_CUSTOM_FORMAT(INST_SET_NEW, "Instruction Set Definition");
CONFIG_ADD_FORMAT_VAR(INST, "Instruction entry in the instruction set");
Modified: branches/movement/source/main/cDeme.h
===================================================================
--- branches/movement/source/main/cDeme.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cDeme.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -232,7 +232,7 @@
void SetupDemeRes(int id, cResource * res, int verbosity);
void UpdateDemeRes() { deme_resource_count.GetResources(); }
void Update(double time_step) { deme_resource_count.Update(time_step); }
- int GetRelativeCellID(int absolute_cell_id) { return absolute_cell_id % GetSize(); } //!< assumes all demes are the same size
+ int GetRelativeCellID(int absolute_cell_id) const { return absolute_cell_id % GetSize(); } //!< assumes all demes are the same size
void SetCellEventGradient(int x1, int y1, int x2, int y2, int delay, int duration, bool static_pos, int time_to_live);
int GetNumEvents();
Modified: branches/movement/source/main/cOrgInterface.h
===================================================================
--- branches/movement/source/main/cOrgInterface.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cOrgInterface.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -98,10 +98,9 @@
virtual bool UpdateMerit(double new_merit) = 0;
virtual bool TestOnDivide() = 0;
virtual bool SendMessage(cOrgMessage& msg) = 0;
-
virtual bool BcastAlarm(int jump_jabel, int bcast_range) = 0;
virtual void DivideOrgTestamentAmongDeme(double value) = 0;
-
+ virtual void SendFlash() = 0;
};
#endif
Modified: branches/movement/source/main/cOrgMessagePredicate.h
===================================================================
--- branches/movement/source/main/cOrgMessagePredicate.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cOrgMessagePredicate.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -24,14 +24,19 @@
#ifndef cOrgMessagePredicate_h
#define cOrgMessagePredicate_h
+#include "cDeme.h"
+#include "cDemeCellEvent.h"
+#include "cOrganism.h"
+#include "cOrgMessage.h"
+#include "cPopulation.h"
+#include "cStats.h"
+
#include <iostream>
#include <functional>
#include <set>
+#include <vector>
-#include "cOrgMessage.h"
-#include "cOrganism.h"
-
/*! \brief An STL-compatible predicate on cOrgMessages. The intent here is to
provide a straightforward way to track arbitrary messages *wherever* they appear
in the population. The most utility can be had from message predicates if they're
@@ -40,7 +45,7 @@
{
virtual ~cOrgMessagePredicate() { }
virtual bool operator()(const cOrgMessage& msg) = 0;
- virtual void Print(std::ostream& out) { }
+ virtual void Print(int update, std::ostream& out) { }
virtual void Reset() { }
virtual bool PreviouslySatisfied() = 0;
virtual cString GetName() = 0;
@@ -49,6 +54,35 @@
};
+/*! A predicate that tracks all sent messages. */
+struct cOrgMessagePred_AllData : public cOrgMessagePredicate
+{
+ typedef std::vector<cOrgMessage> t_message_list;
+
+ cOrgMessagePred_AllData(cWorld* world) : m_world(world) { }
+ virtual ~cOrgMessagePred_AllData() { }
+
+ virtual bool operator()(const cOrgMessage& msg) {
+ m_msgs.push_back(msg);
+ return true;
+ }
+
+ virtual void Print(int update, std::ostream& out) {
+ for(t_message_list::iterator i=m_msgs.begin(); i!=m_msgs.end(); ++i) {
+ out << update << " ALL " << i->GetData() << " " << i->GetLabel() << endl;
+ }
+ }
+
+ virtual void Reset() { m_msgs.clear(); }
+ virtual bool PreviouslySatisfied() { return false; }
+ virtual cString GetName() { return "cOrgMessagePred_All"; }
+ virtual void UpdateStats(cStats& stats) { }
+ virtual cDemeCellEvent* GetEvent() { return NULL; }
+
+ cWorld* m_world;
+ t_message_list m_msgs;
+};
+
/*! A predicate that returns true and tracks the sending cell_id for messages
that contain the same data field as this predicate was constructed with.
*/
@@ -63,7 +97,7 @@
return true;
}
- virtual void Print(std::ostream& out) {
+ virtual void Print(int update, std::ostream& out) {
out << "data==" << m_data << ":{";
for(std::set<int>::iterator i=m_cell_ids.begin(); i!=m_cell_ids.end(); ++i) {
out << *i << ",";
@@ -98,7 +132,7 @@
return true;
}
- virtual void print(std::ostream& out) {
+ virtual void print(int update, std::ostream& out) {
// cPopulationCell::t_id_map& ids = cPopulationCell::GetRandomCellIDMap();
// int badMSGs = 0;
//
@@ -169,7 +203,7 @@
}
//need to print update!!!
- virtual void Print(std::ostream& out) {
+ virtual void Print(int update, std::ostream& out) {
if(m_event->IsDead()) {
return;
}
@@ -261,7 +295,7 @@
return m_event_received;
}
- virtual void Print(std::ostream& out) {
+ virtual void Print(int update, std::ostream& out) {
if(m_event->IsDead()) {
return;
}
Modified: branches/movement/source/main/cOrganism.cc
===================================================================
--- branches/movement/source/main/cOrganism.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cOrganism.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -602,6 +602,7 @@
void cOrganism::PrintStatus(ostream& fp, const cString& next_name)
{
fp << "---------------------------" << endl;
+ fp << "U:" << m_world->GetStats().GetUpdate() << endl;
m_hardware->PrintStatus(fp);
m_phenotype.PrintStatus(fp);
fp << endl;
@@ -805,3 +806,26 @@
InitOpinions();
m_opinion->opinion_list.push_back(std::make_pair(opinion, m_world->GetStats().GetUpdate()));
}
+
+
+/*! Called when an organism receives a flash from a neighbor. */
+void cOrganism::ReceiveFlash() {
+ m_hardware->ReceiveFlash();
+}
+
+
+/*! Called by the "flash" instruction. */
+void cOrganism::SendFlash(cAvidaContext& ctx) {
+ assert(m_interface);
+
+ // Check to see if we should lose the flash:
+ if((m_world->GetConfig().SYNC_FLASH_LOSSRATE.Get() > 0.0) &&
+ (m_world->GetRandom().P(m_world->GetConfig().SYNC_FLASH_LOSSRATE.Get()))) {
+ return;
+ }
+
+ // Flash not lost; continue.
+ m_interface->SendFlash();
+ m_world->GetStats().SentFlash(*this);
+ DoOutput(ctx);
+}
Modified: branches/movement/source/main/cOrganism.h
===================================================================
--- branches/movement/source/main/cOrganism.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cOrganism.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -439,6 +439,14 @@
};
cOpinionSupport* m_opinion; //!< Lazily-initialized pointer to the opinion data.
// -------- End of opinion support --------
+
+ // -------- Synchronization support --------
+public:
+ //! Called when a neighboring organism issues a "flash" instruction.
+ void ReceiveFlash();
+ //! Sends a "flash" to all neighboring organisms.
+ void SendFlash(cAvidaContext& ctx);
+ // -------- End of synchronization support --------
};
Modified: branches/movement/source/main/cPopulation.cc
===================================================================
--- branches/movement/source/main/cPopulation.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cPopulation.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -1147,14 +1147,15 @@
deme_count[from_deme_id]--;
deme_count[to_deme_id]++;
- cDeme & from_deme = deme_array[from_deme_id];
- cDeme & to_deme = deme_array[to_deme_id];
+ cDeme& from_deme = deme_array[from_deme_id];
+ cDeme& to_deme = deme_array[to_deme_id];
+ // Ideally, the below bit of code would be replaced with a call to ReplaceDeme:
+ // ReplaceDeme(from_deme, to_deme);
+ //
+ // But, use of InjectClone messes that up, breaking consistency. So the next
+ // time that someone comes in here looking to refactor, consider fixing this.
- /// ReplaceDeme(cDeme& source_deme, cDeme& target_deme)
-
-
-
// Do the actual copy!
for (int i = 0; i < from_deme.GetSize(); i++) {
int from_cell_id = from_deme.GetCellID(i);
@@ -1205,7 +1206,13 @@
// Stat-tracking:
m_world->GetStats().CompeteDemes(fitness);
-
+
+ // This is to facilitate testing. Obviously we can't do competition if there's
+ // only one deme, but we do want the stat-tracking.
+ if(fitness.size()==1) {
+ return;
+ }
+
// 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);
@@ -1232,7 +1239,7 @@
if(deme_counts[i] == 1)
ReplaceDeme(deme_array[i], deme_array[i]);
}
-
+
// 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) {
@@ -2172,7 +2179,7 @@
}
}
-return successfully_seeded;
+ return successfully_seeded;
}
void cPopulation::InjectDemeFounder(int _cell_id, cGenotype& _genotype, cPhenotype* _phenotype)
Modified: branches/movement/source/main/cPopulationInterface.cc
===================================================================
--- branches/movement/source/main/cPopulationInterface.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cPopulationInterface.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -335,3 +335,17 @@
}
}
}
+
+/*! Send a flash to all neighboring organisms. */
+void cPopulationInterface::SendFlash() {
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
+ assert(cell.IsOccupied());
+
+ for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+ cPopulationCell* neighbor = cell.ConnectionList().GetFirst();
+ if(neighbor->IsOccupied()) {
+ neighbor->GetOrganism()->ReceiveFlash();
+ }
+ cell.ConnectionList().CircNext();
+ }
+}
Modified: branches/movement/source/main/cPopulationInterface.h
===================================================================
--- branches/movement/source/main/cPopulationInterface.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cPopulationInterface.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -105,9 +105,10 @@
bool TestOnDivide();
//! Send a message to the faced organism.
bool SendMessage(cOrgMessage& msg);
- bool BcastAlarm(int jump_label, int bcast_range);
-
+ bool BcastAlarm(int jump_label, int bcast_range);
void DivideOrgTestamentAmongDeme(double value);
+ //! Send a flash to all neighboring organisms.
+ void SendFlash();
};
Modified: branches/movement/source/main/cStats.cc
===================================================================
--- branches/movement/source/main/cStats.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cStats.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -1268,8 +1268,7 @@
void cStats::SentMessage(const cOrgMessage& msg)
{
// Check to see if this message matches any of our predicates.
- for(message_pred_ptr_list::iterator i=m_message_predicates.begin();
- i!=m_message_predicates.end(); ++i) {
+ for(message_pred_ptr_list::iterator i=m_message_predicates.begin(); i!=m_message_predicates.end(); ++i) {
(**i)(msg); // Predicate is responsible for tracking info about messages.
}
}
@@ -1331,29 +1330,24 @@
/*! This method prints information contained within all active message predicates.
-about specific messages that are being tracked.
-The messages that are being tracked are setup by the AddTrackedMessage method below.
-
-The format of this log file is:
-<update> \
-<predicate>:{<cell_id>,...}...
-*/
+ Each row of the data file has the following format:
+ update predicate_name predicate_data...
+ */
void cStats::PrintPredicatedMessages(const cString& filename)
{
cDataFile& df = m_world->GetDataFile(filename);
df.WriteColumnDesc("update [update]");
- df.WriteColumnDesc("predicate:{p_info,...}...");
+ df.WriteColumnDesc("predicate name: [pname]");
+ df.WriteColumnDesc("predicate data: [pdata]");
df.FlushComments();
- df.WriteAnonymous(GetUpdate());
std::ofstream& out = df.GetOFStream();
for(message_pred_ptr_list::iterator i=m_message_predicates.begin();
i!=m_message_predicates.end(); ++i) {
- (*i)->Print(out);
+ (*i)->Print(GetUpdate(), out);
(*i)->Reset();
- out << " ";
}
- df.Endl();
+// df.Endl();
}
void cStats::PrintPredSatFracDump(const cString& filename) {
@@ -1712,7 +1706,6 @@
df.WriteComment("First column gives the current update, all further columns give the number");
df.WriteComment("number of generations that passed between the parent and current deme's founders");
-
df.Write(m_update, "Update");
for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
cDeme& deme = m_world->GetPopulation().GetDeme(i);
@@ -1745,3 +1738,94 @@
m_deme_fitness.clear();
}
+
+
+/*! Prints the cell data from every cell, including the deme for that cell. */
+void cStats::PrintCellData(const cString& filename) {
+ cDataFile& df = m_world->GetDataFile(filename);
+ df.WriteComment("Cell data per udpate.");
+ df.WriteTimeStamp();
+
+ for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+ const cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+ df.Write(GetUpdate(), "Update [update]");
+ df.Write(cell.GetID(), "Global cell ID [globalid]");
+ df.Write(cell.GetDemeID(), "Deme ID for cell [demeid]");
+ df.Write(cell.GetCellData(), "Cell data [data]");
+ df.Endl();
+ }
+}
+
+
+void cStats::PrintCurrentOpinions(const cString& filename) {
+ cDataFile& df = m_world->GetDataFile(filename);
+ df.WriteComment("Current opinions of each organism.");
+ df.WriteTimeStamp();
+ df.WriteComment("1: Update [update]");
+ df.WriteComment("2: Global cell ID [globalid]");
+ df.WriteComment("3: Current opinion [opinion]");
+ df.FlushComments();
+
+ for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+ const cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+ df.WriteAnonymous(GetUpdate());
+ df.WriteAnonymous(cell.GetID());
+ if(cell.IsOccupied() && cell.GetOrganism()->HasOpinion()) {
+ df.WriteAnonymous(cell.GetOrganism()->GetOpinion().first);
+ } else {
+ df.WriteAnonymous(0);
+ }
+ df.Endl();
+ }
+}
+
+/*! Called when an organism issues a flash instruction.
+
+ We do some pretty detailed tracking here in order to support the use of flash
+ messages in deme competition. All flashes are tracked per deme.
+ */
+void cStats::SentFlash(cOrganism& organism) {
+ ++m_flash_count;
+ if(organism.GetOrgInterface().GetDeme() != 0) {
+ const cDeme* deme = organism.GetOrgInterface().GetDeme();
+ m_flash_times[GetUpdate()][deme->GetID()].push_back(deme->GetRelativeCellID(organism.GetCellID()));
+ }
+}
+
+
+/*! Print statistics about synchronization flashes. */
+void cStats::PrintSynchronizationData(const cString& filename) {
+ cDataFile& df = m_world->GetDataFile(filename);
+
+ df.WriteComment("Avida synchronization data");
+ df.WriteTimeStamp();
+ df.Write(m_update, "Update [update]");
+ df.Write(m_flash_count, "Flash count [fcount]");
+ df.Endl();
+
+ m_flash_count = 0;
+ m_flash_times.clear();
+}
+
+
+/*! Print detailed synchronization data. */
+void cStats::PrintDetailedSynchronizationData(const cString& filename) {
+ cDataFile& df = m_world->GetDataFile(filename);
+
+ df.WriteComment("Detailed Avida synchronization data");
+ df.WriteComment("Rows are (update, demeid, cellid) tuples, representing the update at which that cell flashed.");
+ df.WriteTimeStamp();
+
+ for(PopulationFlashes::iterator i=m_flash_times.begin(); i!=m_flash_times.end(); ++i) {
+ for(DemeFlashes::iterator j=i->second.begin(); j!=i->second.end(); ++j) {
+ for(CellFlashes::iterator k=j->second.begin(); k!=j->second.end(); ++k) {
+ df.Write(i->first, "Update [update]");
+ df.Write(j->first, "Deme ID [demeid]");
+ df.Write(*k, "Deme-relative cell ID that issued a flash at this update [relcellid]");
+ df.Endl();
+ }
+ }
+ }
+
+ m_flash_times.clear();
+}
Modified: branches/movement/source/main/cStats.h
===================================================================
--- branches/movement/source/main/cStats.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/main/cStats.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -868,6 +868,33 @@
private:
std::vector<double> m_deme_fitness; //!< Fitness of each deme during last deme competition.
+
+ // -------- Cell data support --------
+public:
+ //! Prints the cell data from every cell in the population.
+ void PrintCellData(const cString& filename);
+
+ // -------- Opinion support --------
+public:
+ //! Prints the current opinions of all organisms in the population.
+ void PrintCurrentOpinions(const cString& filename);
+
+ // -------- Synchronization support --------
+public:
+ typedef std::vector<int> CellFlashes; //!< Typedef for a list of cell IDs.
+ typedef std::map<int, CellFlashes> DemeFlashes; //!< Typedef for cell IDs (in this deme) -> list of cell IDs.
+ typedef std::map<int, DemeFlashes> PopulationFlashes; //!< Typedef for deme IDs -> flashes in that deme.
+ //! Called immediately after an organism has issued a "flash" to its neighbors.
+ void SentFlash(cOrganism& organism);
+ //! Retrieve the cell ID -> flash time map.
+ const PopulationFlashes& GetFlashTimes() { return m_flash_times; }
+ //! Print statistics about synchronization flashes.
+ void PrintSynchronizationData(const cString& filename);
+ //! Print detailed information regarding synchronization flashes.
+ void PrintDetailedSynchronizationData(const cString& filename);
+protected:
+ int m_flash_count; //!< Number of flashes that have occured since last PrintSynchronizationData.
+ PopulationFlashes m_flash_times; //!< For tracking flashes that have occurred throughout this population.
};
Modified: branches/movement/source/script/AvidaScript.h
===================================================================
--- branches/movement/source/script/AvidaScript.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/script/AvidaScript.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -164,6 +164,7 @@
AS_DIRECT_INTERPRET_ERR_KEY_NOT_FOUND,
AS_DIRECT_INTERPRET_ERR_MATRIX_OP_TYPE_MISMATCH,
AS_DIRECT_INTERPRET_ERR_MATRIX_SIZE_MISMATCH,
+ AS_DIRECT_INTERPRET_ERR_NATIVE_OBJECT_TYPE_MISMATCH,
AS_DIRECT_INTERPRET_ERR_OBJECT_ASSIGN_FAIL,
AS_DIRECT_INTERPRET_ERR_TYPE_CAST,
AS_DIRECT_INTERPRET_ERR_UNDEFINED_TYPE_OP,
Modified: branches/movement/source/script/cASNativeObject.h
===================================================================
--- branches/movement/source/script/cASNativeObject.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/script/cASNativeObject.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -33,17 +33,40 @@
class cASNativeObject
{
+private:
+ int m_ref_count;
public:
- cASNativeObject() { ; }
+ cASNativeObject() : m_ref_count(1) { ; }
virtual ~cASNativeObject() { ; }
- bool CallMethod(int mid, int argc, cASCPPParameter args[]) { return false; } // @TODO
+ virtual const char* GetType() = 0;
+ virtual bool CallMethod(int mid, int argc, cASCPPParameter args[]) = 0;
+
int LookupValue(const cString& val_name) { return AS_NOT_FOUND; } // @TODO
int LookupMethod(const cString& meth_name) { return AS_NOT_FOUND; } // @TODO
- void Release() { ; }
+ inline cASNativeObject* GetReference() { m_ref_count++; return this; }
+ inline void RemoveReference() { m_ref_count--; if (m_ref_count == 0) delete this; }
+ inline bool IsShared() { return (m_ref_count > 1); }
};
+
+template<class NativeClass, const char* TypeName>
+class tASNativeObject : public cASNativeObject
+{
+private:
+ NativeClass* m_object;
+
+public:
+ tASNativeObject(NativeClass* obj) : m_object(obj) { ; }
+ ~tASNativeObject() { delete m_object; }
+
+ const char* GetType() { return TypeName; }
+
+ bool CallMethod(int mid, int argc, cASCPPParameter args[]) { return false; } // @TODO;
+};
+
+
#endif
Modified: branches/movement/source/script/cDirectInterpretASTVisitor.cc
===================================================================
--- branches/movement/source/script/cDirectInterpretASTVisitor.cc 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/script/cDirectInterpretASTVisitor.cc 2008-09-29 12:20:07 UTC (rev 2804)
@@ -116,7 +116,10 @@
case TYPE(CHAR): m_call_stack[sp + var_id].value.as_char = asChar(m_rtype, m_rvalue, node); break;
case TYPE(FLOAT): m_call_stack[sp + var_id].value.as_float = asFloat(m_rtype, m_rvalue, node); break;
case TYPE(INT): m_call_stack[sp + var_id].value.as_int = asInt(m_rtype, m_rvalue, node); break;
- case TYPE(OBJECT_REF): INTERPRET_ERROR(INTERNAL); // @TODO - assignment
+
+ case TYPE(OBJECT_REF):
+ m_call_stack[sp + var_id].value.as_nobj->RemoveReference();
+ m_call_stack[sp + var_id].value.as_nobj = asNativeObject(symtbl->GetVariableType(var_id).info, m_rtype, m_rvalue, node);
case TYPE(VAR):
m_call_stack[sp + var_id].value = m_rvalue;
@@ -212,7 +215,10 @@
case TYPE(CHAR): m_call_stack[var_idx].value.as_char = asChar(val.type, val.value, node); break;
case TYPE(FLOAT): m_call_stack[var_idx].value.as_float = asFloat(val.type, val.value, node); break;
case TYPE(INT): m_call_stack[var_idx].value.as_int = asInt(val.type, val.value, node); break;
- case TYPE(OBJECT_REF): INTERPRET_ERROR(INTERNAL); // @TODO - foreach assignment
+ case TYPE(OBJECT_REF):
+ m_call_stack[var_idx].value.as_nobj->RemoveReference();
+ m_call_stack[var_idx].value.as_nobj = asNativeObject(var_type.info, val.type, val.value, node);
+ break;
case TYPE(ARRAY):
m_call_stack[var_idx].value.as_array->RemoveReference();
@@ -306,7 +312,7 @@
case TYPE(DICT): m_call_stack[m_sp + var_id].value.as_dict = asDict(m_rtype, m_rvalue, node); break;
case TYPE(FLOAT): m_call_stack[m_sp + var_id].value.as_float = asFloat(m_rtype, m_rvalue, node); break;
case TYPE(INT): m_call_stack[m_sp + var_id].value.as_int = asInt(m_rtype, m_rvalue, node); break;
- case TYPE(OBJECT_REF): INTERPRET_ERROR(INTERNAL); // @TODO - var def assignment
+ case TYPE(OBJECT_REF): m_call_stack[m_sp + var_id].value.as_nobj = asNativeObject(node.GetType().info, m_rtype, m_rvalue, node); break;
case TYPE(MATRIX): m_call_stack[m_sp + var_id].value.as_matrix = asMatrix(m_rtype, m_rvalue, node); break;
case TYPE(STRING):
delete m_call_stack[m_sp + var_id].value.as_string;
@@ -342,6 +348,8 @@
} else {
INTERPRET_ERROR(INTERNAL);
}
+ } else if (node.GetType().type == TYPE(OBJECT_REF)) {
+ // @TODO - set native object ref to special NULL value
}
}
@@ -1243,7 +1251,7 @@
case TYPE(DICT): m_call_stack[sp + var_id].value.as_dict = asDict(m_rtype, m_rvalue, node); break;
case TYPE(FLOAT): m_call_stack[sp + var_id].value.as_float = asFloat(m_rtype, m_rvalue, node); break;
case TYPE(INT): m_call_stack[sp + var_id].value.as_int = asInt(m_rtype, m_rvalue, node); break;
- case TYPE(OBJECT_REF): INTERPRET_ERROR(INTERNAL); // @TODO - func call arg assignment
+ case TYPE(OBJECT_REF): m_call_stack[sp + var_id].value.as_nobj = asNativeObject(func_symtbl->GetVariableType(var_id).info, m_rtype, m_rvalue, node); break;
case TYPE(MATRIX): m_call_stack[sp + var_id].value.as_matrix = asMatrix(m_rtype, m_rvalue, node); break;
case TYPE(STRING):
{
@@ -1275,7 +1283,7 @@
case TYPE(DICT): m_rvalue.as_dict = asDict(m_rtype, m_rvalue, node); break;
case TYPE(FLOAT): m_rvalue.as_float = asFloat(m_rtype, m_rvalue, node); break;
case TYPE(INT): m_rvalue.as_int = asInt(m_rtype, m_rvalue, node); break;
- case TYPE(OBJECT_REF): INTERPRET_ERROR(INTERNAL); // @TODO - return
+ case TYPE(OBJECT_REF): m_rvalue.as_nobj = asNativeObject(node.GetType().info, m_rtype, m_rvalue, node); break;
case TYPE(MATRIX): m_rvalue.as_matrix = asMatrix(m_rtype, m_rvalue, node); break;
case TYPE(STRING): m_rvalue.as_string = asString(m_rtype, m_rvalue, node); break;
case TYPE(VAR): break;
@@ -1434,7 +1442,7 @@
switch (node.GetType().type) {
case TYPE(ARRAY): m_rvalue.as_ref = new cArrayVarRef(m_call_stack[sp + var_id].value); break;
case TYPE(DICT): m_rvalue.as_ref = new cDictVarRef(m_call_stack[sp + var_id].value); break;
- case TYPE(OBJECT_REF): INTERPRET_ERROR(INTERNAL); // @TODO - var ref object assignment
+ case TYPE(OBJECT_REF): m_rvalue.as_ref = new cNativeObjectVarRef(m_call_stack[sp + var_id].value); break;
case TYPE(MATRIX): m_rvalue.as_ref = new cMatrixVarRef(m_call_stack[sp + var_id].value); break;
case TYPE(STRING): m_rvalue.as_ref = new cStringVarRef(m_call_stack[sp + var_id].value); break;
@@ -1459,7 +1467,7 @@
case TYPE(STRING): m_rvalue.as_string = new cString(*m_call_stack[sp + var_id].value.as_string); break;
- case TYPE(OBJECT_REF): INTERPRET_ERROR(INTERNAL); // @TODO - var ref assignment
+ case TYPE(OBJECT_REF): m_rvalue.as_nobj = m_call_stack[sp + var_id].value.as_nobj->GetReference(); break;
default:
INTERPRET_ERROR(INTERNAL);
@@ -1490,7 +1498,10 @@
case TYPE(CHAR): m_call_stack[var_idx].value.as_char = asChar(val.type, val.value, node); break;
case TYPE(FLOAT): m_call_stack[var_idx].value.as_float = asFloat(val.type, val.value, node); break;
case TYPE(INT): m_call_stack[var_idx].value.as_int = asInt(val.type, val.value, node); break;
- case TYPE(OBJECT_REF): INTERPRET_ERROR(INTERNAL); // @TODO - assignment
+ case TYPE(OBJECT_REF):
+ m_call_stack[var_idx].value.as_nobj->RemoveReference();
+ m_call_stack[var_idx].value.as_nobj = asNativeObject(var_type.info, val.type, val.value, node);
+ break;
case TYPE(VAR):
m_call_stack[var_idx].value = val.value;
@@ -1757,6 +1768,22 @@
}
+cASNativeObject* cDirectInterpretASTVisitor::asNativeObject(const cString& info, const sASTypeInfo& type, uAnyType value,
+ cASTNode& node)
+{
+ switch (type.type) {
+ case TYPE(OBJECT_REF):
+ if (type.info != info) INTERPRET_ERROR(NATIVE_OBJECT_TYPE_MISMATCH, *info, *type.info);
+ return value.as_nobj;
+
+ default:
+ INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(OBJECT_REF)));
+ }
+
+ return NULL;
+}
+
+
cString* cDirectInterpretASTVisitor::asString(const sASTypeInfo& type, uAnyType value, cASTNode& node)
{
switch (type.type) {
@@ -1786,9 +1813,9 @@
return str;
}
- case TYPE(OBJECT_REF): // @TODO - as string
+ case TYPE(OBJECT_REF):
{
- cString* str = new cString(cStringUtil::Stringf("< object >"));
+ cString* str = new cString(cStringUtil::Stringf("< %s object @ %p >", value.as_nobj->GetType(), value.as_nobj));
return str;
}
@@ -2196,9 +2223,7 @@
case TYPE(ARRAY): return value.as_array == lval.value.as_array;
case TYPE(DICT): return value.as_dict == lval.value.as_dict;
case TYPE(MATRIX): return value.as_matrix == lval.value.as_matrix;
-
- case TYPE(OBJECT_REF): // @TODO - aggregate value compare
- return value.as_void == lval.value.as_void;
+ case TYPE(OBJECT_REF): return value.as_nobj == lval.value.as_nobj;
default:
break;
@@ -2497,8 +2522,21 @@
}
+bool cDirectInterpretASTVisitor::cNativeObjectVarRef::Get(const sAggregateValue& idx, sAggregateValue& val)
+{
+ // @TODO - get indexed native var
+ return false;
+}
+bool cDirectInterpretASTVisitor::cNativeObjectVarRef::Set(sAggregateValue& idx, sAggregateValue& val)
+{
+ // @TODO - set indexed native var
+ return false;
+}
+
+
+
bool cDirectInterpretASTVisitor::cObjectIndexRef::Get(const sAggregateValue& idx, sAggregateValue& val)
{
sAggregateValue o_val;
@@ -2721,6 +2759,13 @@
case AS_DIRECT_INTERPRET_ERR_MATRIX_SIZE_MISMATCH:
std::cerr << "matrix size mismatch for '" << VA_ARG_STR << "' operation" << ERR_ENDL;
break;
+ case AS_DIRECT_INTERPRET_ERR_NATIVE_OBJECT_TYPE_MISMATCH:
+ {
+ const char* otype = VA_ARG_STR;
+ const char* itype = VA_ARG_STR;
+ std::cerr << "expected object of type '" << otype << "', received '" << itype << "'" << ERR_ENDL;
+ }
+ break;
case AS_DIRECT_INTERPRET_ERR_OBJECT_ASSIGN_FAIL:
std::cerr << "aggregate assignment failed" << ERR_ENDL;
break;
Modified: branches/movement/source/script/cDirectInterpretASTVisitor.h
===================================================================
--- branches/movement/source/script/cDirectInterpretASTVisitor.h 2008-09-28 23:08:43 UTC (rev 2803)
+++ branches/movement/source/script/cDirectInterpretASTVisitor.h 2008-09-29 12:20:07 UTC (rev 2804)
@@ -54,6 +54,7 @@
cLocalDict* as_dict;
cLocalMatrix* as_matrix;
cObjectRef* as_ref;
+ cASNativeObject* as_nobj;
void* as_void;
} uAnyType;
@@ -133,6 +134,7 @@
int asInt(const sASTypeInfo& type, uAnyType value, cASTNode& node);
double asFloat(const sASTypeInfo& type, uAnyType value, cASTNode& node);
cLocalMatrix* asMatrix(const sASTypeInfo& type, uAnyType value, cASTNode& node);
+ cASNativeObject* asNativeObject(const cString& info, const sASTypeInfo& type, uAnyType value, cASTNode& node);
cString* asString(const sASTypeInfo& type, uAnyType value, cASTNode& node);
ASType_t getRuntimeType(ASType_t ltype, ASType_t rtype, bool allow_str = false);
@@ -307,20 +309,20 @@
bool Set(sAggregateValue& idx, sAggregateValue& val);
};
- class cNativeObjectRef : public cObjectRef
+ class cNativeObjectVarRef : public cObjectRef
{
private:
- cASNativeObject* m_no;
+ uAnyType& m_var;
public:
- cNativeObjectRef();
- ~cNativeObjectRef() { m_no->Release(); }
+ cNativeObjectVarRef(uAnyType& var) : m_var(var) { ; }
+ ~cNativeObjectVarRef() { ; }
bool IsWritable() { return false; }
- bool Get(sAggregateValue& val) { return false; }
- bool Get(const sAggregateValue& idx, sAggregateValue& val) { return false; }
+ bool Get(sAggregateValue& val) { val.value = m_var; val.type = AS_TYPE_OBJECT_REF; return false; }
+ bool Get(const sAggregateValue& idx, sAggregateValue& val);
bool Set(sAggregateValue& val) { return false; }
- bool Set(sAggregateValue& idx, sAggregateValue& val) { return false; }
+ bool Set(sAggregateValue& idx, sAggregateValue& val);
};
class cObjectIndexRef : public cObjectRef
More information about the Avida-cvs
mailing list