A simulation run has always two steps: First, we have to build the model as introduced in the last section. Second, we have to hand over the model to the simulator.
There are two types of simulators offered in this framework: time-step and discrete-event based. Each type has a sequential and a concurrent variant. Concurrent simulators can run agents with the same time stamp in parallel, sequential ones call the agents’ doEvent
methods one by one. A concurrent simulator is favorable if the gain of speed by parallelization outperforms the overhead cost of multi-threading. Just try both variants with the same model!
package org.simplesim.examples.gameoflife; import org.simplesim.core.messaging.DirectMessageForwarding; import org.simplesim.core.messaging.MessageForwardingStrategy; import org.simplesim.core.scheduling.Time; import org.simplesim.simulator.SequentialTSSimulator; import org.simplesim.simulator.Simulator; public final class Main { public static final int GRID_DX=300; public static final int GRID_DY=200; private static final double LIFE_PROBABILITY=0.35d; public static void main(String[] args) { final Model model=new Model(GRID_DX,GRID_DY); model.createCells(LIFE_PROBABILITY); model.connectCells(); final View view=new View("JSimpleSim exmaple: Conway's Game of Life",GRID_DX,GRID_DY); final MessageForwardingStrategy mfs=new DirectMessageForwarding(); final Simulator simulator=new SequentialTSSimulator(model,mfs); // final Simulator simulator=new ConcurrentTSSimulator(model,mfs); simulator.registerEventsProcessedListener(view); simulator.runSimulation(Time.INFINITY); view.close(); } }
If we run the simulation model this way, there might happen a lot, but we can’t see any changes. So, we need a way to monitor the agents’ states. Preferably only for those agents that were part of the last simulation cycle.
In JSimpleSim the simulators offer listeners to register for this purpose. The simulator provides the listener with a list of all relevant agents to be queried. The data can then be displayed graphically or dumped to a database to log it. In this tutorial, there is a simple viewport showing the grid of cells.
package org.simplesim.examples.gameoflife; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.image.BufferStrategy; import javax.swing.JFrame; import javax.swing.WindowConstants; import org.simplesim.core.instrumentation.Listener; import org.simplesim.core.scheduling.Time; import org.simplesim.model.Agent; import org.simplesim.simulator.Simulator; @SuppressWarnings("serial") public class View extends JFrame implements Listener<Simulator> { private static final int CELL_SIZE=4; public View(String title, int width, int height) { super(title); final Dimension size=new Dimension(CELL_SIZE*width,CELL_SIZE*height); setPreferredSize(size); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setVisible(true); pack(); createBufferStrategy(2); } @Override public void notifyListener(Time unused,Simulator source) { final BufferStrategy bs=getBufferStrategy(); do { do { final Graphics g=bs.getDrawGraphics(); for (Agent cell : source.getCurrentEventList()) { final CellState cs=((Cell) cell).getState(); if (cs.isAlive()) g.setColor(Color.YELLOW); else g.setColor(Color.BLUE); final int x=cs.getPosX()*CELL_SIZE; final int y=cs.getPosY()*CELL_SIZE; g.fillRect(x,y,CELL_SIZE,CELL_SIZE); } g.dispose(); } while (bs.contentsRestored()); bs.show(); } while (bs.contentsLost()); } public void close() { setVisible(false); dispose(); } }
This tutorial showed the necessary steps to set up a basic model and to run a simulation. It also introduced some fundamental base classes of JSimpleSim that you can use in your own projects. The advanced tutorial will explain some more elaborate topics.