Salabim

Latest version: v24.0.9

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

Scan your dependencies

Page 15 of 25

2.3.2.1

===========================
Bug fixes
---------
Fatal error in Component.cancel() when tracing standby components fixed.

2.3.2

=========================
New functionality
-----------------
The methods
AnimateText
AnimateRectangle
AnimateLine
AnimatePolygon
AnimatePoints
AnimateCircle
AnimateImage
AnimateQueue
AnimateMonitor
AnimateMonitorTimestamp
now have an additional parameter, parent.
When a process finishes, either by reaching the end or by a cancel, all animation objects with that
component as its parent will be automatically removed.


Bug fixes
---------
Fatal error when tracing standby components fixed.

After a reset of a timestamped monitor, the animation of that monitor did not start at the left hand side of
the graph. Fixed.

Some minor error handling problems with checking for types fixed.


Demonstration of animation features
-----------------------------------
In order to demonstrate the new style animation classes, the following files (with comments) are included
in the GitHub distribution:
Demo animation classes.py (requires the file Pas un pipe.py)
Demo queue animation.py
Demo animation dynamic.py
Demo animation dynamic lambda.py

2.3.1

=========================
New functionality
-----------------
Monitors can now be weighted. Initializing a Monitor instance has therefore a new parameter, weighted.
If weighted is set to True, the tally method can be used to specify the weight.
Monitor.weight() returns the sum of all weights.
Monitor.value_weight() returns the sum of all weights equal to or in value
Monitor.bin_weight() returns the sum of all weights > lowerbound and <= upperbound.
The name of the weight (used in Print_histogram and print_statistics) can be specified by the user (default is weight).


sim.Animate(circle0=) now supports also ellipses and circle arcs. Please consult the documentation for the correct
parameter usage.
It is highly recommended to use the new style AnimateCircle, which has some more parameters now:
radius1 is the height of the ellipse (if omitted, a circle will be drawn)
arc_angle0 is the start angle of the arc (default 0)
arc_angle1 is the end angle of the arc (default 360, thus a full circle)
draw_arc indicates whether the arcs should be drawn (default False)
Note that all the parameters may be a scalar, a function with 0, 1 or 2 arguments or a method with one argument (t).
Note also that the text is always positioned relative to the full circle/ellipse, regardless of the arc_angles.
Example:
sim.AnimateCircle(radius=100, radius1=50, arc_angle1=lambda t: t*10)


Bug fixes
---------
Bug in closing an animation under Spyder or Idle fixed.
Bug in Environment.snaphot() under Pythonista fixed.


Internal
--------
Major overhaul of monitor off values and handling of duration for MonitorTimestamped.
Timestamped monitors now share most of their functionality with weighted monitors.

2.3.0

=========================
New functionality
-----------------
As from this version, animation is more powerful and easier to use. Although the old style
Animate class is still available, it is recommended to use the new style classes.

The documentation is not yet completely up-to-date. Please read these release notes carefully to get more information.

All the docstrings (and therefore the reference section of the manual) are however up-to-date.
It is planned to publish a number of tutorial videos or guides, both for basic and advanced animation.

To visualize rectangles, lines, points, polygon, texts, circles and images salabim offers the new classes
- AnimateCircle
- AnimateImage
- AnimateLine
- AnimatePoints
- AnimatePolygon
- AnimateRectangle
- AnimateText

The main difference with the Animate class is that no automatic linear interpolation over time is supported.
But, each of the characteristics may be still changed over time easily!
All visualizations (apart from AnimateText) have an attached text field that will be displayed relative to
the shape.
Thus, for instance, it possible to say:
vis = sim.AnimateRectangle(spec=(100, 100, 300, 50), text='some text')
and then a rectangle with the text 'some text' in the middle will be displayed.
In contrast to Animate, updating any of the specifying fields does not require the update method, but can be
done directly.
In the above example you can just say
vis.text='yet another text' or vis.x=100

One of the key features of this new visualization is that all the specifying fields can now be functions or methods.
This make is possible to automatically update fields, e.g.
vis = sim.AnimateText(lambda:'mean of histogram = ' + str(hist1.mean()), x=100, y=100)
which will show and update the current mean of the histogram
or
vis = sim.AnimateRectangle(spec=(0, 0, 60, 20), x=100, y=lambda t:t+10)
which results in a rectangle, moving from bottom to top.
The animation_objects method of Component now accepts any of the new visualization class instances as well as
Animate instances.

