openprocess 0.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. cpnpy/__init__.py +46 -0
  2. openprocess/__init__.py +57 -0
  3. openprocess/analysis/__init__.py +0 -0
  4. openprocess/analysis/state_space.py +521 -0
  5. openprocess/analysis/state_space_process.py +251 -0
  6. openprocess/cli.py +742 -0
  7. openprocess/exercises/1 Petri nets/Exercise 1.1 Order handling/answer.pnml +31 -0
  8. openprocess/exercises/1 Petri nets/Exercise 1.1 Order handling/question.md +38 -0
  9. openprocess/exercises/2 Soundness/Exercise 2.1 Spot the flaw/answer.pnml +27 -0
  10. openprocess/exercises/2 Soundness/Exercise 2.1 Spot the flaw/net.pnml +29 -0
  11. openprocess/exercises/2 Soundness/Exercise 2.1 Spot the flaw/question.md +65 -0
  12. openprocess/exercises/3 Discovery/Exercise 3.1 The alpha-algorithm/log.txt +1 -0
  13. openprocess/exercises/3 Discovery/Exercise 3.1 The alpha-algorithm/question.md +67 -0
  14. openprocess/exercises/4 Regions/Exercise 4.1 Regions of a transition system/question.md +75 -0
  15. openprocess/exercises/4 Regions/Exercise 4.1 Regions of a transition system/ts.txt +5 -0
  16. openprocess/exercises/5 Markings/Exercise 5.1 Markings and matrices/net.pnml +27 -0
  17. openprocess/exercises/5 Markings/Exercise 5.1 Markings and matrices/question.md +65 -0
  18. openprocess/exercises/6 Inductive Miner/Exercise 6.1 Cuts and trees/log.txt +1 -0
  19. openprocess/exercises/6 Inductive Miner/Exercise 6.1 Cuts and trees/question.md +62 -0
  20. openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/log.txt +1 -0
  21. openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/m1.pnml +36 -0
  22. openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/m2.pnml +28 -0
  23. openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/m3.pnml +30 -0
  24. openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/net.pnml +36 -0
  25. openprocess/exercises/7 Conformance/Exercise 7.1 Replay, alignments and workflows/question.md +69 -0
  26. openprocess/exercises/pack.md +14 -0
  27. openprocess/flow/__init__.py +50 -0
  28. openprocess/flow/box.py +466 -0
  29. openprocess/flow/boxes/__init__.py +7 -0
  30. openprocess/flow/boxes/check.py +119 -0
  31. openprocess/flow/boxes/compare.py +16 -0
  32. openprocess/flow/boxes/cpn.py +53 -0
  33. openprocess/flow/boxes/discover.py +124 -0
  34. openprocess/flow/boxes/filter.py +80 -0
  35. openprocess/flow/boxes/input.py +124 -0
  36. openprocess/flow/boxes/output.py +52 -0
  37. openprocess/flow/boxes/predict.py +186 -0
  38. openprocess/flow/boxes/science.py +159 -0
  39. openprocess/flow/boxes/sweeps.py +18 -0
  40. openprocess/flow/convert.py +187 -0
  41. openprocess/flow/datasets.py +198 -0
  42. openprocess/flow/explain.py +115 -0
  43. openprocess/flow/library.py +222 -0
  44. openprocess/flow/record.py +385 -0
  45. openprocess/flow/runner.py +357 -0
  46. openprocess/flow/sweep.py +92 -0
  47. openprocess/flow/types.py +290 -0
  48. openprocess/flow/workflow.py +628 -0
  49. openprocess/gui/__init__.py +0 -0
  50. openprocess/gui/app.py +90 -0
  51. openprocess/gui/arc_editing.py +295 -0
  52. openprocess/gui/canvas.py +1414 -0
  53. openprocess/gui/flow/__init__.py +8 -0
  54. openprocess/gui/flow/canvas.py +854 -0
  55. openprocess/gui/flow/page.py +972 -0
  56. openprocess/gui/flow/templates.py +131 -0
  57. openprocess/gui/flow/viewers.py +665 -0
  58. openprocess/gui/items.py +1275 -0
  59. openprocess/gui/learn/answer_boxes.py +978 -0
  60. openprocess/gui/learn/concealment.py +91 -0
  61. openprocess/gui/learn/mode.py +1181 -0
  62. openprocess/gui/panning.py +241 -0
  63. openprocess/gui/resources/openprocess-icon.png +0 -0
  64. openprocess/gui/studio/__init__.py +1 -0
  65. openprocess/gui/studio/__main__.py +3 -0
  66. openprocess/gui/studio/app.py +4031 -0
  67. openprocess/gui/studio/charts.py +115 -0
  68. openprocess/gui/studio/compare_page.py +487 -0
  69. openprocess/gui/studio/cpn_page.py +1858 -0
  70. openprocess/gui/studio/definition_view.py +284 -0
  71. openprocess/gui/studio/derivation_view.py +421 -0
  72. openprocess/gui/studio/documents.py +152 -0
  73. openprocess/gui/studio/dotted_chart.py +1401 -0
  74. openprocess/gui/studio/file_dialogs.py +143 -0
  75. openprocess/gui/studio/filter_dialog.py +247 -0
  76. openprocess/gui/studio/graph_builders.py +176 -0
  77. openprocess/gui/studio/graph_view.py +682 -0
  78. openprocess/gui/studio/instances.py +413 -0
  79. openprocess/gui/studio/log_editor.py +675 -0
  80. openprocess/gui/studio/log_page.py +800 -0
  81. openprocess/gui/studio/markdown_view.py +127 -0
  82. openprocess/gui/studio/mathtext.py +260 -0
  83. openprocess/gui/studio/ml_highlighter.py +75 -0
  84. openprocess/gui/studio/model_page.py +760 -0
  85. openprocess/gui/studio/net_comparison.py +124 -0
  86. openprocess/gui/studio/notes_overlay.py +275 -0
  87. openprocess/gui/studio/petri_page.py +844 -0
  88. openprocess/gui/studio/regions_view.py +502 -0
  89. openprocess/gui/studio/sidebar.py +149 -0
  90. openprocess/gui/studio/style.py +503 -0
  91. openprocess/gui/studio/tool_icons.py +134 -0
  92. openprocess/gui/studio/updates.py +439 -0
  93. openprocess/gui/studio/widgets.py +899 -0
  94. openprocess/gui/studio/workers.py +60 -0
  95. openprocess/gui/studio/workspace.py +447 -0
  96. openprocess/gui/theme.py +394 -0
  97. openprocess/gui/tidy.py +86 -0
  98. openprocess/io/__init__.py +0 -0
  99. openprocess/io/cpn_reader.py +389 -0
  100. openprocess/io/cpn_writer.py +357 -0
  101. openprocess/learn/__init__.py +23 -0
  102. openprocess/learn/answers.py +188 -0
  103. openprocess/learn/checks.py +953 -0
  104. openprocess/learn/computed.py +1180 -0
  105. openprocess/learn/context.py +145 -0
  106. openprocess/learn/exam.py +169 -0
  107. openprocess/learn/exercise-packs.md +325 -0
  108. openprocess/learn/importer.py +216 -0
  109. openprocess/learn/notation.py +474 -0
  110. openprocess/learn/pack.py +511 -0
  111. openprocess/learn/sheet.py +296 -0
  112. openprocess/mining/__init__.py +73 -0
  113. openprocess/mining/analysis.py +689 -0
  114. openprocess/mining/columns.py +282 -0
  115. openprocess/mining/compare_nets.py +246 -0
  116. openprocess/mining/conformance/__init__.py +0 -0
  117. openprocess/mining/conformance/alignments.py +263 -0
  118. openprocess/mining/conformance/quality.py +145 -0
  119. openprocess/mining/conformance/token_replay.py +252 -0
  120. openprocess/mining/csv_import.py +222 -0
  121. openprocess/mining/definitions.py +584 -0
  122. openprocess/mining/dfg.py +187 -0
  123. openprocess/mining/discovery/__init__.py +0 -0
  124. openprocess/mining/discovery/alpha.py +168 -0
  125. openprocess/mining/discovery/heuristics.py +332 -0
  126. openprocess/mining/discovery/inductive.py +477 -0
  127. openprocess/mining/discovery/state_regions.py +62 -0
  128. openprocess/mining/filtering.py +237 -0
  129. openprocess/mining/footprint.py +183 -0
  130. openprocess/mining/invariants.py +191 -0
  131. openprocess/mining/layout.py +279 -0
  132. openprocess/mining/log.py +364 -0
  133. openprocess/mining/petrinet.py +354 -0
  134. openprocess/mining/playout.py +75 -0
  135. openprocess/mining/pm4py_bridge.py +82 -0
  136. openprocess/mining/pnml.py +223 -0
  137. openprocess/mining/processtree.py +216 -0
  138. openprocess/mining/regions.py +476 -0
  139. openprocess/mining/stats.py +160 -0
  140. openprocess/mining/structure.py +374 -0
  141. openprocess/mining/transition_system.py +409 -0
  142. openprocess/mining/xes.py +399 -0
  143. openprocess/ml/__init__.py +0 -0
  144. openprocess/ml/ast_nodes.py +332 -0
  145. openprocess/ml/builtins.py +364 -0
  146. openprocess/ml/colorsets.py +522 -0
  147. openprocess/ml/errors.py +60 -0
  148. openprocess/ml/evaluator.py +754 -0
  149. openprocess/ml/lexer.py +277 -0
  150. openprocess/ml/multiset.py +417 -0
  151. openprocess/ml/parser.py +737 -0
  152. openprocess/ml/values.py +319 -0
  153. openprocess/model/__init__.py +0 -0
  154. openprocess/model/declarations.py +617 -0
  155. openprocess/model/examples.py +98 -0
  156. openprocess/model/net.py +701 -0
  157. openprocess/model/plain.py +192 -0
  158. openprocess/references.py +280 -0
  159. openprocess/sim/__init__.py +0 -0
  160. openprocess/sim/binding.py +620 -0
  161. openprocess/sim/export.py +66 -0
  162. openprocess/sim/simulator.py +315 -0
  163. openprocess/teaching/__init__.py +4 -0
  164. openprocess/teaching/answers.py +4 -0
  165. openprocess/teaching/checks.py +5 -0
  166. openprocess/teaching/pack.py +4 -0
  167. openprocess/teaching/sheet.py +4 -0
  168. openprocess-0.7.0.dist-info/METADATA +927 -0
  169. openprocess-0.7.0.dist-info/RECORD +173 -0
  170. openprocess-0.7.0.dist-info/WHEEL +5 -0
  171. openprocess-0.7.0.dist-info/entry_points.txt +6 -0
  172. openprocess-0.7.0.dist-info/licenses/LICENSE +21 -0
  173. openprocess-0.7.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,927 @@
