libpetri 2.13.0 → 3.0.1
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.
- package/README.md +89 -130
- package/dist/chunk-6NH64RCU.js +1016 -0
- package/dist/chunk-6NH64RCU.js.map +1 -0
- package/dist/{chunk-7VJ5CYUU.js → chunk-JZIEWVAV.js} +905 -62
- package/dist/chunk-JZIEWVAV.js.map +1 -0
- package/dist/{chunk-JVI5HFRX.js → chunk-VCDOKWVU.js} +2 -2
- package/dist/{chunk-E3ZWB645.js → chunk-YVIPJ6KM.js} +1 -1
- package/dist/chunk-YVIPJ6KM.js.map +1 -0
- package/dist/debug/index.d.ts +2 -2
- package/dist/debug/index.js +2 -2
- package/dist/doclet/index.d.ts +12 -3
- package/dist/doclet/index.js +8 -4
- package/dist/doclet/index.js.map +1 -1
- package/dist/doclet/resources/petrinet-diagrams.css +21 -0
- package/dist/doclet/resources/petrinet-diagrams.js +3575 -3573
- package/dist/dot-exporter-3STXYK74.js +9 -0
- package/dist/{render-ZGZEZ5RK.js → elk-place-YVNQFGXI.js} +3 -258
- package/dist/elk-place-YVNQFGXI.js.map +1 -0
- package/dist/{event-store-DKTenPbC.d.ts → event-store-BFX_yJ8I.d.ts} +1 -1
- package/dist/export/index.d.ts +1 -1
- package/dist/export/index.js +2 -2
- package/dist/index.d.ts +91 -38
- package/dist/index.js +368 -294
- package/dist/index.js.map +1 -1
- package/dist/pan-zoom-Cp51IkDl.d.ts +33 -0
- package/dist/{petri-net-C3LSY-vm.d.ts → petri-net-WSScMyDL.d.ts} +43 -29
- package/dist/preprocess-FN3F75JR.js +193 -0
- package/dist/preprocess-FN3F75JR.js.map +1 -0
- package/dist/render-QOHGDWNE.js +78 -0
- package/dist/render-QOHGDWNE.js.map +1 -0
- package/dist/render-dom/index.d.ts +28 -29
- package/dist/render-dom/index.js +14 -21
- package/dist/render-dom/index.js.map +1 -1
- package/dist/verification/index.d.ts +273 -7
- package/dist/verification/index.js +7 -1
- package/dist/verification/index.js.map +1 -1
- package/dist/viewer/index.d.ts +24 -32
- package/dist/viewer/index.js +9 -1003
- package/dist/viewer/index.js.map +1 -1
- package/dist/viewer/viewer.css +21 -0
- package/dist/viewer/viewer.iife.js +3575 -3573
- package/package.json +2 -2
- package/dist/chunk-7VJ5CYUU.js.map +0 -1
- package/dist/chunk-E3ZWB645.js.map +0 -1
- package/dist/dot-exporter-SHBYMMJ3.js +0 -9
- package/dist/render-ZGZEZ5RK.js.map +0 -1
- /package/dist/{chunk-JVI5HFRX.js.map → chunk-VCDOKWVU.js.map} +0 -0
- /package/dist/{dot-exporter-SHBYMMJ3.js.map → dot-exporter-3STXYK74.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,172 +1,131 @@
|
|
|
1
|
-
# libpetri
|
|
1
|
+
# libpetri for TypeScript
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/libpetri)
|
|
4
|
+
[](https://www.typescriptlang.org/)
|
|
5
|
+
[](https://github.com/debe/libpetri/blob/main/LICENSE)
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
The TypeScript 6 implementation of libpetri: typed Coloured Time Petri Nets for Promise-based applications, with modular composition, two execution backends, observability, DOT export, and formal verification.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
src/
|
|
9
|
-
├── core/ # Net definition: places, transitions, arcs, timing, output specs
|
|
10
|
-
├── runtime/ # Async bitmap-based executor, marking, compiled net
|
|
11
|
-
├── event/ # Event store and net event types (discriminated union)
|
|
12
|
-
├── export/ # DOT (Graphviz) diagram exporter
|
|
13
|
-
└── verification/ # SMT-based property verification (Z3)
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
### Core (`src/core/`)
|
|
17
|
-
|
|
18
|
-
Immutable net definitions with typed, colored tokens.
|
|
19
|
-
|
|
20
|
-
| Type | Description |
|
|
21
|
-
|------|-------------|
|
|
22
|
-
| `Place<T>` | Typed token container (phantom type for compile-time safety) |
|
|
23
|
-
| `EnvironmentPlace<T>` | External event injection point |
|
|
24
|
-
| `Transition` | Arc specs, timing, priority, guards, action binding |
|
|
25
|
-
| `PetriNet` | Immutable net definition; `bindActions()` separates structure from runtime behavior |
|
|
26
|
-
| `Out` | Discriminated union for output specs: `and`, `xor`, `place`, `timeout`, `forward-input` |
|
|
27
|
-
| `In` | Input arc specs with cardinality: `one`, `exactly`, `all`, `at-least` |
|
|
28
|
-
| `Timing` | TPN firing intervals: `immediate`, `deadline`, `delayed`, `window`, `exact` |
|
|
29
|
-
| `TransitionAction` | `(ctx: TransitionContext) => Promise<void>` — async action bound to a transition |
|
|
30
|
-
|
|
31
|
-
### Runtime (`src/runtime/`)
|
|
32
|
-
|
|
33
|
-
Async single-threaded executor using bitmap-based enablement tracking.
|
|
34
|
-
|
|
35
|
-
| Type | Description |
|
|
36
|
-
|------|-------------|
|
|
37
|
-
| `BitmapNetExecutor` | Main executor — dirty-set tracking, priority scheduling, deadline enforcement |
|
|
38
|
-
| `CompiledNet` | Precomputed bitmap masks and reverse indices for O(W) enablement checks |
|
|
39
|
-
| `Marking` | Mutable FIFO token state per place |
|
|
40
|
-
|
|
41
|
-
Key performance features:
|
|
42
|
-
- `Uint32Array` bitmaps for place marking and transition dirty sets
|
|
43
|
-
- Kernighan's bit-trick for dirty set iteration
|
|
44
|
-
- Pre-allocated buffers to reduce GC pressure
|
|
45
|
-
- Precomputed reverse index (place → affected transitions)
|
|
46
|
-
|
|
47
|
-
### Event (`src/event/`)
|
|
9
|
+
See the [project README](https://github.com/debe/libpetri#why-a-petri-net) for the motivation and an order workflow using every arc type, concurrent actions, and timeout routing.
|
|
48
10
|
|
|
49
|
-
|
|
11
|
+
## Install
|
|
50
12
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
### Export (`src/export/`)
|
|
56
|
-
|
|
57
|
-
`dotExport(net, config)` generates DOT (Graphviz) diagram syntax with proper Petri net visual conventions, including arc types (inhibitor, read, reset), timing annotations, and priority labels.
|
|
58
|
-
|
|
59
|
-
### Verification (`src/verification/`)
|
|
60
|
-
|
|
61
|
-
SMT-based formal verification using Z3. Encodes the Petri net as an integer linear program and checks reachability properties.
|
|
62
|
-
|
|
63
|
-
Supported properties:
|
|
64
|
-
- **Deadlock freedom** — no reachable state where all transitions are disabled
|
|
65
|
-
- **Mutual exclusion** — two places never both hold tokens simultaneously
|
|
66
|
-
- **Place bounds** — token count in a place never exceeds a limit
|
|
67
|
-
- **Unreachability** — a marking is never reachable
|
|
68
|
-
|
|
69
|
-
Also computes **P-invariants** (Farkas variant) and supports IC3/PDR-style incremental verification.
|
|
70
|
-
|
|
71
|
-
### ν-nets (`src/runtime/`)
|
|
13
|
+
```bash
|
|
14
|
+
npm install libpetri
|
|
15
|
+
```
|
|
72
16
|
|
|
73
|
-
|
|
17
|
+
libpetri is ESM-only. The core runtime has no browser-only assumption; optional viewer and documentation entry points declare their own peer dependencies.
|
|
74
18
|
|
|
75
|
-
## Quick
|
|
19
|
+
## Quick start
|
|
76
20
|
|
|
77
21
|
```typescript
|
|
78
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
BitmapNetExecutor, PetriNet, Transition,
|
|
24
|
+
one, outPlace, place, tokenOf,
|
|
25
|
+
} from 'libpetri';
|
|
79
26
|
|
|
80
|
-
// Define places
|
|
81
27
|
const input = place<string>('input');
|
|
82
28
|
const output = place<string>('output');
|
|
83
29
|
|
|
84
|
-
|
|
85
|
-
const process = Transition.builder('process')
|
|
30
|
+
const uppercase = Transition.builder('uppercase')
|
|
86
31
|
.inputs(one(input))
|
|
87
32
|
.outputs(outPlace(output))
|
|
88
33
|
.action(async (ctx) => {
|
|
89
|
-
|
|
90
|
-
ctx.output(output, value.toUpperCase());
|
|
34
|
+
ctx.output(output, ctx.input(input).toUpperCase());
|
|
91
35
|
})
|
|
92
36
|
.build();
|
|
93
37
|
|
|
94
|
-
|
|
95
|
-
const net = PetriNet.builder('Example').transition(process).build();
|
|
96
|
-
|
|
97
|
-
// Execute
|
|
38
|
+
const net = PetriNet.builder('example').transition(uppercase).build();
|
|
98
39
|
const executor = new BitmapNetExecutor(
|
|
99
40
|
net,
|
|
100
41
|
new Map([[input, [tokenOf('hello')]]]),
|
|
101
42
|
);
|
|
102
|
-
|
|
103
|
-
|
|
43
|
+
|
|
44
|
+
const result = await executor.run();
|
|
45
|
+
console.log(result.peekFirst(output)?.value); // HELLO
|
|
104
46
|
```
|
|
105
47
|
|
|
106
|
-
##
|
|
48
|
+
## Execution and concurrency
|
|
49
|
+
|
|
50
|
+
`BitmapNetExecutor` is the reference implementation. `PrecompiledNetExecutor` compiles the same net into flat arrays, opcode streams, and priority-partitioned ready queues for production hot paths.
|
|
51
|
+
|
|
52
|
+
The orchestrator owns the marking and invokes ready actions without awaiting earlier actions first. Promise continuations therefore overlap naturally, while marking updates remain serialized. CPU-heavy synchronous code still blocks the JavaScript event loop; move it to a worker or external service.
|
|
53
|
+
|
|
54
|
+
Use places and transitions for coordination rather than hiding concurrency inside `Promise.all`: the net can then visualize, trace, replay, and verify the fan-out and join.
|
|
107
55
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
56
|
+
## Package entry points
|
|
57
|
+
|
|
58
|
+
| Import | Purpose |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `libpetri` | Core model, runtime, events, and composition |
|
|
61
|
+
| `libpetri/export` | DOT mapping and rendering |
|
|
62
|
+
| `libpetri/verification` | Structural analysis, state classes, and Z3-backed SMT verification |
|
|
63
|
+
| `libpetri/debug` | Debug protocol and session archives |
|
|
64
|
+
| `libpetri/viewer` | Interactive DOT/SVG viewer, the canonical renderer |
|
|
65
|
+
| `libpetri/render-dom` | Thin compatibility wrapper over `libpetri/viewer` |
|
|
66
|
+
| `libpetri/doclet` | TypeDoc integration |
|
|
67
|
+
|
|
68
|
+
The model supports input, output, read, inhibitor, and reset arcs; immediate, deadline, delayed, window, and exact timing; AND/XOR/timeout routing; environment places; reusable subnets; place fusion; and ν-net identity correlation.
|
|
69
|
+
|
|
70
|
+
## Visualization
|
|
71
|
+
|
|
72
|
+
`libpetri/viewer` is the canonical renderer. It lays nodes out with ELK, routes edges orthogonally, and draws the result through Graphviz `nop2`, then adds pan/zoom, cluster collapse, subnet toggling, and filtering. Every first-party surface uses it: the debug UI, the TypeDoc plugin here, the Java javadoc taglet, and the Rust docgen all embed the same bundle, so a net looks the same whichever port documented it.
|
|
113
73
|
|
|
114
74
|
```typescript
|
|
115
|
-
import {
|
|
116
|
-
|
|
117
|
-
const items = place<string>('items');
|
|
118
|
-
const slots = place<string>('slots');
|
|
119
|
-
const put = place<string>('put');
|
|
120
|
-
const get = place<string>('get');
|
|
121
|
-
|
|
122
|
-
const buffer = SubnetDef.builder<void>('Buffer')
|
|
123
|
-
.place(items).place(slots)
|
|
124
|
-
.transition(enqueue).transition(dequeue)
|
|
125
|
-
.inputPort('put', put)
|
|
126
|
-
.outputPort('get', get)
|
|
127
|
-
.build();
|
|
75
|
+
import { dotExport } from 'libpetri/export';
|
|
76
|
+
import { mount } from 'libpetri/viewer';
|
|
128
77
|
|
|
129
|
-
const
|
|
130
|
-
|
|
78
|
+
const handle = await mount(dotExport(net), document.getElementById('diagram')!, {
|
|
79
|
+
chrome: true,
|
|
80
|
+
});
|
|
81
|
+
handle.fit();
|
|
82
|
+
```
|
|
131
83
|
|
|
132
|
-
|
|
133
|
-
const b1ToB2 = place<string>('b1_to_b2');
|
|
134
|
-
const b2ToConsumer = place<string>('b2_to_c');
|
|
84
|
+
The viewer is browser-only and declares `@viz-js/viz`, `panzoom`, and `elkjs` as optional peer dependencies, so a headless runtime install does not pull in a rendering stack. Install all three wherever you mount it:
|
|
135
85
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
bind.bindPort('put', producerToB1).bindPort('get', b1ToB2))
|
|
139
|
-
.compose(b2, (bind) =>
|
|
140
|
-
bind.bindPort('put', b1ToB2).bindPort('get', b2ToConsumer))
|
|
141
|
-
.fuse(FusionSet.of('sharedSlots', b1.port<string>('slots'), b2.port<string>('slots')))
|
|
142
|
-
.build();
|
|
86
|
+
```bash
|
|
87
|
+
npm install @viz-js/viz panzoom elkjs
|
|
143
88
|
```
|
|
144
89
|
|
|
145
|
-
|
|
146
|
-
rewrite; channels (`bindChannel`) merge transitions with arc union, timing
|
|
147
|
-
intersection, and caller-wins identity. `FusionSet` declares N-ary place
|
|
148
|
-
equivalence applied **after** all `compose(...)` calls, regardless of
|
|
149
|
-
registration order. Per-instance action overrides are supplied via
|
|
150
|
-
`Instance.bindActions({ originalName: action })`. See
|
|
151
|
-
[`spec/11-modular-composition.md`](../spec/11-modular-composition.md).
|
|
90
|
+
Without `elkjs` the default layout throws and names the missing peer; `mount(dot, el, { layout: 'graphviz' })` falls back to stock Graphviz layout, which is the one supported way to render without it.
|
|
152
91
|
|
|
153
|
-
|
|
92
|
+
Not every path through the package produces the same picture:
|
|
154
93
|
|
|
155
|
-
|
|
156
|
-
|
|
94
|
+
| Path | Layout | Edges |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| `mount()` from `libpetri/viewer` | ELK placement, ELK routes via `nop2` | orthogonal |
|
|
97
|
+
| `renderDotToContainer()` from `libpetri/render-dom` | delegates to `mount()` | orthogonal |
|
|
98
|
+
| the TypeDoc plugin | embeds the viewer, mounts client-side | orthogonal |
|
|
99
|
+
| `dotToSvg()` from `libpetri/doclet` | stock Graphviz `dot` | diagonal splines |
|
|
100
|
+
| `dotExport()` piped to your own `dot -Tsvg` | stock Graphviz `dot` | diagonal splines |
|
|
101
|
+
|
|
102
|
+
If a diagram renders with diagonal edges where you expected right angles, it went through one of the bottom two rows, or through a viewer bundle older than 2.10.5. Generated doc pages record which one drew them in `data-libpetri-viewer` on the diagram container.
|
|
157
103
|
|
|
158
|
-
|
|
159
|
-
.initialMarking(m => m.tokens(input, 1))
|
|
160
|
-
.property(deadlockFree())
|
|
161
|
-
.verify();
|
|
104
|
+
### TypeDoc plugin
|
|
162
105
|
|
|
163
|
-
|
|
106
|
+
Register the plugin and declare the block tag it reads:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"plugin": ["libpetri/doclet"],
|
|
111
|
+
"blockTags": ["@petrinet"]
|
|
112
|
+
}
|
|
164
113
|
```
|
|
165
114
|
|
|
166
|
-
|
|
115
|
+
An `@petrinet` tag on a symbol that builds or exposes a net renders that net as a diagram in the generated page, with the DOT source in a collapsible block underneath. The viewer bundle is inlined into the HTML, so the output is self-contained and works offline with no `dot` binary and no network access.
|
|
116
|
+
|
|
117
|
+
## Build and test
|
|
167
118
|
|
|
168
119
|
```bash
|
|
169
|
-
npm
|
|
170
|
-
npm run
|
|
171
|
-
npm
|
|
120
|
+
npm install
|
|
121
|
+
npm run build
|
|
122
|
+
npm run check
|
|
123
|
+
npm test
|
|
172
124
|
```
|
|
125
|
+
|
|
126
|
+
## Project links
|
|
127
|
+
|
|
128
|
+
- [Language-agnostic specification](https://github.com/debe/libpetri/blob/main/spec/00-index.md)
|
|
129
|
+
- [Lean soundness and backend-refinement proofs](https://github.com/debe/libpetri/blob/main/lean/README.md)
|
|
130
|
+
- [Changelog](https://github.com/debe/libpetri/blob/main/CHANGELOG.md)
|
|
131
|
+
- [Apache License 2.0](https://github.com/debe/libpetri/blob/main/LICENSE)
|