Animation of queues is now specified with the class AnimateQueue, although Queue.animate() is still supported.
One queue can now be animated in several ways, whereas previously one queue could be animated only once. See
Demo queue animation.py for an example.
It possible to restrict the number of components shown (max_length).
Is possible to change all the parameters of the queue animation and the shown components dynamically.
See for instance Elevator animated.py where the queue position moves up and down.
Or see Machine shop animated.py where the shape of the components changes dynamically.
Internally, the animation of queues uses a new, more efficient, algorithm.

Most examples have been updated to use this new visualization functionality.

Texts can now spawn multiple lines (lines separated by linefeeds). Also, a list or tuple of strings may
be used instead, in which case each element of the list/tuple will be treated as another line.
This is particularly useful to present (dynamic) monitor values.
With AnimateText, it is possible to restrict the number of lines (parameter max_lines) shown.


Class Animate has a new animation parameter, as_points that applies to lines, rectangles and polygons.
If as_points is False (the default), all lines will be drawn.
If as_points is True, only the end point will be drawn as a square with a width equal to the linewidth.
Technical remark: the advantage of using as_points this instead of a series of individual squares
is that there is only one bitmap to be placed on the canvas, which may lead to better performance in many cases.
Also this is used internally for AnimateMonitor() (see below).
Points are also available in the new AnimatePoints class.


Class AnimateMonitor() can be used to visualize the value of a timestamped monitor over time. It is
particularly useful for visualizing the length of a queue, the various monitors of a resource or
the value of a state.
It is possible to connect the lines (very useful for 'duration' monitors, like queue length) or just show
the individual points.
This class can also visualize the relationship between the index and the value of a non time stamped monitor.
The points can be just shown or connected with a line.
It is possible to use
Monitor.animate() and
MonitorTimestamp.animate()
as an alternative, although not recommended.

The MMc animated.py model demonstrates the use of the (timestamped) monitor animation.


Monitor and MonitorTimestamp can now be used to create a merged (timestamped) monitor.
This is done by providing a list of (timestamped) monitors (all have to have the same type), like
mc = MonitorTimestamp(name='m1 and m2', merge=(m1, m2))
For monitors, just all of the tallied x-values are copied from the to be merged monitors.
For timestamped monitors, the x-values are summed, for all the periods where all the monitors were on.
Periods where one or more monitors were off, are excluded.
Note that the merge only takes place at creation of the (timestamped) monitor and not dynamically later.

Sample usage:
Suppose we have three types of products, that each have a queue for processing, so
a.processing, b.processing, c.processing.
If we want to print the histogram of the combined (=summed) length of these queues:
MonitorTimestamp(name='combined processing length',
merge=(a.processing.length, b.processing.length, c.processing.length)).print_histogram()
and to print the histogram of the length_of_stay for all entries:
Monitor(name='combined processing length of stay',
merge=(a.processing.length_of_stay, b.processing.length_of_stay, c.processing.length_of_stay)).print_histogram()


CumPdf is a new distribution type that is similar to Pdf, but where cumulative probability values are used.
This is particularly useful for dichotomies, like failing probabilities:
failrate = 0.1
if CumPdf(True, failrate, False,1)
print('failed!')


All methods
print_histogram()
print_histograms()
print_statistics()
print_info()
now have an additional parameter as_str, that allows the output to be returned
as a string, rather than print the information (the default is False, so just print):
This is particularly useful for animation of that information (see demo queue animation.py) or to
write directly to a file.


sim.Random() is a new class that makes a randomstream. It is essentially the same as sim.random.Random().


Queue.name(value), Resource.name(value) and State.name(value) now also update the derived names.

API changes
-----------
The API of Component has changed slightly. The parameter process now defaults to None, which means that
it tries to run the process generator method, if any.
If you don't want to start the process generator method, even if it exists, now set process='' (this was None).

The API of Environment had changed slightly. The parameter random_seed now defaults to None, which means that
1234567 will be used as the random seed value. If random_seed is '*', a system generated, non reproducable,
random seed will be used.