1
+ Metadata-Version: 2.4
2
+ Name: openprocess
3
+ Version: 0.7.0
4
+ Summary: Process mining, Petri nets and workflows in one open app: every algorithm visible, every result reproducible, every step teachable
5
+ Author: Sam Struthers
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/s4mstruthers/openprocess
8
+ Project-URL: Changelog, https://github.com/s4mstruthers/openprocess/blob/main/CHANGELOG.md
9
+ Project-URL: Releases, https://github.com/s4mstruthers/openprocess/releases
10
+ Keywords: process mining,petri nets,workflow nets,coloured petri nets,event logs,conformance checking,teaching
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Intended Audience :: Education
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Scientific/Engineering
17
+ Classifier: Topic :: Education
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Provides-Extra: app
22
+ Requires-Dist: PySide6>=6.6; extra == "app"
23
+ Requires-Dist: certifi; extra == "app"
24
+ Provides-Extra: gui
25
+ Requires-Dist: PySide6>=6.6; extra == "gui"
26
+ Requires-Dist: certifi; extra == "gui"
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=8.0; extra == "dev"
29
+ Provides-Extra: science
30
+ Requires-Dist: numpy>=1.24; extra == "science"
31
+ Requires-Dist: pandas>=2.0; extra == "science"
32
+ Requires-Dist: scipy>=1.10; extra == "science"
33
+ Requires-Dist: matplotlib>=3.7; extra == "science"
34
+ Provides-Extra: predict
35
+ Requires-Dist: scikit-learn>=1.3; extra == "predict"
36
+ Provides-Extra: pm4py
37
+ Requires-Dist: pm4py>=2.7; extra == "pm4py"
38
+ Dynamic: license-file
39
+
40
+ <p align="center">
41
+ <img src="docs/logo/openprocess-logo.svg" alt="OpenProcess" width="600">
42
+ </p>
43
+
44
+ <p align="center">
45
+ <b>Process mining, Petri nets and workflows in one open app.</b><br>
46
+ Every algorithm is there to read, every result can be reproduced, every step can be taught.<br>
47
+ Pure Python and Qt. No Java, no Wine, no separate simulator to install.
48
+ </p>
49
+
50
+ <p align="center">
51
+ <a href="https://github.com/s4mstruthers/openprocess/releases/latest"><img alt="Latest release" src="https://img.shields.io/github/v/release/s4mstruthers/openprocess?label=download&color=2563EB"></a>
52
+ <a href="https://pypi.org/project/openprocess/"><img alt="PyPI" src="https://img.shields.io/pypi/v/openprocess?color=2563EB"></a>
53
+ <a href="https://github.com/s4mstruthers/openprocess/actions/workflows/build-apps.yml"><img alt="Tests and builds" src="https://img.shields.io/github/actions/workflow/status/s4mstruthers/openprocess/build-apps.yml?label=tests"></a>
54
+ <a href="LICENSE"><img alt="MIT licence" src="https://img.shields.io/badge/licence-MIT-0F2A6B"></a>
55
+ </p>
56
+
57
+ <p align="center">
58
+ <a href="https://github.com/s4mstruthers/openprocess/releases/latest"><b>⬇ Download for macOS, Windows or Linux</b></a>
59
+ · no Python needed · or <code>pip install openprocess[app]</code> · <a href="#install">install guide</a>
60
+ </p>
61
+
62
+ ![Drawing a WF-net and checking its soundness](docs/screenshots/petri-analysis.png)
63
+
64
+ **OpenProcess Studio** is the workbench; **OpenProcess Learn** is the teaching
65
+ mode built on it. Together they bring under one roof what usually takes several
66
+ tools (and, until version 0.7, went by the name CPNpy):
67
+
68
+ | | What you can do | Instead of |
69
+ |---|---|---|
70
+ | **Petri nets & WF-nets** | Draw nets the way the lectures do. Get a soundness verdict with a counterexample for every violation, and replay it in the token game. Also: behavioural properties, P- and T-invariants, the footprint matrix, the reachability graph, PNML import and export. | WoPeD, ProM, pen and paper |
71
+ | **Process mining** | Import XES or CSV logs, or type textbook logs like `[<a,b,c>^3, <a,c>^2]`. Filter them, explore variants, the dotted chart and the process map. Discover models (α-algorithm, Inductive Miner, Heuristics Miner, state-based regions). Check conformance (token replay, alignments, precision…) and compare logs. | ProM, Disco |
72
+ | **Coloured Petri nets** | Open, edit and save CPN Tools models (`.cpn`), hierarchical ones included. Step through or simulate them, compute the state space, and export a simulation as an event log to mine. | CPN Tools / CPN IDE |
73
+ | **Workflows** | Boxes on a canvas: a log, a miner, a fitness check, a comparison, a sweep over a setting, a prediction pipeline. Click a box to see its result, *how* it got there (the α-algorithm's eight steps, the replay per variant), its code and its settings. Change a setting and only what follows runs again. Saved as a `.cpnflow` file with everything needed to get the same numbers back. Your own algorithm is one Python function in a `boxes/` folder. | RapidProM |
74
+ | **Learn** | A mode of its own for worksheets, built on the app: answer in boxes on the sheet (sets, markings, matrices, cuts and trees, alignments, a net in the editor or a workflow on the canvas beside it) and press **Check**. Most answers are checked automatically, often against answers worked out from the given log or net. Packs are plain Markdown, can be exams with a clock and points, and a past exam imports as a skeleton pack. Demo exercises included. | Answer sheets, a notes app and guesswork |
75
+ | **Folders** | Open a folder such as *Week 2*: every log and net in it is listed in the sidebar, with its subfolders. The folder and the app stay in step both ways: new nets and edits are saved into it as you go, and changes made in Finder show up by themselves. | Finder windows and *File ▸ Open* every time |
76
+
77
+ ---
78
+
79
+ ## Contents
80
+
81
+ - [Install](#install)
82
+ - [Quick start](#quick-start)
83
+ - [Folders: one per week](#folders-one-per-week)
84
+ - [Petri nets and WF-nets](#petri-nets-and-wf-nets)
85
+ - [Process mining](#process-mining)
86
+ - [Learn](#learn)
87
+ - [Coloured Petri nets](#coloured-petri-nets)
88
+ - [Working on the canvas](#working-on-the-canvas)
89
+ - [Keyboard shortcuts](#keyboard-shortcuts)
90
+ - [Files](#files)
91
+ - [For developers](#for-developers)
92
+ - [Workflows](#workflows)
93
+ - [Workflows from Python](#workflows-from-python)
94
+ - [Limitations and roadmap](#limitations-and-roadmap)
95
+
96
+ ---
97
+
98
+ ## Install
99
+
100
+ OpenProcess runs on **macOS, Windows and Linux**. Download the app, or run it from
101
+ source if you want to change the code.
102
+
103
+ ### Download the app
104
+
105
+ No Python needed. Take the file for your system from the
106
+ [latest release](https://github.com/s4mstruthers/openprocess/releases/latest):
107
+
108
+ | System | File | Then |
109
+ |---|---|---|
110
+ | macOS | `OpenProcess-…-macOS-arm64.dmg` (Apple silicon) or `…-macOS-x64.dmg` (Intel) | Open it and drag **OpenProcess** onto **Applications**. |
111
+ | Windows | `OpenProcess-…-Windows-x64.zip` | Unzip it anywhere and start `OpenProcess\OpenProcess.exe`. For a desktop shortcut: right-click `OpenProcess.exe` ▸ *Send to* ▸ *Desktop*. |
112
+ | Linux | `OpenProcess-…-Linux-x64.tar.gz` | `tar xzf OpenProcess-*.tar.gz`, then `./OpenProcess/install-desktop-entry.sh` to add it to the applications menu and the desktop. |
113
+
114
+ The apps are not signed with a paid developer certificate, so the system asks
115
+ once, the first time you start one:
116
+
117
+ - **macOS** says Apple could not check it. Click *Done*, then open *System
118
+ Settings ▸ Privacy & Security* and click *Open Anyway* next to OpenProcess. (Or
119
+ in Terminal: `xattr -dr com.apple.quarantine /Applications/OpenProcess.app`.)
120
+ - **Windows** shows *Windows protected your PC*. Click *More info*, then
121
+ *Run anyway*.
122
+
123
+ Later versions install themselves: the app says when one is out, or ask with
124
+ **Help ▸ Check for Updates…**.
125
+
126
+ ### With pip
127
+
128
+ For a script, a notebook, a box of your own, or CI, OpenProcess is a normal
129
+ Python package with no required dependencies:
130
+
131
+ ```
132
+ pip install openprocess # the engine: process mining, Petri nets, workflows, Learn
133
+ pip install "openprocess[app]" # also the desktop app: then `openprocess studio`
134
+ pip install "openprocess[app,science]" # and the pandas, SciPy and matplotlib boxes
135
+ ```
136
+
137
+ Code written for CPNpy keeps working: `import cpnpy` is `openprocess` under
138
+ its old name (with a one-line warning), so existing boxes and exercise packs
139
+ run unchanged.
140
+
141
+ ### From source
142
+
143
+ You need Python 3.10 or newer, with Qt through PySide6. The easiest way to set
144
+ it up is a **conda** environment called `openprocess`, defined in `environment.yml`.
145
+
146
+ #### 1. Get conda (once)
147
+
148
+ Install [Miniforge](https://github.com/conda-forge/miniforge), a small conda
149
+ that uses the conda-forge packages.
150
+
151
+ | System | How |
152
+ |---|---|
153
+ | macOS | `brew install miniforge`, then `conda init zsh` and open a new terminal. (Or the installer from the Miniforge page.) |
154
+ | Windows | Download and run **Miniforge3-Windows-x86_64.exe** from the Miniforge page. Then use the **Miniforge Prompt** from the Start menu (or run `conda init powershell` once in it to use conda in PowerShell). |
155
+ | Linux | `curl -LO https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh`, then `bash Miniforge3-Linux-x86_64.sh` and open a new terminal. |
156
+
157
+ #### 2. Get the code and create the environment
158
+
159
+ The same commands on every system (Terminal on macOS and Linux, Miniforge
160
+ Prompt or PowerShell on Windows):
161
+
162
+ ```bash
163
+ git clone https://github.com/s4mstruthers/openprocess.git
164
+ cd OpenProcess
165
+ conda env create -f environment.yml # Python 3.12, PySide6, pytest, OpenProcess itself
166
+ conda activate openprocess
167
+ ```
168
+
169
+ No git? Use **Code ▸ Download ZIP** on GitHub, unzip it and `cd` into the
170
+ folder.
171
+
172
+ #### 3. Start the app
173
+
174
+ ```bash
175
+ openprocess-studio
176
+ ```
177
+
178
+ `python -m openprocess.gui.studio` does the same. After pulling changes that touch
179
+ `environment.yml` or `pyproject.toml`, run
180
+ `conda env update -f environment.yml --prune`.
181
+
182
+ <details>
183
+ <summary><b>Without conda</b> (plain Python and pip)</summary>
184
+
185
+ With Python 3.10 or newer from python.org or your package manager, make a
186
+ virtual environment in the project folder:
187
+
188
+ | System | Commands |
189
+ |---|---|
190
+ | macOS / Linux | `python3 -m venv .venv`<br>`source .venv/bin/activate` |
191
+ | Windows (PowerShell) | `py -m venv .venv`<br>`.venv\Scripts\Activate.ps1` |
192
+ | Windows (cmd) | `py -m venv .venv`<br>`.venv\Scripts\activate.bat` |
193
+
194
+ Then, on every system:
195
+
196
+ ```bash
197
+ pip install -e ".[app,dev]"
198
+ openprocess-studio
199
+ ```
200
+
201
+ If PowerShell refuses to run `Activate.ps1`, allow local scripts once with
202
+ `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned`.
203
+ </details>
204
+
205
+ **Linux:** Qt needs a few system libraries that desktop installs usually
206
+ have. If the app does not start and the error mentions the "xcb" platform
207
+ plugin or `libEGL.so.1`, install them, e.g. on Ubuntu/Debian:
208
+ `sudo apt install libxcb-cursor0 libxkbcommon-x11-0 libegl1`.
209
+
210
+ Keyboard shortcuts follow the system: **⌘** on a Mac, **Ctrl** on Windows
211
+ and Linux (see [Keyboard shortcuts](#keyboard-shortcuts)).
212
+
213
+ ---
214
+
215
+ ## Quick start
216
+
217
+ **Work in a folder** (recommended): **File ▸ Open Folder…**
218
+ (⌥⌘O / Ctrl+Alt+O) and pick a folder such as *Week 2*, or drop the folder
219
+ onto the window. See [Folders](#folders-one-per-week).
220
+
221
+ **Check whether a WF-net is sound**
222
+
223
+ 1. **File ▸ New Petri Net** (⌘N / Ctrl+N).
224
+ 2. Pick **Place** and click on the canvas. Type a name and press Return (or
225
+ click elsewhere to keep the suggested name), and the tool switches back to
226
+ Select on its own. Do the same with **Transition**.
227
+ 3. Pick **Arc** and drag from a place to a transition, or the other way
228
+ round. Drag again from the same node to add more arcs.
229
+ 4. Open the **Analysis** tab on the right. It shows whether the net is a
230
+ WF-net, whether it is sound, its behavioural properties and its
231
+ footprint. Everything updates after each edit.
232
+ 5. If it isn't sound, press **Show ▶** next to a finding. The net switches to
233
+ *Step through* and fires the counterexample, so you can see the problem
234
+ marking.
235
+
236
+ To try this without drawing, use **File ▸ Open Example Petri Net ▸ Order
237
+ handling (unsound — try Analysis)**.
238
+
239
+ **Mine a log**
240
+
241
+ 1. **✎ Log from notation…** (⌘L / Ctrl+L) and type `[<a,b,c,d>^3, <a,c,b,d>^2, <a,e,d>]`
242
+ (pasting `[⟨a,b,c,d⟩³, …]` from the book works too), or open a `.xes` /
243
+ `.csv` file.
244
+ 2. Look through the tabs: *Overview*, *Variants*, *Cases*, *Dotted chart*,
245
+ *Process map*, *Footprint*. **Filter…** keeps part of the log as a new
246
+ log.
247
+ 3. On the *Discover* tab, pick an algorithm: the model and how it was
248
+ derived update straight away. **Open as model →** adds the result to the sidebar (under **MODELS**, or
249
+ **UNSAVED** in a folder until you press **Keep** to save it there).
250
+ 4. On the model's *Conformance* tab, choose a log and press **Check
251
+ conformance**.
252
+
253
+ **Simulate a coloured net**
254
+
255
+ **File ▸ Open Coloured Petri Net…** (⇧⌘O / Ctrl+Shift+O), then *Step through* or
256
+ *Simulate*.
257
+
258
+ ---
259
+
260
+ ## Folders: one per week
261
+
262
+ Keep each week's material in a folder (the logs from the course, the nets
263
+ you draw) and open it: **File ▸ Open Folder…** (⌥⌘O / Ctrl+Alt+O), or drag
264
+ the folder onto the window. **The sidebar and the folder always match**:
265
+ what you see in OpenProcess is what is in Finder (or Explorer), and the other way
266
+ round.
267
+
268
+ ![The folder Week 2 in the sidebar, with its subfolders, one net open and the others listed](docs/screenshots/workspace.png)
269
+
270
+ **In the sidebar**
271
+
272
+ - **Every event log and net in the folder** is listed, open or not. Files
273
+ that are not open yet are lighter: **click one to open it**. Closing a file
274
+ (✕ or ⌘W) puts it back in that state; it stays in the folder.
275
+ - **Folders** shows the folder as it is on disk, with collapsible subfolders
276
+ (folders first, then files, by name). **By kind** groups the files into
277
+ event logs, Petri nets and coloured nets instead. The choice, and which
278
+ subfolders are open, is remembered for each folder.
279
+ - **Organise from the app**: right-click for **New Folder…**, **Rename…**,
280
+ **Show in Finder** and **Move to Bin** (recoverable from the Bin; never a
281
+ hard delete). **Drag files onto a subfolder** to move them on disk. An open
282
+ file that is moved or renamed stays open, unsaved edits included. Drag a
283
+ file out of the sidebar to Finder to copy it there.
284
+ - Subfolders are listed up to three levels deep and 500 files (a row says
285
+ so when there are more), with hidden files and tools' folders
286
+ (`__pycache__`, `.git`, …) skipped, as Finder does.
287
+
288
+ **From the app to the folder**
289
+
290
+ - **New nets are files from the start**: *New Petri Net* creates
291
+ `Untitled 1.pnml` (a coloured net, `Untitled 1.cpn`) in the folder. Rename
292
+ the net (double-click its name) and the file is renamed with it.
293
+ - **Edits are saved as you go** (autosave): a second after you stop editing,
294
+ and when you switch to another file or quit. There is no "edited" dot, and
295
+ undo still works. Turn it off with **File ▸ Autosave**. **File ▸ Revert to
296
+ Saved…** goes back to the file as it was when you opened it.
297
+ A `.cpn` model made in CPN Tools is not autosaved (OpenProcess would rewrite it
298
+ in its own writer) until you save it once yourself with ⌘S.
299
+ - **Logs you make are files too**: a log typed in notation is saved as
300
+ `<name>.log.txt` (still in notation), a filtered log as `<log> (filtered).xes` next to the log it
301
+ came from, and a CPN simulation's log as `<model> simulation.xes`.
302
+ - **A discovered model** stays in the **UNSAVED** group until you press
303
+ **Keep**, so trying algorithms does not fill the folder. Keep saves it as
304
+ PNML next to its log.
305
+ - Saving writes a temporary file and then swaps it in, so a crash never
306
+ leaves a half-written file.
307
+
308
+ **From the folder to the app**
309
+
310
+ - Files **added, renamed or deleted in Finder** (or by any other app, a
311
+ `git pull`, iCloud) appear and disappear by themselves, in about half a
312
+ second on macOS.
313
+ - **An open file changed on disk** (a `.xes` exported again from ProM, a
314
+ `.pnml` edited in WoPeD) is **reloaded** by itself. If it also has edits in
315
+ OpenProcess that are not saved yet, a bar above the page asks: *Reload (lose my
316
+ edits)* or *Keep Mine*. OpenProcess's own saves are recognised and never reload.
317
+ - **An open file moved or renamed in Finder**, within the folder, stays open
318
+ and follows the file to its new place, unsaved edits included.
319
+ - **An open file deleted, or moved out of the folder,** stays open, shown in
320
+ italics with a *missing* bar: *Save As…* to keep it. It is not quietly
321
+ recreated.
322
+ - If a net **cannot be saved automatically** (a read-only folder, a full
323
+ disk), a bar says so once and the net is saved with ⌘S again, with its
324
+ "edited" dot, until saving works.
325
+ - A file still being copied in is not read half-way.
326
+ - With iCloud Drive's *Optimise Mac Storage*, files that are only in iCloud
327
+ are listed with a ☁: click one to download and open it.
328
+
329
+ **Files from elsewhere**
330
+
331
+ Opening a file from outside the folder (*File ▸ Open…*, *Open Recent*, or
332
+ dropping it on the window) asks whether to **copy it into the folder** (the
333
+ default: the original stays where it is), **move it in**, or **open it from
334
+ where it is**. Tick *Always do this* to stop asking for that folder, or set
335
+ the default in **Settings**. A file with the same name already in the folder
336
+ is never overwritten silently: *Keep Both* (`Wilma 50 2.xes`) or *Replace*
337
+ (the old one goes to the Bin). Dropping a file onto a subfolder in the
338
+ sidebar puts it there. Files opened where they are appear under **OTHER
339
+ FILES**.
340
+
341
+ **Coming back**
342
+
343
+ - **What you had open comes back** the next time you open the folder, and
344
+ the app reopens the last folder at launch. This is kept in a small hidden
345
+ file, `.openprocess`, in the folder, with paths relative to the folder, so it
346
+ keeps working if you move or sync the folder. Delete it to start fresh.
347
+ - Switch with **File ▸ Open Recent Folder**, the buttons on the welcome
348
+ page, or the **⋯** menu next to the folder's name, which also has *Show in
349
+ Finder*, *New Folder…* and *Close Folder*.
350
+
351
+ Opening a folder closes the files that are not in it (it asks first about
352
+ unsaved changes). Without a folder, the app works with loose files as
353
+ before: nothing is autosaved or created on disk until you save it, and the
354
+ files you had open come back at launch (*File ▸ Reopen Files at Launch*
355
+ turns that off).
356
+
357
+ A tip for the course: one folder per week inside your course folder, e.g.
358
+ `Process Mining/Week 2`, with the week's logs and the nets you make.
359
+
360
+ ---
361
+
362
+ ## Petri nets and WF-nets
363
+
364
+ Nets drawn as in the lectures and the book:
365
+
366
+ - **Places** are circles with black tokens inside, drawn as dots up to 5 and
367
+ as a number above that.
368
+ - **Transitions** are boxes with their name inside. A **silent (τ)**
369
+ transition is a black bar.
370
+ - **Arc weights** above 1 are written on the arc.
371
+ - **Names** go inside the places and transitions, which grow to fit them.
372
+ Tick **Names outside** in the toolbar to put them underneath instead; you
373
+ can then drag each name where you want it. Both are saved in the PNML file.
374
+
375
+ Select anything to edit it in the **Element** tab: a place's name and
376
+ tokens, whether a transition is silent, an arc's weight and direction.
377
+
378
+ **Analysis tab**
379
+
380
+ Every property is defined mathematically in
381
+ [**docs/definitions.md**](docs/definitions.md). In the app, **hover over a
382
+ property** (the ones marked ⓘ) to see its definition *filled in for your
383
+ net* — with your place names, and when it fails, the marking and firing
384
+ sequence that break it. **Click** it to keep the definition open and follow
385
+ links to the definitions it builds on; **Help ▸ Definitions** lists them all.
386
+
387
+ <p align="center"><img src="docs/screenshots/petri-definition.png" alt="The definition of option to complete, filled in for the order-handling net" width="480"></p>
388
+
389
+ - **WF-net:** exactly one source place *i*, one sink place *o*, and every
390
+ node on a path between them.
391
+ - **Soundness:**
392
+ - (i) option to complete;
393
+ - (ii) proper completion;
394
+ - (iii) no dead transitions.
395
+
396
+ Every violation comes with a firing sequence as its counterexample, and
397
+ **Show ▶** plays it on the net.
398
+ - **Short-circuited net N̄:** the net plus a transition *t\** from *o* back
399
+ to *i*. By the soundness theorem, the net is sound iff (N̄, [i]) is **live
400
+ and bounded**; both are shown, with the transition that can't fire again
401
+ and the marking where that happens. Safe and deadlock-free are shown too.
402
+ **Open the short-circuited net** draws it.
403
+ - **Structure:** **free-choice**, **well-structured** (no PT- or TP-handles
404
+ in N̄, with the two paths of a handle spelled out) and **S-coverable**,
405
+ plus the start and end rule: a quick check for transitions that need *i*
406
+ or *o* together with another place.
407
+ - **Invariants:** the **P-invariants** (weighted token counts that never
408
+ change, e.g. `start + c1 + c3 + end = 1`) and the **T-invariants** (of N̄
409
+ for a WF-net), and whether they cover the net. Covered by P-invariants
410
+ means bounded from any marking; a transition in no T-invariant of N̄ proves
411
+ the WF-net unsound. **Incidence matrix…** shows the matrix they come from.
412
+ - **Behavioural properties** of the net as drawn: bounded, safe,
413
+ deadlock-free, dead transitions, live, reversible. A WF-net always stops
414
+ in [o], so that dead marking is marked as expected.
415
+ - **Footprint:** the → ← ‖ # matrix of the net's behaviour, to compare with
416
+ a log's footprint (α-algorithm, footprint conformance).
417
+ - **Reachability graph…**, or a coverability graph with ω when the net is
418
+ unbounded.
419
+ - **Conformance with a log…** opens the net as a model next to your logs,
420
+ for token replay and alignments.
421
+
422
+ | The counterexample, replayed | The footprint of the net |
423
+ |---|---|
424
+ | ![Counterexample in the token game](docs/screenshots/petri-counterexample.png) | ![Footprint of a sound net](docs/screenshots/petri-footprint.png) |
425
+
426
+ **Also on the Petri net page**
427
+
428
+ - **Step through / Simulate:** the token game, fired by hand or at random.
429
+ With **Trace** ticked, every fired transition shows its step numbers and
430
+ the arcs the tokens used light up, the latest step strongest.
431
+ - **Generate event log…:** plays the net out many times and opens the
432
+ traces as a log.
433
+ - **Saving:** nets are saved as **PNML** (ProM, WoPeD and PM4Py read it), or
434
+ as `.cpn`. *Save As* names the net after its file. With a folder open, a
435
+ new net is `Untitled 1.pnml` in the folder from the start and is saved as
436
+ you edit ([Folders](#folders-one-per-week)); without one, it is called
437
+ *Untitled 1* until you save it.
438
+ - **Renaming:** double-click the net's name in the sidebar, or its title
439
+ above the canvas. The file is renamed with it, in the same folder (an
440
+ existing file is never overwritten).
441
+ - **Opening:** a `.pnml` file opens in this editor. A model you discovered
442
+ has **✎ Edit a copy** to bring it here.
443
+
444
+ ![Renaming a transition in place](docs/screenshots/petri-editing.png)
445
+
446
+ ---
447
+
448
+ ## Process mining
449
+
450
+ | Log overview | Dotted chart |
451
+ |---|---|
452
+ | ![Overview](docs/screenshots/studio-overview.png) | ![Dotted chart](docs/screenshots/studio-dotted-chart.png) |
453
+
454
+ - **Logs:**
455
+ - XES, XES.GZ and CSV (you map the columns);
456
+ - the course's notation, e.g. `[<a,b,c,d>^3, <a,e,d>]` (or `⟨a,b⟩³` as
457
+ in the book);
458
+ - XES, CSV and notation export.
459
+ - **Edit…** a log after opening it: as notation (a log you typed comes back
460
+ exactly as you typed it, so you can change it), or case by case — add,
461
+ delete, duplicate and reorder events and cases, edit activities,
462
+ timestamps and resources, rename or remove an activity everywhere. The
463
+ edit is saved to the log's file; XES and CSV logs keep their other
464
+ attributes.
465
+ - **Filter** (as in ProM and Disco): keep cases in a time frame, cases that
466
+ start or end with chosen activities, only the events of chosen activities
467
+ (or the cases that do or do not contain them), cases of a certain length,
468
+ and the most frequent variants. A preview shows what is left; the result
469
+ opens as a new log.
470
+ - **Explore:** overview figures, variants, cases, a ProM-style **dotted
471
+ chart**, a **process map** (directly-follows graph with frequency or
472
+ performance), and the **footprint** matrix.
473
+ - Dotted chart axes: actual time, time since case start, % of case
474
+ duration, or logical order (in the log, or within the case).
475
+ - Time unit (Auto, or seconds up to years) and a grid step you can type in.
476
+ - Colour and shape by any attribute. The default palette can be changed
477
+ per value: right-click a value in the legend and pick its colour.
478
+ - **Discover:**
479
+ - α-algorithm, which shows its eight steps;
480
+ - Inductive Miner and IMf;
481
+ - Heuristics Miner, as a dependency graph or as a Petri net: which forks
482
+ are AND and which XOR is learned from the log (a causal net, whose
483
+ bindings are listed). Like in ProM, such a net fits its log but is not
484
+ always sound;
485
+ - **state-based regions**, two-phase: the log becomes a transition system
486
+ through a state function you choose (the prefix, postfix or both of each
487
+ event; as a set, multiset or sequence; over the last *k* events or all
488
+ of them), and its minimal regions become the places. The derivation
489
+ shows the transition system (pick a trace to light up the states it
490
+ passes through), the regions, GER and minimal pre- and post-regions of
491
+ every event, state separation and forward closure, and whether the
492
+ net's reachability graph is isomorphic to the transition system.
493
+ - **Transition systems** (File ▸ New Transition System…, or a `ts.txt` file):
494
+ type one as `s0 -a-> s1, s0 -b-> s2` and get the same region analysis and
495
+ synthesis. *Is this a region?* answers yes or no for any set of states
496
+ (type it or click the states), and for no names the event and the two
497
+ transitions that cross it differently.
498
+ - **Models:**
499
+ - token game;
500
+ - soundness and properties;
501
+ - reachability graph;
502
+ - PNML / PNG / SVG export.
503
+ - **Conformance:**
504
+ - token-based replay and optimal alignments, both drawn on the model;
505
+ - fitness, precision, generalisation and simplicity;
506
+ - alignments per variant.
507
+ - **Compare logs:** key figures, activity and variant shares, and linked
508
+ dotted charts, side by side.
509
+ - **Compare nets** (File ▸ Compare Nets…): do two nets allow the same
510
+ complete traces? Silent steps are ignored and transitions matched by
511
+ label, so layout and place names do not matter. You get the shortest
512
+ traces that differ, both ways, each replayable in the token game. Exact
513
+ for bounded nets; for unbounded ones, up to a trace length (and it says
514
+ so).
515
+
516
+ | Process map | Discovering a model |
517
+ |---|---|
518
+ | ![Process map](docs/screenshots/studio-process-map.png) | ![Discover](docs/screenshots/studio-discover.png) |
519
+
520
+ | α-algorithm result | Conformance (alignments on the model) |
521
+ |---|---|
522
+ | ![Alpha](docs/screenshots/studio-alpha.png) | ![Conformance](docs/screenshots/studio-conformance.png) |
523
+
524
+ | Comparing two logs | Linked dotted charts of three boarding strategies |
525
+ |---|---|
526
+ | ![Comparing two logs](docs/screenshots/compare.png) | ![Linked dotted charts](docs/screenshots/compare-dotted.png) |
527
+
528
+ The app follows the system's light or dark appearance:
529
+
530
+ ![Dark mode](docs/screenshots/studio-alpha-dark.png)
531
+
532
+ ---
533
+
534
+ ## Learn
535
+
536
+ OpenProcess Learn is the teaching side of the app, built on top of it: exercise
537
+ packs with answer boxes that the app checks. Click an exercise folder in the
538
+ sidebar, **Learn ▸ Open Exercise Pack…**, or **Learn ▸ Open Demo Exercises**
539
+ (it asks where to put a copy, since your answers are saved next to the
540
+ exercises): the window switches to a view made for working through a pack
541
+ without distractions, and *Exit* brings your folder back exactly as it was.
542
+
543
+ - **The worksheet** on the left is the question top to bottom, with an
544
+ answer box wherever one is needed: yes/no, multiple choice, a set
545
+ (`{a, b}`, sets of sets, or pairs like `({a}, {b,d})`), a number, a short
546
+ text, a **footprint matrix**, a **firing sequence** (which you can play in
547
+ the net), a **marking** or a set of markings, the net as **(P, T, F, m₀)**,
548
+ an **incidence matrix** or a **reachability graph**, the Inductive Miner's
549
+ **cuts, sublogs and process tree**, a **replay table** (p, c, m, r), an
550
+ **alignment**, a **ranking** of models, a **prediction** of what an
551
+ algorithm will give, free text, a **net to draw** in the editor beside it,
552
+ or a **workflow to build** on the canvas beside it.
553
+ - **Check** says whether each answer is right — and when it is not, how far
554
+ off it is (“2 of your items are right, 1 is missing”, the wrong cells of a
555
+ matrix, which part of the tuple is off, the shortest traces where your net
556
+ differs, which you can replay) without giving the answer away. Typed
557
+ notations show how they are read as you type. *Hint* and *Show answer* are
558
+ there when you want them.
559
+ - **The materials** on the right are what the exercise gives: the log, the
560
+ transition system, the given net (to play, not change), your own net, and
561
+ the Workflow tab. Results that would give answers away — soundness, the
562
+ footprint, discovered models, regions… — stay hidden until you reveal them.
563
+ - **Notes** (✎ in the top bar) opens scratch paper under the worksheet for
564
+ working things out, kept with the exercise.
565
+ - **Points and exams.** Every answer box is worth points (a partly right
566
+ answer earns a part), and the overview shows the score so far. A pack can
567
+ be an **exam**: a clock in the top bar, no hints or answers, nothing
568
+ revealed, and the answers locked when the time is up. *⋯ ▸ Export Marks…*
569
+ writes the marks as CSV. A pack can also give every student a **variant**
570
+ of its own (a log played out from a net with a seed made from their name).
571
+ - **Your work is saved as you go**, in the exercise's folder:
572
+ `my answers.json`, `my answer.pnml` for a net, `my workflow.cpnflow` for a
573
+ workflow and `my notes.md`.
574
+
575
+ **Writing a pack** (for a course or an exam) is plain Markdown: put an
576
+ `answer` block wherever students should answer.
577
+
578
+ ````
579
+ **b.** Give the start activities $T_I$.
580
+
581
+ ```answer
582
+ type: set
583
+ compute: alpha.T_I
584
+ points: 2
585
+ hint: Which activities does a trace begin with?
586
+ ```
587
+ ````
588
+
589
+ `compute:` works the right answer out from the exercise's own log, net or
590
+ transition system (α-algorithm steps, the Inductive Miner's cuts, soundness
591
+ and its conditions, markings and matrices, replay, regions, fitness… and any
592
+ box of the workflow library: `box(alpha_miner).net.transitions`), so most
593
+ answers need not be written by hand. **Learn ▸ Writing Exercise Packs**
594
+ ([openprocess/learn/exercise-packs.md](openprocess/learn/exercise-packs.md)) lists every
595
+ box type and computed answer. From a terminal, `openprocess exercises check <pack>`
596
+ reports mistakes in a pack before you share it, `openprocess exercises marks <pack>`
597
+ prints the marks, `openprocess exercises computes` lists every compute, and
598
+ `openprocess exercises import exam.txt <pack>` (or **Learn ▸ Make a Pack from an
599
+ Exam…**) turns a past exam's text into a skeleton pack, one exercise per
600
+ question with an answer block per part, for you to finish. Exercises written
601
+ for earlier versions still work: a sheet written in lettered parts (a., b., …)
602
+ gets a box under each part, with that part of `answer.md` as its model answer.
603
+
604
+ The code is `openprocess.learn` (no Qt: the worksheet format, the notations, the
605
+ computed answers and the checks) and `openprocess.gui.learn` (the window).
606
+
607
+ ## Coloured Petri nets
608
+
609
+ A reimplementation of the modelling, simulation and analysis parts of CPN
610
+ Tools / CPN IDE, including their **CPN ML** inscription language: colour
611
+ sets, variables, functions, guards and timed tokens.
612
+
613
+ - **Edit:** places, transitions and arcs, with their inscriptions, guards,
614
+ time delays and declarations (syntax-highlighted). Undo and redo cover
615
+ everything.
616
+ - **Hierarchy:** substitution transitions run their subpages (a port place
617
+ is the socket place it is assigned to), also several levels deep. Select
618
+ a substitution transition and press **Open subpage** to go there.
619
+ - **Step through:** green transitions are enabled. Click one to fire it, or
620
+ pick an exact binding in the inspector. **Back** undoes a step, and
621
+ **Trace** highlights the path so far.
622
+ - **Simulate:** Play (1–60 firings per second) or Fast-forward. The firing
623
+ history can be exported **as an event log** and mined straight away.
624
+ - **State space:** runs in a separate process, so it can be stopped at any
625
+ moment. It reports dead markings, home markings, liveness and bounds.
626
+ - **Rendering:** models look the way CPN Tools and CPN IDE draw them
627
+ (bendpoints, label positions, token bubbles), and they save back to
628
+ `.cpn`.
629
+
630
+ | Stepping through a model | Editing an arc (handles on every bend) |
631
+ |---|---|
632
+ | ![Step through](docs/screenshots/cpn-step-through.png) | ![Arc editing](docs/screenshots/cpn-arc-editing.png) |
633
+
634
+ ![State space](docs/screenshots/cpn-state-space.png)
635
+
636
+ ---
637
+
638
+ ## Working on the canvas
639
+
640
+ Both editors work the same way. Arcs follow the rules of CPN IDE.
641
+
642
+ | To… | Do this |
643
+ |---|---|
644
+ | Add a place / transition | Pick **Place** / **Transition**, click the canvas, type the name, press Return (or just click elsewhere: the name box closes and keeps the name) |
645
+ | Rename | Double-click the place or transition, or use the Element tab |
646
+ | Rename a net or log | Double-click its name in the sidebar or the title above the canvas. A net named after its file (as every opened or saved net is) renames the file too, in the same folder. |
647
+ | Connect | Move the mouse just outside a place or transition and drag the faint arrow that appears onto another node. Or pick **Arc** and drag from one node to another, or click one node, then the other. Joining two places (or two transitions) is refused, with an explanation. Esc cancels. |
648
+ | Grow a net quickly | Drag a node's arrow (or, with **Arc**, drag from a node) out onto empty canvas: a see-through preview shows what letting go will add — a transition after a place, a place after a transition — joined by an arc. It lines up with nodes it is nearly level with (or lands on the grid). Type its name, or click its arrow and keep going. One undo takes the node and its arc away. |
649
+ | Pan | Scroll (two fingers on a trackpad; Shift + wheel goes sideways), drag with the middle mouse button, or hold Space and drag. The canvas goes on in every direction, so there is always room to start a new part beside the net; *Fit* frames the whole net again. If the net is panned right out of view, a button at the top of the canvas points to it and brings it back. |
650
+ | Zoom | ⌘-scroll / Ctrl+scroll or pinch zooms about the pointer; or − % + in the corner |
651
+ | Keep things neat | Tick **Snap to grid** (next to *Names outside*): new and moved places, transitions and arc bends land on the canvas's dots. **Snap All to Grid** neatens a net drawn freely: every place, transition and arc bend moves to the nearest dot, and the layout stays yours. Undo puts it back. |
652
+ | Move things | Drag them. Nodes snap into line with other nodes (dashed guides show it). Drag on empty canvas to select several. |
653
+ | Bend an arc | Press anywhere on the arc and drag: that adds a bend. Drag an existing bend (a small circle) to move it. |
654
+ | Remove a bend | Drag it back into line with its neighbours |
655
+ | Slide a straight segment | Drag the bar in the middle of a horizontal or vertical segment |
656
+ | Reconnect an arc | Drag one of its ends onto another node |
657
+ | Move a label | Drag it (names can be dragged once **Names outside** is ticked) |
658
+ | Delete | Select, then Delete or Backspace (⌫) |
659
+ | Undo / redo | ⌘Z / ⇧⌘Z (Ctrl+Z / Ctrl+Shift+Z), or ↶ ↷ |
660
+
661
+ The tool buttons have icons, and the mouse cursor over the canvas shows the
662
+ active tool: a plain pointer for Select, a crosshair with a circle, square
663
+ or arrow for the others.
664
+
665
+ ---
666
+
667
+ ## Keyboard shortcuts
668
+
669
+ The app shows each shortcut the way your system writes it.
670
+
671
+ | Action | macOS | Windows / Linux |
672
+ |---|---|---|
673
+ | New Petri net | ⌘N | Ctrl+N |
674
+ | New coloured Petri net | ⇧⌘N | Ctrl+Shift+N |
675
+ | Open… | ⌘O | Ctrl+O |
676
+ | Open folder… | ⌥⌘O | Ctrl+Alt+O |
677
+ | Open coloured Petri net… | ⇧⌘O | Ctrl+Shift+O |
678
+ | Log from notation… | ⌘L | Ctrl+L |
679
+ | Compare logs… | ⇧⌘C | Ctrl+Shift+C |
680
+ | Save / Save As | ⌘S / ⇧⌘S | Ctrl+S / Ctrl+Shift+S |
681
+ | Undo / Redo | ⌘Z / ⇧⌘Z | Ctrl+Z / Ctrl+Shift+Z (or Ctrl+Y) |
682
+ | Delete selection | ⌫ | Delete or Backspace |
683
+ | Step (fire one random enabled transition) | ⌘. | Ctrl+. |
684
+ | Zoom in / out / fit / 100 % | ⌘+ / ⌘− / ⌘0 / ⌥⌘0 | Ctrl++ / Ctrl+− / Ctrl+0 / Ctrl+Alt+0 |
685
+ | Zoom with the mouse | ⌘-scroll or pinch | Ctrl+scroll or pinch |
686
+ | Pan | scroll, middle-drag, or Space + drag | scroll, middle-drag, or Space + drag |
687
+ | Toggle sidebar | ⌥⌘S | Ctrl+Alt+S |
688
+ | Settings… | ⌘, | Ctrl+, |
689
+ | Welcome page | ⌘1 | Ctrl+1 |
690
+ | Export selected… | ⌘E | Ctrl+E |
691
+ | Close / close all | ⌘W / ⇧⌘W | Ctrl+W / Ctrl+Shift+W |
692
+ | Cancel drawing an arc | Esc | Esc |
693
+
694
+ ---
695
+
696
+ ## Files
697
+
698
+ | Format | Read | Write |
699
+ |---|---|---|
700
+ | Event logs: `.xes`, `.xes.gz`, `.csv` | ✓ | `.xes`, `.xes.gz`, `.csv` |
701
+ | Logs in textbook notation: `log.txt`, `*.log.txt` | ✓ | |
702
+ | Transition systems: `ts.txt`, `*.ts.txt` (`s0 -a-> s1`) | ✓ | ✓ |
703
+ | Petri nets: `.pnml` (with positions, weights, τ, arc bends) | ✓ | ✓ |
704
+ | CPN Tools models: `.cpn` | ✓ | ✓ |
705
+ | Pictures of nets and charts | | `.png`, `.svg` |
706
+ | Folder state: `.openprocess` (hidden, in the folder) | ✓ | ✓ |
707
+
708
+ Example files: `examples/petri/*.pnml` (Petri nets), `examples/*.cpn`
709
+ (coloured nets) and `tests/data/` (a plane-boarding model and log from the
710
+ course).
711
+
712
+ ---
713
+
714
+ ## For developers
715
+
716
+ ```bash
717
+ pytest -q # the whole suite, including GUI tests that run offscreen
718
+ openprocess --help # command line: check, simulate, state space, mining
719
+ ```
720
+
721
+ The same commands work on macOS, Windows and Linux. `openprocess mine` covers the
722
+ process mining side: `stats`, `filter`, `discover` (α, IM, IMf, heuristics),
723
+ `conform`, `soundness` and `invariants`; `openprocess exercises check`, `marks`,
724
+ `import` and `computes` serve exercise packs. `docs/definitions.md` is
725
+ generated from `openprocess/mining/definitions.py`; after editing a definition, run
726
+ `python -m openprocess.mining.definitions > docs/definitions.md` (a test checks it).
727
+ Likewise [`docs/references.md`](docs/references.md) — every source OpenProcess's
728
+ notation and algorithms follow, also in the app under **Help ▸ References** —
729
+ is generated from `openprocess/references.py` with
730
+ `python -m openprocess.references > docs/references.md`.
731
+
732
+ The engines (`openprocess.mining`, `openprocess.ml`, `openprocess.sim`, `openprocess.analysis`)
733
+ have **no dependencies**, so they work in a notebook or a script:
734
+
735
+ ```python
736
+ from openprocess.mining import read_xes, inductive_miner
737
+ from openprocess.mining.analysis import check_soundness
738
+
739
+ net = inductive_miner(read_xes("log.xes").simple_log()).net
740
+ report = check_soundness(net)
741
+ print(report.sound, report.findings)
742
+ ```
743
+
744
+ [**docs/how-it-works.md**](docs/how-it-works.md) covers the architecture, the
745
+ CPN ML subset, binding search, timed nets, the state space, the file format
746
+ and the project layout.
747
+
748
+ ## Workflows
749
+
750
+ **File ▸ New Workflow** opens a workflow that already runs on the first log of
751
+ your folder (or a typed log): *Discover and check* (a log, the Inductive
752
+ Miner, a fitness check), *Compare discovery* (three miners side by side),
753
+ *Noise sweep* (one setting over a range, the scores stacked), *Fitness with
754
+ confidence* (bootstrap intervals, a test and a plot; needs the `science`
755
+ extra) and *Predict the next activity*. Or start empty.
756
+
757
+ - **Boxes** are listed on the left in groups (Input, Filter, Discover, Check,
758
+ Compare, Output, Science, Predict, Coloured nets, Sweep, Yours) with a
759
+ search field. Click one to add it, or double-click the canvas.
760
+ - **Connect** by dragging from the dot on the right of a box: while you drag,
761
+ only the inputs that take that kind of result light up, so a wrong
762
+ connection cannot be made. Click a wire and press Delete to remove it.
763
+ - **Click a box** for the side panel: **Result** (the net, the log's figures,
764
+ the table, the figure), **How** (what the box reported: notes, intermediate
765
+ values, the derivation), **Code** (the box's few lines and, under them, the
766
+ actual algorithm it calls: the α-algorithm's eight steps, the Inductive
767
+ Miner's cuts, with the work each follows and *Whole file* for the module)
768
+ and **Settings** (a control per setting; *Sweep* a number over a range).
769
+ **⤢** opens the tab in a window of its own.
770
+ - **Only what changed runs again.** Every box shows a status dot: waiting,
771
+ running, done, failed (the error is on the Result tab; the rest keeps
772
+ working), or waiting for your OK.
773
+ - **Record** shows the workflow as Python and the file with its record;
774
+ **Re-run** says what changed since it was saved (an input file, a box file,
775
+ a seed) before running everything again.
776
+ - **Your own boxes**: a `.py` file in the folder's `boxes/` subfolder (see
777
+ below). The app asks once per folder before running them, and reloads a
778
+ box when its file is saved.
779
+ - **Groups**: select boxes and press ⌘G to make one box of them, with the
780
+ connections that reach outside; double-click it to open its own canvas,
781
+ ⇧⌘G to ungroup. *Save as a box* in the side panel writes the group to
782
+ `boxes/`, so it is listed under *Yours* and can be used in any workflow.
783
+ - **From a page**: *As a workflow* on a log's Discover tab or a model page,
784
+ and *Use in a workflow* on the net canvas, open a workflow with that file
785
+ as its source.
786
+ - **Export experiment** writes a zip with the workflow file and its record,
787
+ the inputs, your boxes, every result as a file (CSV, PNML, SVG, XES), a
788
+ `requirements.lock` and a README that says what was run: supplementary
789
+ material for a paper, which `openprocess run --check` can verify.
790
+ - **The three panels** (box list, canvas, side panel) resize by dragging the
791
+ gaps, hide with *⇤ Boxes* / *Panel ⇥* or the View menu, and come back with
792
+ *View ▸ Reset Workflow Layout*.
793
+
794
+ ## Workflows from Python
795
+
796
+ Every algorithm is also a **box**: a Python function with type hints that
797
+ the app (from 0.7) draws on a canvas. A workflow of boxes runs from Python
798
+ or from the command line, and its `.cpnflow` file records what is needed
799
+ to get the same numbers again: fingerprints of the input files and of the
800
+ box code, every seed, and the installed packages.
801
+
802
+ ```python
803
+ from openprocess.flow import Workflow, Runner, save
804
+ from openprocess.flow.boxes.input import open_log
805
+ from openprocess.flow.boxes.discover import inductive_miner
806
+ from openprocess.flow.boxes.check import check_fit
807
+
808
+ wf = Workflow("orders")
809
+ log = wf.add(open_log, {"file": "orders.xes"})
810
+ model = wf.add(inductive_miner, {"noise": 0.2})
811
+ fit = wf.add(check_fit)
812
+ wf.connect(log, model); wf.connect(model, fit, "model"); wf.connect(log, fit, "log")
813
+ run = Runner().run(wf)
814
+ print(run.value(fit).metrics) # fitness, precision, generalisation, simplicity
815
+ print(run.result(model).explanation.steps) # how the Inductive Miner got there
816
+ save(wf, "orders.cpnflow", run)
817
+ ```
818
+
819
+ ```bash
820
+ openprocess run orders.cpnflow --check # re-run; fails if any result differs from the record
821
+ openprocess run orders.cpnflow --sweep noise=0..0.5 step 0.1
822
+ openprocess boxes # the 47 boxes, with a folder's boxes/
823
+ openprocess datasets list # the BPI Challenge, Sepsis, ... logs by name
824
+ ```
825
+
826
+ A box of your own is one function in a `boxes/` folder:
827
+
828
+ ```python
829
+ from openprocess.flow import box, EventLog, TransitionSystem
830
+
831
+ @box(group="Discover")
832
+ def last_two(log: EventLog, representation: str = "multiset") -> TransitionSystem:
833
+ """The last two activities as the state."""
834
+ ...
835
+ ```
836
+
837
+ `pip install -e ".[science]"` adds the pandas, NumPy, SciPy and matplotlib
838
+ boxes (describe, bootstrap intervals, tests, plots). Large logs are read
839
+ into columns rather than objects, so a million events fit in memory.
840
+ [**docs/workflows.md**](docs/workflows.md) has the whole framework: writing
841
+ a box, the types, the *How* tab, sweeps, the prediction pipeline, the
842
+ record and running in CI.
843
+
844
+ **Building the apps.** `packaging/` turns OpenProcess into a standalone app with
845
+ PyInstaller. In the environment:
846
+
847
+ ```bash
848
+ pip install pyinstaller
849
+ python packaging/build.py # → dist/OpenProcess.app or dist/OpenProcess/, plus a .dmg / .zip / .tar.gz
850
+ ```
851
+
852
+ The script also smoke-tests the result. Each system can only build its own
853
+ app, so the [Build apps](.github/workflows/build-apps.yml) workflow builds all
854
+ of them on GitHub: for every pull request (after the test suite passes; not
855
+ for documentation-only changes) and for every release tag. Download them from
856
+ the run's page, under *Artifacts*, or start a build by hand with *Run
857
+ workflow* on the Actions tab.
858
+
859
+ **Publishing a release:**
860
+
861
+ 1. Add a section for the new version at the top of
862
+ [CHANGELOG.md](CHANGELOG.md) (`## 0.4.0`, then a few bullet points). Write
863
+ it for the people using the app: it becomes the text of the release on
864
+ GitHub, and the app shows it when it offers the update.
865
+ 2. Set `__version__` in `openprocess/__init__.py` to the same version and merge
866
+ both into `main`. It is the only place the version is written:
867
+ `pyproject.toml`, the download names and the app's update check all read
868
+ it from there.
869
+ 3. Tag that commit with the same version and push the tag:
870
+
871
+ ```bash
872
+ git pull
873
+ git tag v0.4.0
874
+ git push origin v0.4.0
875
+ ```
876
+
877
+ About five minutes later the
878
+ [Releases page](https://github.com/s4mstruthers/openprocess/releases) has the
879
+ macOS (Apple silicon and Intel), Windows and Linux apps. The build refuses a
880
+ tag that does not match `__version__`, or a version with no section in
881
+ `CHANGELOG.md`.
882
+
883
+ **Updates.** Each time it opens, the app checks the latest release on GitHub
884
+ (*Settings* turns that off). If there is a newer version, a slim bar at the
885
+ top of the window says so, without getting in the way: **What's New** shows
886
+ the changelog of every version you don't have yet, **Install Now** installs
887
+ it, **Skip This Version** stays quiet until the next one, and **✕** closes the
888
+ bar until next time. **Help ▸ Check for Updates…** checks straight away.
889
+ Installing downloads the file for the system, checks it against the SHA-256
890
+ GitHub lists for it, unpacks it next to the app, and restarts into the new
891
+ version (the old one is kept until the new one is in place).
892
+
893
+ Run from source (a git clone), the app never changes itself: the bar's
894
+ button says **How to Update** and explains `git pull`. It only appears when
895
+ the clone is older than the latest release. See
896
+ `openprocess/gui/studio/updates.py`.
897
+
898
+ ---
899
+
900
+ ## Limitations and roadmap
901
+
902
+ Plainly stated:
903
+
904
+ 1. **A subpage used by several substitution transitions** (one module,
905
+ several instances) is reported as a problem rather than simulated: give
906
+ each use its own copy of the page. Subpages used once, at any depth,
907
+ simulate.
908
+ 2. **No CPN monitors or simulation reports**, and **no fairness
909
+ properties** in the state space report (it says so).
910
+ 3. **CPN ML is a large subset, not all of Standard ML**: no `exception`
911
+ declarations or `handle`, no `datatype` or `structure` declarations, and
912
+ characters are one-letter strings. See
913
+ [docs/how-it-works.md](docs/how-it-works.md#the-cpn-ml-subset).
914
+ 4. **Alignments are exact but unoptimised**: they can take seconds on
915
+ heavily concurrent models. They run in the background.
916
+ 5. **Plain Petri nets live on one page.**
917
+ 6. **Regions are found exhaustively**, so only for transition systems of up
918
+ to 26 states (the result says when this limit is hit), and label
919
+ splitting for transition systems that are not elementary is not
920
+ suggested yet. Transition systems are typed, not drawn.
921
+
922
+ Next up: several instances of a subpage, CPN monitors, and signed apps that
923
+ open without a security prompt.
924
+
925
+ ## Licence
926
+
927
+ MIT. See [LICENSE](LICENSE).