Our next step will be to establish network connections among the agents.

There is an important point that should be made here, even if it is entirely semantic: All of the agents are already in the network- that is, they are already in the network projection. The context contains the network projection (or projections, if there happen to be more than one). When an agent is added to the context, it is also added to all of the projections that the context includes. To say that an agent is in the 'network' is to say that it is contained in the projection. However, at the moment, the 'network' does not include any actual links between agents. It is tempting, when looking at a case in which some agents are linked to others, while other agents are not linked, to say that the linked agents are in the network and the unlinked ones are not, but according to the usage here, this is incorrect.

In this step we will connect agents together in the network we have just created. This will take place just after the 'borrowing' of agents has occurred, so that there will be some local and some non-local agents in the network. The algorithm for connecting agents will be:

Connections will be undirected, so an agent can end up with more than 5 connections (because it will have the five that it made, plus the connections any other agents have made to it.)

To do this, we need to make three changes. First, declare the new, schedulable function of the model class (in model.h):

class RepastHPCDemoModel{
	int stopAt;
	int countOfAgents;
	repast::Properties* props;
	repast::SharedContext<RepastHPCDemoAgent> context;
	
	RepastHPCDemoAgentPackageProvider* provider;
	RepastHPCDemoAgentPackageReceiver* receiver;

	repast::SVDataSet* agentValues;
	repast::SharedNetwork<RepastHPCDemoAgent, repast::RepastEdge<RepastHPCDemoAgent> >* agentNetwork;
	
public:
	RepastHPCDemoModel(std::string propsFile, int argc, char** argv, boost::mpi::communicator* comm);
	~RepastHPCDemoModel();
	void init();
	void requestAgents();
	void connectAgentNetwork();
	void cancelAgentRequests();
	void removeLocalAgents();
	void moveAgents();
	void doSomething();
	void initSchedule(repast::ScheduleRunner& runner);
	void recordResults();
};

Then create this function in the model.cpp file:

void RepastHPCDemoModel::connectAgentNetwork(){
	repast::SharedContext<RepastHPCDemoAgent>::const_local_iterator iter    = context.localBegin();
	repast::SharedContext<RepastHPCDemoAgent>::const_local_iterator iterEnd = context.localEnd();
	while(iter != iterEnd) {
		RepastHPCDemoAgent* ego = &**iter;
		std::vector<RepastHPCDemoAgent*> agents;
		agents.push_back(ego);                          // Omit self
		context.selectAgents(5, agents, true);          // Choose 5 other agents randomly
		// Make an undirected connection
		for(size_t i = 0; i < agents.size(); i++){
         	    std::cout << "CONNECTING: " << ego->getId() << " to " << agents[i]->getId() << std::endl;
  	  	    agentNetwork->addEdge(ego, agents[i]);	
		}
		iter++;
	}	
}

Note: If an edge being added to a network has the same source and target nodes (in the same roles) as an existing edge, the new edge may not be added; if there is a possibility of adding a duplicate edge, a check should be made first to ensure that there is no duplication and, if a duplicate is found, it should be removed first.

Finally, add this function to the schedule of events:

void RepastHPCDemoModel::initSchedule(repast::ScheduleRunner& runner){
	runner.scheduleEvent(1, repast::Schedule::FunctorPtr(new repast::MethodFunctor<RepastHPCDemoModel> (this, &RepastHPCDemoModel::requestAgents)));
	runner.scheduleEvent(1.1, repast::Schedule::FunctorPtr(new repast::MethodFunctor<RepastHPCDemoModel> (this, &RepastHPCDemoModel::connectAgentNetwork)));
	runner.scheduleEvent(2, 1, repast::Schedule::FunctorPtr(new repast::MethodFunctor<RepastHPCDemoModel> (this, &RepastHPCDemoModel::doSomething)));
	runner.scheduleEvent(3, repast::Schedule::FunctorPtr(new repast::MethodFunctor<RepastHPCDemoModel> (this, &RepastHPCDemoModel::moveAgents)));
	runner.scheduleEndEvent(repast::Schedule::FunctorPtr(new repast::MethodFunctor<RepastHPCDemoModel> (this, &RepastHPCDemoModel::recordResults)));
	runner.scheduleStop(stopAt);
	
	// Data collection
	runner.scheduleEvent(1.5, 5, repast::Schedule::FunctorPtr(new repast::MethodFunctor<RepastHPCDemoModel>(agentValues, &repast::DataSet::record)));
	runner.scheduleEvent(10.6, 10, repast::Schedule::FunctorPtr(new repast::MethodFunctor<RepastHPCDemoModel>(agentValues, &repast::DataSet::write)));
	runner.scheduleEndEvent(repast::Schedule::FunctorPtr(new repast::MethodFunctor<RepastHPCDemoModel>(agentValues, &repast::DataSet::write)));
}