Salabim is a powerful discrete event simulation package in pure Python that can be used to model transport systems, production logistics, warehousing, communication systems, healthcare, mining, etc, It uses a process description methodology comparable to SimPy, but offers much more functionality: real-time animation, queue handling, monitoring of process characteristics, advanced statistical sampling and more. Go to www.salabim.org for details and resources.
A component now supports a level monitor 'status' that keeps track of all the statuses a component has been in. For instance, component.status.print_histogram(values=True) will print something like Histogram of x.1.status duration 40
value duration %
data 4.300 10.8 ********
interrupted 4 10 ********
passive 11.500 28.7 ***********************
requesting 10.100 25.2 ********************
scheduled 10.100 25.3 ********************
And of course, it is possible to get the duration a component was in a certain status, like passive_time = component.status.value_duration(sim.passive). You can even get the status of the component at a moment in the past, with e.g. status_4_units_ago = c1.status(env.now() - 4)
In line with this change, the various statutes (passive, scheduled, ...) are no longer functions, but just strings. So now, therefore it is also possible to say passive_time = component.status.value_duration("passive") This will be quite transparent from the user. Only if the text representation of a status was required, status() had to be called, like print(f"car status={car.status()()}") From this version on, this should read print(f"car status={car.status()}") , which is also more intuitive. Alternatively, you can now also write print(f"car status={car.status.value}")
This makes the methods Component.ispassive(), Component.isscheduled, etc. less required as component.status() == "passive" and component.status() == "scheduled" are arguably easier to understand.
The package salabim now has a function statuses() that returns a tuple with all statuses a component can be in. So print(sim.statuses()) will print ('current', 'data', 'interrupted', 'passive', 'requesting', 'scheduled', 'standby', 'waiting')
Component.mode is now a monitor. That makes it possible to get an overview of all modes a component has been in, either as a histogram or an animated monitor. And it is possible to get the duration a component was in a certain mode, with e.g. red_time = c1.mode.value_duration("red") It is even possible to get the mode a component was in at a given moment, like mode_4_units_ago = c1.mode(env.now() - 4) Because of this you can't use mode(x) anymore to set the mode directly. In order to do that, you have to use the new method set_mode: c1.set_mode("green") or c1.mode.value = "green" Both options do store the modetime correctly. Please observe that the initial value for mode is now the null string and not None.
New method: Monitor.values() to assess all values in a monitor. The values returned will be alphabetically sorted (not case sensitive), just as in Monitor.print_histogram(). The method supports both ex0 and force_numeric parameter flags. Example (with same monitor as above): print(x1.status.values()) will print ['data', 'interrupted', 'passive', 'requesting', 'scheduled']
The values parameter of print_histogram() can now also be an iterable (i.e. tuple, list or set). In that case, the statistics of only these values will be shown. Example (with same monitor as above): x1.status.print_histogram(values = sim.statuses()) will print Histogram of x.1.status duration 40
value duration %
current 0 0
data 4.300 10.8 ********
interrupted 4 10 ********
passive 11.500 28.7 ***********************
requesting 10.100 25.2 ********************
scheduled 10.100 25.3 ********************
standby 0 0
waiting 0 0
Any not shown values will be shown at the bottom as '<rest>'. So, again with the same monitor as above: x1.status.print_histogram(values = ("passive", "requesting", "error")) will print Histogram of x.1.status duration 40
value duration %
passive 11.500 28.7 ***********************
requesting 10.100 25.2 ********************
error 0 0
<rest> 18.400 46.0
AnimateMonitor and Monitor.animate has got a new parameter: vertical_map. This parameter should be a function that accepts one argument (the value to be plotted). By default vertical_map is float. The function vertical_map should result in a float or raise a TypeError or ValueError. E.g. to map "red" to the value 1, "blue" to 2, etc., you could provide a mapping function like: vertical_map = "unknown red blue green yellow".split().index Note that in this example any value other than red, blue, green or yellow would map to 0 (via a ValueError exception). This vertical_map function can also be used to map to a logarithmic scale: vertical_map = lambda value_y: math.log(value_y) * 10
AnimateMonitor and Monitor.animate can now show labels and corresponding lines. There is full control of the colours, linewidth, fonts, placement, etc. See the docstring or documentation for details. There is a sample model (demo animation of labeled monitors.py) in the sample model folder to illustrate the usage of this new functionality with the new Component.status and Component.mode monitors.
The tests for which value(s) to include in Montitor.value_number_of_entries() Monitor.value_duration() Monitor.value_weight() are now direct and do not involve string conversion anymore. Normally, this won't cause any compatibility issues.
The setup information (used in PyPI) now includes a set of classifiers as well as requires_python information.
Salabim requires Python 3.6 from now on.
The statuses requesting and waiting were internally stored as scheduled and 'translated' in the status() method. Now, these statuses are natively stored as such (in the status monitor).
python-announce-list@python.org