Authors: |
|
---|---|
Version: | 12.021 |
Date: | 2003-June-9 |
SimPy version: | 1.3 |
Web-site: | http://simpy.sourceforge.net/ |
Python-Version: | 2.2, 2.3 |
Created: | 2002-December-10 |
With version 1.3, SimPy now has a tracing utility, SimulationTrace, which can aid with developing, debugging, understanding, teaching, documenting SimPy models. See the SimPy Manual for details on how to use this utility.
This document briefly outlines the commands available in SimPy. It refers to SimPy version 1.3 or later. The facilities described require Python 2.2 or later.
NOTE: When using Python 2.2, the following import statement must be used at the head of SimPy scripts:
A SimPy model is made up of Processes, Resources and Monitors and operations on them.
Basic structure of a SimPy simulation:
from SimPy.Simulation import * which imports all facilities for the simulation program.
initialize() which sets up the simulation model
... the activation of at least one process....
simulate(until=endtime) starts the simulation which will run until:
- there are no more events to execute (then now() is the time of the last event), or
- the simulation time reaches endtime, now() == endtime
- the stopSimulation() command is executed (then now() is the time when stopSimulation() was executed).
stopSimulation() will stop all simulation activity.
now() always returns the current simulation time.
Processes inherit from class Process, imported from SimPy.Simulation.
class Pclass(Process): defines a new Process class (here, Pclass). Such a class must have at least these two methods:
__init__(self,..), the first line of which must be a call to the Class __init__ in the form: Process.__init__(self,name='a_process'). Other commands can be used to initialize attributes of the object.
An execution method, which may have arguments, describes the actions of a process object and must contain at least one of the yield statements to make it a Python generator function. The yield statements are:
- yield hold,self,t to execute a time delay of length t (unless the process is interrupted, see below). The process continues at the statement following after a delay in simulated time.
- yield passivate,self to suspend operations indefinitely.
- yield request,self,r (see Resources, below)
- yield request,self,rp,priority (see Resources, below)
- yield release,self,r (see Resources, below)
p = Pclass(..), constructs a new Pclass object, called, p, where the arguments are those specified in the Class's __init__ method.
By the process itself:
By other processes:
self.interrupt(victim) interrupts another process. The interrupt is just a signal. After this statement, the interrupting process immediately continues its current method.
The victim must be active to be interrupted (that is executing a yield hold,self,t) otherwise the interruption has no effect.
The introduction of interrupts changes the semantics of yield hold. After before=now(); yield hold,self,T, we have the post-condition now()== before+T OR (self.interrupted() AND now()< before+T). The program must allow for this, i.e., for interrupted, incomplete activities.
When interrupted, the victim prematurely and immediately returns from its yield hold. It can sense if it has been interrupted by calling:
The interruption is reset at the victims next call to a yield hold,. Alternatively it can be reset by calling
self.interruptReset()
The modeller may define Resources. These inherit from class Resource which is imported at the start of the program: from SimPy.Simulation import Resource
A Resource, r, is established using the command:
A Resource, r, has the following attributes:
A unit of resource, r, can be requested and later released by a process using the following yield commands:
If a Resource, r is defined with priority queueing (that is qType==PriorityQ) a request can be made for a unit by:
If a Resource, r, is defined with priority queueing (that is qType=PriorityQ) and also preemption (that is preemptable=1) a request can be made for a unit by:
If there are several lower priority processes, that with the lowest priority is suspended, put at the front of the waitQ and the higher priority, preempting process gets its resource unit and is put into the activeQ. The preempted process is the next one to get a resource unit (unless another preemption occurs). The time for which the preempted process had the resource unit is taken into account when the process gets into the activeQ again. Thus, the total hold time is always the same, regardless of whether or not a process gets preempted.
SimPy uses the standard random variate routines in the Python random module.
A Monitor is an object that can record statistics about values observed in the simulation. These inherit from class Monitor which is imported at the start of the program:
A monitor is defined using the command
There are two modes of statistical gathering, tallying which is used to record observations of isolated values (such as waiting times) and accumulating which is used to record time averages of values that continue in time (such as numbers of customers in the system). A monitor, m, has the following methods:
These messages are returned by simulate(), as in message=simulate(until=123).
Upon a normal end of a simulation, simulate() returns the message:
The following messages, returned by simulate(), are produced at a premature termination of the simulation but allow continuation of the program.
These messages are generated when SimPy-related fatal exceptions occur. They end the SimPy program. Fatal SimPy error messages are output to sysout.
We will be grateful for any corrections or suggestions for improvements to the document.