Salabim

Latest version: v24.0.13

Safety actively analyzes 666166 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 10 of 26

21.0.2

==========================
Improved functionality (0)
--------------------------
The probabilities parameter of sim.Pdf can now be any iterable, so not just list or tuple.
This can be useful when using the keys or values of a dict as probabilities.

Improved functionality (1)
--------------------------
The spec parameter of sim.Pdf can now be a dict, where the keys are the x-values and the values
are the probabilities. In that case, the probabilities parameter can't be used.
E.g.
d = sim.Pdf({1:10, 2:70, 3:20})
d = sim.Pdf(dict(red=45, yellow=10, green=45))

Change in distribution (0)
--------------------------
The test scripts are now also available on GitHub (in the /test folder).

Bug fix (0)
-----------
Slicing of a merged level monitor didn't work properly, because the attribute start of the merged
monitor was not set correctly. Fixed.

21.0.1

==========================
Bug fix (0)
-----------
Bug in Component._remove() fixed.

21.0.0

==========================
New functionality (0)
---------------------
Added Environment.title()
With this, the title of the canvas window can be set. The title is set to "", the title will be completely suppressed.

Added Environment.show_menu_buttons()
With this, the menu buttons can be hidden

Added parameter title and show_menu_buttons to Environment.animation_parameters

The title of the canvas window now defaults to salabim, instead of tk. This can be overruled with Environment.title()

20.0.6

==========================
New functionality (0)
---------------------
Monitors can now optionally collect statistics only.
This minimizes memory usage as individual tallies will not be stored in that case.
But beware that some important functionality is not available in stats_only monitors (see below).

You can define the stats_only status at creation time of the monitor, like:
m = sim.Monitor('m', stats_only=True)

But, it is also possible to reset a monitor with a different stats_only value.
This can be useful if you want a system monitor, like Component.mode or Component.status to not keep individual
tallied values:
class Car(sim.Component):
def setup(self):
self.mode.reset(stats_only=True)
When stats_only is active, values are always forced to numeric, with a fallback value of 0.

Monitor with stats_only=True support
__call__/get (without arguments), base_name, deregister, duration, duration_zero, maximum, mean,
minimum, monitor, name, number_of_entries, number_of_entries_zero, print_histogram,
print_histograms, print_statistics, register, rename, reset, reset_monitors, sequence_number,
setup, stats_only, std, t, tally, weight, weight_zero

Monitors with stats_only=True do NOT support (these will raise a NotImplementedError):
__call__/get (with an argument), arithmeric operations (+, *, /), animate, bin_duration,
bin_number_of_entries, bin_weight, freeze, histogram_autoscale, median, merge, multiply,
percentile, slice, slicing, to_days, to_hours, to_microseconds, to_milliseconds, to_minutes,
to_seconds, to_time_unit, to_weeks, to_years, tx, value_duration, value_number_of_entries,
value_weight, values, x, xduration, xt, xweight

In line with the above, Queue.reset_monitors, Resource.reset_monitors, State.reset_monitors now
have a stats_only parameter, with which all monitors can set/reset the stats_only status.
So, if you want all eight monitors belonging to a resource, but the requesters' to be stats_only, you can write
r.reset_monitors(stats_only=True)
r.requesters.monitors(stats_only=False)

The current stats_only mode can be queried with Monitor.stats_only() .

New functionality (1)
---------------------
Queue.all_monitors() returns all (2) monitors associated with the queue
Resource.all_monitors() returns all (8) monitors associated with the resource
State.all_monitors() returns all (3) monitors associated with the state

Change of functionality (0)
---------------------------
Monitor.t is no longer a property, but a method. That means that to get the last tally time and value
of monitor m, you can write
last_tally_t = m.t()
last_tally = m() or last_tally = m.get()

Bug fix (0)
-----------
Non-level monitors did not always calculate the ex0=True mean and ex0=True std correctly when weights
other than one were in the monitor. Fixed.

20.0.5

==========================
Added functionality (0)
-----------------------
The methods Component.request() and Component.wait() now also support the urgent and priority parameters, which
make it possible to fine-tune race conditions.

Added functionality (1)
-----------------------
ComponentGenerator can now 'propagate' keyword parameters to the components generated.
In line with this, the name parameter is changed to generator_name, in order to make it possible to
define the name of the generated components.
Example:

import salabim as sim

class Worker(sim.Component):
def process(self, collar):
print(f"I am {self.name()} and I have a {collar} collar")

env = sim.Environment(trace=True)
sim.ComponentGenerator(Worker, "technician generator", iat=sim.Uniform(2,4), name="technician.", collar="blue")
sim.ComponentGenerator(Worker, "manager generator", iat=sim.Uniform(3,6), name="manager.", collar="white")
env.run(10)

Added functionality (2)
-----------------------
sim.Environment() has now an extra parameter, blind_animation that can be used to create videos
without showing the animation during production.
This is particularly useful when running a simulation on a platform where tkinter is not supported,
such a server.
This functionality can also be used to slightly increase the performance of video production.

Example usage:
try:
import tkinter
blind_animation = False
except ImportError:
blind_animation = True
env = sim.Environment(blind_animation = blind_animation)

Improved functionality (0)
--------------------------
Monitor.print_histogram() can now show a user specified collection of values. This can be done by giving
an iterable to the values parameter. If not all values present in the monitor are given, a <rest> value
will be shown at the bottom. Like:
x0.status.print_histogram(values=["scheduled", "current", "passive"])
may result in
Histogram of x.0.status
duration 50

value duration %
scheduled 10.100 20.2 ****************
current 0 0
passive 31.600 63.2 **************************************************
<rest> 8.300 16.6 *************

By default, the values are shown in the given order, but can also be sorted on value by specifying
sort_on_value=True.

Improved functionality (1)
--------------------------
Monitor.print_histogram() with values now supports sorting on weight (=number of entries if
all weights are 1) (for non-level monitors) and sorting on duration (for level monitors).
Therefore, two parameters have been added to print_histogram(): sort_on_weight and sort_on_duration.

So,
x0.status.print_histogram(values=["scheduled", "current", "passive"], sort_on_duration=True)
may result in
Histogram of x.0.status
duration 50

value duration %
passive 31.600 63.2 **************************************************
scheduled 10.100 20.2 ****************
current 0 0
<rest> 8.300 16.6 *************

Improved functionality (2)
--------------------------
Monitor.values() now supports sorting on weight (=number of entries if all weights are 1) (for non-level monitors) and sorting on duration (for level monitors).
Therefore, two parameters have been added to values(): sort_on_weight and sort_on_duration.
So, in the above example,
print(x0.status.values())
may result in
['data', 'interrupted', 'passive', 'scheduled']
, whereas
print(x0.status.values(sort_on_duration))
may result in
['passive', 'scheduled', data', 'interrupted']

Internal change (0)
-------------------
The Component.__del__ now explicitly checks for the existence of an _animation_children attribute to prevent
an error when deleting a component which is not completely initialized yet.

20.0.4

==========================
New functionality (0)
---------------------
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')

New functionality (1)
---------------------
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_functionality (3)
---------------------
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']

New functionality (4)
---------------------
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 ************************************

New functionality (5)
---------------------
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

New functionality (6)
---------------------
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.

Changed functionality (0)
-------------------------
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.

Distribution change (0)
-----------------------
The setup information (used in PyPI) now includes a set of classifiers as well as requires_python information.

Compatibility change (0)
------------------------
Salabim requires Python 3.6 from now on.

Internal change (0)
-------------------
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).

Page 10 of 26

© 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.