A lightweight tool for modeling and simulation of Stochastic Petri Nets (SPNs).
ℹ️ Tested with Python 3.11
Make sure Graphviz is installed system-wide by downloading and executing the installer (tested with version 8.1.0).
Ensure the Graphviz executables are added to your PATH environment variable.
- Add
C:\Program Files\Graphviz\binto User Path - Add
C:\Program Files\Graphviz\bin\dot.exeto System Path
You may need to restart your terminal or IDE after changing environment variables.
git clone https://github.com/jo-chr/pyspn.git # 1. Clone repository
pip install -r requirements.txt # 2. Install requirements
python3 examples/one_server.py # 3. Run single-server queue exampleFormally, the class of SPNs that can be modeled using PySPN is defined as:
where:
-
$P = {P_1,P_2,..,P_m}$ is the set of places, drawn as circles; -
$T = {T_1,T_2,..,T_n}$ is the set of transitions along with their distribution functions or weights, drawn as bars; -
$A = A^I \cup A^O \cup A^H$ is the set of arcs, where$A^O$ is the set of output arcs,$A^I$ is the set of input arcs and$A^H$ is the set of inhibitor arcs and each of the arcs has a multiplicity assigned to it; -
$G = {g_1,g_2,..,g_r}$ is the set of guard functions which are associated with different transitions; - and
$m_0$ is the initial marking, defining the distribution of tokens in the places.
Each transition is represented as
Find sample SPNs under examples/. Currently, places, timed transitions (t_type = "T"), immediate transitions (t_type = "I"), output arcs, input arcs, inhibitor arcs, guard functions, and memory policies are supported.
A place with its required arguments is defined like so:
p1 = Place(label="Place 1", n_tokens=0)A timed transition with its required arguments and a sample distribution function is defined like so:
t1 = Transition(label="Transition 1", t_type="T")
t1.set_distribution(distribution="expon", a=0.0, b=1.0/1.0)An immediate transition with its required arguments and a sample weight is defined like so:
t2 = Transition(label="Transition 2", t_type="I")
t2.set_weight(weight=0.8)For timed transitions, some of the supported distributions are:
| Distribution | Parameter |
|---|---|
| Deterministic ("det") | a (fixed delay) |
| Exponential ("expon") | a, b |
| Normal ("norm") | a, b |
| Lognormal ("lognorm") | a, b, c |
| Uniform ("uniform") | a, b |
| Triangular ("triang") | a, b, c |
| Weibull ("weibull_min") | a, b, c |
More distributions can be easily implemented in RNGFactory.py. See Scipy's documentation for details regarding the distributions and their parameters.
Guard functions are defined like so:
def guard_t1():
if len(p1.n_tokens) >= 2:
return True
else: return False
t1.set_guard_function(guard_t1)The default setting is Race Enable ("ENABLE").
The memory policy can be set during instantiation
t1 = Transition(label="Transition_1", t_type="T", memory_policy="AGE")or by using a function call
t1.set_memory_policy("AGE")In our recent update, transitions with join and fork situation are automatically detected.
In many manufacturing systems, some resources don’t process tasks strictly one-by-one. A classic example is a conveyor belt (or continuous-flow machine): while one item is still being processed, the next item can enter the system before the first one finishes. That means several tasks (tokens) can be “in the same activity” at the same time.
To model this behavior in PySPN, we added a feature called parallel timing:
t1 = Transition(label="Transition_1", t_type="T", parallel_timing=True)Export and import SPNs as pickle files using the export_spn() and import_spn() functions of spn_io module.
Simulate a SPN like so:
simulate(spn, max_time = 100, verbosity = 2, protocol = True)For the verbosity there are 3 levels of what is printed in the terminal:
- 0: No information;
- 1: Only final simulation statistics;
- 2: Initial markings, firing of transitions, and final statistics;
- 3: Initial markings, firing of transitions and the resulting marking and state, and final statistics.
The simulation protocol capturing the markings throughtout the simulation can be found under output/protocol/.
Visualize a SPN like so:
draw_spn(spn, show=False, file="sample_spn", rankdir="LR")The graph can be found under output/graphs/.
Output graph example for the example "two_server_with_guard&multiplicity.py"
If you are using the tool for a scientific project please consider citing our publications:
# SAGE Publications Sage 2025 (Journal Paper)
@article{friederich2025pyspn,
title={PySPN: a Python library for stochastic Petri net modeling, simulation, and event log generation},
author={Friederich, Jonas and Khodadadi, Atieh and Lazarova-Molnar, Sanja},
journal={SIMULATION},
pages={00375497251343625},
year={2025},
publisher={SAGE Publications Sage UK: London, England}
}
# EAI SIMUtools 2023 - 15th EAI International Conference on Simulation Tools and Techniques (preprint, accepted for presentation)
@misc{friederich_2023,
doi = {10.13140/RG.2.2.25334.16967},
url = {https://www.researchgate.net/publication/375758652_PySPN_An_Extendable_Python_Library_for_Modeling_Simulation_of_Stochastic_Petri_Nets},
year = 2023,
month = {Nov},
author = {Friederich, Jonas and Lazarova-Molnar, Sanja},
title = {{PySPN}: An Extendable Python Library for Modeling & Simulation of Stochastic Petri Nets},
conference = {EAI SIMUtools 2023 - 15th EAI International Conference on Simulation Tools and Techniques},
note = {preprint}
}
For questions/feedback feel free to contact me: [email protected].
