SimPy: Simulating Systems in Python
Pages: 1, 2
When finished with the staff member, the customer then
releases and hangs up in the two
release statements in lines 35 and 36. The released staff
member can then pick up the customer waiting at the head of the
queue. Similarly, the released phone line is immediately available for
The next few lines are housekeeping. We calculate the delay experienced (line 38), determine whether the customer is "happy" or not, incrementing the count of "happy" customers and and print out a trace line. (In practice this trace would be used only in debugging or to feed a statistical program for further analysis.) Then the customer leaves the system and the corresponding object vanishes.
Where do customers come from? They must arrive at random. Experienced simulators use a trick to simulate random events. The time between random arrivals is uncertain with an exponential probability distribution. All we need to do is to generate a sample from that distribution and to allow the Process to hold for that time. Each time we go round the loop a different number is generated and a different delay occurs. A statistician testing the resulting sequence of arrival times would be unable to detect any difference from pure randomness. We use that trick here.
An object of class
Traffic generates a customer
sequence (line 43). This is another SimPy
Process and the
active generator method is called
generate (on line
43 class Traffic(Process): 44 """Generates Customer arrivals""" 45 Rate = 40.0 # (per hour) arrival rate 46 rv = Random() # a random variable 47 48 def __init__(self): 49 Process.__init__(self) 50 51 def generate(self): 52 while True: 53 cust=Customer() # new customer call 54 activate(cust,cust.serviceNeed()) 55 timeToNext = Traffic.rv.expovariate(Traffic.Rate) 56 yield hold,self,timeToNext 57
Rate of arrivals is fixed on line 45. In a
practical example this would be obtained from real data or from
estimates and would most likely be read in. It may be a function of
time of day as well. Line 46 establishes
rv, a random
We create a sequence of customers in an infinite loop. A customer
is created in line 53 and the
activated in line 54. That customer acts independently from this point
on. The time to the next arrival is generated by a sample from the
correct distribution (line 55) and the
simulates the delay. The required random number routines were imported
from the standard Python module in line 5.
Finally we get to the main script that runs the simulation. Line 58
initializes the simulation system. Among other tasks this sets up the
event scheduling system which will run the simulation clock and make
sure events occur in the correct sequence. The next two lines
establish the two Resources, the three
phone lines, and
staff. We assume that calls have no priority
scheme and that queues have a normal first-come, first-served
Line 61 establishes the
traffic object which will
generate our randomly arriving customers. The next line activates
No simulation starts before line 63. The simulation will now run until time 6*24, that is, 24 hours a day for 6 days, at which point it will stop, and the next statement, printing out the results, is executed.
58 initialize() 59 phone = Resource(capacity=3) 60 staff = Resource(capacity=3) 61 traffic = Traffic() 62 activate(traffic, traffic.generate()) 63 simulate(until=6*24) # hours 64 print "Total arrivals: %s / Total served: %s / Total unhappy: %s"\ 65 %(Customer.customers,Customer.customersServed,\ 66 Customer.customersServed - Customer.customersHappy)
So what do we do with this model? The original request was to discover the effect of changing the number of lines or the number of staff on customer happiness. To do this we must vary these numbers through a series of runs. We have to be careful about these experiments. Although using random numbers to generate the arrivals makes the model more realistic (randomness usually leads to queues), it means that a single run cannot be believed by itself. You have to make a series of replications to get a better idea of the result. Of course we can easily extend the displayed program to carry out series of runs, though such extensions are not shown here.
The SimPyCo helpdesk currently has a PABX with 3 incoming lines and 3 staff present. The helpdesk hours are Monday through Saturday, 24 hours a day. Plugging these figures into the simulation program shows a very high percentage of unhappy customers (99%) over the six day week.
To find out how many staff and lines are needed, we now run the simulation for 4 staff/4 lines and 5 staff/5 lines. The results are 86% and 0% unhappy customers, respectively. We repeat the run and now get 78% and 0%. So, as in the real world, the simulation shows variation from week to week, due to the randomness in the arrival of customer calls. The more often one runs the simulation, the better one can estimate the mean levels of unhappy customers.
This program uses the Open Source VPython plotting package (http://vpython.org). Interfacing to VPython and other packages will be explained in a future article on SimPy. If you can't wait for that, download VPython and play with the program, it is simple enough. Enjoy!
There is another real world issue we can address with the simulation: does the level of unhappy customers change over the work week? To analyse the time behavior, we extended the program with graphical output.
We ran the program for the same 3/3, 4/4 and 5/5 options, for 5 simulated weeks. The graphs produced clearly show that in all 5 weeks,
the helpdesk with 3 lines/3 staff is rapidly saturated and stays saturated for the whole week,
Figure 2 -- three lines and three staff members over five weeks
with 4 lines/4 staff, it shows great variability over time in delay times suffered by customers, with significant differences between weeks-- a highly unstable, unmanageable, unpredictable configuration; and
Figure 3 -- four lines and four staff members over five weeks
with 5 lines/5 staff, only in one week out of the five simulated is there a period with any unhappy customer.
Figure 4 -- five lines and five staff members over five weeks
The conclusion for SimPyCo management is that they must increase both the number of lines and the number of manned desks to at least 5 to cope with the current customer arrival rate of 40 calls per hour.
With its constructs
Monitor (which we have not time to explain here),
SimPy is a powerful but easy to use LEGO-like toolbox for describing
and simulating many classes of complex dynamic systems, whether or not
they yet exist. This power is greatly enhanced by the object
orientation of Python, allowing easy extension by subclassing and
inheriting. This way, generic models of frequently occurring
situations ("the production line model", "the service counter model",
"the network model", etc.) can be built and then used with little
additional code for specific systems. Python gives further power to
the SimPy user by being so richly endowed with interfaces to a wide
variety of packages (many of which are open source), such as graphics,
data bases, spreadsheets, and statistics.
We hope this article gave you a taste of the power and ease of use of SimPy. There are many facets of SimPy we have not touched on. how is SimPy using generators? How does one build OO models? How does one collect and analyze SimPy run data efficiently and elegantly? We will cover some of these in a future article. In the meantime, why not download SimPy, run its tutorial and test programs, and build your own simulation model? It is fun and might be profitable!
SimPy site: Download SimPy from here, including:
- A brief cheat-sheet of the facilities that SimPy provides in the form of a listing of commands and methods for processes, resources, and monitors.
- An extensive manual with simple examples.
- An introduction to interfacing SimPy models with GUI and plotting applications.
- The Bank, a tutorial for SimPy showing the gradual development of a multi-server bank model.
Fundamentals Of Object-Oriented Simulation
Klaus Müller is an Open Source software developer and a freelance consultant on military information systems.
Tony Vignaux does some teaching in simulation and continues his research interests.
Return to Python DevCenter.