Salabim

Latest version: v24.0.9

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

Scan your dependencies

Page 13 of 25

2.4.0

=========================
New Functionality
-----------------
Complete overhaul of Monitor/MonitorTimestamp internals, resulting in more consistent operation.
The documentation has been updated accordingly.
MonitorTimestamp is phased out and replaced by level monitors, which are instances of Monitor.
Timestamped monitors are now called level monitors, whereas non timestamped monitors are now called
non-level monitors.
non-level monitors now always timestamp the entry, which makes slicing and more useful animation possible.
It is no longer required (and possible) to indicate that a non-level monitor is weighted. If a weight is
required, just tally with a weight != 1.

Animation of non-level monitors is now also shown on a timescale, thus making it easier to see
the relation with a level monitor, e.g. length and length_of_stay of a queue.

This has a number of consequences for the API:

MonitorTimestamp ==> Monitor(level=True)
Merging of monitors not anymore part of the init, but is a separate method:
m = Monitor(merge=(m1, m2, m3)) ==> m = m1.merge(m2, m3)

It is no longer necessary (and possible) to specify weighted=True in init of Monitor.
All non-level monitors now support weighted, if required.
m = Monitor(weighted=True) ==> m = Monitor()

The (level monitor only) method .get() or direct call can now also be used to get the value of the level at a
specified time within the monitored period, e.g.
print('queue length at time 100 was', q.length.get(100))
or alternatively:
print('queue length at time 100 was', q.length(100))

