salabim 24.0.9__tar.gz → 24.0.10__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {salabim-24.0.9 → salabim-24.0.10}/PKG-INFO +1 -1
- {salabim-24.0.9 → salabim-24.0.10}/README.md +64 -64
- {salabim-24.0.9 → salabim-24.0.10}/pyproject.toml +1 -1
- {salabim-24.0.9 → salabim-24.0.10}/salabim/salabim.py +78 -43
- {salabim-24.0.9 → salabim-24.0.10}/salabim.egg-info/PKG-INFO +1 -1
- {salabim-24.0.9 → salabim-24.0.10}/salabim/DejaVuSansMono.ttf +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/salabim/LICENSE.txt +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/salabim/__init__.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/salabim/calibri.ttf +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/salabim/mplus-1m-regular.ttf +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/salabim.egg-info/SOURCES.txt +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/salabim.egg-info/dependency_links.txt +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/salabim.egg-info/top_level.txt +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/setup.cfg +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test salabim.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_cap_now.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_componentgenerator.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_datetime.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_distributions.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_misc.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_monitor.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_process.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_queue.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_state.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_store.py +0 -0
- {salabim-24.0.9 → salabim-24.0.10}/tests/test_timeunit.py +0 -0
@@ -1,64 +1,64 @@
|
|
1
|
-
<img src="https://www.salabim.org/salabim_logo_payoff.png" width=400 />
|
2
|
-
|
3
|
-
Salabim is a Python library for object-oriented discrete event simulation (DES) and animation.
|
4
|
-
|
5
|
-
### Introduction
|
6
|
-
|
7
|
-
Discrete event simulation (DES) finds applications in various logistical domains including production facilities, warehousing, airports, hospitals, mining, materials handling, steel mills, and computer network analysis.
|
8
|
-
|
9
|
-
Salabim follows a well-proven and intuitive process description method similar to Tomas and Must.</br>The package provides:
|
10
|
-
|
11
|
-
- Components
|
12
|
-
- Queues
|
13
|
-
- Resources
|
14
|
-
- Stores
|
15
|
-
- States
|
16
|
-
- Monitors for data collection and presentation
|
17
|
-
- 2D and 3D animation (including video production) (see below)
|
18
|
-
- Tracing facilities
|
19
|
-
- Advanced statistical sampling
|
20
|
-
|
21
|
-
In contrast to some other Python DES packages, salabim does not require the use of yield statements for process control, making it more straightforward to use. Salabim has minimal requirements, especially when animation is disabled.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
### Some salabim animations
|
26
|
-
|
27
|
-
<img src="https://www.salabim.org/cymulation3d.gif" width=700 />
|
28
|
-
|
29
|
-
<img src="https://www.salabim.org/elevator.gif" width=700 />
|
30
|
-
|
31
|
-
<img src="https://www.salabim.org/lights-3d.gif" width=700 />
|
32
|
-
|
33
|
-
### Features and documentation
|
34
|
-
|
35
|
-
- Cross-platform support: salabim runs on Windows, macOS, Linux, iOS/iPadOS (Pythonista), and can even be used with "Python In Excel".
|
36
|
-
- Comprehensive documentation: Visit [www.salabim.org/manual](www.salabim.org/manual) for detailed documentation.
|
37
|
-
|
38
|
-
### Resources
|
39
|
-
|
40
|
-
The salabim package can be found on GitHub: www.github.com/salabim/salabim
|
41
|
-
|
42
|
-
And on PyPI: https://pypi.org/project/salabim/
|
43
|
-
|
44
|
-
### Contributing and Reporting Issues
|
45
|
-
|
46
|
-
Contributions to salabim are highly appreciated! You can contribute by issuing a pull request or submitting an issue on [GitHub](https://github.com/salabim/salabim). Alternatively, you can use the [salabim Google user group](https://groups.google.com/g/salabim) for discussions and reporting issues.
|
47
|
-
|
48
|
-
### License
|
49
|
-
|
50
|
-
Salabim is licensed under the MIT License. For details, please refer to the [LICENSE](LICENSE) file.
|
51
|
-
|
52
|
-
### Support
|
53
|
-
|
54
|
-
Ruud van der Ham, the core developer, is available and willing to help users with issues related to the package and modeling in general. He also provides services such as code and model reviews, consultancy, and training.
|
55
|
-
|
56
|
-
### Getting Started
|
57
|
-
|
58
|
-
To start using salabim, visit [www.salabim.org](www.salabim.org) for installation instructions and further details.
|
59
|
-
|
60
|
-
### Badges
|
61
|
-
|
62
|
-
![PyPI](https://img.shields.io/pypi/v/salabim) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/salabim) ![PyPI - Implementation](https://img.shields.io/pypi/implementation/salabim)
|
63
|
-
![PyPI - License](https://img.shields.io/pypi/l/salabim) ![Black](https://img.shields.io/badge/code%20style-black-000000.svg)
|
64
|
-
![GitHub last commit](https://img.shields.io/github/last-commit/salabim/salabim)
|
1
|
+
<img src="https://www.salabim.org/salabim_logo_payoff.png" width=400 />
|
2
|
+
|
3
|
+
Salabim is a Python library for object-oriented discrete event simulation (DES) and animation.
|
4
|
+
|
5
|
+
### Introduction
|
6
|
+
|
7
|
+
Discrete event simulation (DES) finds applications in various logistical domains including production facilities, warehousing, airports, hospitals, mining, materials handling, steel mills, and computer network analysis.
|
8
|
+
|
9
|
+
Salabim follows a well-proven and intuitive process description method similar to Tomas and Must.</br>The package provides:
|
10
|
+
|
11
|
+
- Components
|
12
|
+
- Queues
|
13
|
+
- Resources
|
14
|
+
- Stores
|
15
|
+
- States
|
16
|
+
- Monitors for data collection and presentation
|
17
|
+
- 2D and 3D animation (including video production) (see below)
|
18
|
+
- Tracing facilities
|
19
|
+
- Advanced statistical sampling
|
20
|
+
|
21
|
+
In contrast to some other Python DES packages, salabim does not require the use of yield statements for process control, making it more straightforward to use. Salabim has minimal requirements, especially when animation is disabled.
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
### Some salabim animations
|
26
|
+
|
27
|
+
<img src="https://www.salabim.org/cymulation3d.gif" width=700 />
|
28
|
+
|
29
|
+
<img src="https://www.salabim.org/elevator.gif" width=700 />
|
30
|
+
|
31
|
+
<img src="https://www.salabim.org/lights-3d.gif" width=700 />
|
32
|
+
|
33
|
+
### Features and documentation
|
34
|
+
|
35
|
+
- Cross-platform support: salabim runs on Windows, macOS, Linux, iOS/iPadOS (Pythonista), and can even be used with "Python In Excel".
|
36
|
+
- Comprehensive documentation: Visit [www.salabim.org/manual](www.salabim.org/manual) for detailed documentation.
|
37
|
+
|
38
|
+
### Resources
|
39
|
+
|
40
|
+
The salabim package can be found on GitHub: www.github.com/salabim/salabim
|
41
|
+
|
42
|
+
And on PyPI: https://pypi.org/project/salabim/
|
43
|
+
|
44
|
+
### Contributing and Reporting Issues
|
45
|
+
|
46
|
+
Contributions to salabim are highly appreciated! You can contribute by issuing a pull request or submitting an issue on [GitHub](https://github.com/salabim/salabim). Alternatively, you can use the [salabim Google user group](https://groups.google.com/g/salabim) for discussions and reporting issues.
|
47
|
+
|
48
|
+
### License
|
49
|
+
|
50
|
+
Salabim is licensed under the MIT License. For details, please refer to the [LICENSE](LICENSE) file.
|
51
|
+
|
52
|
+
### Support
|
53
|
+
|
54
|
+
Ruud van der Ham, the core developer, is available and willing to help users with issues related to the package and modeling in general. He also provides services such as code and model reviews, consultancy, and training.
|
55
|
+
|
56
|
+
### Getting Started
|
57
|
+
|
58
|
+
To start using salabim, visit [www.salabim.org](www.salabim.org) for installation instructions and further details.
|
59
|
+
|
60
|
+
### Badges
|
61
|
+
|
62
|
+
![PyPI](https://img.shields.io/pypi/v/salabim) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/salabim) ![PyPI - Implementation](https://img.shields.io/pypi/implementation/salabim)
|
63
|
+
![PyPI - License](https://img.shields.io/pypi/l/salabim) ![Black](https://img.shields.io/badge/code%20style-black-000000.svg)
|
64
|
+
![GitHub last commit](https://img.shields.io/github/last-commit/salabim/salabim)
|
@@ -8,7 +8,7 @@ authors = [
|
|
8
8
|
{name = "Ruud van der Ham", email = "rt.van.der.ham@gmail.com"}
|
9
9
|
]
|
10
10
|
description = "salabim - discrete event simulation in Python"
|
11
|
-
version = "24.0.
|
11
|
+
version = "24.0.10"
|
12
12
|
readme = "README.md"
|
13
13
|
requires-python = ">=3.7"
|
14
14
|
dependencies = [
|
@@ -1,13 +1,13 @@
|
|
1
|
-
# _ _ _ ____ _ _ ___
|
2
|
-
# ___ __ _ | | __ _ | |__ (_) _ __ ___ |___ \ | || | / _ \
|
3
|
-
# / __| / _` || | / _` || '_ \ | || '_ ` _ \ __) || || |_ | | | | |
|
4
|
-
# \__ \| (_| || || (_| || |_) || || | | | | | / __/ |__ _| _ | |_| | _
|
5
|
-
# |___/ \__,_||_| \__,_||_.__/ |_||_| |_| |_| |_____| |_| (_) \___/ (_)
|
1
|
+
# _ _ _ ____ _ _ ___ _ ___
|
2
|
+
# ___ __ _ | | __ _ | |__ (_) _ __ ___ |___ \ | || | / _ \ / | / _ \
|
3
|
+
# / __| / _` || | / _` || '_ \ | || '_ ` _ \ __) || || |_ | | | | | || | | |
|
4
|
+
# \__ \| (_| || || (_| || |_) || || | | | | | / __/ |__ _| _ | |_| | _ | || |_| |
|
5
|
+
# |___/ \__,_||_| \__,_||_.__/ |_||_| |_| |_| |_____| |_| (_) \___/ (_)|_| \___/
|
6
6
|
# discrete event simulation
|
7
7
|
#
|
8
8
|
# see www.salabim.org for more information, the documentation and license information
|
9
9
|
|
10
|
-
__version__ = "24.0.
|
10
|
+
__version__ = "24.0.10"
|
11
11
|
|
12
12
|
import heapq
|
13
13
|
import random
|
@@ -445,10 +445,8 @@ class Monitor:
|
|
445
445
|
*args,
|
446
446
|
**kwargs,
|
447
447
|
):
|
448
|
-
|
449
|
-
|
450
|
-
else:
|
451
|
-
self.env = env
|
448
|
+
self.env = _set_env(env)
|
449
|
+
|
452
450
|
if isinstance(self.env, Environment):
|
453
451
|
_set_name(name, self.env._nameserializeMonitor, self)
|
454
452
|
else:
|
@@ -855,8 +853,10 @@ class Monitor:
|
|
855
853
|
else:
|
856
854
|
stop += self.env._offset
|
857
855
|
stop_action = "b" # non inclusive
|
858
|
-
|
859
|
-
|
856
|
+
if self.env._animate:
|
857
|
+
stop=min(stop,self.env._t)
|
858
|
+
else:
|
859
|
+
stop = min(stop, self.env._now - self.env._offset) # not self.now() in order to support frozen monitors
|
860
860
|
actions.append((start, "a", 0, 0))
|
861
861
|
actions.append((stop, stop_action, 0, 0))
|
862
862
|
else:
|
@@ -888,8 +888,33 @@ class Monitor:
|
|
888
888
|
new._x.append(curx)
|
889
889
|
|
890
890
|
enabled = False
|
891
|
+
if self.env._animate:
|
892
|
+
_x=self._x[:]
|
893
|
+
_t=self._t[:]
|
894
|
+
if self._x:
|
895
|
+
_x.append(self._x[-1])
|
896
|
+
_t.append(self.env._t)
|
897
|
+
if isinstance(self._weight,bool):
|
898
|
+
_weight=self._weight
|
899
|
+
else:
|
900
|
+
_weight=self._weight[:]
|
901
|
+
_weight.append(self._weight[-1])
|
902
|
+
else:
|
903
|
+
_x=self._x
|
904
|
+
_t=self._t
|
905
|
+
_weight=self._weight
|
906
|
+
|
907
|
+
|
908
|
+
if self.env._animate:
|
909
|
+
if self._x:
|
910
|
+
_x.append(_x[-1])
|
911
|
+
_t.append(self.env._t)
|
912
|
+
try:
|
913
|
+
_weight.append(self.weight[-1])
|
914
|
+
except AttributeError:
|
915
|
+
... # ignore if bool
|
891
916
|
for t, type, x, weight in heapq.merge(
|
892
|
-
actions, zip(self._t, itertools.repeat("c"),
|
917
|
+
actions, zip(self._t, itertools.repeat("c"), _x, _weight if (_weight and not self._level) else (1,) * len(_x))
|
893
918
|
):
|
894
919
|
if new._level:
|
895
920
|
if type == "a":
|
@@ -3472,6 +3497,9 @@ class DynamicClass:
|
|
3472
3497
|
if callable(c):
|
3473
3498
|
if inspect.isfunction(c):
|
3474
3499
|
nargs = c.__code__.co_argcount
|
3500
|
+
if c.__defaults__ is not None:
|
3501
|
+
c.__defaults__ = tuple(self if x == object else x for x in c.__defaults__) # indicate that object refers to animation object itself
|
3502
|
+
nargs -= len(c.__defaults__)
|
3475
3503
|
if nargs == 0:
|
3476
3504
|
return c()
|
3477
3505
|
if nargs == 1:
|
@@ -4290,10 +4318,8 @@ class Queue:
|
|
4290
4318
|
"""
|
4291
4319
|
|
4292
4320
|
def __init__(self, name: str = None, monitor: Any = True, fill: Iterable = None, capacity: float = inf, env: "Environment" = None, *args, **kwargs) -> None:
|
4293
|
-
|
4294
|
-
|
4295
|
-
else:
|
4296
|
-
self.env = env
|
4321
|
+
self.env = _set_env(env)
|
4322
|
+
|
4297
4323
|
_set_name(name, self.env._nameserializeQueue, self)
|
4298
4324
|
self._head = Qmember()
|
4299
4325
|
self._tail = Qmember()
|
@@ -5816,7 +5842,8 @@ class Animate3dBase(DynamicClass):
|
|
5816
5842
|
self, visible: bool = True, keep: bool = True, arg: Any = None, layer: float = 0, parent: "Component" = None, env: "Environment" = None, **kwargs
|
5817
5843
|
) -> None:
|
5818
5844
|
super().__init__()
|
5819
|
-
self.env =
|
5845
|
+
self.env = _set_env(env)
|
5846
|
+
|
5820
5847
|
self.visible = visible
|
5821
5848
|
self.keep = keep
|
5822
5849
|
self.arg = self if arg is None else arg
|
@@ -7060,10 +7087,8 @@ class Component:
|
|
7060
7087
|
env: "Environment" = None,
|
7061
7088
|
**kwargs,
|
7062
7089
|
):
|
7063
|
-
|
7064
|
-
|
7065
|
-
else:
|
7066
|
-
self.env = env
|
7090
|
+
self.env = _set_env(env)
|
7091
|
+
|
7067
7092
|
_set_name(name, self.env._nameserializeComponent, self)
|
7068
7093
|
self._qmembers = {}
|
7069
7094
|
self._process = None
|
@@ -14101,7 +14126,7 @@ class Environment:
|
|
14101
14126
|
|
14102
14127
|
also the legend for line numbers will be printed
|
14103
14128
|
|
14104
|
-
|
14129
|
+
note that the header is only printed if trace=True
|
14105
14130
|
"""
|
14106
14131
|
len_s1 = len(self.time_to_str(0))
|
14107
14132
|
self.print_trace((len_s1 - 4) * " " + "time", "current component", "action", "information", "" if PythonInExcel else "line#")
|
@@ -14670,7 +14695,7 @@ class Environment:
|
|
14670
14695
|
if self._last_animate != self._animate or self._last_paused != self._paused:
|
14671
14696
|
for key in self._ui_window.key_dict:
|
14672
14697
|
field = self._ui_window[key]
|
14673
|
-
if type(field) != sg.
|
14698
|
+
if type(field) != sg.HorizontalSeparator:
|
14674
14699
|
if self._paused:
|
14675
14700
|
field.update(visible=True)
|
14676
14701
|
else:
|
@@ -14847,9 +14872,10 @@ class Animate2dBase(DynamicClass):
|
|
14847
14872
|
screen_coordinates = locals_["screen_coordinates"]
|
14848
14873
|
over3d = locals_["over3d"]
|
14849
14874
|
|
14850
|
-
self.env =
|
14875
|
+
self.env = _set_env(env)
|
14876
|
+
|
14851
14877
|
self.sequence = self.env.serialize()
|
14852
|
-
self.arg = self if arg
|
14878
|
+
self.arg = self if arg in (None, object) else arg
|
14853
14879
|
self.over3d = _default_over3d if over3d is None else over3d
|
14854
14880
|
self.screen_coordinates = screen_coordinates
|
14855
14881
|
self.attached_to = attached_to
|
@@ -15927,7 +15953,8 @@ class Animate:
|
|
15927
15953
|
animation_to: float = inf,
|
15928
15954
|
env: "Environment" = None,
|
15929
15955
|
):
|
15930
|
-
self.env =
|
15956
|
+
self.env = _set_env(env)
|
15957
|
+
|
15931
15958
|
self._image_ident = None # denotes no image yet
|
15932
15959
|
self._image = None
|
15933
15960
|
self._image_x = 0
|
@@ -17049,7 +17076,8 @@ class AnimateEntry:
|
|
17049
17076
|
env: "Environment" = None,
|
17050
17077
|
xy_anchor: str = "sw",
|
17051
17078
|
):
|
17052
|
-
self.env =
|
17079
|
+
self.env = _set_env(env)
|
17080
|
+
|
17053
17081
|
self.env.ui_objects.append(self)
|
17054
17082
|
self.type = "entry"
|
17055
17083
|
self.value = value
|
@@ -17194,7 +17222,8 @@ class AnimateButton:
|
|
17194
17222
|
env: "Environment" = None,
|
17195
17223
|
xy_anchor: str = "sw",
|
17196
17224
|
):
|
17197
|
-
self.env =
|
17225
|
+
self.env = _set_env(env)
|
17226
|
+
|
17198
17227
|
self.type = "button"
|
17199
17228
|
self.t0 = -inf
|
17200
17229
|
self.t1 = inf
|
@@ -17375,7 +17404,7 @@ class AnimateSlider:
|
|
17375
17404
|
labelcolor: ColorType = None, # only for backward compatibility
|
17376
17405
|
layer: float = None, # only for backward compatibility
|
17377
17406
|
):
|
17378
|
-
self.env =
|
17407
|
+
self.env = _set_env(env)
|
17379
17408
|
n = round((vmax - vmin) / resolution) + 1
|
17380
17409
|
self.vmin = vmin
|
17381
17410
|
self.vmax = vmin + (n - 1) * resolution
|
@@ -22637,10 +22666,7 @@ class State:
|
|
22637
22666
|
"""
|
22638
22667
|
|
22639
22668
|
def __init__(self, name: str = None, value: Any = False, type: str = "any", monitor: bool = True, env: "Environment" = None, *args, **kwargs):
|
22640
|
-
|
22641
|
-
self.env = g.default_env
|
22642
|
-
else:
|
22643
|
-
self.env = env
|
22669
|
+
self.env = _set_env(env)
|
22644
22670
|
_set_name(name, self.env._nameserializeState, self)
|
22645
22671
|
self._value = value
|
22646
22672
|
with self.env.suppress_trace():
|
@@ -23115,11 +23141,7 @@ class Resource:
|
|
23115
23141
|
*args,
|
23116
23142
|
**kwargs,
|
23117
23143
|
):
|
23118
|
-
|
23119
|
-
self.env = g.default_env
|
23120
|
-
else:
|
23121
|
-
self.env = env
|
23122
|
-
|
23144
|
+
self.env = _set_env(env)
|
23123
23145
|
if initial_claimed_quantity != 0:
|
23124
23146
|
if not anonymous:
|
23125
23147
|
raise ValueError("initial_claimed_quantity != 0 only allowed for anonymous resources")
|
@@ -23648,10 +23670,8 @@ class PeriodMonitor:
|
|
23648
23670
|
|
23649
23671
|
def __init__(self, parent_monitor: "Monitor", periods: Iterable = None, period_monitor_names: Iterable = None, env: "Environment" = None):
|
23650
23672
|
self.pc = _PeriodComponent(pm=self, skip_standby=True, suppress_trace=True)
|
23651
|
-
|
23652
|
-
|
23653
|
-
else:
|
23654
|
-
self.env = env
|
23673
|
+
self.env = _set_env(env)
|
23674
|
+
|
23655
23675
|
if periods is None:
|
23656
23676
|
periods = 24 * [1]
|
23657
23677
|
self.periods = periods
|
@@ -26928,6 +26948,21 @@ def reset() -> None:
|
|
26928
26948
|
random_seed() # always start with seed 1234567
|
26929
26949
|
|
26930
26950
|
|
26951
|
+
def _set_env(env):
|
26952
|
+
"""
|
26953
|
+
returns g._default_env if env is None
|
26954
|
+
returns env, otherwise
|
26955
|
+
|
26956
|
+
will raise a ValueError if g.default_env is None (nit initialized)
|
26957
|
+
"""
|
26958
|
+
|
26959
|
+
if env is None:
|
26960
|
+
if g.default_env is None:
|
26961
|
+
raise ValueError("no default environment. Did yout forget to call sim.Environment()?")
|
26962
|
+
return g.default_env
|
26963
|
+
return env
|
26964
|
+
|
26965
|
+
|
26931
26966
|
App = Environment
|
26932
26967
|
|
26933
26968
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|