[Avida-SVN] r1083 - in branches/coopcomm/source: cpu main

dknoester at myxo.css.msu.edu dknoester at myxo.css.msu.edu
Wed Nov 15 11:35:52 PST 2006


Author: dknoester
Date: 2006-11-15 14:35:46 -0500 (Wed, 15 Nov 2006)
New Revision: 1083

Modified:
   branches/coopcomm/source/cpu/cHardwareCPU.cc
   branches/coopcomm/source/cpu/cHardwareCPU.h
   branches/coopcomm/source/cpu/cInstLibCPU.h
   branches/coopcomm/source/main/cOrgMessage.h
   branches/coopcomm/source/main/cOrganism.cc
   branches/coopcomm/source/main/cOrganism.h
Log:
The intent behind this update is to discourage organisms from sending old data.

This commit adds the following new instructions:
dc-send-msg: Implements a new flavor of send-msg, where the label field
	is forced to be the origination time of the data field (in updates),
	and sending a message has a dynamic instruction cost, where each
	call to dc-send-msg stalls for $now()-origination_time$ instructions.

cost-to-send: Returns the cost (in instructions) of calling dc-send-msg now.

Other changes:
Each cInstEntryCPU has an additional field, costFunction, where cost functions
are defined similarly to tHardwareCPUMethod (returns an int instead of bool).
The cInstLibCPU has been extended to include an array of cost functions, 
where these cost functions (which default to NULL) are used to determine the
"dynamic cost" of executing their associated instruction.  The dynamic cost
is then paid, similar to first-time and static costs, as part of
cHardwareCPU::SingleProcess_PayCosts.

Grep cHardwareCPU for "dc-send-msg" to see an example.



Modified: branches/coopcomm/source/cpu/cHardwareCPU.cc
===================================================================
--- branches/coopcomm/source/cpu/cHardwareCPU.cc	2006-11-14 18:22:29 UTC (rev 1082)
+++ branches/coopcomm/source/cpu/cHardwareCPU.cc	2006-11-15 19:35:46 UTC (rev 1083)
@@ -64,10 +64,14 @@
     const tHardwareCPUMethod function;
     const bool is_default;
     const cString desc;
+    const tDynamicCostCPUMethod costFunction;
     
