[Avida-SVN] r1146 - in branches/coopcomm/source: actions main

dknoester at myxo.css.msu.edu dknoester at myxo.css.msu.edu
Sun Dec 17 19:05:22 PST 2006


Author: dknoester
Date: 2006-12-17 22:05:22 -0500 (Sun, 17 Dec 2006)
New Revision: 1146

Modified:
   branches/coopcomm/source/actions/PopulationActions.cc
   branches/coopcomm/source/actions/PrintActions.cc
   branches/coopcomm/source/main/cOrgMessage.h
   branches/coopcomm/source/main/cOrganism.cc
   branches/coopcomm/source/main/cPopulation.cc
   branches/coopcomm/source/main/cPopulation.h
   branches/coopcomm/source/main/cPopulationCell.cc
   branches/coopcomm/source/main/cPopulationCell.h
   branches/coopcomm/source/main/cStats.cc
   branches/coopcomm/source/main/cStats.h
Log:
Added more detailed logging options for leader election, including:
- Changed IDs
- Elected IDs
- Message logging
and Cell IDs.

Note: The message_log.dat file has been renamed to message_summary.dat.



Modified: branches/coopcomm/source/actions/PopulationActions.cc
===================================================================
--- branches/coopcomm/source/actions/PopulationActions.cc	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/actions/PopulationActions.cc	2006-12-18 03:05:22 UTC (rev 1146)
@@ -984,14 +984,21 @@
 };
 
 
+/*! A DemeFitnessFunction that also ratchets the leader when a deme has reached agreement.
+By "ratchet," we mean that the elected leader's ID is reset, and the fitness of this deme
+includes a reward for having elected that leader.
+*/
 struct ratcheting_popular_vote 
 : public std::binary_function<cPopulation::t_CellIterator, cPopulation::t_CellIterator, double> {
+  //! Returns a description of this fitness function.
   static std::string GetDescription() {
     return "ratcheting popular vote";
   }
   
-  ratcheting_popular_vote(cWorld* world, const cString& args)
-  : m_world(world) {
+  //! Constructor; must be supplied with the world and deme_id.
+  ratcheting_popular_vote(unsigned int deme_id, cWorld* world, const cString& args)
+  : m_demeId(deme_id)
+  , m_world(world) {
     m_previousLeaders.clear();
   }
   
@@ -1003,8 +1010,7 @@
   In this case, we want to do the following: First, run the vote calculator.  Then,
   tally up the votes, and remove the votes for a given set of IDs.
   
-  The resulting fitness is max_vote^r_1 + max_vote^r_2..., where r is the number 
-  of times that this deme has beeen ratcheted.
+  The resulting fitness is (current_max_votes + num_previous_leaders*100)^2.
   */
   double operator()(cPopulation::t_CellIterator begin, cPopulation::t_CellIterator end) {
     vote_calculator vc = std::for_each(begin, end, vote_calculator());
@@ -1012,32 +1018,41 @@
     std::pair<vote_calculator::vote_tally, max_vote> vt = vc.tally(max_vote());
     if(vt.second.m_maxVote == 100) {
       m_previousLeaders.push_back(vt.second.m_maxID);
+      cPopulationCell* cell = cPopulationCell::GetRandomCellIDMap()[vt.second.m_maxID];
+      m_world->GetStats().DemeElected(m_demeId, vt.second.m_maxID, cell->GetID());
       vt.second.m_maxVote = 0;
       // and reset the leader ID
-      cPopulationCell::GetRandomCellIDMap()[vt.second.m_maxID]->ResetRandomCellID();
+      cell->ResetRandomCellID();
     }
         
-    // square it so that there's always a huge benefit to getting just one more.
+    // Square it so that there's always a huge benefit to getting just one more.
     return pow(vt.second.m_maxVote + m_previousLeaders.size()*100, 2);
-  }
+  }  
   
-  std::vector<int> m_previousLeaders;
-  cWorld* m_world;
+  std::vector<int> m_previousLeaders; //!< The list of previous leaders.
+  unsigned int m_demeId; //!< The id of the deme associated with this fitness function.
+  cWorld* m_world; //!< Pointer to the world (for cStats).
 };
 
 
