First Steps with RePast

Lets take a few first steps with our modeling frameworks.  We will be fairly brief , limiting ourselves to simple "kicking the tires" and writing a hello world in each ABM system (here is the NetLogo First Steps).  Our goal is to gain a feel for what each system is capable of so that we can make intelligent decisions on which one to use for a given task.  Note: most images below can be clicked on for a full size image.

Introducing RePast

To download RePast, go to their web site, downloading the package for your system.  As of this writing, the version is 2.0.1, and requires Java 1.4.  The site has a mail list sign-up, which I recommend. 

The package includes considerable browser-based documentation in the docs/ directory for fast viewing, and the readme.html includes an overall description.  The docs/how_to/how_to.html gets into running and programming RePast, while docs/api/ contains the JavaDocs.



Start RePast by double clicking the lib/repast.jar file.  When it starts, you are presented with the control strip which is part of every model. You can browse the Model Library, by clicking on the folder icon. Start by selecting the SugarScape model from the list presented, then clicking on "load".    You'll see the setup to the right.

To run the model, click either the "Single Step" or "Forward" buttons.  To pause the model, click the "Pause" button.  The parameters can be set using the parameter window controls.  The simulation is a version of the SugarScape model made famous by Axtell and Epstein in their 1996 book Growing Artificial Societies.


RePast is a Java Language based system. For those new to Java, the Java Tutorial is an excellent place to start.  Download for easy use.

Take some time to browse through the RePast HowTo . Its Running a Simulation and GUI sections are good starting places for how to use the demos. The SimpleModel HowTo describes initial programming using the SimpleModel class we'll use below.  The FAQ is a good place if all else fails!   The code for the demos is in the downloaded src/ directory under uchicago/src/sim. 

Its a good idea to bookmark your local copy of the API documentation, for both Java and RePast.  They will be your constant companion as you write models!


Buttons: A "Hello World" Model

 
Just as in the NetLogo introduction, we'll use the example of a rapid "phase transition" presented in Stuart Kauffman's "At Home in the Universe".  This is modeled by a set of buttons which, during each turn, a random pair are chosen to be tied together. 

Initially there are lots of isolated pairs tied together.  Later threes, fours and abruptly there is a steep transition to most of the buttons being tied together .. an emergent giant cluster.  In the example shown here, there are 500 buttons and we plot 1000 turns.  The rapid change occurs at around the 1/4 mark where the number of threads is about half the number of buttons.

 

We can model this RePast by having the buttons be agents, with both color and a group ID, placed randomly on the graphic window.  Each tick we will chose a pair of agents, connecting them together and changing all of their group of agents to be the same color and have the same group ID.  At the end of each turn we will find the largest group cluster, posting its size. Before we start, you can browse the final two Java source files.

We'll build the model in phases, in order to simplify the process.

Buttons Phase 1: Minimal TutModel.java

For our first phase, we'll build a minimal subclass of SimpleModel (See: API Docs, HowTo Docs).  It will not need an agent class yet, because we'll simply do all the initialization necessary to pop-up a DisplaySurface .. the window in which the agents operate (API Docs, HowTo Docs).  You can view the Java source for our first phase.  To compile and run the model you use:
      javac -classpath lib/repast.jar:. TutModel.java
java -classpath lib/repast.jar:. TutModel &

Note that I've changed directory to where the java file is, and made a link to the RePast lib/ directory .. both to simplify the compilation and execution of the model. The results are to the right:



