ptnet_core/lib.rs
1/*!
2This module provides a set of traits for modeling and analyzing various forms of place/transition or Petri nets.
3
4A Petri net is a graphical and mathematical modeling tool. The concept of Petri nets has its origin in Carl Adam Petri's
5dissertation "*Kommunikation mit Automaten*", submitted in 1962 to the faculty of Mathematics and Physics at the
6Technische Universität Darmstadt, Germany.
7
8Petri nets are a well-used tool for describing and studying systems that are characterized as being concurrent,
9asynchronous, distributed, parallel, nondeterministic, and/or stochastic. As a graphical tool, Petri nets can be used as
10a visual-communication aid similar to flow charts, block diagrams, and networks. In addition, tokens are used in these
11nets to simulate the dynamic and concurrent activities of systems. As a mathematical tool, it is possible to set up
12state equations, algebraic equations, and other mathematical models governing the behavior of systems.
13
14## Definitions
15
16A Net \\(N\\) consists of a tuple of *places* (the set \\(P\\)), *transitions* (the set \\(T\\)), and *arcs* (the set
17\\(A\\)) that connect them. Note that arcs are historically known as *flow relations* and the set is named \\(F\\).
18
19$$\tag{Net} N = \left\langle P,T,A \right\rangle$$
20
21The sets of places \\(P\\) and transitions \\(T\\) are disjoint.
22
23$$ P \cap T = \emptyset$$
24
25Arcs are a directed connection between a place/transition pair. We will use the notation \\(\overset{a}{\leftarrow}\\)
26for the source end and \\(\overset{a}{\rightarrow}\\) for the target end of an arc \\(a\\).
27
28$$\tag{Net Arc} A = \left(P \times T \right) \cup \left(T \times P \right)$$
29
30*Input arcs* connect a source place to a target transition.
31
32$$\tag{Input Arc} a_{in} = \left \\{ a \in A | \overset{a}{\rightarrow} \in T \right \\}$$
33$$ a_{in}(t) = \left \\{ a \in A | \overset{a}{\rightarrow} = t \right \\}$$
34
35The set of *input places* for a transition \\(t\\) is called its *preset* or \\({}^{\bullet}t\\).
36
37$$\tag{Preset} {}^{\bullet}t = \left \\{ p \in P | A(p,t) \right \\}$$
38
39*Output arcs* connect a source transition to a target place.
40
41$$\tag{Output Arc} a_{out} = \left \\{ a \in A | \overset{a}{\leftarrow} \in T \right \\}$$
42$$ a_{out}(t) = \left \\{ a \in A | \overset{a}{\leftarrow} = t \right \\}$$
43
44The set of *output places* for a transition \\(t\\) is called its *postset* or \\(t^{\bullet}\\).
45
46$$\tag{Postset} t^{\bullet} = \left \\{ p \in P | A(t,p) \right \\}$$
47
48Places can contain *tokens*; the current state of the modeled system (termed the *marking function* \\(M\\)) is given by the
49number of tokens in each place.
50
51$$\tag{Marking Function} M: P \mapsto \mathbb{N}$$
52
53The initial marking of a net is noted as \\(M_{im}\\) or more commonly \\(M_0\\). A *marked net* extends the Net tuple
54with a particular marking \\(M\\).
55
56$$\tag{Marked Net} N = \left\langle P,T,A,M \right\rangle$$
57
58Transitions are active components. They model activities which can occur (the transition *fires*), thus changing the
59state of the system (the marking of the Petri net). Transitions are only allowed to fire if they are *enabled*, which
60means that all the preconditions for the activity must be fulfilled, i.e. there are enough tokens available in the input
61places. For this check we use the undefined function \\(min\\) which can only be defined as we define the type of tokens
62later.
63
64$$\tag{Enabled Function} enabled\left(t \in T \right) = \forall p \in {}^{\bullet}t: min(A(p,t))$$
65
66A net \\(N\\) is therefore enabled *iff* any transition in \\(N\\) is enabled.
67
68$$enabled\left(N\right) \iff \exists t \in T: enabled\left(t\right)$$
69
70When the transition fires, it removes tokens from its input places and adds some at all of its output places. The number
71of tokens removed or added depends on the cardinality of each arc.
72
73The firing of transitions in the marking \\(M_n\\) results in the new marking \\(M_{n+1}\\). The interactive firing of
74transitions in subsequent markings is called the **token game**.
75
76## Classification
77
78This is a high-level classification of Petri Nets originally made by Monika Trompedeller in 1995, and is based on a
79survey by L. Bernardinello and F. De Cindio from 1992. The classification has not been updated since then and is
80therefore chiefly of historic interest. The classification is, however, useful for getting a quick overview of the main
81differences between various kinds of Petri Nets.
82
83* **Level 1**: nets characterized by places which can represent boolean values (\\(\mathbb{B}\\)), i.e., a place is
84 marked by at most one unstructured token.
85 * Condition/Event systems
86 * Elementary nets
87* **Level 2**: nets characterised by Places which can represent positive integer values (\\(\mathbb{N^{+}}\\)), i.e.,
88 a place is marked by a number of unstructured tokens.
89 * Place/Transition systems
90 * (Ordinary) Petri nets
91 * Free choice systems
92 * S-Systems
93 * State Machines
94 * T-Systems
95 * Marked Graphs
96* **Level 3**: nets characterised by Places which can represent high-level values, i.e., a place is marked by a
97 multi-set of structured tokens.
98 * Algebraic Petri nets
99 * Product nets
100 * Traditional High-Level nets
101 * Predicate/Transition Petri nets
102 * Colored Petri nets
103 * Well-Formed nets
104 * Regular nets
105
106## Extensions
107
108Note that the table below uses \\(\mathbb{B}\\) to represent the set of boolean values \\(\left\\{ \bot,\top \right \\}\\).
109
110| Name | Abbreviation | Token Type | Arc Weight | Place Capacities | Timed | Stochastic | Level |
111|-------------------|--------------|------------------------------|------------|------------------|-------|------------|-------|
112| Elementary net | EN | \\(M(p)\in \mathbb{B}\\) | No | No | No | No | 1 |
113| Petri net | PN | \\(M(p)\in \mathbb{N^{+}}\\) | Yes | No | No | No | 2 |
114| Colored Petri net | CPN | \\(M(p)\in C\\) | Yes | Yes | No | No | 3 |
115
116## Restrictions
117
118Instead of extending the Petri net formalism, we can also look at restricting it, and look at particular types of Petri
119nets, obtained by restricting the syntax in a particular way.
120
121For example Ordinary Petri nets are the nets where all arc weights are 1 and all place capacity is infinite.
122
123$$\tag{PN Restriction} \forall p\in P: K(p) = \infty \land \forall a\in A: W(a) = 1$$
124
125Restricting further, the following types of ordinary Petri nets are commonly used and studied.
126
127In a *state machine* (SM), every transition has one incoming arc, and one outgoing arc, and all markings have exactly
128one token. As a consequence, there can not be **concurrency**, but there can be **conflict** (i.e. nondeterminism).
129
130$$\tag{SM Restriction} \forall t\in T: |t^{\bullet}|=|{}^{\bullet} t|=1$$
131
132In a *marked graph* (MG), every place has one incoming arc, and one outgoing arc. This means, that there can **not** be
133**conflict**, but there can be **concurrency**.
134
135$$\tag{MG Restriction} \forall p\in P: |p^{\bullet}|=|{}^{\bullet} p|=1$$
136
137In a *free choice* net (FC), every arc from a place to a transition is either the only arc from that place or the only arc
138to that transition, i.e. there can be **both concurrency and conflict**, but **not at the same time**.
139
140$$\tag{FC Restriction} \forall p\in P: (|p^{\bullet}|\leq 1) \vee ({}^{\bullet} (p^{\bullet})=\\{p\\})$$
141
142A free choice net is an *S-system* iff its underlying net is an S-net.
143
144$$\tag{S-net} \forall t\in T: |{}^{\bullet}t| \le 1 \land |t^{\bullet}| \le 1$$
145
146A free choice net is a *T-system* iff its underlying net is a T-net. In a T-System there is never any conflict because
147there are no (forward) branched places.
148
149$$\tag{T-net} \forall p\in P: | {}^{\bullet}p | \le 1 \land | p^{\bullet} | \le 1$$
150
151*Extended free choice* (EFC) – a Petri net that can be **transformed into** an FC.
152
153In an *asymmetric choice net* (AC), concurrency and conflict (in sum, **confusion**) may occur, but **not symmetrically**.
154
155$$\tag{AC Restriction} \forall p_1,p_2\in P: (p_1{}^{\bullet} \cap p_2{}^{\bullet} \neq \emptyset) \to [(p_1{}^{\bullet} \subseteq p_2{}^{\bullet}) \vee (p_2{}^{\bullet} \subseteq p_1{}^{\bullet})]$$
156
157*/
158
159#![warn(
160 unknown_lints,
161 // ---------- Stylistic
162 absolute_paths_not_starting_with_crate,
163 elided_lifetimes_in_paths,
164 explicit_outlives_requirements,
165 macro_use_extern_crate,
166 nonstandard_style, /* group */
167 noop_method_call,
168 rust_2018_idioms,
169 single_use_lifetimes,
170 trivial_casts,
171 trivial_numeric_casts,
172 // ---------- Future
173 future_incompatible, /* group */
174 rust_2021_compatibility, /* group */
175 // ---------- Public
176 missing_debug_implementations,
177 // missing_docs,
178 unreachable_pub,
179 // ---------- Unsafe
180 unsafe_code,
181 unsafe_op_in_unsafe_fn,
182 // ---------- Unused
183 unused, /* group */
184)]
185#![deny(
186 // ---------- Public
187 exported_private_dependencies,
188 // ---------- Deprecated
189 anonymous_parameters,
190 bare_trait_objects,
191 ellipsis_inclusive_range_patterns,
192 // ---------- Unsafe
193 deref_nullptr,
194 drop_bounds,
195 dyn_drop,
196)]
197
198use std::{
199 fmt::{Debug, Display},
200 hash::Hash,
201};
202
203// ------------------------------------------------------------------------------------------------
204// Public Types Common
205// ------------------------------------------------------------------------------------------------
206
207pub type NodeIdValue = u64;
208
209///
210/// A node identifier is a numeric value assigned by the Net implementation and which is guaranteed
211/// unique across node types (and arcs if they are identified).
212///
213#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
214pub struct NodeId(NodeIdValue);
215
216///
217/// The trait implemented by Net nodes that have a Net-assigned identity.
218///
219pub trait HasIdentity {
220 ///
221 /// Returns a new Net node with the given identity.
222 ///
223 fn new(id: NodeId) -> Self;
224
225 ///
226 /// Returns the identity for this Net node.
227 ///
228 fn id(&self) -> NodeId;
229}
230
231///
232/// A label is a human-readable and generally descriptive text that helps the readability of Net
233/// representations.
234///
235pub trait HasLabel {
236 ///
237 /// Note: if a label is expected and this method returns `None` *and* the object implements
238 /// `HasIdentity` use the `id` value as the label.
239 ///
240 fn label(&self) -> Option<&String>;
241
242 ///
243 /// Set the object's label to the string value `label`.
244 ///
245 fn set_label<S>(&mut self, label: S)
246 where
247 S: Into<String>;
248
249 ///
250 /// Set the object's label to `None`.
251 ///
252 fn unset_label(&mut self);
253
254 ///
255 ///
256 ///
257 fn with_label<S>(self, label: S) -> Self
258 where
259 S: Into<String>,
260 Self: Sized;
261}
262
263///
264/// A display label is a computed label that may be used in a specific representation to present
265/// data from different node attributes.
266///
267pub trait HasDisplayLabel {
268 ///
269 /// Compute the display label for this Net node.
270 ///
271 /// Note: if a display label is expected and this method returns `None` *and* the object implements
272 /// `HasLabel` use the `label` value as the display label.
273 ///
274 fn display_label(&self) -> Option<String>;
275}
276
277// ------------------------------------------------------------------------------------------------
278// Implementations
279// ------------------------------------------------------------------------------------------------
280
281impl Display for NodeId {
282 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283 write!(f, "{}", self.0)
284 }
285}
286
287impl AsRef<NodeIdValue> for NodeId {
288 fn as_ref(&self) -> &NodeIdValue {
289 &self.0
290 }
291}
292
293impl From<NodeId> for NodeIdValue {
294 fn from(value: NodeId) -> Self {
295 value.0
296 }
297}
298
299impl NodeId {
300 ///
301 /// Construct a new NodeId from a given numeric value. This is inherently unsafe outside of the
302 /// libraries themselves. However, it can be useful in testing and so it remains public.
303 ///
304 pub fn new_unchecked(id: NodeIdValue) -> Self {
305 Self(id)
306 }
307
308 pub fn as_place_string(&self) -> String {
309 format!("p{}", self)
310 }
311
312 pub fn as_transition_string(&self) -> String {
313 format!("t{}", self)
314 }
315}
316
317// ------------------------------------------------------------------------------------------------
318// Modules Errors
319// ------------------------------------------------------------------------------------------------
320
321pub mod error;
322
323// ------------------------------------------------------------------------------------------------
324// Modules Core Definitions
325// ------------------------------------------------------------------------------------------------
326
327pub mod net;
328
329pub mod sim;
330
331// ------------------------------------------------------------------------------------------------
332// Modules Extensions
333// ------------------------------------------------------------------------------------------------
334
335pub mod guarded;
336
337pub mod structured;
338
339pub mod inhibited;
340
341pub mod prioritied;
342
343pub mod timed;
344
345pub mod weighted;
346
347// ------------------------------------------------------------------------------------------------
348// Modules Formatting/Tracing
349// ------------------------------------------------------------------------------------------------
350
351pub mod fmt;
352
353pub mod trace;