+/*! A fitness function that maintains the state of the function objects used to calculate
+the fitness for each deme.
+*/
 template< typename DemeFitnessFunction >
 struct stateful_fitness : public std::unary_function<cPopulation::t_CellRangeList, void> {
+  //! Returns a description of the fitness function.
   static std::string GetDescription() {
     return "Stateful fitness:" + DemeFitnessFunction::GetDescription();
   }
   
+  //! Constructor.
   stateful_fitness(cWorld* world, const cString& args) 
   : m_world(world)
   , m_args(args) {
     reset();
   }
   
+  //! Calculates the fitness of each deme.
   void operator()(cPopulation::t_CellRangeList cell_ranges) {
     typedef typename std::vector<DemeFitnessFunction>::iterator dffiter;
     cPopulation::t_CellRangeList::iterator demei = cell_ranges.begin();
@@ -1048,21 +1063,34 @@
     }                                                                   
   }
 
+  //! Resets the fitness function used for each deme.
   void reset() {
     m_demeFitness.clear();
     for(unsigned int i=0; i<m_world->GetPopulation().GetDemes().size(); ++i) {
-      m_demeFitness.push_back(DemeFitnessFunction(m_world,m_args));
+      m_demeFitness.push_back(DemeFitnessFunction(i,m_world,m_args));
     }    
   }
   
+  //! Retrieve the fitnesses of each deme.
   const std::vector<double>& fitnesses() { return m_fitness; }
   
+  //! List of dunction objects that calculate deme fitness.
   std::vector<DemeFitnessFunction> m_demeFitness;
-  std::vector<double> m_fitness;
-  cWorld* m_world;
-  cString m_args;
+  std::vector<double> m_fitness; //!< Current fitnesses of each deme.
+  cWorld* m_world; //!< Pointer to the world (for cPopulation).
+  cString m_args; //!< Initialization arguments (for resetting function objects).
 };
 
+
+/*! An adaptable compete demes event.
+This event is modeled after the STL's Adaptable{Unary,Binary} Functions, in that
+it uses templates to modify much of its behavior.
+
+- Every time this event is fired (based on events.cfg), the fitness of each deme
+is calculated using the FitnessFunction.
+- Then, if the CompetitionPredicate evaluates to true, then the demes are competed
+against each other according to the CompetitionStrategy.
+*/
 template< typename FitnessFunction, 
           typename CompetitionStrategy=ga_competition_strategy<FitnessFunction>,
           typename CompetePredicate=always_compete<FitnessFunction> >
@@ -1072,6 +1100,7 @@
   typedef CompetitionStrategy competition_strategy;
   typedef CompetePredicate compete_predicate;
   
