Contrary to node algorithms (distributed algorithms), you do not need to inherit from a particular class in order to write a centralized algorithm. Still, you may want to react to some of JBotSim's events, which is what this tutorial is mainly about.
As you know, node algorithms react to various events by means of overriding methods from the Node
class.
These methods are not available in other Java classes.
However, you can listen to these events from within an arbitrary class, via the following interfaces:
TopologyListener
: be notified when new nodes are added or removed, through overridding
onNodeAdded()
and onNodeRemoved()
.ConnectivityListener
: be notified when new links are added or removed, through
overridding onLinkAdded()
and
onLinkRemoved()
.
These methods are called differently from the ones in a node, because a node is only notified for incident links,
whereas central listeners are notified for all links.ClockListener
: be notified in each round, through overridding
onClock()
.
By default, this method is called after being called on the inner components of the system (including nodes).
This behavior can be redefined by replacing the inner scheduler of JBotSim, see
Scheduling for more (advanced users only).MessageListener
: be notified whenever a message arrives at a node, through overridding
onMessage()
.
This interface is particularly useful for complexity analysis (or to keep logs of an execution).StartListener
: be notified when the topology starts (or restarts).
This is usefull, for instance, for (re)initializing global aspects of the topology.MovementListener
: be notified when a node moves, through overridding onMovement()
.Concretely, what you have to do for ClockListener
(say), is to:
implements ClockListener
in the declaration of your classonClock()
method (filled as desired)addClockListener
on the topology objectAnother option is to define an anonymous listener from anywhere as follows
topology.addClockListener(new ClockListener(){
@Override
public void onClock(){
// your code
}
});
The example in the next section uses the first option by creating a regular java class which implements a number of interfaces.
Here is a possible class realizing a centralized algorithm that relies on JBotSim's events.
import io.jbotsim.core.Link;
import io.jbotsim.core.Node;
import io.jbotsim.core.Topology;
import io.jbotsim.core.event.ClockListener;
import io.jbotsim.core.event.TopologyListener;
import io.jbotsim.core.event.ConnectivityListener;
public class MyCentralizedAlgorithm implements ClockListener, TopologyListener,
ConnectivityListener{
private Topology tp;
public MyCentralizedAlgorithm(Topology tp){
this.tp = tp;
tp.addClockListener(this);
tp.addTopologyListener(this);
tp.addConnectivityListener(this);
}
@Override
public void onClock() {
if (tp.getTime() % 100 == 0)
System.out.println("It is " + tp.getTime() + " o'clock!");
}
@Override
public void onNodeAdded(Node node) {
System.out.println("Hi " + node);
}
@Override
public void onNodeRemoved(Node node) {
System.out.println("Goodbye " + node);
}
@Override
public void onLinkAdded(Link link) {
System.out.println("Nodes " + link.endpoint(0) + " and " +
link.endpoint(1) + " got in touch!");
}
@Override
public void onLinkRemoved(Link link) {
System.out.println("Nodes " + link.endpoint(0) + " and " +
link.endpoint(1) + " left each other!");
}
}
Finally, we create the algorithm from within the main()
method as follows:
public static void main(String[] args) {
Topology tp = new Topology();
new MyCentralizedAlgorithm(tp);
new JViewer(tp);
tp.start();
}
Typical purposes for centralized algorithms are to code adversaries (also called deamons), which may perform global operations in between rounds (e.g. add or remove links or nodes), while the distributed algorithms on the nodes keep executing. Another typical use of centralized algorithms is to implement classical graph algorithms (e.g. a BFS or a DFS), although in this case no particular event is required, except perhaps for updating the computation when the graph changes.