[Avida-cvs] [avida-svn] r1027 - in branches/coopcomm/source: actions cpu main

dknoester at myxo.css.msu.edu dknoester at myxo.css.msu.edu
Thu Oct 5 14:33:14 PDT 2006


Author: dknoester
Date: 2006-10-05 17:33:14 -0400 (Thu, 05 Oct 2006)
New Revision: 1027

Modified:
   branches/coopcomm/source/actions/PopulationActions.cc
   branches/coopcomm/source/actions/PrintActions.cc
   branches/coopcomm/source/cpu/cHardwareCPU.cc
   branches/coopcomm/source/cpu/cHardwareCPU.h
   branches/coopcomm/source/main/cOrgMessage.h
   branches/coopcomm/source/main/cOrganism.cc
   branches/coopcomm/source/main/cOrganism.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
   branches/coopcomm/source/main/cTaskLib.cc
   branches/coopcomm/source/main/cTaskLib.h
Log:
Ok, a number of changes here.

First, this update includes part of a mechanism for set/get-leader-id.  It's incomplete, mostly because I ran out of time.  Don't use them (yet), or go ahead and fix them.

Second, there's a new thing in cStats that allows generic message tracking.  See cOrgMessage.h, PrintActions.cc, cStats.cc, and PopulationActions.cc for an example of how to use it.  Note that the predicates are stateful - They could be used to track a particular message throughout the population, and note that they can also be added at runtime.



Modified: branches/coopcomm/source/actions/PopulationActions.cc
===================================================================
--- branches/coopcomm/source/actions/PopulationActions.cc	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/actions/PopulationActions.cc	2006-10-05 21:33:14 UTC (rev 1027)
@@ -18,6 +18,7 @@
 #include "cInstUtil.h"
 #include "cPopulation.h"
 #include "cPopulationCell.h"
+#include "cOrgMessage.h"
 #include "cStats.h"
 #include "cWorld.h"
 
@@ -1299,6 +1300,46 @@
 };
 
 
+/*! \brief An event that adds a predicate to be evaluated for every sent message.
+
+\todo Clean this up; use a vector of predicates.
+*/
+class cActionAddMessagePredicate : public cAction
+{
+public:
+  //! Constructor.
+  cActionAddMessagePredicate(cWorld* world, const cString& args) : 
+  cAction(world, args),
+  m_leader1(NULL),
+  m_leader2(NULL)
+  { }
+  
+  //! Return a string description of the arguments for this action.
+  static const cString GetDescription() 
+  { 
+    return "Tracks cells that send data.";
+  }
+  
+  //! Perform this action.
+  void Process(cAvidaContext& ctx)
+  {
+    cPopulationCell::t_id_map& ids = cPopulationCell::GetRandomCellIDMap();
+    assert(ids.size()>0);
+    
+    cPopulationCell::t_id_map::reverse_iterator i = ids.rbegin();
+    
+    m_leader1 = new cOrgMessage_PredDataEQU(i->first);
+    ++i;
+    m_leader2 = new cOrgMessage_PredDataEQU(i->first);
+    m_world->GetStats().AddMessagePredicate(m_leader1);
+    m_world->GetStats().AddMessagePredicate(m_leader2);
+  }
+private:
+  cOrgMessage_PredDataEQU* m_leader1;
+  cOrgMessage_PredDataEQU* m_leader2;
+};
+    
+
 void RegisterPopulationActions(cActionLibrary* action_lib)
 {
   action_lib->Register<cActionInject>("Inject");
@@ -1334,7 +1375,8 @@
   // Coop-comm actions.
   action_lib->Register<cActionResetRandomCellIDs>("ResetRandomCellIDs");
   action_lib->Register<cActionSetStaticBaseStation>("SetStaticBaseStation");
-
+  action_lib->Register<cActionAddMessagePredicate>("AddMessagePredicate");
+  
   // @DMB - The following actions are DEPRECATED aliases - These will be removed in 2.7.
   action_lib->Register<cActionInject>("inject");
   action_lib->Register<cActionInjectRandom>("inject_random");

Modified: branches/coopcomm/source/actions/PrintActions.cc
===================================================================
--- branches/coopcomm/source/actions/PrintActions.cc	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/actions/PrintActions.cc	2006-10-05 21:33:14 UTC (rev 1027)
@@ -72,6 +72,7 @@
 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);
 
 
 #define POP_OUT_FILE(METHOD, DEFAULT)                                                     /*  1 */ \
