Getting Started

Update date:

Forewords

This document aims at explaining how to implement an application with the ** MECSYCO framework**. It focuses on a technical and implementation viewpoint (how to code), neither modelling, nor meta-modelling viewpoints (how to model, why these choices).

Some knowledge about multi-modelling, the MECSYCO concepts, NetLogo modeling, the Java programming language and Maven could be helpful.

The environment used in this tutorial is Eclipse 4.16.0 with the Java Development Kit 1.8.

Setup

Download the MecsycoScholar project and import it in Eclipse (see the usage guide).

The tutorial can be done directly in this project, or you can create your own Maven project -see the ‘pom.xml’ file of MecsycoScholar project to have an example.

Random walk model

At first, you can take a look about the model’s behavior.

You can run the model located at My Models/Netlogo-Models/random_walk_1.nlogo via the NetLogo Editor (Figure 1). This editor is not shipped with the Getting Started project (see NetLogo webpage).

NetLogo random walk model view
Figure 1: NetLogo random walk model view

The model creates a pool of walkers – NetLogo turtles – positioned at the origin. For each step – NetLogo tick – the hidden walkers die and the other ones move in a random direction. When a walker overpasses the border of the world, in other words, is on a gray ground, it is hidden Therefore the count of walkers decreases over time.

The petri network in figure 2 represents a walker’s state. Each place is a fulfilled condition and a transition is an event. Only one transition is playable by step.

Petri network of a walker state
Figure 2: Petri network of a walker state

The walkers out of the world scope are hidden and die at the next simulation step. Thus, after each step, the hidden walkers represent the walkers who leave the world. We use this characteristic for retrieving and exchanging the walkers.

Minimal example

A minimal example is the launching of a NetLogo model from a MECSYCO model. The MECSYCO model (Figure 3) only consists in a m-agent and a Model Artifact.

Random walk MECSYCO model
Figure 3: Random walk MECSYCO modeling

The m-agent is a generic component shipped with the MECSYCO core. It intercepts each step of the simulation it is in charge of, and communicates via the model artifact.

A model artifact is a domain-specific component. However, it is possible to have a generic artifact simulator-dependent. At this time, a generic version of the NetLogo model artifact is available in the package mecsyco-world-netlogo in MecsycoJava.

A model artifact is like the interface between the model instance under simulation and the m-agent. A NetLogo model artifact also adds output and input ports to the NetLogo model. The model artifact created for the current example adds one output and one input ports. The output port provides the walkers which leave the world. The received walkers in the input port spawn at the world’s origin.

The figure 4 presents an intuitive scheme of the NetLogo model equipped with an output port and an input port.

Connectable Random walk model
Figure 4: Random walk model with ports

launcher.MinimalExampleLauncher instantiates this model.


EventMAgent agent1 = new EventMAgent("world-1", maxSimulationTime);

ModelArtifact modelArtifact =
  new SimpleRandomWalkModelArtifact(firstModelPath, firstWorldName, width, height);
agent1.setModelArtifact(modelArtifact);

agent1.startModelSoftware();
agent1.setModelParameters();
agent1.start();
Code 1: instantiation of the model with a loopback

At line 2, the m-agent is created with the duration of the simulation (maxSimulationTime). Here, the duration quantifies the number of NetLogo ticks to perform.

The model artifact is created at line 5 with the path to the model (firstModelPath).

Model with loopback

We would like to retrieve the walkers which leave the world and spawn them at the world’s origin. The simpler way to do it is to create a loopback on the model connecting the output port to the input port (figure 5).

random walk model with loopback
Figure 5: Random walk model with loopback

In a MECSYCO model, the connection between output and input ports is modeled with a coupling artifact. It is also a generic component shipped with the core. It links two m-agents (or a m-agent with itself).

The equivalent MECSYCO model is shown in the figure 6.

MECSYCO model with a loopback
Figure 6: MECSYCO model with a loopback

Only three extra lines of code are needed to establish this connection (Code 2 line 8 to 10).


