[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