@@ -1532,6 +1533,7 @@
   action_lib->Register<cActionPrintIDData>("PrintIDData");  
   action_lib->Register<cActionPrintMessageDataPerUpdate>("PrintMessageDataPerUpdate");
   action_lib->Register<cActionPrintMessageSnapshot>("PrintMessageSnapshot");
+  action_lib->Register<cActionPrintPredicatedMessages>("PrintPredicatedMessages");
   
   // @DMB - The following actions are DEPRECATED aliases - These will be removed in 2.7.
   action_lib->Register<cActionPrintAverageData>("print_average_data");

Modified: branches/coopcomm/source/cpu/cHardwareCPU.cc
===================================================================
--- branches/coopcomm/source/cpu/cHardwareCPU.cc	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/cpu/cHardwareCPU.cc	2006-10-05 21:33:14 UTC (rev 1027)
@@ -356,7 +356,9 @@
     cInstEntryCPU("retrieve-msg", &cHardwareCPU::Inst_ReceiveMessage),
     cInstEntryCPU("get-id", &cHardwareCPU::Inst_GetID),
     cInstEntryCPU("get-pos", &cHardwareCPU::Inst_GetPosition),
-    cInstEntryCPU("get-facing", &cHardwareCPU::Inst_GetFacing)
+    cInstEntryCPU("get-facing", &cHardwareCPU::Inst_GetFacing),
+    cInstEntryCPU("set-leader", &cHardwareCPU::Inst_SetLeader),
+    cInstEntryCPU("get-leader", &cHardwareCPU::Inst_GetLeader)
   };
   
   const int n_size = sizeof(s_n_array)/sizeof(cNOPEntryCPU);
@@ -3445,3 +3447,39 @@
 	GetRegister(facing) = organism->GetFacing();
 	return true;
 }
+
+
+/*! Set the leader of this organism to the organism that is currently being
+faced.  Note that an organism can have only one leader.  A false return means
+that this organism is currently facing an unoccupied cell.
+
+If there's a false return, then we set ?BX? to 0.  Otherwise, we set ?BX? to the 
+ID of the faced organism.
+*/
+bool cHardwareCPU::Inst_SetLeader(cAvidaContext& ctx)
+{
+  organism->SetLeader();
+  return Inst_GetLeader(ctx);
+}
+
+
+/*! Returns the ID of the organism that is currently this organism's leader.
+Note that technically this is a compound instruction, as we're effectively querying
+this organism's leader for its ID.
+
+As above, if we do not have a leader, return false and set ?BX? to 0.  Otherwise,
+set ?BX? to the ID of the faced organism.
+*/
+bool cHardwareCPU::Inst_GetLeader(cAvidaContext& ctx)
+{
+  cOrganism* org = organism->GetLeader();
+  const int id_reg = FindModifiedRegister(REG_BX);
+  
+  if(org) {
+    GetRegister(id_reg) = org->GetRandomCellID();
+    return true;
+  } else {
+    GetRegister(id_reg) = 0;
+    return false;
+  }
+}

Modified: branches/coopcomm/source/cpu/cHardwareCPU.h
===================================================================
--- branches/coopcomm/source/cpu/cHardwareCPU.h	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/cpu/cHardwareCPU.h	2006-10-05 21:33:14 UTC (rev 1027)
@@ -477,6 +477,8 @@
   bool Inst_GetID(cAvidaContext& ctx); //!< Retrieve this organism's ID.
   bool Inst_GetPosition(cAvidaContext& ctx); //!< Retrieve this organism's position.
   bool Inst_GetFacing(cAvidaContext& ctx); //!< Retrieve this organism's facing.
+  bool Inst_SetLeader(cAvidaContext& ctx); //!< Set the leader of this organism.
+  bool Inst_GetLeader(cAvidaContext& ctx); //!< Retrieve the leader of this organism.
 };
 
 

