Thibaut Démare
LITIS - Université du Havre
NeX Days' 2015 - Agadir, Morocco
28 - 30 April 2015
We use the same model as in GAMA but this time, fully implemented in Graphstream.
We will use two Java classes:
MobileDevice, represents a moving person with a communication device,
MobilitySimulation, represents a set of persons and runs the simulation.
We will start from these two classes that already implement a fully functional random waypoint simulation, and use GraphStream to represent the associated graph and make some measures on it.
mobilitydirectory in the project,
MobilitySimulation.
MobilitySimulationrole is to register a set of
MobileDeviceobjects and to run in a loop methods to make them move and to check which other mobile devices they can connect to.
MobilitySimulation()the constructor, inits and runs the simulation.
addMobileDevices()registers a set of mobile devices in the simulation.
moveMobileDevices()makes each device move toward its target or wait.
checkConnections()sees toward which mobile devices connections can be made or removed
MobilitySimulation(in orange), note that we refer to a field
graphthat is already present:
public MobilitySimulation() {
graph = new SingleGraph("mobility model");
graph.display(false);
addMobileDevices(deviceCount);
initConnectedComponents();
for(int step=0; step<steps; step++) {
moveMobileDevices();
checkConnections();
showConnectedComponents();
sleep();
}
}
MobileDevice. Here are the main methods:
MobileDevice()Builds a new mobile device knowing its name and the global graph.
next()Chooses the next action to do.
closeTo()True if the devices is close to another one.
nextTarget()Chooses a next target destination.
move()Move a little toward the target.
atTarget()True if arrived at target.
checkConnections()Check new connections or connections to remove.
We will also add one field and complete the constructor.
Each device maps to a node in the global graph of the simulation:
protected Node node;
public MobileDevice(Graph graph, String name) {
this.graph = graph;
this.x = Math.random();
this.y = Math.random();
nextTarget();
node = graph.addNode(name);
}
When the device moves, we must also tell the corresponding node representation in the display to move:
protected void move() {
x += (targetx-x)*speed;
y += (targety-y)*speed;
node.setAttribute("x", x);
node.setAttribute("y", y);
}
We use specific UI attributes to specify the abscissa and ordinate of the node.
We have a valid code, we can start to test.
xand
yof the mobile device, but to show you how it works, we will use the coordinates of the node in the graph we set previously in
move().
closeTo()method and change it with:
protected boolean closeTo(Node other) {
double otherxy[] = nodePosition(other);
return(Math.abs(x-otherxy[0]) < 0.07 && Math.abs(y-otherxy[1]) < 0.07);
}
nodePosition()is a static method in the
GraphPosLengthUtilsclass that allows easy retrieval of the coordinate attributes in nodes. This class also allows to easily compute edges lengths for example.
We will now check the connections to create or remove due to the displacement of devices.
checkConnectivity()method:
protected void checkConnections() {
removeConnections();
createConnections();
}
protected void removeConnections() {
Iterator<?extends Edge> edges = node.getEdgeIterator();
while(edges.hasNext()) {
Edge edge = edges.next();
if(!closeTo(edge.getOpposite(node))) {
edges.remove();
}
}
}
closeTo()we know if we must remove the edge with the iterator.
GraphPosLengthUtils.edgeLength().
Now we will create connections for devices that are now close enough.
protected void createConnections() {
for(Node other: graph) {
if(other != node && closeTo(other)) {
if(!node.hasEdgeToward(other.getId())) {
graph.addEdge(
String.format("%s-%s", node.getId(), other.getId()),
node.getId(), other.getId());
}
}
}
}
node.hasEdgeToward()), and then create the new connection with
graph.addEdge().
We will add a dynamically updating measure on the graph: the number of connected components. We will also see how to add information on the graph, here the connected components count.
First we add two fields, one for the display on the graph, called a sprite, the other for the algorithm that will observe the graph and constantly update the number of components:
protected Sprite cc;
protected ConnectedComponents ccalgo;
ConnectedComponentsclass comes from the
gs-algopackage which contains lots of such algorithms.
The connected components only need to know the graph. After this it will update itself each time the graph changes.
SpriteManagerto create a sprite, that is a graphical representation on the graph display, to add a label to print the number of connected components.
protected void initConnectedComponents() {
ccalgo = new ConnectedComponents();
ccalgo.init(graph);
SpriteManager sm = new SpriteManager(graph);
cc = sm.addSprite("cc");
cc.setPosition(Units.PX, 10, 10, 0);
}
Now we display the measure, by updating the sprite at each simulation step:
protected void showConnectedComponents() {
cc.setAttribute("ui.label", "Connected components " +
ccalgo.getConnectedComponentsCount());
}
MobilitySimulation()constructor, just after
graph.display(), add:
...
graph.display(false);
graph.addAttribute("ui.antialias");
graph.addAttribute("ui.stylesheet",
"edge { fill-color: grey; } sprite { size: 0px; }");
addMobileDevices(deviceCount);
...
Get the Slides and Materials on-line:
NeX2015)