Skip to content

Commit 4d85c2c

Browse files
Merge branch 'release' of https://github.com/pm4py/pm4py-core into github-release
2 parents bf88107 + 0c1eb9e commit 4d85c2c

File tree

6 files changed

+68
-5
lines changed

6 files changed

+68
-5
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ RUN apt-get -y install g++ libboost-all-dev libncurses5-dev wget
1212
RUN apt-get -y install libtool flex bison pkg-config g++ libssl-dev automake
1313
RUN apt-get -y install libjemalloc-dev libboost-dev libboost-filesystem-dev libboost-system-dev libboost-regex-dev python3-dev autoconf flex bison cmake
1414
RUN apt-get -y install libxml2-dev libxslt-dev libfreetype6-dev libsuitesparse-dev
15+
RUN pip install -U cvxopt
1516
RUN pip install -U wheel six pytest
1617
RUN pip install asttokens==2.0.5 backcall==0.2.0 colorama==0.4.4 cycler==0.11.0 decorator==5.1.1 deprecation==2.1.0 executing==0.8.3 fonttools==4.32.0 graphviz==0.19.2 intervaltree==3.1.0 ipython==8.2.0 jedi==0.18.1 jinja2==3.1.1 jsonpickle==2.1.0 kiwisolver==1.4.2 lxml==4.8.0 MarkupSafe==2.1.1 matplotlib==3.5.1 matplotlib-inline==0.1.3 mpmath==1.2.1 networkx==2.8 numpy==1.22.3 packaging==21.3 pandas==1.4.2 parso==0.8.3 pickleshare==0.7.5 pillow==9.1.0 prompt-toolkit==3.0.29 pure-eval==0.2.2 pydotplus==2.0.2 pygments==2.11.2 pyparsing==3.0.8 python-dateutil==2.8.2 pytz==2022.1 pyvis==0.1.9 scipy==1.8.0 setuptools==62.0.0 six==1.16.0 sortedcontainers==2.4.0 stack-data==0.2.0 stringdist==1.0.9 sympy==1.10.1 tqdm==4.64.0 traitlets==5.1.1 wcwidth==0.2.5
1718

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pm4py.view_petri_net(pnet, initial_marking, final_marking, format="svg")
1919
```
2020

2121
## Installation
22-
pm4py can be installed on Python 3.7.x / 3.8.x / 3.9.x by doing:
22+
pm4py can be installed on Python 3.7.x / 3.8.x / 3.9.x / 3.10.x by doing:
2323
```bash
2424
pip install -U pm4py
2525
```

pm4py/algo/simulation/playout/petri_net/variants/basic_playout.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@ class Parameters(Enum):
3737
NO_TRACES = "noTraces"
3838
MAX_TRACE_LENGTH = "maxTraceLength"
3939
PETRI_SEMANTICS = "petri_semantics"
40+
INITIAL_TIMESTAMP = "initial_timestamp"
41+
INITIAL_CASE_ID = "initial_case_id"
4042

4143

4244
def apply_playout(net, initial_marking, no_traces=100, max_trace_length=100,
45+
initial_timestamp=10000000, initial_case_id=0,
4346
case_id_key=xes_constants.DEFAULT_TRACEID_KEY,
4447
activity_key=xes_constants.DEFAULT_NAME_KEY, timestamp_key=xes_constants.DEFAULT_TIMESTAMP_KEY,
4548
final_marking=None, return_visited_elements=False, semantics=petri_net.semantics.ClassicSemantics()):
@@ -56,6 +59,10 @@ def apply_playout(net, initial_marking, no_traces=100, max_trace_length=100,
5659
Number of traces to generate
5760
max_trace_length
5861
Maximum number of events per trace (do break)
62+
initial_timestamp
63+
Increased timestamp from 1970 for the first event
64+
initial_case_id
65+
Case id of the first event
5966
case_id_key
6067
Trace attribute that is the case ID
6168
activity_key
@@ -68,7 +75,7 @@ def apply_playout(net, initial_marking, no_traces=100, max_trace_length=100,
6875
Semantics of the Petri net to be used (default: petri_net.semantics.ClassicSemantics())
6976
"""
7077
# assigns to each event an increased timestamp from 1970
71-
curr_timestamp = 10000000
78+
curr_timestamp = initial_timestamp
7279
all_visited_elements = []
7380

7481
for i in range(no_traces):
@@ -104,7 +111,7 @@ def apply_playout(net, initial_marking, no_traces=100, max_trace_length=100,
104111

105112
for index, visited_elements in enumerate(all_visited_elements):
106113
trace = log_instance.Trace()
107-
trace.attributes[case_id_key] = str(index)
114+
trace.attributes[case_id_key] = str(index+initial_case_id)
108115
for element in visited_elements:
109116
if type(element) is PetriNet.Transition and element.label is not None:
110117
event = log_instance.Event()
@@ -135,6 +142,8 @@ def apply(net: PetriNet, initial_marking: Marking, final_marking: Marking = None
135142
Parameters of the algorithm:
136143
Parameters.NO_TRACES -> Number of traces of the log to generate
137144
Parameters.MAX_TRACE_LENGTH -> Maximum trace length
145+
Parameters.INITIAL_TIMESTAMP -> The first event is set with INITIAL_TIMESTAMP increased from 1970
146+
Parameters.INITIAL_CASE_ID -> Numeric case id for the first trace
138147
Parameters.PETRI_SEMANTICS -> Petri net semantics to be used (default: petri_nets.semantics.ClassicSemantics())
139148
"""
140149
if parameters is None:
@@ -145,10 +154,15 @@ def apply(net: PetriNet, initial_marking: Marking, final_marking: Marking = None
145154
xes_constants.DEFAULT_TIMESTAMP_KEY)
146155
no_traces = exec_utils.get_param_value(Parameters.NO_TRACES, parameters, 1000)
147156
max_trace_length = exec_utils.get_param_value(Parameters.MAX_TRACE_LENGTH, parameters, 1000)
157+
initial_timestamp = exec_utils.get_param_value(Parameters.INITIAL_TIMESTAMP, parameters, 10000000)
158+
initial_case_id = exec_utils.get_param_value(Parameters.INITIAL_CASE_ID, parameters, 0)
148159
return_visited_elements = exec_utils.get_param_value(Parameters.RETURN_VISITED_ELEMENTS, parameters, False)
149160
semantics = exec_utils.get_param_value(Parameters.PETRI_SEMANTICS, parameters, petri_net.semantics.ClassicSemantics())
150161

151-
return apply_playout(net, initial_marking, max_trace_length=max_trace_length, no_traces=no_traces,
162+
return apply_playout(net, initial_marking, max_trace_length=max_trace_length,
163+
initial_timestamp=initial_timestamp,
164+
initial_case_id=initial_case_id,
165+
no_traces=no_traces,
152166
case_id_key=case_id_key, activity_key=activity_key, timestamp_key=timestamp_key,
153167
final_marking=final_marking, return_visited_elements=return_visited_elements,
154168
semantics=semantics)

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ pyvis
1414
scipy
1515
stringdist
1616
sympy
17-
tqdm
17+
tqdm

tests/execute_tests.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
from tests.simplified_interface import SimplifiedInterfaceTest
4141
from tests.ocel_filtering_test import OcelFilteringTest
4242
from tests.ocel_discovery_test import OcelDiscoveryTest
43+
from tests.simulation_test import SimulationTest
4344

4445
ocel_filtering_test = OcelFilteringTest()
4546
ocel_discovery_test = OcelDiscoveryTest()
@@ -74,5 +75,6 @@
7475
woflan_test = WoflanTest()
7576
diagn_dataframe_test = DiagnDfConfChecking()
7677
simplified_test = SimplifiedInterfaceTest()
78+
simulation_test = SimulationTest()
7779

7880
unittest.main()

tests/simulation_test.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import os
2+
import unittest
3+
4+
from pm4py.objects.petri_net.importer import importer as pnml_importer
5+
from pm4py.algo.simulation.playout.petri_net import algorithm as simulator
6+
from tests.constants import INPUT_DATA_DIR
7+
from datetime import datetime
8+
9+
10+
class SimulationTest(unittest.TestCase):
11+
def test_simulate_petrinet(self):
12+
net, im, fm = pnml_importer.apply(
13+
os.path.join(INPUT_DATA_DIR, "running-example.pnml"))
14+
number_of_traces = 10
15+
eventlog = simulator.apply(net, im, fm, variant=simulator.Variants.BASIC_PLAYOUT,
16+
parameters={
17+
simulator.Variants.BASIC_PLAYOUT.value.Parameters.NO_TRACES: number_of_traces})
18+
self.assertEqual(len(eventlog), number_of_traces)
19+
case_id_default = 0
20+
last_case_id = case_id_default + number_of_traces - 1
21+
timestamp_default = 10000000
22+
self.assertEqual(eventlog[0].attributes['concept:name'], str(case_id_default))
23+
self.assertEqual(datetime.timestamp(eventlog[0][0]['time:timestamp']), timestamp_default)
24+
self.assertEqual(eventlog[-1].attributes['concept:name'], str(last_case_id))
25+
26+
def test_simulate_petrinet_start_params(self):
27+
net, im, fm = pnml_importer.apply(
28+
os.path.join(INPUT_DATA_DIR, "running-example.pnml"))
29+
number_of_traces = 10
30+
timestamp = 50000000
31+
case_id = 5
32+
eventlog = simulator.apply(net, im, fm, variant=simulator.Variants.BASIC_PLAYOUT,
33+
parameters={
34+
simulator.Variants.BASIC_PLAYOUT.value.Parameters.NO_TRACES: number_of_traces,
35+
simulator.Variants.BASIC_PLAYOUT.value.Parameters.INITIAL_TIMESTAMP:
36+
timestamp,
37+
simulator.Variants.BASIC_PLAYOUT.value.Parameters.INITIAL_CASE_ID: case_id})
38+
self.assertEqual(len(eventlog), number_of_traces)
39+
last_case_id = case_id + number_of_traces - 1
40+
self.assertEqual(eventlog[0].attributes['concept:name'], str(case_id))
41+
self.assertEqual(datetime.timestamp(eventlog[0][0]['time:timestamp']), timestamp)
42+
self.assertEqual(eventlog[-1].attributes['concept:name'], str(last_case_id))
43+
44+
45+
if __name__ == "__main__":
46+
unittest.main()

0 commit comments

Comments
 (0)