Most of the other chapters are about model-building, this is about simulation. JSimpleSim features discrete event simulation (DES) as well as the time-step (TS) apporach. In TS mode, the simulation advances by constant time slices and every agent of the model is activated once per step. In DES mode, the simulation is event-driven.
Simulators
Let us have a look at how event-driven simulation is implemented. First, all agents are queried for their time of next event (tone) and scheduled in a global event queue. Agents may also implement a local event queue to organize their internal events, but any agent has got exactly one tone as the time-stamp of its very next event.
A simulator schedules the events and excutes all events (corresponding to agents) with the same time-stamp. Afterwards, agents are re-scheduled with their new tone and message forwarding is done. Finally, model changes are applied.
In most cases, there will be several agents with the same time-stamp. These can be excuted sequentially or concurrently, depending on the chosen simulator. Currently, there four simulators:
SequentialTSSimulator
SequentialDESimulator
ConcurrentTSSimulator
ConcurrentDESimulator
Please note that you can change the simulator without changing the model, so there is no effort to try various execution modes. See an example:
import org.simplesim.core.messaging.ForwardingStrategy; import org.simplesim.core.messaging.RoutedMessageForwarding; import org.simplesim.core.scheduling.Time; import org.simplesim.model.RoutingDomain; import org.simplesim.simulator.SequentialDESimulator; import org.simplesim.simulator.ConcurrentDESimulator; import org.simplesim.simulator.Simulator; public class SimpleDomain extends RoutingDomain { public static void main(String[] args) { SimpleDomain root=new SimpleDomain(); root.setAsRootDomain(); root.addEntity(new SimpleAgent()); SimpleDomain subdomain=new SimpleDomain(); subdomain.addEntity(new SimpleAgent()); subdomain.addEntity(new SimpleAgent()); root.addEntity(subdomain); ForwardingStrategy fs=new RoutedMessageForwarding(root); Simulator simulator=new SequentialDESimulator(root,fs); simulator.runSimulation(new Time(100)); simulator=new ConcurrentDESimulator(root,fs); simulator.runSimulation(new Time(100)); } }
Concurrency
Concurrent execution might speed up a simulation run considerably. However, the usual pitfalls of concurrent programming apply. Most of them are mitigated by the JSimpleSim framework, some have to be avoided during agent design:
- All internal variables of an agent have to be stored in its
AgentState
. The state is the only data an agent may change during its activation. - Constant model data (for example context variables or external parameters) may be read during execution.
- Communication with other agents has to be done exclusively by message exchange.
- Model changes have to be done by issuing a
ChangeRequest
. - Never ever change a variable outside of the
AgentState
! - Make sure objects are referenced either in a
Message
or theAgentState
– never both! There might be the risk of inadvertently changing variables outside the internal state.