It is now possible to slice a monitor with Monitor.slice(), which has two applications:
- to get statistics on a monitor with respect to a given time period, most likely a subrun
- to get statistics on a monitor with respect to a recurring time period, like hour 0-1, hour 0-2, etc.
Examples:
for i in range(10):
start = i * 1000
stop = (i+1) * 1000
print(f'mean length of q in [{start},{stop})={q.length.slice(start,stop).mean()}'
print(f'mean length of stay in [{start},{stop})={q.length_of_stay.slice(start,stop).mean()}'

for i in range(24):
print(f'mean length of q in hour {i}={q.length.slice(i, i+1, 24).mean()}'
print(f'mean length of stay of q in hour {i}={q.length_of_stay.slice(i, i+1, 24).mean()}'

Instead of slice(), a monitor can be sliced as well with the standard slice operator [], like:
q.length[1000:2000].print_histogram()
q.length[2:3:24].print_histogram()


It is now possible to change the format of times in trace, animation, etc. with the method
Environment.time_to_str_format()
For instance, if 5 decimals in the trace are to be shown instead of the default 3, issue:
env.time_to_str_format('{:10.5f}')
Make sure that the format represents 10 characters.
See the docstring / documentation for more information.


From now on it is possible, but definitely not required, to set the dimension of the time unit when defining an environment, like
env = sim.Environment(time_unit='hours')
Salabim supports 'years', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds' and 'n/a' as dimension.

If the time unit is set, times can be specified in any dimension, like
yield self.hold(env.seconds(20))
The following methods for conversion to the current time unit are available:
Environment.years()
Environment.weeks()
Environment.days()
Environment.hours()
Environment.minutes()
Environment.seconds()
Environment.milliseconds()
Environment.microseconds()
Example:
env = sim.Environment(time_unit='hours')
env.run(env.days(10))
This effectively let the simulation run for 240 (hours).

The following methods for conversion from time current time unit are available:
Environment.to_years()
Environment.to_weeks()
Environment.to_days()
Environment.to_hours()
Environment.to_minutes()
Environment.to_seconds()
Environment.to_milliseconds()
Environment.to_microseconds()
Example:
env = sim.Environment(time_unit='hours')
env.run(env.days(14))
print('it is now', env.to_days(env.now()), 'weeks')
output: it is now 2 weeks

Finally, the current time unit dimension can be queried with Environment.get_time_unit().
Example:
env = sim.Environment(time_unit='hours')
env.run(env.days(10))
print('it is now', env.now()), env.get_time_unit())
output: it is now 240 hours

All distributions, apart from IntUniform, Poisson and Beta now have an additional parameter, time_unit.
If the time_unit is specified at initialization of Environment(), the time_unit of the distribution
can now be specified.
As an example, suppose env has been initialized with env = sim.Environment(time_unit='hours').
If we then define a duration distribution as:
duration_dis = sim.Uniform(10, 20, 'days')
, the distribution is effectively uniform between 240 and 480 (hours).
This facility makes specification of duration distribution easier and more intuitive.
Refer to the docstrings or documentation for details.

By default the time unit dimension is 'n/a', which means that conversions are not possible.

The documentation has a new chapter Miscellaneous/Time units covering this topic.


Announcement
------------
The class PeriodMonitor that was added in version 2.3.4 will be phased out in a future release.
Slicing monitors (see above) is much more reliable and versatile.


Reminder
--------
Python 2.7 will no longer be supported as from 31 December 2018.
Please upgrade to Python 3.x as soon as possible.

2.3.4.2

===========================
Bug fixes
---------
Serious bug in MonitorTimestamp caching mechanism resulted in sometimes not updating the statistics, when
animation is off. Fixed.

2.3.4.1

===========================
Bug fixes
---------
Joren van Lindert showed that the percentile calculation for (timestamped) monitors was incorrect.
A new algorithm is implemented.

Bug in merging (timestamped)monitors fixed.

2.3.4

=========================
New functionality
-----------------
From this version, salabim supports so called period monitors with the class PeriodMonitor.
These period monitors can be used to get statistics about (timestamped) monitors per specific period.
For instance if the time unit is hours a period monitor with 24 periods of 1, will give 24 monitors
containing data about hour 0-1, 1-2, ... 23-24 (modulo 24).
It is not necessary that the durations are all the same.
The most obvious use case of this new functionality is to get period information about the builtin
queue monitors length and length_of_stay.
qlength_per_hours= sim.PeriodMonitor(q.length, periods=24 * [1])
q_length_of_stay_per_hour = sim.PeriodMonitor(q.length_of_stay, periods=24 * [1])
Then after a run, the histogram of the length of stay for hour 0-1 (modulo 24) can be printed with
q_length_of_stay_per_hour[0].print_histogram()
And the mean length for hour 2-3 (modulo 24) can be retrieved with
q_length_per_hour[2].mean()
Have a look at the sample program 'Demo periodmonitor.py' for an example, and the docstring or the
latest documentation for the exact API specification.
Please note that this class is still experimental functionality that might change in a future version.


It is now possible to indicate that after a specific component returns control to the event scheduler,
standby component should not be activated. This is particularly useful when a data collection component
becomes current every so often. In that case, activating standby component is not useful and will just
consume processing power.
There are two ways to indicate that a component should skip standby activation:
- Component.skip_standby()
- at initialization of a component, with the skip_standby parameter.
Component.skip_standby() can also be used to query the current value.


New methods
-----------
Added the methods
- Environment.user_to_screen_coordinates_x()
- Environment.user_to_screen_coordinates_y()
- Environment.user_to_screen_coordinates_size()
- Environment.screen_to_usercoordinates_x()
- Environment.screen_to_usercoordinates_y()
- Environment.screen_to_usercoordinates_size()
to convert between user and screen coordinates and vice versa.
These methods are particularly useful for position and sizing AnimateButtons, AnimateSliders or AnimateEntries.


Improved functionality
----------------------
It is no longer required that a process of a component contains a yield statement.
So now ordinary methods (non generators) can now be activated.
This is particularly useful for decision processes that do not consume any time.
Note that these non generator methods can also be called with (keyword) parameters.


Implementation notes
--------------------
Check for hasprocess() changed.
Substantial refactoring to allow for non generator processes to be supported, particularly
with respect to proper tracing.

Process as defined in Component inititalization and Component.activate are no longer assessed
by eval(), but by getattr(), resulting in more stable code.


Bug fixes
---------
Bug in MonitorTimestamp.xduration() fixed.


Announcement
------------
Python 2.7 will no longer be supported as from 31 December 2018.
Please upgrade to Python 3.x as soon as possible.

2.3.3.2

===========================
Changed functionality
---------------------
If Environment.run() is given a till or a duration, main will become active at the specified time.
If not, main will become active when there are no more events on the event list. This will be shown
in the trace with 'ends on no events left'.
So, if you don't want a simulation to stop at the moment the event list becomes empty, issue
env.run(sim.inf)
This can particularly be useful if you don't want to stop an animation when there are no events left.


The placement of the title of AnimateQueue() and Queue.animate() when the direction is 'n' or 's' has
been changed. Now the title is always displayed horizontally.


Implementation note
-------------------
Error reporting for AnimateEntry on Pythonista now only when actually animating.


Big fix
-------
On Pythonista, setting env.video parameter without animating, caused a crash. Fixed.

2.3.3.1

===========================

Implementation note
-------------------
Not documented tkinter_init and tkinit_exit code removed.

Bug fix
-------
From version 2.3.3 main will be reactivated once there are no more events. This functionality was not
supported when running animated. Fixed.

Sometimes an animation object was not removed correctly (under tkinter). Fixed.

Page 13 of 25

© 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.