Note: This how to is best read together with the source code from the sample simulations.
Overview
The kinds of simulations that can be written using Repast fall into two broad
categories: batch-run, and non-batch run. A batch run simulation reads in a
specially formatted parameter file detailing the starting and ending values of
a model's parameters, how to increment these parameters and the number of runs
to complete. The simulation then begins to run without user interference.
A non-batch run requires a user to start and stop a run through a graphical user interface, and allows the user to graphically set starting parameters. In addition a non-batch simulation allows a user to graphically display and manipulate (i.e. probe) an agent's state during the course of a run, as well as the models.
What follows explains the basics of how to write both these kinds of simulations, paying special attention to what must done for a model to set the initial parameters from a parameter file, to allow a user to graphically set starting parameters, and to allow probing to occur.
The Agent
Both batch and non-batch run simulations are largely similar. A typical
simulation of either kind written with Repast will have at least two classes
written by the user, the agent class and the model class. (See the source code
to the sample simulations for detailed examples). The agent class will be
largely simulation specific, although Repast does provide some minimal (at this
time) support for cooperation type agents, through the
GameAgent interface and the
Game abstract class. If the agent is to be displayed, it should
implement one of the Drawable interfaces (see How To
Create Displays for more). If a user wishes an agent to be probeable,
that is, have its state graphically displayable and manipulable, the agent must
be coded using the Accessor
method pattern.
The Model
A model, such as SugarModel.java or EnnModel.java (in
repast/demos/sugarscape/src/src/uchicago/src/sim/sugarScape and
repastdemos/enn/src/src/uchicago/src/sim/enn respectively) sets up and controls
both the representational and infrastructure parts of a Repast simulation. All
Repast simulation models must implement the
SimModel interface. Repast provides an abstract class
SimModelImpl that partialy implements this interface and it is expected
that most if not all models will extend this class.
Assuming then that a user is writing his or her own model that extends SimModelImpl , a typical model class should have the following parts:
Any model that extends SimModelImpl also inherits the rngSeed variable which can be accessed through getRngSeed and setRngSeed.
public int getNumAgents() {
return numAgents;
}
public void setNumAgents(int numAgents) {
this.numAgents = numAgents;
}
Consequently, if a user wants to display some initial starting parameter
and have this parameter be modifiable, the name of the parameter must be
returned by the getInitParam() method and the model must contain the
appropriate get and set methods. For example, if a modeler wants a parameter
that contains the number of initial agents to be displayable, and modifiable,
some String such as "numAgents" must be present in the array returned by
getInitParam and the model must have a getNumAgents method and a setNumAgents
method. The source code to the example simulations all follow this pattern and
are good examples of it.Probing objects (agents, environment and so forth) during the course of a simulation run requires that the same accessor pattern be present. In these cases, however, only the get method need be present for the variable to be displayed. For example, an agent has a variable sugar that tracks the amount of sugar that this agent has collected. The author of this simulation would like to be able to probe this agent and have this variable displayed during the course of a simulation run. In order for the value of the sugar variable to be displayed, the agent must have a getSugar method. If the agent has no setSugar method then "Sugar" is considered read-only and will be displayed as such in a field entitled "Sugar:". If the agent has both getSugar and setSugar methods then value of the Sugar variable will be able to be modified by the user during the course of a simulation run.
You can limit what can be probed on non-models (agents, environments and so forth) by implementing the CustomProbeable interface on these non-model objects. The CustomProbeable interface contains a single method public String[] getProbedProperties() that functions like a model's getInitParams() method. By implementing the interface and returning an array of Strings that are the names of the properties you want probed, you can limit probing to only those properties. For example, suppose getProbedProperties returns "Sugar", and "Age". The probing mechanism would only look for and return values through getSugar, setSugar and getAge, setAge methods. This inteface can be useful when your agent extends other classes whose properties you do not want displayed. The OvalNode agents in the jiggle demonstration simulation are a good examples of this.
Typically, only Strings, booleans and numbers are probed. However, this does not mean that only agent variables of these types can be the source of such probes. Translation from one type to another can be done inside the get and set methods. For example a get method may iterate over a Vector of values and return those values as a comma delimited String and the set method may parse such a String and insert those values into the Vector. The hypercycle demonstration simulation is an example of this. However, if the probed parameter is itself some non-String, numeric, or non-boolean class, the parameter will be displayed as a button. Clicking on this button, will then probe the parameter itself and display the results in a new window.
The default display type for parameters is a text field. If you wish to display check boxes for boolean parameters or combo-boxes to delimit a range of choices, then see How To Create Property Descriptors .
The initial model parameters should be set to whatever defaults the user wants to see initially, and a Schedule should be created here (i.e. schedule = new Schedule(1);) and if the model is a gui model a DisplaySurface should be created here as well (i.e. displaySurface = new DisplaySurface(this, "Heat Bugs Display"); ).
Objects that rely on parameter values should NOT be created or setup here. Any parameter manipulation either through the user interface or through parameter files occurs after setup() is called. As a result your objects will be created using incorrect parameter values.
The relationship between the various tool bar buttons and the actual execution of code is as follows. When the setup button is clicked, the code in the setup() method is executed. When the initialize button is clicked, the code in begin() is executed. When the step button is clicked, the code in begin() is executed and any behavoir scheduled for the next tick is executed. When the start button is clicked, begin() is executed, and the simulation enters a loop where any behavoir scheduled for the next tick is executed, the tick count is incremented and the next schedule behavoir is executed and so on until the user clicks the stop or pause button.
If you chose to include a main method in your model, this main method should
create an instance of your model, of SimInit and then load your model with
SimInit instance. For example,
The above loads the Repast model MyModel with no parameter file and in
gui mode. However, you can also specify a parameter file and whether this
should be run in batch mode or not. See the api docs for
SimInit
for the details.
public static void main(String[] args) {
SimInit init = new SimInit();
MyModel model = new MyModel();
init.load(model, null, false);
}
Batch Parameters
The get/set method pattern is used differently by a batch model. Just as a
non-batch model's initial parameters can be displayed and manipulated through
its get and set methods, a non-batch model uses the same methods to set its
initial parameters from a parameter file. See How To Use
Parameters and Parameter Files for more information.