Modified: branches/coopcomm/source/main/cOrgMessage.h
===================================================================
--- branches/coopcomm/source/main/cOrgMessage.h	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/main/cOrgMessage.h	2006-10-05 21:33:14 UTC (rev 1027)
@@ -12,6 +12,8 @@
 #define cOrgMessage_h
 
 #include <functional>
+#include <iostream>
+#include <set>
 
 #include "cOrganism.h"
 
@@ -82,6 +84,44 @@
   double MeanLabel() { return (m_count>0) ? m_label / m_count : 0; }
 };
 
+/*! \brief An STL-compatible predicate on cOrgMessages.
+*/
+struct cOrgMessage_Predicate : public std::unary_function<cOrgMessage, bool> {
+  virtual bool operator()(cOrgMessage& msg) = 0;
+  virtual void print(std::ostream& out) { }
+  virtual void reset() { }
+};
+
+/*! 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.
+*/
+struct cOrgMessage_PredDataEQU : public cOrgMessage_Predicate {
+  cOrgMessage_PredDataEQU(unsigned int data) : m_data(data) { }
+  
+  virtual bool operator()(cOrgMessage& msg) {
+    if(m_data==msg.GetData()) {
+      m_cell_ids.insert(msg.GetSender()->GetCellID());
+    }
+  }
+
+  virtual void print(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 << ",";
+    }
+    out << "}";
+  }
+  
+  virtual void reset() { 
+    m_cell_ids.clear();
+  }
+  
+  unsigned int m_data;
+  std::set<int> m_cell_ids;
+};
+
+
+
 #ifdef ENABLE_UNIT_TESTS
 namespace nOrgMessage {
   /**

Modified: branches/coopcomm/source/main/cOrganism.cc
===================================================================
--- branches/coopcomm/source/main/cOrganism.cc	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/main/cOrganism.cc	2006-10-05 21:33:14 UTC (rev 1027)
@@ -31,6 +31,8 @@
 #include "cStats.h"
 
 #include <iomanip>
+#include <algorithm>
+#include <functional>
 
 using namespace std;
 
@@ -58,6 +60,7 @@
   , is_running(false)
   , m_retrieve_pos(0)
   , last_cell_sent_to(-1)
+  , m_pLeader(NULL)
 {
   // Initialization of structures...
   m_hardware = m_world->GetHardwareManager().Create(this);
@@ -86,6 +89,11 @@
   // 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();
+  }
+  
   assert(is_running == false);
   delete m_hardware;
   delete m_interface;
@@ -644,3 +652,27 @@
     return &m_received_messages.at(m_retrieve_pos++);
   }
 }
+
+
+bool cOrganism::SetLeader()
+{
+  if(m_pLeader) {
+    t_organism_list& orgs=m_pLeader->GetLeadOrganisms();
+    t_organism_list::iterator i=std::find_if(orgs.begin(), orgs.end(),
+                                            std::bind2nd(std::equal_to<cOrganism*>(), this));
+    if(i != orgs.end()) {
+      orgs.erase(i);
+    }
+  }
+  
+  m_pLeader = m_interface->GetNeighbor();
+  if(m_pLeader) {
+    m_pLeader->GetLeadOrganisms().push_back(this);
+  }
+}
+
+
+cOrganism* cOrganism::GetLeader()
+{
+  return m_pLeader;
+}

Modified: branches/coopcomm/source/main/cOrganism.h
===================================================================
--- branches/coopcomm/source/main/cOrganism.h	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/main/cOrganism.h	2006-10-05 21:33:14 UTC (rev 1027)
@@ -85,6 +85,7 @@
   // received.  This may change in future versions.
   typedef std::vector<cOrgMessage> t_message_list; //!< Container for cOrgMessages.
   typedef std::map<unsigned int, cOrgMessage> t_sorted_messages; //!< A sorted container for cOrgMessages.
+  typedef std::vector<cOrganism*> t_organism_list; //!< Used to store a list of organisms.
   
 protected:
   cWorld* m_world;
@@ -149,6 +150,8 @@
   t_sorted_messages m_sorted_recv_messages; //!< Sorted map of received messages.
   t_sorted_messages m_sorted_sent_messages; //!< Sorted map of sent messages.
   int last_cell_sent_to;
+  cOrganism* m_pLeader; //!< A pointer to the organism that is this one's leader.
+  t_organism_list m_lead; //!< A list of pointers to organisms that this organism leads.
   
   cOrganism(); // @not_implemented
   cOrganism(const cOrganism&); // @not_implemented
@@ -310,6 +313,14 @@
   int GetFacing() { assert(m_interface); return m_interface->GetFacing(); }
   //!
   int getLastSent(){ return last_cell_sent_to; }
+  //! Set the leader of this organism to the organism currently faced.
+  bool SetLeader();
+  //! Get the cOrganism that is currently the leader of this organism.
+  cOrganism* GetLeader();
+  //! Remove the leader from this organism.
+  void ResetLeader() { m_pLeader = NULL; }
+  //! Get the list of organisms lead by this one.
+  t_organism_list& GetLeadOrganisms() { return m_lead; }
 };
 
 

Modified: branches/coopcomm/source/main/cPopulationCell.cc
===================================================================
--- branches/coopcomm/source/main/cPopulationCell.cc	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/main/cPopulationCell.cc	2006-10-05 21:33:14 UTC (rev 1027)
@@ -72,7 +72,7 @@
   m_y = y;
   // At least to start with, guarantee that all random IDs are unique.
   while(true) {
-    m_rand_id = m_world->GetRandom().GetUInt(UINT_MAX);
+    m_rand_id = m_world->GetRandom().GetUInt(INT_MAX); // max value must be an int.
     t_id_map::iterator i=s_rand_ids.find(m_rand_id);
     if(i==s_rand_ids.end()) {
       break;
@@ -224,6 +224,6 @@
 void cPopulationCell::ResetRandomCellID()
 {
   s_rand_ids.erase(m_rand_id);
-  m_rand_id = m_world->GetRandom().GetUInt(UINT_MAX);
+  m_rand_id = m_world->GetRandom().GetUInt(INT_MAX); // Max value must be an int.
   s_rand_ids.insert(std::make_pair(m_rand_id, this));
 }

Modified: branches/coopcomm/source/main/cPopulationCell.h
===================================================================
--- branches/coopcomm/source/main/cPopulationCell.h	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/main/cPopulationCell.h	2006-10-05 21:33:14 UTC (rev 1027)
@@ -91,6 +91,7 @@
   static unsigned int GetMaxRandomCellID();
   //! Returns the cell with the current maximal ID.
   static cPopulationCell* GetMaxRandomCell();
+  static t_id_map& GetRandomCellIDMap() { return s_rand_ids; }
   //! Reset this cell's random ID.
   void ResetRandomCellID();  
 };

Modified: branches/coopcomm/source/main/cStats.cc
===================================================================
--- branches/coopcomm/source/main/cStats.cc	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/main/cStats.cc	2006-10-05 21:33:14 UTC (rev 1027)
@@ -16,7 +16,6 @@
 #include "tDataEntry.h"
 #include "cWorld.h"
 #include "cWorldDriver.h"
-#include "cOrgMessage.h"
 #include "cPopulation.h"
 #include "cPopulationCell.h"
 #include "cOrganism.h"
@@ -912,6 +911,12 @@
       m_cell_sent_leader.insert(msg.GetSender()->GetCellID());
     }
   }
+  
+  // Check to see if this message matches any of our predicates.
+  for(t_predicate_list::iterator i=m_predicate_list.begin(); 
+      i!=m_predicate_list.end(); ++i) {
+    (**i)(msg); // Predicate is responsible for tracking info about messages.
+  }
 }
 
 
@@ -1070,3 +1075,41 @@
   }
   df.Endl();  
 }
+
+
+/*! This method prints information about the 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>,...}...
+*/
+void cStats::PrintPredicatedMessages(const cString& filename)
+{
+  cDataFile& df = m_world->GetDataFile(filename);
+  df.WriteColumnDesc("Update.");
+  df.WriteColumnDesc("predicate:{p_info,...}...");
+  df.FlushComments();
+  
+  df.WriteAnonymous(m_update);
+  std::ofstream& out = df.GetOFStream();
+  for(t_predicate_list::iterator i=m_predicate_list.begin();
+      i!=m_predicate_list.end(); ++i) {
+    (*i)->print(out);
+    (*i)->reset();
+    out << " ";
+  }
+  df.Endl();  
+}
+
+
+/*! This method adds a message to be tracked to the list of all tracked messages.
+The particular type of tracking depends on the predicate P that is passed in.
+Specificly, if P(msg) == true, the message is tracked, else it is not.
+
+NOTE: cStats does NOT own the predicate pointer!
+*/
+void cStats::AddMessagePredicate(cOrgMessage_Predicate* predicate)
+{
+  m_predicate_list.push_back(predicate);
+}

Modified: branches/coopcomm/source/main/cStats.h
===================================================================
--- branches/coopcomm/source/main/cStats.h	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/main/cStats.h	2006-10-05 21:33:14 UTC (rev 1027)
@@ -40,15 +40,19 @@
 #ifndef nGeometry_h
 #include "nGeometry.h"
 #endif
+#include "cOrgMessage.h"
 
 class cGenotype;
 class cInjectGenotype;
 class cWorld;
-class cOrgMessage;
 class cOrganism;
 
 class cStats
 {
+public:
+  //! Typedef for a list of predicates, used to determine if a message should be tracked.
+  typedef std::vector<cOrgMessage_Predicate*> t_predicate_list;
+  
 private:
   cWorld* m_world;
   
@@ -253,6 +257,7 @@
   unsigned int m_data_is_leader; //!< Count of messages where the data field is the leader's ID.
   cDoubleSum m_data_is_id_not_sender; //!< Sum of message data fields where the data field is an ID that is not the sender's ID.
   std::set<int> m_cell_sent_leader; //!< Set of all cells that sent a message carrying the leader's ID.
+  t_predicate_list m_predicate_list; //!< The list of predicates used to choose which messages to track.
   
   cStats(); // @not_implemented
   cStats(const cStats&); // @not_implemented
@@ -614,7 +619,11 @@
   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);
+  
   //added by ben for messaging stats
   void IncSent() {num_msg_sent++;} //!< inc. number of messages sent
   void IncSentToNonFacing() {num_msg_sent_to_nonfacing++;}

Modified: branches/coopcomm/source/main/cTaskLib.cc
===================================================================
--- branches/coopcomm/source/main/cTaskLib.cc	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/main/cTaskLib.cc	2006-10-05 21:33:14 UTC (rev 1027)
@@ -358,6 +358,8 @@
     NewTask(name, "Reward the sender for sending toward the sink", &cTaskLib::Task_SendTowardSink);
   else if(name == "send-not-toward-sink")
     NewTask(name, "Reward the sender for not sending toward the sink", &cTaskLib::Task_SendNotTowardSink);
+  else if(name == "graph-equ-tree")
+    NewTask(name, "Reward an organism for being part of a tree.", &cTaskLib::Task_GraphEquTree);
   
   // Make sure we have actually found a task  
   if (task_array.GetSize() == start_size) {
@@ -1995,3 +1997,12 @@
     return 1.0;
   return 0.0;
 }
+
+
+/*! This task rewards an organism for being part of a tree.  The rules for tree-ness
+are that the graph is connected and the graph has n-1 edges.
+*/
+double cTaskLib::Task_GraphEquTree(cTaskContext* ctx) const
+{
+  return 0.0;
+}

Modified: branches/coopcomm/source/main/cTaskLib.h
===================================================================
--- branches/coopcomm/source/main/cTaskLib.h	2006-10-05 18:58:10 UTC (rev 1026)
+++ branches/coopcomm/source/main/cTaskLib.h	2006-10-05 21:33:14 UTC (rev 1027)
@@ -242,6 +242,8 @@
   double Task_SendTowardSink(cTaskContext* ctx) const;
   //! Reward an organism for sending message to organism who is not closer to the sink
   double Task_SendNotTowardSink(cTaskContext* ctx) const;
+  //! Rewards an organism for being part of a tree.
+  double Task_GraphEquTree(cTaskContext* ctx) const;
 };
 
 




More information about the Avida-cvs mailing list