/* This is our agent class. It implements MASON's Steppable interface
* (which allow us to use MASON schedule to direct activations as well
* as extends JUNG's SparseVertex class, allowing for exploiting JUNG to
* operate and display the connections network. */
package jungnetwork;
import java.util.Iterator;
import java.util.Set;
import sim.engine.SimState;
import sim.engine.Steppable;
import edu.uci.ics.jung.graph.impl.SparseGraph;
import edu.uci.ics.jung.graph.impl.SparseVertex;
import edu.uci.ics.jung.graph.impl.UndirectedSparseEdge;
public class NodeAgent extends SparseVertex implements Steppable {
private static final long serialVersionUID = 1L;
// Handle to simulation
public PreferentialAttachment sim;
// Number of activations left
public int timer;
// Handle to graph
public SparseGraph graph;
public NodeAgent(PreferentialAttachment attachment, int timer) {
this.sim = attachment;
this.timer = timer;
this.graph = (SparseGraph) attachment.graph;
}
public void step(SimState state) {
/*
* Each time the agent is activated, it will either add or drop a single
* connection to other agents. The probability of dropping is increasing
* in number of connections agent already has, equals 1 when agent's
* degree reaches maxDegree cap.
*/
double rand = sim.random.nextDouble();
if ((this.degree() / sim.maxDegree) < rand) {
/*
* Decision to establish a new connection has been made. Target node
* will be selected with probability proportional to its degree
* using Boltzmann transformation - implementing preferential
* attachment logic.
*/
double temperature = sim.temperature;
SparseVertex gfrom = this;
Set graphSet = graph.getVertices();
Iterator i = graphSet.iterator();
double verSum = 0;
while (i.hasNext()) {
verSum += Math.exp(temperature * ((SparseVertex) i.next()).degree());
}
double cumSum = 0;
rand = state.random.nextDouble();
i = graphSet.iterator();
SparseVertex nextVertex;
do {
nextVertex = (SparseVertex) i.next();
cumSum += Math.exp(temperature * nextVertex.degree());
} while (i.hasNext() && (rand > (cumSum / verSum)));
graph.addEdge(new UndirectedSparseEdge(gfrom, nextVertex));
} else {
// Cognitive capacity exhausted. A random edge will be removed.
UndirectedSparseEdge toRemove = (UndirectedSparseEdge) this.getOutEdges().toArray()[state.random.nextInt(this.degree())];
graph.removeEdge(toRemove);
}
// Connection operations have been finished. If it is still possible,
// agent will register itself on the schedule for next activation.
if (this.timer > 0) {
this.timer--;
sim.schedule.scheduleOnce(sim.schedule.time() - Math.log(sim.random.nextDouble()), this);
}
}
}