Lets look at the program.  (Note: In the code examples below, I've left the import statements and comments out for simplicity, and made minor formatting changes to fit the code into the tables better.)

The Class name is "TutModel", extending SimpleModel.  It has two variables: the Display Surface and its size (buttons along an edge).

The class only has three methods: "setup" and "buildModel", along with a static (Class) "main" method who's only job is to start the model.

Setup is called when a model is initialized, or is restarted, both from the Control Panel.  BuildModel is called when the model is first run, either by the Step or the Run buttons in the Control Panel.

Both are discussed in the HowTo.

Note that only 16 lines of code got us running!

If you run this model, clicking on Step or Run simply increase the tick count with no other effect because we have not added a "step" method. 

So this is a "no-op" model at this point, but has the initial structure we need to get started.

public class TutModel extends SimpleModel {
private DisplaySurface dsurf;
private int spaceSize = 50;

public void setup() {
super.setup();

if (dsurf != null) dsurf.dispose();
dsurf = new
DisplaySurface(this,"Buttons Display");
super.registerDisplaySurface
("Buttons Display",dsurf);
}

public void buildModel() {
Object2DTorus space = new
Object2DTorus(spaceSize, spaceSize);

Object2DDisplay display = new
Object2DDisplay(space);
dsurf.addDisplayable(display,"Buttons Space");

dsurf.display();
}

public static void main(String[] args) {
SimInit init = new SimInit();
init.loadModel(new TutModel(), null, false);
}
}

Buttons Phase 2: Introducing Agents -- TutAgent.java

In NetLogo, Turtles are provided as part of the framework.  In RePast, the Agents are implemented by the programmer, almost from scratch. This is facilitated by the use of Java Interfaces, in particular the Drawable interface.  By implementing the methods: "draw", "getX" and "getY", any object can be placed in the RePast Space (API, HowTo) created in Phase 1.

In our second phase, we create our Button "agent", TutAgent.java, along with the changes needed in TutModel.java needed to incorporate the agents and initialize them randomly on the DisplaySurface.  TutAgent is quite minimal, just enough to be Turtle-like: have a color, an ID (who) and be a Drawable.

The changes to TutModel are the minimum to add the agents: introduce a variable "buttons" to hold the number of buttons and add a loop creating the buttons.


To compile and run the new pair of java files do:

      javac -classpath lib/repast.jar:. TutAgent.java TutModel.java
java -classpath lib/repast.jar:. TutModel &
Here is the entire new TutAgent class.  It implements Drawable by  providing "draw", "getX", "getY", thus letting it be put into RePast Spaces.

We added the "who" and "color" attributes to make the TutAgent be turtle-like, both for our button experiment and for future NetLogo-like models in RePast.

We added "setXY" method, and the "space" instance variable so that TutAgents could add themselves to spaces automatically for the TutModel.  Thus "setXY" both updates the x, y instance variables and places the agent correctly in the space. 

Note "setXY" also removes us from out prior position in the space if need be.

public class TutAgent implements Drawable {
private int who;
private int x, y;
private Color color;
private Object2DTorus space;

public TutAgent(Object2DTorus space, int who){
this.who = who;
this.space = space;
}

public void draw(SimGraphics g) {
g.drawFastCircle(color);
}

public void setXY(int x, int y) {
if (space.getObjectAt(this.x, this.y)==this)
space.putObjectAt(this.x, this.y,null);
this.x = x;
this.y = y;
space.putObjectAt(x,y,this);
}

//Getter/Setters
public int getX() { return x; }
public int getY() { return y; }
public int getWho(){ return who; }

public void setColor(Color color) {
this.color = color;
}
}
Here are the changes in TutModel from phase 1.  We add the instance variable "buttons" for the number of buttons to use in the model. 

Nothing is added to "setup".  In "buildModel" we simply add the code to create the buttons (TutAgent's) and initialize them randomly, both random colors and random positions.

The call to btn.setXY, in addition to setting the x and y instance variables, adds the TutAgent to the RePast "space" .. the grid the agents live on.  See above.

We also add the TutAgent to a list, agentList, which is part of the SimpleModel class as a convenience.

public class TutModel extends SimpleModel {
...
private int buttons = 500;
...

public void buildModel() {
...
for (int i = 0; i<buttons; i++) {
int x = getNextIntFromTo(0, spaceSize - 1);
int y = getNextIntFromTo(0, spaceSize - 1);
Color color = new Color(
getNextIntFromTo(0,255),
getNextIntFromTo(0,255),
getNextIntFromTo(0,255)
);

TutAgent btn = new TutAgent(space, i);
btn.setXY(x,y);
btn.setColor(color);
agentList.add(btn);
}
...
}
}

Buttons Phase 3: Adding Behavior to TutModel -- Step()

The third phase is to add behavior to the TutModel.  This is done by providing a "step" method, which is called by SimpleModel each tick of the scheduler.

Now when we run the demo model, we see the buttons begin to change colors and after running for a bit, the colors merge to being primarily the same color.

Here is the new source code for TutModel.java and TutAgent.java.


The change to TutModel is to add the "step" method.

Like in the NetLogo model, we chose two random buttons, and then merge their groups by making all of the group1 agents become group2 agents.

Note the final call to dsurf.updateDisplay().  This is how the changes occur to the display.  It is more efficient having the Model explicitly decide when to redraw the display  rather than having it always do so.

public class TutModel extends SimpleModel {
...
public void step(){
TutAgent a1=(TutAgent)agentList.get
(getNextIntFromTo(0,buttons-1));
TutAgent a2=(TutAgent)agentList.get
(getNextIntFromTo(0,buttons-1));
int g1=a1.getGroup();
int g2=a2.getGroup();
for (int i = 0; i < agentList.size(); i++) {
TutAgent a = (TutAgent)agentList.get(i);
if (a.getGroup() == g1) {
a.setGroup(g2);
a.setColor(a2.getColor());
}
}
dsurf.updateDisplay();
}
}
The change to TutAgent is to add the group instance variable which starts out set to "who".

We provide getters/setters for "group" so that we can merge the groups during the "step" method above.

This completes TutAgent, there will be no more changes to it.

public class TutAgent implements Drawable {
...
private int group;
...

public TutAgent(Object2DTorus space, int who){
...
this.group = who;
}
...
public void setGroup(int group)
{this.group = group;}
public int getGroup() { return group; }
}

Buttons Phase 4: Adding Graphs and Parameters to TutModel

We complete our RePast model by adding parameters and a graph.

Only TutModel changes.  It adds two features, user setable parameters (for number of buttons and size of the space), and a graph showing the growth of the largest cluster of connected buttons.

Here is the final source code for TutModel.java and TutAgent.java.


Only TutModel changes.  The first change is to add parameters for the "buttons" and "spaceSize" variables.

To tell RePast which elements to include in the parameter panel, we create a constructor for the TutModel which sets the SimpleModel variable "params" to a string array of the parameters to display. (See getInitParam in SimpleModel)

RePast requires all user parameters to be available via getter/setter methods, which we also add to TutModel

public class TutModel extends SimpleModel {
...
public TutModel () {
params = new String[] {"Buttons", "SpaceSize"};
}
...
public int getButtons() { return buttons; }
public void setButtons(int buttons)
{this.buttons = buttons;}
public int getSpaceSize() { return spaceSize; }
public void setSpaceSize(int spaceSize)
{this.spaceSize = spaceSize;}
}


Our second change is to add the cluster size graph to the model.

First, we add two instance variables: "clusterSz", which holds the largest cluster of buttons so far, and "plot", the RePast OpenSequenceGraph object.

In "setup", we initialize both .. clusterSz to 1, and plot to have the desired name and axis labels, and to plot the clusterSz variable via a new Sequence instance.  Graphs can have many of these, one per plot line.  We only need one.  Note the use of a dynamically created class with a single method reporting clusterSz.

In "buildModel", we use the current value of "buttons" to set the axes to reasonable values, and pop-up the plot window.

In "step" we add code to manage "clusterSz", updating it if the current size is greater.  We then plot the current value by calling "plot.step".  Finally we pause the model when we get to the point that all the buttons are connected.

public class TutModel extends SimpleModel {
...
private int clusterSz;
private OpenSequenceGraph plot;
...
public void setup() {
...
clusterSz = 1;
...
if (plot != null) plot.dispose();
plot = new OpenSequenceGraph("Buttons", this);
plot.setAxisTitles("time", "cluster");
plot.addSequence("MaxCluster", new Sequence() {
public double getSValue() {return clusterSz;}
});
}

public void buildModel() {
...
plot.setXRange(0, buttons*2);
plot.setYRange(0, buttons);

plot.display();
}
...
public void step(){
...
int thisClusterSz = 0;
for (int i = 0; i < agentList.size(); i++) {
...
if (a.getGroup() == g2)
thisClusterSz++;
}
clusterSz = Math.max(clusterSz,thisClusterSz);

plot.step();
if (clusterSz == buttons)
getController().pauseSim();
}
}

Summary and Home Work!

In this fairly elementary (2 files with 88 executable lines of code) RePast tutorial, we've tried several things:
Here are a few explorations you can try for your next steps into RePast
  1. Our current model lets multiple buttons exist at a single space location.  Change the program to allow only one agent to exist on a given x, y location.
  2. Our current model can pick up the same button and connect it to itself!  Change the program so that this does not happen.
  3. Our current model randomly merges two groups of buttons.  Change the model to merge the smaller group into the larger one.
  4. Add extensive Java Doc comments and run javadoc to create your own API documentation.
  5. Create a .jar file from the class files, and create a Manifest that knows where the main() procedure is.
Feel free to contact me if you run into difficulties or have suggestions for improving the tutorial!

Back to NetLogo

Now that you've completed this tutorial, you can compare it to the NetLogo First Steps.