EventMAgent agent1 = new EventMAgent("world-1", maxSimulationTime);

ModelArtifact modelArtifact =
  new SimpleRandomWalkModelArtifact(firstModelPath, firstWorldName, width, height);
agent1.setModelArtifact(modelArtifact);

CentralizedEventCouplingArtifact couplingArtifact = new CentralizedEventCouplingArtifact();
agent1.addInputCouplingArtifact(couplingArtifact, "in");
agent1.addOutputCouplingArtifact(couplingArtifact, "out");

agent1.startModelSoftware();
agent1.setModelParameters();
agent1.start();
Code 2: instantiation of the MECSYCO model with a loopback

The lines 9 and 10 specify respectively the destination – the model input - and the source – the model output – of the coupling artifact. In this example, the coupling artifact links the m-agent with itself.

Since there is only an input and an output, the chosen port names (“in” and “out”) are not relevant. When there exists several input ports and/or output ports, the port name enables a simple port discrimination in the model artifact.

At each tick, the m-agent gets the hidden walkers from the model artifact output and then sends them to the model artifact input. The model artifact creates as many new walkers as received. Freshly created walkers have the same color and the same size than the received ones. Then, when you run the MECSYCO model, you note that the count of walkers is constant over time.

Hum… I admit that the new walkers are hardly noticeable. Why not use another color for freshly created walkers?

Discovering operation

It would be great to change the color of each exchanged walker before their transmission to the model artifact. In more generic terms, we would like to apply transformations on the exchanged data.

MECSYCO has such a feature. It’s named operation. There are no needs to introduce a new model artifact or modify the existing one.

An operation is symbolized by a point and it is placed on a coupling artifact (Figure 7). It is applied to the data which cross the coupling artifact.

MECSYCO model with an operation
Figure 7: MECSYCO model with an operation.

The operation is shipped with the example (operation.TurtleColorSetter). Only two lines are required for adding this operation (Code 3 lines 8 and 11).


EventMAgent agent1 = new EventMAgent("world-1", maxSimulationTime);

ModelArtifact modelArtifact =
  new SimpleRandomWalkModelArtifact(firstModelPath, firstWorldName, width, height);
agent1.setModelArtifact(modelArtifact);

EventOperation colorSetter = new TurtleColorSetter (NetLogoColorConstants.Red);

CentralizedEventCouplingArtifact couplingArtifact = new CentralizedEventCouplingArtifact();
couplingArtifact.addEventOperation(colorSetter);
agent1.addInputCouplingArtifact(couplingArtifact, "in");
agent1.addOutputCouplingArtifact(couplingArtifact, "out");

agent1.startModelSoftware();
agent1.setModelParameters();
agent1.start();
Code 3: MECSYCO model instantiation with an operation.

Then you can observe in figure 8 that the newly created walkers appear at the model’s origin.

Effect of the color setter operation
Figure 9: Effect of the color setter operation.

Great, isn’t it?

Interacting models

Well! You are ready to make two NetLogo models interact!

We would like to simply retrieve the walkers which leave a given world and then inject them in the other world (Figure 9).

Two interacting random walk models
Figure 9: Two interacting random walk models.

Figure 10 exhibits the equivalent MECSYCO model.

Interacting random walk models
Figure 10: MECSYCO model of two interacting models.

The walker’s color depends on the world where it appears the first time. The walkers from the first world are green and the walkers from the second one are red.

Create a new launcher InteractingRandomWalkLauncher based on model.SingleRandomWalkLauncher (Code 4).


public class InteractingRandomWalkLauncher {
  // Display Settings
  public final static String firstWorldName = "World 1";

  public final static String secondWorldName = "World 2";

  public final static int width = 460;

  public final static int height = 520;

  // Model settings
  public final static double maxSimulationTime = 1000;

  public final static String firstModelPath =
    "My Models/Netlogo-Models/random_walk_1.nlogo";

  public final static String secondModelPath =
    "My Models/Netlogo-Models/random_walk_2.nlogo";