The API of Environment.random_seed has changed slightly. If the argument seed is '*', a system generated, non
reproducable random seed will be used.

State.animate() is phased out. Use the standard visualization classes, like AnimateRectangle,
AnimateCircle and AnimateTex instead.


Future changes
--------------
Python 2.7 will not be supported in a future version. Please upgrade to Python 3.x as soon as possible .


Internal changes
----------------
Most default parameters are now None, instead of omitted, which is completely phased out.
This makes it easier to specify default arguments, like:
myname = None
sim.Component(name=myname)
This internal change required a couple of changes to the API (see above).
Apart from that, the user shouldn't notice this rather dramatic internal change (>500 replacements in the code!).

Animating lines and polygons without any points is now supported.

2.2.23

==========================
New functionality
-----------------
Component.leave() can now be called without a queue, in which case, the component will leave all queues
it is in, apart from internal queues (Resource.claimers(), Resource.requesters and State.waiters()).
It is not necessary that the component is in any queue.
The best use case is to leave the one and only queue it is in without having to specify the
queue, like
self.enter(q1)
...
self.leave()

Also, Component.leave() now returns the component (self). This is useful for daisy chaining, like:
def process(self):
while True:
self.leave().enter(q1)
yield self.hold(p1())
self.leave().enter(q2)
yield self.hold(p2())
self.leave().enter(q3)
yield self.hold(p3())
With this code, the component 'hops' from queue to queue, with minimal effort.


In line with this daisy chaining of leave, the methods
Component.enter(),
Component.enter_at_head()
Component.enter_sorted()
Component.enter_in_front_of()
Component.enter_behind()
now return the component (self).

With this new functionality, it is possible to do things like
self.enter(q1).enter(q2).enter(q3)
for a component to enter three queues on just one line.


Monitor.print_histograms() introduced as an alias for Monitor.print_histogram()
MonitorTimestamped.print_histograms() introduced as an alias for MonitorTimestamped.print_histogram()
Monitor.reset_monitors() introduced as an alias for Monitor.reset()
MonitorTimestamped.reset_monitors() introduced as an alias for MonitorTimestamped.reset()

These four new methods make it possible to intermix resources, states, queues, (timestamped) monitors when
printing histograms or resetting the monitors, like:
for obj in [my_queue, my_resource, my_monitor, my_timestamped_monitor]:
obj.print_histograms()
obj.reset_monitors()


Introduced methods register and deregister for classes:
Component
Monitor
MonitorTimestamped
Queue
Resource
State
This makes it easier to do collective actions on a number of component, queues, (timestamped)monitors, queues,
resources and/or states.
A registry is just a list of objects, which can for instance be used as:
monitors = []
m1 = sim.Monitor(name='m1').register(monitors)
m2 = sim.Monitor(name='m2').register(monitors)
queues = []
q1 = sim.Queue(name='q1').register(queues)
q2 = sim.Queue(name='q2').register(queues)
...
for obj in monitors + queues:
obj.print_histograms()
obj.reset_histograms()

Another example:
components = []
while(...):
MyComp().register(components)
...
print('all components in system:')
for component in components:
print(component.name())

Make sure to deregister any objects that are not used anymore, otherwise these will not be garbage collected!

Note that it is possible to mix several types of class in a registry (list).


Documentation update
--------------------
In contrast to documentation so far, the priority parameter in Component.enter_sorted, Component.priority()
and Queue.add_sorted() does not have to be float.
It can be any type as long as it can be compared with the other priorities in the queue.
Example 1:
q=sim.Queue('q')
X().enter_sorted(q, (1,1))
X().enter_sorted(q, (0,2))
X().enter_sorted(q, (1,0))
X().enter_sorted(q, (1,3))
q.print_info()
will print
Queue 0x11a0136d8
name=q
component(s):
x.1 enter_time 0.000 priority=(0, 2)
x.2 enter_time 0.000 priority=(1, 0)
x.0 enter_time 0.000 priority=(1, 1)
x.3 enter_time 0.000 priority=(1, 3)

Example 2:
q=sim.Queue('q')
X().enter_sorted(q, 'one')
X().enter_sorted(q, 'two')
X().enter_sorted(q, 'three')
X().enter_sorted(q, 'four')
q.print_info()
will print
Queue 0x1279a82b0
name=q
component(s):
x.3 enter_time 0.000 priority=four
x.0 enter_time 0.000 priority=one
x.2 enter_time 0.000 priority=three
x.1 enter_time 0.000 priority=two

