Centralized algorithm

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.

Listening to the events (from outside)

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:

Concretely, what you have to do for ClockListener (say), is to:

  1. add implements ClockListener in the declaration of your class
  2. add the corresponding onClock() method (filled as desired)
  3. register your class through calling addClockListener on the topology object

Another 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.

A basic example

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.