  // Entry point
  public static void main(String... args) {
    // Model 1
    EventMAgent agent1 = new EventMAgent("world-1", maxSimulationTime);
    ModelArtifact modelArtifact1 =
      new SimpleRandomWalkModelArtifact(firstModelPath, firstWorldName, width, height);
    agent1.setModelArtifact(modelArtifact1);
    CentralizedEventCouplingArtifact couplingArtifact1 =
      new CentralizedEventCouplingArtifact();

    // Model 2
    EventMAgent agent2 = new EventMAgent("world-2", maxSimulationTime);
    ModelArtifact modelArtifact2 =
      new SimpleRandomWalkModelArtifact(secondModelPath, secondWorldName, width, height);
    agent2.setModelArtifact(modelArtifact2);
    CentralizedEventCouplingArtifact couplingArtifact2 =
      new CentralizedEventCouplingArtifact();

    // Connections
    agent1.addInputCouplingArtifact(couplingArtifact1, "in");
    agent1.addOutputCouplingArtifact(couplingArtifact2, "out");
    agent2.addInputCouplingArtifact(couplingArtifact2, "in");
    agent2.addOutputCouplingArtifact(couplingArtifact1, "out");

    // Software initializations
    agent1.startModelSoftware();
    agent2.startModelSoftware();

    // Model initializations
    agent1.setModelParameters();
    agent2.setModelParameters();

    // SImulation launching
    agent1.start();
    agent2.start();
  }
}
Code 4: InteractingRandomWalkLauncher class.

The result of the previous code is shown in figure 11.

Interacting models running
Figure 11: View of two interacting random walk models.

Of course you can create more worlds and connect them together.

Operation creation

Any kind of transformations can be applied on the exchanged data. A MECSYCO model allows the combination of operations.

For instance, we could combine a size setter operation with the color setter operation of the first example. The associated MECSYCO model is in the figure 12.

MECSYCO model with two operations
Figure 12: MECSYCO model with two operations.

The size setter operation is not part of the getting started package. It is an opportunity for creating your first operation!

Create a new class named TurtleSizeSetter extending mecsyco.core.operation.EventOperation. The apply method must be defined (Code 5).


public class TurtleSizeSetter extends EventOperation {
  @Override
  public @Nullable SimulData apply (SimulEvent aEvent) {
    final SimulData data = aEvent.getData();
    final @Nullable SimulData result;

    if (data instanceof SimulVector) {
      SimulVector<?> candidates = (SimulVector<?>) data;

      for (int i = 0, count = candidates.count(); i < count; i++) {
        if (candidates.item(i) instanceof NetLogoTurtle) {
          final NetLogoTurtle t = (NetLogoTurtle) candidates.item(i);

          if (! t.getSize().equals(4)) {
            candidates = candidates.replacedAny(i, t.withSize(4));
          }
        }
      }

      result = candidates;
    }
    else {
      result = null;
    }

    return result;
  }
}
Code 5: TurtleSizeSetter class.

The argument aEvent is the exchanged event. Typed as mecsyco.core.type.SimulEvent, it consists of the time where an event occurs and the associated exchanged data, typed as mecsyco.type.core.SimulVector.

The SimulVector contains a set of walkers typed as mecsyco.world.netlogo.type.NetLogoTurtle. This last type embeds the NetLogo turtle’s characteristics, in particular their color and their size.

Add the operation into the coupling artifact (Code 6 and Figure 13).


EventMAgent agent1 = new EventMAgent("world-1", maxSimulationTime);

ModelArtifact modelArtifact =
  new SimpleRandomWalkModelArtifact(firstModelPath, firstWorldName, width, height);
agent1.setModelArtifact(modelArtifact);

EventOperation colorSetter = new TurtleColorSetter(NetLogoColorConstants.Red);
EventOperation sizeSetter = new TurtleSizeSetter();