Note: Avoid mixing enter_sorted or add_sorted with enter, enter_at_head, add, append or add_at_head when using
non float priorities.


Bug fixes
---------
Bug in State introduced in version 2.2.22 fixed.

2.2.22

==========================
New functionality
-----------------
Monitor.print_histogram() and MonitorTimestamp.print_histogram() now support auto scaling of
the bin_width, lowerbound and number_of_bins, when none of these parameters are specified.
The autoscaling algorithm method can be overridden if required (see Histogram.histogram_autoscale).
For example, the following code
m = sim.Monitor('normal distribution')
for i in range(100000):
m.tally(sim.Normal(10,2)())
m.print_histogram()

will print:

Histogram of normal distribution
all excl.zero zero
-------------- ------------ ------------ ------------
entries 10000 10000 0
mean 9.989 9.989
std.deviation 1.989 1.989

minimum 1.881 1.881
median 9.978 9.978
90% percentile 12.550 12.550
95% percentile 13.245 13.245
maximum 17.597 17.597

<= entries % cum%
1 0 0 0 |
2 1 0.0 0.0 |
3 3 0.0 0.0 |
4 14 0.1 0.2 |
5 43 0.4 0.6 |
6 153 1.5 2.1 *|
7 439 4.4 6.5 *** |
8 925 9.2 15.8 ******* |
9 1532 15.3 31.1 ************ |
10 1938 19.4 50.5 *************** |
11 1895 18.9 69.4 *************** |
12 1475 14.8 84.2 *********** |
13 940 9.4 93.6 ******* |
14 424 4.2 97.8 *** |
15 165 1.7 99.5 * |
16 34 0.3 99.8 |
17 15 0.1 100.0 |
18 4 0.0 100.0 |
inf 0 0 100.0 |

Monitor.print_histogram() and MonitorTimestamp.print_histogram() now supports the presentation of
individual values, by specifying values=True.
This is especially useful when collecting the status of a component over time, like:

Histogram of Status
duration 300
entries 57

value duration entries
idle 88.558( 29.5%) 9( 15.8%) ***********************
produce A 37.459( 12.5%) 9( 15.8%) *********
produce B 8.425( 2.8%) 2( 3.5%) **
produce C 44.352( 14.8%) 10( 17.5%) ***********
produce D 54.775( 18.3%) 12( 21.1%) **************
store 38.591( 12.9%) 8( 14.0%) **********
transport 27.841( 9.3%) 7( 12.3%) *******

Monitor.value_number_of_entries() introduced. The method can be used to check how many entries have an x
equal to value or an x that is in value.

MonitorTimestamp.value_duration() introduced. The method can be used to check the duration of an x
equal to value or an x that is in value.

MonitorTimestamp.value_number_of_entries() introduced. The method can be used to check how many entries have an x
equal to value or an x that is in value.

Introduced Queue.print_histograms(). This method prints autoscaled histograms of the
- length timstamped monitor
- length_of_stay monitor

Introduced Resource.print_histograms(). This method prints autoscaled histograms of the
- requesters().length timstamped monitor
- requesters().length_of_stay monitor
- claimers().length timstamped monitor
- claimers().length_of_stay monitor
- capacity timestamped monitor
- available_quantity timestamped monitor
- claimed_quantity timestamped monitor

Introduced State.print_histograms(). This method prints autoscaled histograms of the
- waiters().length timestamped monitor
- waiters().length_of_stay monitor
- value timestamped monitor

MonitorTimestamp.number_of_entries() introduced, to be used to retrieve the number of entries.

Component.name(), Environment.name(), Monitor.name(), MonitorTimestamp.name(), Queue.name()
Resource.name() and State.name() now can be used to change the name of the object.
Note that the base_name and the sequence_number will not change upon a name change.

Function regular_polygon introduced.


Renamed
-------
MonitorTimestamp.bin_count() is now called MonitorTimestamp.bin_duration()
Monitor.bin_count() is now called Monitor.bin_number_entries()


Bug fix
-------
Problem when PIL was not installed (correctly).

Page 15 of 25

© 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.