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,296 @@
1
+ """An exercise as a worksheet: its question text with answer boxes in it.
2
+
3
+ An exercise is a folder with a ``question.md``. The question is ordinary
4
+ Markdown (with ``$…$`` maths); wherever the student should answer, the
5
+ author puts an *answer block*, a fenced code block marked ``answer``::
6
+
7
+ a. Give the start activities $T_I$.
8
+
9
+ ```answer
10
+ type: set
11
+ compute: alpha.T_I
12
+ hint: Which activities does a trace begin with?
13
+ ```
14
+
15
+ The text between two answer blocks is the question for the second one, so
16
+ the sheet reads top to bottom like the paper version. Inside a block:
17
+
18
+ * ``key: value`` lines (keys are listed in :data:`KEYS`);
19
+ * lines that start with spaces continue the value above them (for a
20
+ ``solution`` of several lines);
21
+ * ``- [x] option`` / ``- [ ] option`` lines are the options of a choice
22
+ (``[x]`` marks the right ones); ``- text`` lines are further accepted
23
+ answers of a ``text`` question.
24
+
25
+ A sheet may start with *front matter* between two ``---`` lines: settings of
26
+ the whole exercise (``points``, ``seed``, ``generate``, ``boxes``), read by
27
+ :mod:`.pack`.
28
+
29
+ The full reference, with every type and what each checks, is
30
+ ``openprocess/learn/exercise-packs.md`` (*Help ▸ Writing Exercise Packs*).
31
+ """
32
+
33
+ from __future__ import annotations
34
+
35
+ import re
36
+ from dataclasses import dataclass, field
37
+ from pathlib import Path
38
+
39
+ #: The kinds of answer box, and what each one is.
40
+ TYPES = {
41
+ "net": "draw or change a Petri net in the editor beside the question",
42
+ "footprint": "fill in a footprint matrix (→ ← ‖ #)",
43
+ "yesno": "answer yes or no",
44
+ "choice": "pick one option (or several, if more than one is right)",
45
+ "set": "write a set, e.g. {a, b} — or a set of sets or of pairs",
46
+ "trace": "write a firing sequence, e.g. ⟨register, send letter⟩",
47
+ "number": "write a number",
48
+ "text": "write a short answer",
49
+ "open": "write freely; compare with the model answer yourself",
50
+ "marking": "write a marking, e.g. [p1, p4^2]",
51
+ "markings": "write a set of markings, e.g. [p1], [p2, p3]",
52
+ "tuple": "write a net as (P, T, F, m0): four boxes",
53
+ "ts": "write a transition system: s0 -a-> s1 lines",
54
+ "matrix": "fill in a matrix with row and column headers",
55
+ "cut": "write a cut of the Inductive Miner, e.g. → {a} {b, c} {d}",
56
+ "log": "write a log in the course's notation, e.g. [<a, b>^2, <a, c>]",
57
+ "tree": "write a process tree, e.g. →(a, ×(b, c), d)",
58
+ "replay": "fill in produced, consumed, missing and remaining tokens per trace",
59
+ "alignment": "write an alignment as two rows of moves (≫ for no move)",
60
+ "ranking": "put the named models in order",
61
+ "predict": "predict a box's result before running it",
62
+ "workflow": "build a workflow in the Workflow tab",
63
+ }
64
+
65
+ #: Types whose editor is a text field with a notation (one line or several).
66
+ TEXT_TYPES = {"marking", "markings", "ts", "cut", "log", "tree", "alignment"}
67
+
68
+ #: Every key an answer block may use.
69
+ KEYS = {"type", "id", "answer", "compute", "hint", "solution", "start", "net", "log", "of",
70
+ "sound", "fits", "ends", "tolerance", "title", "labels", "pattern",
71
+ # the new blocks
72
+ "points", "pairs", "exact", "unseen", "trace", "alignment", "over", "by", "order",
73
+ "box", "value", "as", "settings", "needs", "result", "rows", "columns", "chart", "ts",
74
+ "material"}
75
+
76
+ #: Keys the front matter of a sheet may use.
77
+ FRONT_KEYS = {"points", "seed", "generate", "boxes", "title", "time"}
78
+
79
+ _FENCE = re.compile(r"^(```+|~~~+)\s*answer\s*$", re.I)
80
+ _OPTION = re.compile(r"^-\s*\[( |x|X)\]\s*(.+)$")
81
+ _ITEM = re.compile(r"^-\s+(.+)$")
82
+ _KEY = re.compile(r"^([A-Za-z_]+)\s*:\s?(.*)$")
83
+ #: "start: net.pnml # a comment" -- at least two spaces before the #, because
84
+ #: "a # b" is the α-algorithm's choice relation, often written in an answer.
85
+ _COMMENT = re.compile(r"\s{2,}#\s.*$")
86
+
87
+
88
+ class SheetError(ValueError):
89
+ """A mistake in an answer block, with the line it is on."""
90
+
91
+
92
+ @dataclass
93
+ class Option:
94
+ text: str
95
+ correct: bool
96
+
97
+
98
+ @dataclass
99
+ class Task:
100
+ """One answer box."""
101
+
102
+ type: str
103
+ id: str
104
+ #: The question text just above the box (Markdown).
105
+ prompt: str = ""
106
+ #: Everything the block says, by key (values as written).
107
+ settings: dict[str, str] = field(default_factory=dict)
108
+ options: list[Option] = field(default_factory=list)
109
+ #: ``- text`` lines: more accepted answers (``text``).
110
+ alternatives: list[str] = field(default_factory=list)
111
+ #: The line in question.md where the block starts (for error messages).
112
+ line: int = 0
113
+
114
+ def get(self, key: str, default: str | None = None) -> str | None:
115
+ return self.settings.get(key, default)
116
+
117
+ @property
118
+ def hint(self) -> str | None:
119
+ return self.settings.get("hint")
120
+
121
+ @property
122
+ def solution(self) -> str | None:
123
+ return self.settings.get("solution")
124
+
125
+ @property
126
+ def points(self) -> float:
127
+ """What a right answer earns (``points:``; 1 when the block says nothing)."""
128
+ try:
129
+ return float(self.settings.get("points", "") or 1)
130
+ except ValueError:
131
+ return 1.0
132
+
133
+ @property
134
+ def checkable(self) -> bool:
135
+ """Can the app say whether the answer is right?"""
136
+ if self.type == "open":
137
+ return False
138
+ if self.type == "choice":
139
+ return any(o.correct for o in self.options) or "compute" in self.settings
140
+ if self.type in ("set", "number", "yesno", "marking", "markings", "ts", "matrix", "cut",
141
+ "log", "tree", "replay"):
142
+ return "answer" in self.settings or "compute" in self.settings
143
+ if self.type == "text":
144
+ return "answer" in self.settings or bool(self.alternatives) or \
145
+ "pattern" in self.settings or "compute" in self.settings
146
+ if self.type == "net":
147
+ return any(k in self.settings for k in ("answer", "sound", "fits", "compute"))
148
+ if self.type == "ranking":
149
+ return "over" in self.settings
150
+ if self.type == "predict":
151
+ return "box" in self.settings
152
+ if self.type == "workflow":
153
+ return "needs" in self.settings or "result" in self.settings
154
+ return True # footprint, trace, tuple, alignment
155
+
156
+
157
+ @dataclass
158
+ class Sheet:
159
+ """The question as blocks: Markdown strings and :class:`Task` objects, in order."""
160
+
161
+ title: str
162
+ blocks: list = field(default_factory=list)
163
+ #: The front matter: settings of the whole exercise.
164
+ settings: dict[str, str] = field(default_factory=dict)
165
+
166
+ @property
167
+ def tasks(self) -> list[Task]:
168
+ return [block for block in self.blocks if isinstance(block, Task)]
169
+
170
+ @property
171
+ def points(self) -> float:
172
+ return sum(t.points for t in self.tasks)
173
+
174
+
175
+ def _parse_block(lines: list[str], start_line: int, index: int, prompt: str) -> Task:
176
+ settings: dict[str, str] = {}
177
+ options: list[Option] = []
178
+ alternatives: list[str] = []
179
+ current: str | None = None
180
+ for offset, raw in enumerate(lines):
181
+ number = start_line + offset + 1
182
+ if not raw.strip():
183
+ if current is not None:
184
+ settings[current] += "\n"
185
+ continue
186
+ if raw[0] in " \t" and current is not None:
187
+ settings[current] += ("\n" if settings[current] else "") + raw.strip()
188
+ continue
189
+ line = raw.strip()
190
+ option = _OPTION.match(line)
191
+ if option:
192
+ options.append(Option(option.group(2).strip(), option.group(1) != " "))
193
+ current = None
194
+ continue
195
+ item = _ITEM.match(line)
196
+ if item:
197
+ alternatives.append(item.group(1).strip())
198
+ current = None
199
+ continue
200
+ key = _KEY.match(line)
201
+ if not key:
202
+ raise SheetError(f"line {number}: expected “key: value”, found “{line}”")
203
+ name = key.group(1).lower()
204
+ if name not in KEYS:
205
+ raise SheetError(f"line {number}: unknown key “{name}” (known: "
206
+ + ", ".join(sorted(KEYS)) + ")")
207
+ # "start: net.pnml # a comment": the comment goes.
208
+ settings[name] = _COMMENT.sub("", key.group(2)).strip()
209
+ current = name
210
+ settings = {k: v.strip() for k, v in settings.items()}
211
+ kind = settings.get("type", "").lower()
212
+ if not kind:
213
+ kind = "choice" if options else "text" if alternatives else ""
214
+ if kind not in TYPES:
215
+ raise SheetError(f"line {start_line}: answer block needs a type, one of "
216
+ + ", ".join(TYPES) + (f" (found “{kind}”)" if kind else ""))
217
+ if kind == "choice" and not options:
218
+ raise SheetError(f"line {start_line}: a choice needs options, written as "
219
+ "“- [x] right” and “- [ ] wrong”")
220
+ task_id = settings.get("id") or f"q{index}"
221
+ return Task(kind, task_id, prompt.strip(), settings, options, alternatives, start_line)
222
+
223
+
224
+ def parse_front_matter(text: str) -> tuple[dict[str, str], str]:
225
+ """``---`` lines at the top with ``key: value`` settings, and the rest."""
226
+ lines = text.splitlines()
227
+ if not lines or lines[0].strip() != "---":
228
+ return {}, text
229
+ settings: dict[str, str] = {}
230
+ for number, line in enumerate(lines[1:], 2):
231
+ if line.strip() == "---":
232
+ return settings, "\n".join(lines[number:])
233
+ if not line.strip():
234
+ continue
235
+ key = _KEY.match(line.strip())
236
+ if not key:
237
+ raise SheetError(f"line {number}: expected “key: value” in the front matter")
238
+ settings[key.group(1).lower()] = key.group(2).strip()
239
+ raise SheetError("the front matter is not closed (add a line ---)")
240
+
241
+
242
+ def parse_sheet(text: str, title: str = "") -> Sheet:
243
+ """Split question.md into Markdown and answer blocks."""
244
+ settings, text = parse_front_matter(text)
245
+ lines = text.splitlines()
246
+ blocks: list = []
247
+ markdown: list[str] = []
248
+ index = 0
249
+ position = 0
250
+ heading = title
251
+ while position < len(lines):
252
+ line = lines[position]
253
+ fence = _FENCE.match(line.strip())
254
+ if fence:
255
+ end = position + 1
256
+ while end < len(lines) and not lines[end].strip().startswith(fence.group(1)):
257
+ end += 1
258
+ if end >= len(lines):
259
+ raise SheetError(f"line {position + 1}: the answer block is not closed "
260
+ f"(add a line {fence.group(1)})")
261
+ index += 1
262
+ # The prompt is the text since the previous block (or heading).
263
+ prompt = "\n".join(markdown)
264
+ if prompt.strip():
265
+ blocks.append(prompt)
266
+ task = _parse_block(lines[position + 1:end], position + 1, index,
267
+ _last_paragraphs(prompt))
268
+ blocks.append(task)
269
+ markdown = []
270
+ position = end + 1
271
+ continue
272
+ if not heading and line.startswith("# "):
273
+ heading = line[2:].strip()
274
+ position += 1
275
+ continue
276
+ markdown.append(line)
277
+ position += 1
278
+ if "\n".join(markdown).strip():
279
+ blocks.append("\n".join(markdown))
280
+ ids = [t.id for t in blocks if isinstance(t, Task)]
281
+ duplicates = sorted({i for i in ids if ids.count(i) > 1})
282
+ if duplicates:
283
+ raise SheetError("two answer blocks have the same id: " + ", ".join(duplicates))
284
+ sheet = Sheet(heading or settings.get("title") or "Exercise", blocks, settings)
285
+ return sheet
286
+
287
+
288
+ def _last_paragraphs(markdown: str) -> str:
289
+ """The part of the text that asks the question (for listings and the CLI)."""
290
+ paragraphs = [p.strip() for p in re.split(r"\n\s*\n", markdown) if p.strip()]
291
+ return paragraphs[-1] if paragraphs else ""
292
+
293
+
294
+ def read_sheet(path: str | Path) -> Sheet:
295
+ path = Path(path)
296
+ return parse_sheet(path.read_text(encoding="utf-8", errors="replace"))
@@ -0,0 +1,73 @@
1
+ """Process mining: event logs, discovery, conformance checking.
2
+
3
+ This package is the "ProM half" of the application. Like the CPN engine it
4
+ is pure standard-library Python: every algorithm is implemented here, with
5
+ the textbook definitions in the docstrings, so the code doubles as a study
6
+ companion for the course.
7
+
8
+ Quick start::
9
+
10
+ from openprocess.mining import read_xes, inductive_miner, align_log, precision
11
+
12
+ log = read_xes("PlaneBoarding.xes")
13
+ simple = log.simple_log() # multiset of activity sequences
14
+ model = inductive_miner(simple).net # a sound WF-net
15
+ fitness = align_log(model, simple).average_fitness
16
+ print(fitness, precision(model, simple))
17
+
18
+ Modules
19
+ -------
20
+ ``log``, ``xes``, ``csv_import``, ``stats``
21
+ Event logs: data model, file formats, descriptive statistics.
22
+ ``dfg``, ``footprint``
23
+ Directly-follows graphs and the ordering relations / footprint matrix.
24
+ ``petrinet``, ``pnml``, ``analysis``, ``processtree``
25
+ Labelled P/T nets, PNML, state spaces, properties, WF-net soundness,
26
+ process trees.
27
+ ``discovery``
28
+ α-algorithm, Heuristics Miner (dependency graph), Inductive Miner (IM/IMf),
29
+ state-based regions.
30
+ ``transition_system``, ``regions``
31
+ Transition systems from logs, regions, elementary checks, net synthesis.
32
+ ``compare_nets``
33
+ Do two nets allow the same complete traces?
34
+ ``conformance``
35
+ Token-based replay, alignments, precision, generalisation, simplicity.
36
+ ``layout``
37
+ Automatic layered graph layout for drawing discovered models.
38
+ """
39
+
40
+ from .analysis import (analyse, check_soundness, check_workflow_net, coverability_graph,
41
+ reachability_graph)
42
+ from .conformance.alignments import align_log, align_trace
43
+ from .conformance.quality import generalisation, precision, simplicity
44
+ from .conformance.token_replay import token_replay
45
+ from .compare_nets import compare_nets
46
+ from .csv_import import read_csv
47
+ from .dfg import discover_dfg
48
+ from .discovery.alpha import alpha_miner
49
+ from .discovery.heuristics import heuristics_miner
50
+ from .discovery.inductive import inductive_miner
51
+ from .discovery.state_regions import region_miner
52
+ from .footprint import compare_footprints, footprint_of_log, footprint_of_net
53
+ from .log import (BY_NAME, BY_NAME_COMPLETE, BY_NAME_LIFECYCLE, Classifier, Event, EventLog,
54
+ Trace, format_simple_log, parse_simple_log)
55
+ from .petrinet import Marking, PetriNet
56
+ from .pnml import read_pnml, write_pnml
57
+ from .processtree import Operator, ProcessTree, to_petri_net
58
+ from .regions import analyse_regions, check_region, synthesise
59
+ from .transition_system import (TransitionSystem, parse_transition_system,
60
+ transition_system_from_log)
61
+ from .stats import summarise
62
+ from .xes import read_xes, write_xes
63
+
64
+ __all__ = [
65
+ "BY_NAME", "BY_NAME_COMPLETE", "BY_NAME_LIFECYCLE", "Classifier", "Event", "EventLog",
66
+ "Marking", "Operator", "PetriNet", "ProcessTree", "Trace", "TransitionSystem",
67
+ "align_log", "align_trace", "alpha_miner", "analyse", "analyse_regions", "check_region",
68
+ "check_soundness", "check_workflow_net", "compare_footprints", "compare_nets", "coverability_graph", "discover_dfg",
69
+ "footprint_of_log", "footprint_of_net", "format_simple_log", "generalisation",
70
+ "heuristics_miner", "inductive_miner", "parse_simple_log", "parse_transition_system", "precision",
71
+ "reachability_graph", "read_csv", "read_pnml", "read_xes", "region_miner", "simplicity", "summarise",
72
+ "synthesise", "to_petri_net", "token_replay", "transition_system_from_log", "write_pnml", "write_xes",
73
+ ]