I would like to present here a new discrete simulation package for Python, called salabim.
This might be interesting for (potential) SimPy users.
The process control resembles more the SimPy 2 interface, with statements
like activate, hold and passivate. This is more in line with University of Delft
methodology as seen in tools like Prosim, must and Tomas.
The salabim package supports SimPy like resources and containers,
a full set of process control (including a [powerful standby concept).
The salabim package uses SimPy like environments, but supports also an easy
default environment, so the environment does not have to be passed explicitly
in most cases.
Salabim offers queue handling, tracing, statistical distributions, monitors (for data
collection and presentation) and an animation engine, which runs both under
CPython (with tkinter) and iPad Pythonista.
The animation engine is able to produce videos without any additional components.
To give an idea of a salabim model, we show here our version of the Bank Renege
example model (from the SimPy 3 documentation):
"""
Bank renege example
Scenario:
A counter with a random service time and customers who renege. Based on the
program bank08.py from TheBank tutorial of SimPy 2. (KGM)
"""
import salabim as sim
NEW_CUSTOMERS = 5 # Total number of customers
INTERVAL_CUSTOMERS = 10.0 # Generate new customers roughly every x seconds
MIN_PATIENCE = 1 # Min. customer patience
MAX_PATIENCE = 3 # Max. customer patience
TIME_IN_BANK=12
class Source(sim.Component):
"""Source generates customers randomly"""
def process(self):
for i in range(NEW_CUSTOMERS):
c = Customer()
yield self.hold(sim.Exponential(INTERVAL_CUSTOMERS).sample())
class Customer(sim.Component):
"""Customer arrives, is served and leaves."""
def process(self):
arrive=de.now()
patience = sim.Uniform(MIN_PATIENCE, MAX_PATIENCE).sample()
yield self.request(counter,fail_delay=patience)
wait = de.now() - arrive
if self.request_failed():
# We reneged
de.print_trace('',self.name(),'RENEGED after {:6.3f}'.format(wait)) else:
# We got to the counter
de.print_trace('',self.name(),'waited for {:6.3f}'.format(wait)) yield self.hold(sim.Exponential(TIME_IN_BANK).sample())
# auto release counter
# Setup and start the simulation
print('Bank renege')
de = sim.Environment(trace=True)
# Start processes and run
counter = sim.Resource(capacity=1)
Source()
de.run()
The output looks like:
Bank renege
0.000 main current
source.............0 activate scheduled for 0.000 @process
main run scheduled for inf
0.000 source.............0 current
customer...........0 activate scheduled for 0.000 @process
source.............0 hold scheduled for 3.577
0.000 customer...........0 current
customer...........0 arrrived
customer...........0 request for 1 from resource...........0
customer...........0 request honour scheduled for 0.000
0.000 customer...........0 current
customer...........0 waited for 0.000
customer...........0 hold scheduled for 7.461
3.577 source.............0 current
customer...........1 activate scheduled for 3.577 @process
source.............0 hold scheduled for 6.572
3.577 customer...........1 current
customer...........1 arrrived
customer...........1 request for 1 from resource...........0
customer...........1 request scheduled for 5.134
5.134 customer...........1 current
customer...........1 request failed
customer...........1 RENEGED after 1.557
5.134 customer...........1 ended
6.572 source.............0 current
customer...........2 activate scheduled for 6.572 @process
source.............0 hold scheduled for 8.728
6.572 customer...........2 current
customer...........2 arrrived
customer...........2 request for 1 from resource...........0
customer...........2 request scheduled for 8.465
7.461 customer...........0 current
customer...........0 finished
customer...........0 release 1 from resource...........0
customer...........2 request honour scheduled for 7.461
7.461 customer...........0 ended
7.461 customer...........2 current
customer...........2 waited for 0.889
customer...........2 hold scheduled for 15.157
8.728 source.............0 current
customer...........3 activate scheduled for 8.728 @process
source.............0 hold scheduled for 17.645
8.728 customer...........3 current
customer...........3 arrrived
customer...........3 request for 1 from resource...........0
customer...........3 request scheduled for 11.394
11.394 customer...........3 current
customer...........3 request failed
customer...........3 RENEGED after 2.666
11.394 customer...........3 ended
15.157 customer...........2 current
customer...........2 finished
customer...........2 release 1 from resource...........0
15.157 customer...........2 ended
17.645 source.............0 current
customer...........4 activate scheduled for 17.645 @process
source.............0 hold scheduled for 26.062
17.645 customer...........4 current
customer...........4 arrrived
customer...........4 request for 1 from resource...........0
customer...........4 request honour scheduled for 17.645
17.645 customer...........4 current
customer...........4 waited for 0.000
customer...........4 hold scheduled for 19.997
19.997 customer...........4 current
customer...........4 finished
customer...........4 release 1 from resource...........0
19.997 customer...........4 ended
26.062 source.............0 current
26.062 source.............0 ended
inf main current
Note that the general structure is very similar to SimPy (particularly to version 2).
Unfortunately, the documentation is not yet finished, although all methods and
functions are properly documented, both in the on-line manual and docstrings.
We are working hard to improve the manual.
We welcome SimPy users to have a look at salabim at
www.salabim.org. There you
will find a link to GitHub, where the package, several sample models and the
release notes are available for download.
a e-mail address.
The package is distributed under the MIT license.