3 releases (breaking)

0.3.0 Sep 22, 2024
0.2.0 Sep 14, 2024
0.1.2 Mar 9, 2024
0.1.1 Mar 3, 2024
0.1.0 Mar 3, 2024

#19 in #role

Download history 1/week @ 2024-07-25 186/week @ 2024-09-12 202/week @ 2024-09-19 47/week @ 2024-09-26 7/week @ 2024-10-03 2/week @ 2024-10-10

259 downloads per month

MIT license

94KB
1.5K SLoC

metamodel

Declarative Petri-nets using a rust DSL.

Crates.io Version


lib.rs:

Metamodel - A Rust Library for Abstract State Machine Modeling

See the code below for an example of how to create a Petri-net model using the pflow_metamodel library.

Also see: Macro pflow_metamodel::pflow_dsl for creating models using an internal rust DSL rather than json.

use pflow_metamodel::*;

let model: Model = pflow_json!{{
   "modelType": "petriNet",
   "version": "v0",
   "places": {
     "place0": { "offset": 0, "capacity": 3, "x": 100, "y": 180 }
   },
   "transitions": {
     "txn0": { "role": "role0", "x": 20, "y": 100 },
     "txn1": { "role": "role0", "x": 180, "y": 100 },
     "txn2": { "role": "role0", "x": 20, "y": 260 },
     "txn3": { "role": "role0", "x": 180, "y": 260 }
   },
   "arcs": [
     { "source": "txn0", "target": "place0" },
     { "source": "place0", "target": "txn1", "weight": 3 },
     { "source": "txn2", "target": "place0", "weight": 3, "inhibit": true },
     { "source": "place0", "target": "txn3", "inhibit": true }
   ]
}};

let state = model.vm.initial_vector();
assert_eq!(state, vec![0]);
let res = model.vm.transform(&state, "txn0", 1);
assert!(res.ok);
assert_eq!(state, vec![0]); // input state is _not_ mutated
assert_eq!(res.output, vec![1]);
let t = model.net.transitions.get("txn0");
assert!(t.is_some());
  • Provides a DSL-driven framework for modeling and simulating Petri-nets, wf-nets, and DFAs.
  • State machine data types are executed as a Vector Addition State Machine (VASM).
  • Data models are viewable / shareable in browsers by using https://pflow.dev JSON format.
  • Models can be compressed and shared as base64 encoded blobs.
  • Models can be consistently hashed and shared as CIDs.

Dining Philosophers Example

The following example demonstrates the dining philosophers problem using the PetriNet struct.

use pflow_metamodel::*;

let model = pflow_json!{{
"modelType": "petriNet",
"version": "v0",
"places": {
  "chopstick0": { "offset": 0, "initial": 1, "x": 403, "y": 340 },
  "chopstick1": { "offset": 1, "initial": 1, "x": 534, "y": 345 },
  "chopstick2": { "offset": 2, "initial": 1, "x": 358, "y": 467 },
  "chopstick3": { "offset": 3, "initial": 1, "x": 547, "y": 461 },
  "chopstick4": { "offset": 4, "initial": 1, "x": 451, "y": 536 },
  "0right": { "offset": 5, "x": 415, "y": 181 },
  "0left": { "offset": 6, "x": 545, "y": 177 },
  "1right": { "offset": 7, "x": 719, "y": 288 },
  "1left": { "offset": 8, "x": 769, "y": 404 },
  "2left": { "offset": 9, "x": 686, "y": 584 },
  "2right": { "offset": 10, "x": 594, "y": 678 },
  "3left": { "offset": 11, "x": 315, "y": 679 },
  "3right": { "offset": 12, "x": 216, "y": 608 },
  "4right": { "offset": 13, "x": 148, "y": 397 },
  "4left": { "offset": 14, "x": 183, "y": 289 }
},
"transitions": {
  "0think": { "x": 478, "y": 106 },
  "0eat": { "x": 473, "y": 247 },
  "1eat": { "x": 654, "y": 396 },
  "2eat": { "x": 574, "y": 573 },
  "3eat": { "x": 333, "y": 556 },
  "4eat": { "x": 267, "y": 370 },
  "1think": { "x": 842, "y": 304 },
  "4think": { "x": 72, "y": 314 },
  "3think": { "x": 200, "y": 726 },
  "2think": { "x": 740, "y": 699 }
},
"arcs": [
  { "source": "chopstick0", "target": "0eat" },
  { "source": "chopstick1", "target": "0eat" },
  { "source": "chopstick0", "target": "4eat" },
  { "source": "chopstick2", "target": "4eat" },
  { "source": "chopstick1", "target": "1eat" },
  { "source": "chopstick3", "target": "1eat" },
  { "source": "chopstick2", "target": "3eat" },
  { "source": "chopstick4", "target": "3eat" },
  { "source": "chopstick4", "target": "2eat" },
  { "source": "chopstick3", "target": "2eat" },
  { "source": "0eat", "target": "0right" },
  { "source": "0eat", "target": "0left" },
  { "source": "1eat", "target": "1right" },
  { "source": "1eat", "target": "1left" },
  { "source": "2eat", "target": "2left" },
  { "source": "2eat", "target": "2right" },
  { "source": "3eat", "target": "3right" },
  { "source": "3eat", "target": "3left" },
  { "source": "4eat", "target": "4right" },
  { "source": "4eat", "target": "4left" },
  { "source": "0right", "target": "0think" },
  { "source": "0left", "target": "0think" },
  { "source": "1right", "target": "1think" },
  { "source": "1left", "target": "1think" },
  { "source": "2left", "target": "2think" },
  { "source": "2right", "target": "2think" },
  { "source": "4left", "target": "4think" },
  { "source": "4right", "target": "4think" },
  { "source": "3right", "target": "3think" },
  { "source": "3left", "target": "3think" },
  { "source": "4think", "target": "chopstick0" },
  { "source": "4think", "target": "chopstick2" },
  { "source": "0think", "target": "chopstick0" },
  { "source": "0think", "target": "chopstick1" },
  { "source": "1think", "target": "chopstick1" },
  { "source": "1think", "target": "chopstick3" },
  { "source": "2think", "target": "chopstick3" },
  { "source": "2think", "target": "chopstick4" },
  { "source": "3think", "target": "chopstick2" },
  { "source": "3think", "target": "chopstick4" }
]
}};

Dependencies

~10MB
~337K SLoC