+  //! \todo This is broken; at return the std::string is destroyed.
   static const cString GetDescription() {
     return std::string("Adaptable Deme Competition: " + 
                        FitnessFunction::GetDescription() + " ; " + 
@@ -1703,6 +1732,31 @@
 };
 
 
+class cActionToggleMessageLog : public cAction
+{
+public:
+  cActionToggleMessageLog(cWorld* world, const cString& args) 
+  : cAction(world, args) {
+  }
+  
+  virtual ~cActionToggleMessageLog() { }    
+  
+  //! Return a string description of the arguments for this action.
+  static const cString GetDescription() 
+  { 
+    return "Toggles the level of detail in message logging.";
+  }
+  
+  //! Perform this action.
+  void Process(cAvidaContext& ctx)
+  {
+    m_world->GetStats().ToggleMessageLog();
+  }
+};
+    
+  
+
+
 void RegisterPopulationActions(cActionLibrary* action_lib)
 {
   action_lib->Register<cActionInject>("Inject");
@@ -1741,6 +1795,7 @@
   action_lib->Register<cActionAddMessagePredicate>("AddMessagePredicate");
   action_lib->Register<cActionAddBaseStationPredicate>("AddBaseStationPredicate");
   action_lib->Register<cActionMessageRain>("MessageRain");
+  action_lib->Register<cActionToggleMessageLog>("ToggleMessageLog");
   action_lib->Register<
     cActionAdaptableCompeteDemes< stateful_fitness<ratcheting_popular_vote>,
                                   ga_competition_strategy<stateful_fitness<ratcheting_popular_vote> >,

Modified: branches/coopcomm/source/actions/PrintActions.cc
===================================================================
--- branches/coopcomm/source/actions/PrintActions.cc	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/actions/PrintActions.cc	2006-12-18 03:05:22 UTC (rev 1146)
@@ -66,17 +66,16 @@
 STATS_OUT_FILE(PrintMarketData,		   market.dat		   );
 
 // Coop-comm
-STATS_OUT_FILE(PrintLeaderData, leader_log.dat);
-STATS_OUT_FILE(PrintCellData, cell_log.dat);
-STATS_OUT_FILE(PrintMessageData, message_log.dat);
+STATS_OUT_FILE(PrintCellIDs, cell_ids.dat);
+STATS_OUT_FILE(PrintMessageSummary, message_summary.dat);
 STATS_OUT_FILE(PrintDemeFitness, deme_fitness.dat);
 STATS_OUT_FILE(PrintDemeGenomes, deme_genomes.dat);
-STATS_OUT_FILE(PrintIDData, id_log.dat);
 STATS_OUT_FILE(PrintMessageDataPerUpdate, message.dat);
-STATS_OUT_FILE(PrintMessageSnapshot, msg_snapshot.dat);
 STATS_OUT_FILE(PrintPredicatedMessages, predicated_msgs.dat);
+STATS_OUT_FILE(PrintElectionRecord, election.dat);
+STATS_OUT_FILE(PrintIDChanges, id_changes.dat);
+STATS_OUT_FILE(PrintMessageLog, message_log.dat);
 
-
 #define POP_OUT_FILE(METHOD, DEFAULT)                                                     /*  1 */ \
 class cAction ## METHOD : public cAction {                                                /*  2 */ \
 private:                                                                                  /*  3 */ \
@@ -1529,16 +1528,18 @@
   action_lib->Register<cActionSetVerbose>("SetVerbose");
   
   // Coop-comm actions.
-  action_lib->Register<cActionPrintLeaderData>("PrintLeaderData");
-  action_lib->Register<cActionPrintCellData>("PrintCellData");
-  action_lib->Register<cActionPrintMessageData>("PrintMessageData"); 
+  action_lib->Register<cActionPrintCellIDs>("PrintCellIDs");
+  action_lib->Register<cActionPrintMessageSummary>("PrintMessageSummary"); 
   action_lib->Register<cActionPrintDemeFitness>("PrintDemeFitness");
   action_lib->Register<cActionPrintDemeGenomes>("PrintDemeGenomes");
-  action_lib->Register<cActionPrintIDData>("PrintIDData");  
   action_lib->Register<cActionPrintMessageDataPerUpdate>("PrintMessageDataPerUpdate");
-  action_lib->Register<cActionPrintMessageSnapshot>("PrintMessageSnapshot");
   action_lib->Register<cActionPrintPredicatedMessages>("PrintPredicatedMessages");
+  action_lib->Register<cActionPrintElectionRecord>("PrintElectionRecord");
+  action_lib->Register<cActionPrintIDChanges>("PrintIDChanges");
+  action_lib->Register<cActionPrintMessageLog>("PrintMessageLog");
   
+  
+  
   // @DMB - The following actions are DEPRECATED aliases - These will be removed in 2.7.
   action_lib->Register<cActionPrintAverageData>("print_average_data");
   action_lib->Register<cActionPrintErrorData>("print_error_data");

Modified: branches/coopcomm/source/main/cOrgMessage.h
===================================================================
--- branches/coopcomm/source/main/cOrgMessage.h	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/main/cOrgMessage.h	2006-12-18 03:05:22 UTC (rev 1146)
@@ -26,19 +26,18 @@
   unsigned int m_data;
   unsigned int m_label;
   
-  cOrgMessage() : m_pSender(NULL), m_pReceiver(NULL), m_data(0), m_label(0) { }
+  cOrgMessage() 
+  : m_pSender(NULL), m_pReceiver(NULL), m_data(0), m_label(0) {
+  }
   
 public:
-  cOrgMessage(cOrganism* sender) : 
-    m_pSender(sender),
-    m_pReceiver(NULL),
-    m_data(0),
-    m_label(0)  
-  { }
+  cOrgMessage(cOrganism* sender)
+  : m_pSender(sender), m_pReceiver(NULL), m_data(0), m_label(0) {
+  }
   
-  explicit cOrgMessage(int data, int label) : 
-    m_pSender(NULL), m_pReceiver(NULL), m_data(data), m_label(label) {
-    }
+  explicit cOrgMessage(int data, int label)
+  : m_pSender(NULL), m_pReceiver(NULL), m_data(data), m_label(label) {
+  }
 
   static cOrgMessage EmptyMessage() { return cOrgMessage(); }
   

Modified: branches/coopcomm/source/main/cOrganism.cc
===================================================================
--- branches/coopcomm/source/main/cOrganism.cc	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/main/cOrganism.cc	2006-12-18 03:05:22 UTC (rev 1146)
@@ -87,9 +87,6 @@
 
 cOrganism::~cOrganism()
 {
-  // Stat-tracking.
-  m_world->GetStats().OrganismDeath(this);
-
   // Clean up after organisms that think this one is their leader.
   for(t_organism_list::iterator i=m_lead.begin(); i!=m_lead.end(); ++i) {
     (*i)->ResetLeader();

Modified: branches/coopcomm/source/main/cPopulation.cc
===================================================================
--- branches/coopcomm/source/main/cPopulation.cc	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/main/cPopulation.cc	2006-12-18 03:05:22 UTC (rev 1146)
@@ -268,7 +268,11 @@
     m_demeCellRanges.push_back(t_CellRange(cell_array.GetPtr()+i*deme_size,
                                            cell_array.GetPtr()+(i+1)*deme_size));
   }
-  
+  // Cells need to know which deme they're part of (for cStats).
+  for(int i=0,j=0; i<cell_array.GetSize(); ++i) {
+    j = i / num_demes;
+    cell_array[i].SetDemeID(j);
+  }
   return true;
 }
 
@@ -1868,12 +1872,22 @@
 }
 
 
+cPopulation::t_CellIterator cPopulation::CellBegin() {
+  return cell_array.GetPtr();
+}
+
+cPopulation::t_CellIterator cPopulation::CellEnd() {
+  return cell_array.GetPtr() + cell_array.GetSize();
+}
+
 cPopulationCell& cPopulation::GetCell(int in_num)
 {
   return cell_array[in_num];
 }
 
 
+
+
 void cPopulation::UpdateResources(const tArray<double> & res_change)
 {
   resource_count.Modify(res_change);

Modified: branches/coopcomm/source/main/cPopulation.h
===================================================================
--- branches/coopcomm/source/main/cPopulation.h	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/main/cPopulation.h	2006-12-18 03:05:22 UTC (rev 1146)
@@ -185,6 +185,8 @@
   int GetWorldY() { return world_y; }
 
   t_CellArray& GetCellArray() { return cell_array; }
+  t_CellIterator CellBegin();
+  t_CellIterator CellEnd();
   cPopulationCell& GetCell(int in_num);
   
   const tArray<double>& GetResources() const { return resource_count.GetResources(); }

Modified: branches/coopcomm/source/main/cPopulationCell.cc
===================================================================
--- branches/coopcomm/source/main/cPopulationCell.cc	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/main/cPopulationCell.cc	2006-12-18 03:05:22 UTC (rev 1146)
@@ -13,6 +13,7 @@
 #include "cOrganism.h"
 #include "cTools.h"
 #include "cWorld.h"
+#include "cStats.h"
 
 using namespace std;
 
@@ -25,6 +26,7 @@
   , organism(NULL)
   , mutation_rates(NULL)
   , cur_input(0)
+  , m_demeId(0)
   , organism_count(0)
 {
 }
@@ -34,6 +36,7 @@
   , organism(in_cell.organism)
   , cur_input(in_cell.cur_input)
   , cell_id(in_cell.cell_id)
+  , m_demeId(0)
   , organism_count(in_cell.organism_count)
 {
   for (int i = 0; i < nHardware::IO_SIZE; i++) input_array[i] = in_cell.input_array[i];
@@ -52,6 +55,7 @@
   for (int i = 0; i < nHardware::IO_SIZE; i++) input_array[i] = in_cell.input_array[i];
   cur_input = in_cell.cur_input;
   cell_id = in_cell.cell_id;
+  m_demeId = in_cell.m_demeId;
   organism_count = in_cell.organism_count;
   if (mutation_rates == NULL)
     mutation_rates = new cMutationRates(*in_cell.mutation_rates);
@@ -231,7 +235,13 @@
 */
 void cPopulationCell::ResetRandomCellID()
 {
+  int old_id=m_rand_id;
+  int new_id=m_world->GetRandom().GetUInt(INT_MAX); // Max value must be an int.
+
   s_rand_ids.erase(m_rand_id);
-  m_rand_id = m_world->GetRandom().GetUInt(INT_MAX); // Max value must be an int.
+  m_rand_id = new_id;
   s_rand_ids.insert(std::make_pair(m_rand_id, this));
+  
+  // Now let's log the ID change...
+  m_world->GetStats().CellIDChange(*this, old_id, new_id);
 }

Modified: branches/coopcomm/source/main/cPopulationCell.h
===================================================================
--- branches/coopcomm/source/main/cPopulationCell.h	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/main/cPopulationCell.h	2006-12-18 03:05:22 UTC (rev 1146)
@@ -44,6 +44,7 @@
   int cur_input;                           // Next input to give organism.
 
   int cell_id;           // Unique id for position of cell in population.
+  int m_demeId; //!< The deme that this cell is part of.
   int organism_count;    // Total number of orgs to ever inhabit this cell.
 
   unsigned int m_rand_id; //!< Random identifier for this cell.
@@ -79,6 +80,9 @@
   bool IsOccupied() const { return organism != NULL; }
   bool OK();
   
+  void SetDemeID(int id) { m_demeId = id; }
+  int GetDemeID() const { return m_demeId; }
+  
   //! Returns the random ID for this cell.
   unsigned int GetRandomCellID() const { return m_rand_id; }
   //!< Retrieves the position (x,y) coordinates of this cell.

Modified: branches/coopcomm/source/main/cStats.cc
===================================================================
--- branches/coopcomm/source/main/cStats.cc	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/main/cStats.cc	2006-12-18 03:05:22 UTC (rev 1146)
@@ -92,13 +92,13 @@
   , num_sold(0)
   , num_used(0)
   , num_own_used(0)
-  , m_count_org_died(0)
   , m_count_msgs(0)
   , m_max_id(0)
   , m_data_is_id(0)
   , m_data_is_sender(0)
   , m_data_is_id_and_grt_sender(0)
   , m_data_is_leader(0)
+  , m_detailedMessageLog(false)
 {
   task_cur_count.Resize( m_world->GetNumTasks() );
   task_last_count.Resize( m_world->GetNumTasks() );
@@ -893,6 +893,14 @@
 */
 void cStats::SentMessage(cOrgMessage& msg)
 {
+  if(m_detailedMessageLog) {
+    // Create a message record.
+    m_messagesByDeme[msg.GetSender()->GetCell()->GetDemeID()].push_back(
+      MessageRecord(m_update, msg.GetSender()->GetCellID(),
+                    msg.GetReceiver()->GetCellID(), 
+                    msg.GetLabel(), msg.GetData()));
+  }
+  
   ++m_count_msgs;
   num_msg_sent++; // added because m_count_msgs is reset in cStats::PrintMessageData
   m_msg_data.Add(msg.GetData());
@@ -943,60 +951,76 @@
 }
 
 
-/*! This captures all information related to an organism's death.
-
-This is different than RecordDeath() (above), in that we have a handle to the
-organism that is about to die.  This lets us record things like the max message
-sent by the organism, correlate that to the cell, etc.
-
-\todo mean max-valued message per cell.
-\todo mean message per cell
+/*! Records the leader elected by the given deme.
 */
-void cStats::OrganismDeath(cOrganism* org)
+void cStats::DemeElected(unsigned int deme_id, int leader_id, int cell_id)
 {
-  ++m_count_org_died;
+  m_electionRecord.push_back(ElectionRecord(GetUpdate(), deme_id, leader_id, cell_id));
 }
 
 
-/*! The format of this data file is:
-<update> <id>:<#votes>...
-
-\todo Not yet implemented.
-*/
-void cStats::PrintLeaderData(const cString& filename)
+void cStats::PrintElectionRecord(const cString& filename)
 {
-	cDataFile& df = m_world->GetDataFile(filename);
-  df.Write(m_update, "Update");
+  cDataFile& df = m_world->GetDataFile(filename);
+  df.WriteColumnDesc("Update.");
+  df.WriteColumnDesc("{update of election, deme id, leader id, cell_id}...");
+  
+  df.WriteAnonymous(m_update);
+  std::ofstream& out = df.GetOFStream();
+  for(std::vector<ElectionRecord>::iterator i=m_electionRecord.begin();
+      i!=m_electionRecord.end(); ++i) {
+    out << "{" << i->m_update << "," << i->m_demeId << "," << 
+      i->m_leaderId << "," << i->m_cellId << "} ";
+  }
   df.Endl();
+  m_electionRecord.clear();
 }
 
 
-/*! The format of this data file is:
-<update> \
-<# died orgs> \
-<mean max-valued msg> \
-<#cells that sent the leader's id> \
-<cell-id that sent leader>...
+/*! Records an ID change.
 */
-void cStats::PrintCellData(const cString& filename)
+void cStats::CellIDChange(const cPopulationCell& cell, int old_id, int new_id)
 {
-	cDataFile& df = m_world->GetDataFile(filename);
+  m_idChangeRecord.push_back(IdChangeRecord(GetUpdate(), 
+                                            cell.GetDemeID(), cell.GetID(), old_id, new_id));
+}
+
+
+void cStats::PrintIDChanges(const cString& filename)
+{
+  cDataFile& df = m_world->GetDataFile(filename);
   df.WriteColumnDesc("Update.");
-  df.WriteColumnDesc("Count of organisms that have died.");
-  df.WriteColumnDesc("Number of cells that sent a message containing the leader's ID.");
-  df.WriteColumnDesc("IDs of cells that sent a message carrying the leader's ID (may be empty).");
-  df.FlushComments();  
+  df.WriteColumnDesc("{update of change, deme id, old_id, new_id}...");
+  
+  df.WriteAnonymous(m_update);
+  std::ofstream& out = df.GetOFStream();
+  for(std::vector<IdChangeRecord>::iterator i=m_idChangeRecord.begin();
+      i!=m_idChangeRecord.end(); ++i) {
+    out << "{" << i->m_update << "," << i->m_demeId << "," << 
+    i->m_oldId << "," << i->m_newId << "} ";
+  }
+  df.Endl();  
+  m_idChangeRecord.clear();
+}
 
+
+void cStats::PrintMessageLog(const cString& filename)
+{
+  cDataFile& df = m_world->GetDataFile(filename);
+  df.WriteColumnDesc("Update.");
+  df.WriteColumnDesc("{update, deme id, sender cell-seq. id, recvr cell-seq. id, label, data}...");
+  
   df.WriteAnonymous(m_update);
-  df.WriteAnonymous(m_count_org_died);
-  df.WriteAnonymous((unsigned int)m_cell_sent_leader.size());
-  for(std::set<int>::iterator i=m_cell_sent_leader.begin(); i!=m_cell_sent_leader.end(); ++i) {
-    df.WriteAnonymous(*i);
+  std::ofstream& out = df.GetOFStream();
+  for(t_MessageLog::iterator i=m_messagesByDeme.begin();
+      i!=m_messagesByDeme.end(); ++i) {
+    for(t_MessageRecord::iterator j=i->second.begin(); j!=i->second.end(); ++j) {
+      out << "{" << j->m_update << "," << i->first << "," << j->m_sender << "," << j->m_receiver
+        << "," << j->m_label << "," << j->m_data << "} ";        
+    }
   }
   df.Endl();
-  
-  m_count_org_died = 0;
-  m_cell_sent_leader.clear();
+  m_messagesByDeme.clear();
 }
 
 
@@ -1011,7 +1035,7 @@
 <# msgs: data==leader's ID> \
 <mean non-sender data field and data==ID>
 */
-void cStats::PrintMessageData(const cString& filename)
+void cStats::PrintMessageSummary(const cString& filename)
 {
 	cDataFile& df = m_world->GetDataFile(filename);
   df.Write(m_update, "Update");
@@ -1064,11 +1088,18 @@
   cDataFile& df = m_world->GetDataFile(filename);
   df.WriteComment("Genomes that comprise the deme with maximum fitness.");
   df.WriteColumnDesc("Update.");
+  df.WriteColumnDesc("Deme ID.");
+  df.WriteColumnDesc("Cell begin.");
+  df.WriteColumnDesc("Cell end.");
   df.WriteColumnDesc("Genome ID...");
   df.WriteAnonymous(m_update);
+  df.WriteAnonymous(m_maxDemeIndex);
   
   cPopulation::t_CellRangeList demes = m_world->GetPopulation().GetDemes();
   assert(demes.size()>m_maxDemeIndex);
+  df.WriteAnonymous(demes[m_maxDemeIndex].first - m_world->GetPopulation().CellBegin());
+  df.WriteAnonymous(demes[m_maxDemeIndex].second - m_world->GetPopulation().CellBegin());
+  
   for(cPopulation::t_CellIterator i=demes[m_maxDemeIndex].first;
       i!=demes[m_maxDemeIndex].second; ++i) {
     if(i->IsOccupied()) {
@@ -1078,18 +1109,7 @@
   df.Endl();
 }
 
-/*! The format of this data file is:
-<update> <cell id>:<id>...
 
-\todo Not yet implemented.
-*/
-void cStats::PrintIDData(const cString& filename)
-{
-	cDataFile& df = m_world->GetDataFile(filename);
-  df.Write(m_update, "Update");
-  df.Endl();
-}
-
 //added by ben
 /*! prints message numbers for an update
 */
@@ -1115,33 +1135,20 @@
 }
 
 
-/*! This method iterates through every cell in the population, and for every
-organism that it finds, it prints:
-<cell_id:random_cell_id:mean_data_field:mean_label_field>...
-
-The intent is that these snapshots can be strung together in order to get a picture
-of the types of messages that are being sent throughout the population.
-
-Note: This will generate a large data file.
+/*! This method iterates through every cell in the population and prints the 
+cell-sequential and cell-random IDs.
 */
-void cStats::PrintMessageSnapshot(const cString& filename)
+void cStats::PrintCellIDs(const cString& filename)
 {
   cDataFile& df = m_world->GetDataFile(filename);
   df.WriteColumnDesc("Update.");
-  df.WriteColumnDesc("<cell_id:random_cell_id:mean_data_field:mean_label_field>...");
+  df.WriteColumnDesc("Cell-sequential ID:Cell-random ID...");
 
   df.WriteAnonymous(m_update);
   std::ofstream& out = df.GetOFStream();
   cPopulation::t_CellArray& cells = m_world->GetPopulation().GetCellArray();
   for(int i=0; i<cells.GetSize(); ++i) {
-    if(cells[i].IsOccupied()) {
-      cOrganism::t_message_list& sent = cells[i].GetOrganism()->GetSentMessages();
-      if(sent.empty()) continue;
-      cOrgMessage_Sum sum = std::for_each(sent.begin(), sent.end(), cOrgMessage_Sum());
-      out << cells[i].GetID() << ":" << cells[i].GetRandomCellID() 
-        << ":" << sum.MeanData()
-        << ":" << sum.MeanLabel() << " ";
-    }
+    out << cells[i].GetID() << ":" << cells[i].GetRandomCellID() << " ";
   }
   df.Endl();  
 }

Modified: branches/coopcomm/source/main/cStats.h
===================================================================
--- branches/coopcomm/source/main/cStats.h	2006-12-18 02:23:01 UTC (rev 1145)
+++ branches/coopcomm/source/main/cStats.h	2006-12-18 03:05:22 UTC (rev 1146)
@@ -15,6 +15,7 @@
 #include <fstream>
 #include <iostream>
 #include <set>
+#include <map>
 
 #ifndef defs_h
 #include "defs.h"
@@ -247,7 +248,6 @@
   int num_own_used;
 
   // Stats for coop-comm.
-  unsigned int m_count_org_died; //!< Count of the number of organisms that died.
   unsigned int m_count_msgs; //!< Count of the number of messages sent.
   cDoubleSum m_msg_data; //!< Sum of all message data fields.
   unsigned int m_max_id; //!< The maximum ID in the population.
@@ -262,7 +262,63 @@
   //! The index of the deme with maximum fitness within m_maxDemeFitness; correlates to 
   //! the index of the cell range from cPopulation::GetDemes().
   unsigned int m_maxDemeIndex;
+
+  //! An ElectionRecord is created every time a deme elects a leader.
+  struct ElectionRecord {
+    ElectionRecord(int update, unsigned int deme_id, int leader_id, int cell_id)
+    : m_update(update)
+    , m_demeId(deme_id)
+    , m_leaderId(leader_id)
+    , m_cellId(cell_id) {
+    }
+    
+    int m_update;
+    unsigned int m_demeId;
+    int m_leaderId;
+    int m_cellId;
+  };  
   
+  //! A log of all the elections that have occured since the last PrintElectionRecord.
+  std::vector<ElectionRecord> m_electionRecord;  
+
+  //! An IdChangeRecord is created every time a cell ID changes.
+  struct IdChangeRecord {
+    IdChangeRecord(int update, unsigned int deme_id, int cell_id, int old_id, int new_id)
+    : m_update(update)
+    , m_demeId(deme_id)
+    , m_cellId(cell_id)
+    , m_oldId(old_id)
+    , m_newId(new_id) {
+    }
+    
+    int m_update;
+    unsigned int m_demeId;
+    int m_cellId, m_oldId, m_newId;
+  };
+  
+  //! A log of all the ID changes that have occured since the last PrintIdChangeRecord.
+  std::vector<IdChangeRecord> m_idChangeRecord;  
+
+  struct MessageRecord {
+    MessageRecord(int update, int sender, int receiver, int label, int data)
+    : m_update(update)
+    , m_sender(sender)
+    , m_receiver(receiver)
+    , m_label(label)
+    , m_data(data) {
+    }
+    
+    int m_update, m_sender, m_receiver, m_label, m_data;
+  };
+  
+  typedef std::vector<MessageRecord> t_MessageRecord;
+  typedef std::map<unsigned int, t_MessageRecord > t_MessageLog;
+  //! Messages by deme id.
+  t_MessageLog m_messagesByDeme;
+    
+  //! A flag to indicate if we should be recording all messages.
+  bool m_detailedMessageLog;
+  
   cStats(); // @not_implemented
   cStats(const cStats&); // @not_implemented
   cStats& operator=(const cStats&); // @not_implemented
@@ -613,26 +669,32 @@
   void DemeFitness(const std::vector<double>& deme_fitness);
   //! Capture information related to organism death.
   void OrganismDeath(cOrganism* org);
-  //! Log leadership-specific data.
-  void PrintLeaderData(const cString& filename);
+  //! Called when a deme has elected a leader.
+  void DemeElected(unsigned int deme_id, int leader_id, int cell_id);  
+  //! Print the election records.
+  void PrintElectionRecord(const cString& filename);
+  //! Record that a cell's ID has changed.
+  void CellIDChange(const cPopulationCell& cell, int old_id, int new_id);
+  //! Print the change id records.
+  void PrintIDChanges(const cString& filename);
+  //! Prints a log of all messages sent.
+  void PrintMessageLog(const cString& filename);
   //! Log cell-specific data.
-  void PrintCellData(const cString& filename);
+  void PrintCellIDs(const cString& filename);
   //! Log message-specific data.
-  void PrintMessageData(const cString& filename);
+  void PrintMessageSummary(const cString& filename);
   //! Log the max fitnesses of demes.
   void PrintDemeFitness(const cString& filename);
   //! Log the constituent genomes of the deme with the highest fitness.
   void PrintDemeGenomes(const cString& filename);
-  //! Log ID-specific data.
-  void PrintIDData(const cString& filename);
   //! Print message data file.
   void PrintMessageDataPerUpdate(const cString& filename);
-  //! Print a snapshot of specific message activity.
-  void PrintMessageSnapshot(const cString& filename);
   //! Prints information regarding messages that "passed" their predicate.
   void PrintPredicatedMessages(const cString& filename);
   //! Adds a predicate that will be evaluated for each message.
   void AddMessagePredicate(cOrgMessage_Predicate* predicate);
+  //! Toggles detailed recording of message activity.
+  void ToggleMessageLog() { m_detailedMessageLog = !m_detailedMessageLog; }
   
   //added by ben for messaging stats
   void IncSent() {num_msg_sent++;} //!< inc. number of messages sent




More information about the Avida-cvs mailing list