CentralizedEventCouplingArtifact couplingArtifact = new CentralizedEventCouplingArtifact();
couplingArtifact.addEventOperation(colorSetter);
couplingArtifact.addEventOperation(sizeSetter);
agent1.addInputCouplingArtifact(couplingArtifact, "in");
agent1.addOutputCouplingArtifact(couplingArtifact, "out");

agent1.startModelSoftware();
agent1.setModelParameters();
agent1.start();
Code 6: MECSYCO model instantiation with two operations.
Effect of the olor and size setter operations
Figure 13: Effect of the color and size setter operations.

Model artifact creation

Currently, the agents exchange walkers. However, the only useful information is the number of walkers with a specific color leaving a given world. Instead of exchanging all the walkers, we could create another model artifact exchanging only the number of walker with a specific color. (Figure 14).

Two interacting models exchanging the needed information
Figure 14: Two interacting models exchanging the needed information.

This change requires the creation of a new model artifact.

Create a class named RandomWalkModelArtifact which copy the code of SimpleRandomWalkModelArtifact.

getExternalOutputEvent is the method used by the m-agent for retrieving the events. It represents the output port while processExternalInputEvent is used for introducing a new event into the model and then represents the input port. Only these two methods must be modified.

getExternalOutputEvent must send the color counts, i.e. the number of occurrences of a given walker’s color. common.type.Bag offers facilities to perform this counting.

processExternalInputEvent must retrieve the exchanged data and create the walkers with their attached color (Code 7).


@Override
public void processExternalInputEvent (SimulEvent event, String port) {
  if ("in".equals(port)) {
    final SimulData data = event.getData();

    if (data instanceof Bag) {
      final Bag<?> colors = (Bag<?>) event.getData();

      // Avoid to interpret a command when there is no turtles.
      if (! colors.isEmpty()) {
        final StringBuilder cmd = new StringBuilder(60 * colors.uniqueItemCount());

        for (final Object c : colors.items()) {
          if (c instanceof Number) {
            cmd.append("create-turtles " + colors.countOf(c) + " [set color " + ((Number) c).doubleValue() + " set size g-size] ");
          }
          else {
            modelLogger.warn("Input port 'in' ", new UnexpectedTypeException(Bag.of(Number.class), Bag.of(c.getClass())));
          }
        }

        execCmd(cmd.toString());
      }
    }
    else {
      modelLogger.warn("Input port 'in' ", new UnexpectedTypeException(Bag.class, data.getClass()));
    }
  }
  else {
   modelLogger.warn("The input port '{}' is not supported", port);
  }
}

@Override
public @Nullable SimulEvent getExternalOutputEvent (String port) {
  SimulEvent result = null;

  if ("out".equals(port)) {
    AgentSet turtles;

    try {
      turtles = (AgentSet) comp.report("turtles with [hidden?]");

      if (! turtles.isEmpty()) {
        final Bag<Double> colors = new Bag<>();

        for(final Object item : turtles.agents()) {
          colors.extend((Double) ((Turtle) item).color());
        }

        result = new SimulEvent(colors, eventTime);
      }
    }
    catch (CompilerException e) {
      modelLogger.error("", e);
    }
  }
  else {
    modelLogger.warn("The output port '{}' is not supported", port);
  }

  return result;
}
  
Code 7: ProcessExternalInputEvent and getExternalOutputEvent methods

At the line 8 we retrieve the received data – the color counts – typed as a bag of color. We use the NetLogo color coding and represent a color by a double.

The lines 14 to 20 process the bag of color and build the NetLogo command. In case of error we add a system of warning.

At line 23, execCmd calls the NetLogo interpreter with the previously built command as argument.

At the line 43, we retrieve the hidden turtles thanks to the NetLogo interpreter. The bag of color, instantiated at the 46-th line, is fulfilled at the line 49 with the turtle’s color.

Replace SimpleRandomWalkModelArtifact by RandomWalkModelArtifact in the InteractingRandomWalkLauncher class. The result is identical, as expected but the data exchanged is optimized.

Final notes

You can see the final results in package mecsycoscholar.application.gettingstarted in MecsycoScholar.

The other available examples follow the same principles.