-    cInstEntryCPU(const cString & _name, tHardwareCPUMethod _fun,
-                  bool _def=false, const cString & _desc="")
-      : name(_name), function(_fun), is_default(_def), desc(_desc) {}
+    cInstEntryCPU(const cString & _name, 
+                  tHardwareCPUMethod _fun,
+                  bool _def=false, 
+                  const cString & _desc="", 
+                  tDynamicCostCPUMethod _costFun=NULL)
+      : name(_name), function(_fun), is_default(_def), desc(_desc), costFunction(_costFun) {}
   };
   static const cInstEntryCPU s_f_array[] = {
     /*
@@ -354,7 +358,12 @@
     cInstEntryCPU("skip",      &cHardwareCPU::Inst_Skip),
     
     // Coop-comm
-    cInstEntryCPU("send-msg", &cHardwareCPU::Inst_SendMessage),
+    cInstEntryCPU("send-msg", &cHardwareCPU::Inst_SendMessage,
+                  false, "Sends a message to the faced organism"),
+    cInstEntryCPU("dc-send-msg", &cHardwareCPU::Inst_TimedSendMessage, 
+                  false, "Sends a message to the faced organism (+dynamic cost)",
+                  &cHardwareCPU::DynamicCost_TimedSendMessage),
+    cInstEntryCPU("cost-to-send", &cHardwareCPU::Inst_CostToSend),
     cInstEntryCPU("retrieve-msg", &cHardwareCPU::Inst_RetrieveMessage),
     cInstEntryCPU("retrieve-msg-0-0", &cHardwareCPU::Inst_RetrieveMessage_0_0),
     cInstEntryCPU("get-id", &cHardwareCPU::Inst_GetID),
@@ -376,19 +385,23 @@
   const int f_size = sizeof(s_f_array)/sizeof(cInstEntryCPU);
   static cString f_names[f_size];
   static tHardwareCPUMethod functions[f_size];
+  static tDynamicCostCPUMethod costFunctions[f_size];
   for (int i = 0; i < f_size; i++){
     f_names[i] = s_f_array[i].name;
     functions[i] = s_f_array[i].function;
+    costFunctions[i] = s_f_array[i].costFunction;
   }
   
-  return new cInstLibCPU(n_size, f_size, n_names, f_names, nop_mods, functions);
+  return new cInstLibCPU(n_size, f_size, n_names, f_names, nop_mods, functions, costFunctions);
 }
 
 cHardwareCPU::cHardwareCPU(cWorld* world, cOrganism* in_organism, cInstSet* in_m_inst_set)
 : cHardwareBase(world, in_organism, in_m_inst_set)
+, m_dynamicCosts(s_inst_slib->GetSize(), std::make_pair(false,0))
 {
   /* FIXME:  reorganize storage of m_functions.  -- kgn */
   m_functions = s_inst_slib->GetFunctions();
+  m_costFunctions = s_inst_slib->GetCostFunctions();
   /**/
   m_memory = in_organism->GetGenome();  // Initialize memory...
   Reset();                            // Setup the rest of the hardware...
@@ -534,7 +547,7 @@
 {
 #if INSTRUCTION_COSTS
   assert(cur_inst.GetOp() < inst_cost.GetSize());
-  
+
   // If first time cost hasn't been paid off...
   if ( inst_ft_cost[cur_inst.GetOp()] > 0 ) {
     inst_ft_cost[cur_inst.GetOp()]--;       // dec cost
@@ -550,6 +563,26 @@
       inst_cost[cur_inst.GetOp()] = m_inst_set->GetCost(cur_inst);
     }
   }
+
+  // Does this instruction have a dynamic cost?
+  int inst_idx = m_inst_set->GetLibFunctionIndex(cur_inst);  
+  if(m_costFunctions[inst_idx] != NULL) {
+    if(m_dynamicCosts[inst_idx].first == true) {
+      // If we're currently counting down, decrement the counter.
+      --m_dynamicCosts[inst_idx].second;
+    } else {
+      // Else, set the counter.
+      m_dynamicCosts[inst_idx].second = (this->*(m_costFunctions[inst_idx]))(ctx);
+      m_dynamicCosts[inst_idx].first = true;
+    }
+    
+    // Return false if we're not done yet, reset and fall through when we're done.
+    if(m_dynamicCosts[inst_idx].second > 0) {
+      return false;
+    } else {
+      m_dynamicCosts[inst_idx].first = false;
+    }
+  }
   
   // Prob of exec
   if ( m_inst_set->GetProbFail(cur_inst) > 0.0 ){
@@ -3442,6 +3475,55 @@
 }
 
 
+/*! Sends a message where the label field is set to be the update in which this
+message originated, in updates.
+*/
+bool cHardwareCPU::Inst_TimedSendMessage(cAvidaContext& ctx)
+{
+  const int data_reg = FindNextRegister(FindModifiedRegister(REG_BX));
+
+  cOrgMessage msg = cOrgMessage(organism);
+  msg.SetData(GetRegister(data_reg));
+  if(msg.GetData() == organism->GetRandomCellID()) {
+    msg.SetLabel(m_world->GetStats().GetUpdate());
+  } else {
+    std::pair<bool,int> age = organism->CalcMessageAge(msg);
+    if(age.first) {
+      msg.SetLabel(age.second);
+    } else {
+      msg.SetLabel(m_world->GetStats().GetUpdate());
+    }
+  }
+  return organism->SendMessage(ctx, msg);
+}
+
+
+/*! Returns the dynamic cost of executing the 'send-msg' instruction. */
+int cHardwareCPU::DynamicCost_TimedSendMessage(cAvidaContext& ctx)
+{
+  const int data_reg = FindNextRegister(FindModifiedRegister(REG_BX));
+  
+  cOrgMessage msg = cOrgMessage(organism);
+  msg.SetData(GetRegister(data_reg));
+  
+  std::pair<bool,int> age = organism->CalcMessageAge(msg);
+  if(age.first) {
+    return m_world->GetStats().GetUpdate() - age.second;
+  }
+  
+  return age.second;
+}
+
+
+/*! Returns the cost to send a message based on current register values.
+*/
+bool cHardwareCPU::Inst_CostToSend(cAvidaContext& ctx)
+{
+  GetRegister(FindModifiedRegister(REG_BX)) = DynamicCost_TimedSendMessage(ctx);
+  return true;
+}
+
+
 /*! This method /attempts/ to receive a message -- It may not be possible, as in
 the case of an empty receive buffer.
 

Modified: branches/coopcomm/source/cpu/cHardwareCPU.h
===================================================================
--- branches/coopcomm/source/cpu/cHardwareCPU.h	2006-11-14 18:22:29 UTC (rev 1082)
+++ branches/coopcomm/source/cpu/cHardwareCPU.h	2006-11-15 19:35:46 UTC (rev 1083)
@@ -63,6 +63,7 @@
 {
 public:
   typedef bool (cHardwareCPU::*tHardwareCPUMethod)(cAvidaContext& ctx);
+  typedef int (cHardwareCPU::*tDynamicCostCPUMethod)(cAvidaContext& ctx);
 
 protected:
   // --------  Structure Constants  --------
@@ -105,6 +106,7 @@
 
   // --------  Member Variables  --------
   tHardwareCPUMethod* m_functions;
+  tDynamicCostCPUMethod* m_costFunctions;
 
   cCPUMemory m_memory;          // Memory...
   cCPUStack m_global_stack;     // A stack that all threads share.
@@ -122,6 +124,7 @@
 #if INSTRUCTION_COSTS
   tArray<int> inst_cost;
   tArray<int> inst_ft_cost;
+  std::vector<std::pair<bool,int> > m_dynamicCosts;
 #endif
   
   
@@ -475,6 +478,11 @@
   
   // Coop-comm
   bool Inst_SendMessage(cAvidaContext& ctx); //!< Send a message to the faced organism.
+  bool Inst_TimedSendMessage(cAvidaContext& ctx); //!< Like Inst_SendMessage(), but label is update.
+  //! Returns the dynamic cost of sending a message.
+  int DynamicCost_TimedSendMessage(cAvidaContext& ctx);
+  bool Inst_CostToSend(cAvidaContext& ctx); //!< Returns the cost of sending a message.
+
   bool Inst_RetrieveMessage(cAvidaContext& ctx); //!< Retrieve a message.
   bool Inst_RetrieveMessage_0_0(cAvidaContext& ctx); //!< Retrieve a message and write 0,0 to regs if failed.
   bool Inst_GetID(cAvidaContext& ctx); //!< Retrieve this organism's ID.

Modified: branches/coopcomm/source/cpu/cInstLibCPU.h
===================================================================
--- branches/coopcomm/source/cpu/cInstLibCPU.h	2006-11-14 18:22:29 UTC (rev 1082)
+++ branches/coopcomm/source/cpu/cInstLibCPU.h	2006-11-15 19:35:46 UTC (rev 1083)
@@ -30,28 +30,32 @@
   cString *m_nopmod_names;
   cString *m_function_names;
   const int *m_nopmods;
-  cHardwareCPU::tHardwareCPUMethod *m_functions;
+  cHardwareCPU::tHardwareCPUMethod* m_functions;
+  cHardwareCPU::tDynamicCostCPUMethod* m_costFunctions;
   static const cInstruction inst_error;
   static const cInstruction inst_default;
 
 protected:
   friend class cHardwareCPU;
   
-  cInstLibCPU(
-    size_t nopmod_array_size,
-    size_t function_array_size,
-    cString *nopmod_names,
-    cString *function_names,
-    const int *nopmods,
-    cHardwareCPU::tHardwareCPUMethod *functions
-  ):m_nopmods_array_size(nopmod_array_size),
-    m_function_array_size(function_array_size),
-    m_nopmod_names(nopmod_names),
-    m_function_names(function_names),
-    m_nopmods(nopmods),
-    m_functions(functions)
-  {}
-  cHardwareCPU::tHardwareCPUMethod *GetFunctions(void){ return m_functions; } 
+  cInstLibCPU(size_t nopmod_array_size,
+              size_t function_array_size,
+              cString *nopmod_names,
+              cString *function_names,
+              const int *nopmods,
+              cHardwareCPU::tHardwareCPUMethod *functions,
+              cHardwareCPU::tDynamicCostCPUMethod* costFunctions)
+    : m_nopmods_array_size(nopmod_array_size)
+      , m_function_array_size(function_array_size)
+      , m_nopmod_names(nopmod_names)
+      , m_function_names(function_names)
+      , m_nopmods(nopmods)
+      , m_functions(functions)
+      , m_costFunctions(costFunctions)
+  { }
+  
+  cHardwareCPU::tHardwareCPUMethod* GetFunctions() { return m_functions; }
+  cHardwareCPU::tDynamicCostCPUMethod* GetCostFunctions() { return m_costFunctions; }
 
 public:
   const cString &GetName(const unsigned int id) {

Modified: branches/coopcomm/source/main/cOrgMessage.h
===================================================================
--- branches/coopcomm/source/main/cOrgMessage.h	2006-11-14 18:22:29 UTC (rev 1082)
+++ branches/coopcomm/source/main/cOrgMessage.h	2006-11-15 19:35:46 UTC (rev 1083)
@@ -38,7 +38,6 @@
   explicit cOrgMessage(int data, int label) : 
     m_pSender(NULL), m_pReceiver(NULL), m_data(data), m_label(label) {
     }
-    
 
   static cOrgMessage EmptyMessage() { return cOrgMessage(); }
   
@@ -102,6 +101,7 @@
     if(m_data==msg.GetData()) {
       m_cell_ids.insert(msg.GetSender()->GetCellID());
     }
+    return true;
   }
 
   virtual void print(std::ostream& out) { 

Modified: branches/coopcomm/source/main/cOrganism.cc
===================================================================
--- branches/coopcomm/source/main/cOrganism.cc	2006-11-14 18:22:29 UTC (rev 1082)
+++ branches/coopcomm/source/main/cOrganism.cc	2006-11-15 19:35:46 UTC (rev 1083)
@@ -622,6 +622,29 @@
 }
 
 
+/*! Returns the age of the message, in units of updates.  We do this by searching
+the received messages, looking for an identical data field.  If we find an identical
+data field, then we return the difference between now() and msg.GetLabel(), which will
+have been previously set to the original origination time.  If we do not find an identical
+data field, then we know that this message is orginal, and return 0.
+
+There is some slop here, as m_sorted_recv_messages only contains the most recently
+received message; not the newest.
+*/
+std::pair<bool,int> cOrganism::CalcMessageAge(cOrgMessage& msg)
+{
+  t_sorted_messages::const_iterator i = m_sorted_recv_messages.find(msg.GetData());
+
+  if(i != m_sorted_recv_messages.end()) {
+    // We're forwarding a previously received message.  It was sent during 
+    // the matched message's GetLabel().
+    return std::make_pair(true, i->second.GetLabel());
+  }
+  
+  return std::make_pair(false, m_world->GetStats().GetUpdate());
+}
+
+
 /*! Add this message to the list of messages that this organism has received.  We
 do something a litle funky here, in that we also store a sorted list of the messages
 that have been received.  Yes, we're storing the messages twice.  Yes, there are ways

Modified: branches/coopcomm/source/main/cOrganism.h
===================================================================
--- branches/coopcomm/source/main/cOrganism.h	2006-11-14 18:22:29 UTC (rev 1082)
+++ branches/coopcomm/source/main/cOrganism.h	2006-11-15 19:35:46 UTC (rev 1083)
@@ -291,11 +291,13 @@
   
   
   // Coop-comm
-  //!< Called when this organism attempts to send a message.
+  //! Called when this organism attempts to send a message.
   bool SendMessage(cAvidaContext& ctx, cOrgMessage& msg);
-  //!< Called when this organism has been sent a message.
+  //! Calculates the cummulative age of the passed-in message.
+  std::pair<bool,int> CalcMessageAge(cOrgMessage& msg);  
+  //! Called when this organism has been sent a message.
   bool ReceiveMessage(cOrgMessage& msg);
-  //!< Called when this organism attempts to move a received message into its CPU.
+  //! Called when this organism attempts to move a received message into its CPU.
   const cOrgMessage* RetrieveMessage();
   //! Returns the random cell ID for the cell in which this organism lives.
   unsigned int GetRandomCellID() const { assert(m_interface); return m_interface->GetRandomCellID(); }




More information about the Avida-cvs mailing list