A fundamental- perhaps the fundamental- part of using Repast HPC is the idea of an 'agent package.' When agent information is moved from one process to another, the information must be packaged for transport; this can be called 'serializing' or 'archiving', but the key point is that all of the information needed to build a new copy of the original agent must be provided.
Repast HPC uses the Boost archiving framework to achieve this. The code to archive one of our demo agents is added to the Demo_01_Agent.h and Demo_01_Agent.cpp files, and looks like this:
/* Demo_01_Agent.h */
#ifndef DEMO_01_AGENT
#define DEMO_01_AGENT
#include "repast_hpc/AgentId.h"
#include "repast_hpc/SharedContext.h"
/* Agents */
class RepastHPCDemoAgent{
private:
repast::AgentId id_;
double c;
double total;
public:
RepastHPCDemoAgent(repast::AgentId id);
RepastHPCDemoAgent(repast::AgentId id, double newC, double newTotal);
~RepastHPCDemoAgent();
/* Required Getters */
virtual repast::AgentId& getId(){ return id_; }
virtual const repast::AgentId& getId() const { return id_; }
/* Getters specific to this kind of Agent */
double getC(){ return c; }
double getTotal(){ return total; }
/* Setter */
void set(int currentRank, double newC, double newTotal);
/* Actions */
bool cooperate(); // Will indicate whether the agent cooperates or not; probability determined by = c / total
void play(repast::SharedContext<RepastHPCDemoAgent>* context); // Choose three other agents from the given context and see if they cooperate or not
};
/* Serializable Agent Package */
struct RepastHPCDemoAgentPackage {
public:
int id;
int rank;
int type;
int currentRank;
double c;
double total;
/* Constructors */
RepastHPCDemoAgentPackage(); // For serialization
RepastHPCDemoAgentPackage(int _id, int _rank, int _type, int _currentRank, double _c, double _total);
/* For archive packaging */
template<class Archive>
void serialize(Archive &ar, const unsigned int version){
ar & id;
ar & rank;
ar & type;
ar & currentRank;
ar & c;
ar & total;
}
};
#endif
And
/* Demo_01_Agent.cpp */
#include "Demo_01_Agent.h"
RepastHPCDemoAgent::RepastHPCDemoAgent(repast::AgentId id): id_(id), c(100), total(200){ }
RepastHPCDemoAgent::RepastHPCDemoAgent(repast::AgentId id, double newC, double newTotal): id_(id), c(newC), total(newTotal){ }
RepastHPCDemoAgent::~RepastHPCDemoAgent(){ }
void RepastHPCDemoAgent::set(int currentRank, double newC, double newTotal){
id_.currentRank(currentRank);
c = newC;
total = newTotal;
}
bool RepastHPCDemoAgent::cooperate(){
return repast::Random::instance()->nextDouble() < c/total;
}
void RepastHPCDemoAgent::play(repast::SharedContext<RepastHPCDemoAgent>* context){
std::set<RepastHPCDemoAgent*> agentsToPlay;
agentsToPlay.insert(this); // Prohibit playing against self
context->selectAgents(3, agentsToPlay, true);
double cPayoff = 0;
double totalPayoff = 0;
std::set<RepastHPCDemoAgent*>::iterator agentToPlay = agentsToPlay.begin();
while(agentToPlay != agentsToPlay.end()){
bool iCooperated = cooperate(); // Do I cooperate?
double payoff = (iCooperated ?
((*agentToPlay)->cooperate() ? 7 : 1) : // If I cooperated, did my opponent?
((*agentToPlay)->cooperate() ? 10 : 3)); // If I didn't cooperate, did my opponent?
if(iCooperated) cPayoff += payoff;
totalPayoff += payoff;
agentToPlay++;
}
c += cPayoff;
total += totalPayoff;
}
/* Serializable Agent Package Data */
RepastHPCDemoAgentPackage::RepastHPCDemoAgentPackage(){ }
RepastHPCDemoAgentPackage::RepastHPCDemoAgentPackage(int _id, int _rank, int _type, int _currentRank, double _c, double _total):
id(_id), rank(_rank), type(_type), currentRank(_currentRank), c(_c), total(_total){ }