libpetri 2.12.1 → 3.0.0
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 +47 -136
- package/dist/{chunk-V3WTQRHC.js → chunk-5W6SVYPD.js} +170 -20
- package/dist/chunk-5W6SVYPD.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 +1 -1
- package/dist/doclet/index.js +3 -3
- package/dist/dot-exporter-3STXYK74.js +9 -0
- package/dist/{event-store--nMbAO1v.d.ts → event-store-Df_sAVQ_.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 +383 -368
- package/dist/index.js.map +1 -1
- package/dist/{petri-net-Byc3gSgJ.d.ts → petri-net-UQBBkvLl.d.ts} +39 -36
- package/dist/verification/index.d.ts +13 -6
- package/dist/verification/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-E3ZWB645.js.map +0 -1
- package/dist/chunk-V3WTQRHC.js.map +0 -1
- package/dist/dot-exporter-SHBYMMJ3.js +0 -9
- /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,83 @@
|
|
|
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/`)
|
|
48
|
-
|
|
49
|
-
Observable execution events as a discriminated union (`NetEvent`).
|
|
50
|
-
|
|
51
|
-
Event types: `execution-started`, `execution-completed`, `transition-enabled`, `transition-started`, `transition-completed`, `transition-failed`, `transition-timed-out`, `action-timed-out`, `token-added`, `token-removed`, `log-message`, `marking-snapshot`.
|
|
52
|
-
|
|
53
|
-
`InMemoryEventStore` captures events; `noopEventStore()` is a zero-cost singleton for production.
|
|
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/`)
|
|
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.
|
|
60
10
|
|
|
61
|
-
|
|
11
|
+
## Install
|
|
62
12
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
const marking = await executor.run();
|
|
103
|
-
console.log(marking.peekTokens(output)); // [Token { value: 'HELLO' }]
|
|
104
|
-
```
|
|
105
43
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
complete `PetriNet` plus a typed `Interface` of **ports** (typed places) and
|
|
110
|
-
**channels** (transitions). Instantiating renames every internal element with a
|
|
111
|
-
`prefix/name`; composing into a host substitutes port places and merges
|
|
112
|
-
channel transitions.
|
|
44
|
+
const result = await executor.run();
|
|
45
|
+
console.log(result.peekFirst(output)?.value); // HELLO
|
|
46
|
+
```
|
|
113
47
|
|
|
114
|
-
|
|
115
|
-
import { PetriNet, SubnetDef, FusionSet, place } from 'libpetri';
|
|
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();
|
|
48
|
+
## Execution and concurrency
|
|
128
49
|
|
|
129
|
-
|
|
130
|
-
const b2 = buffer.instantiate('b2').bindActions({ enqueue: enqueueImpl, dequeue: fork() });
|
|
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.
|
|
131
51
|
|
|
132
|
-
|
|
133
|
-
const b1ToB2 = place<string>('b1_to_b2');
|
|
134
|
-
const b2ToConsumer = place<string>('b2_to_c');
|
|
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.
|
|
135
53
|
|
|
136
|
-
|
|
137
|
-
.compose(b1, (bind) =>
|
|
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();
|
|
143
|
-
```
|
|
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.
|
|
144
55
|
|
|
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).
|
|
56
|
+
## Package entry points
|
|
152
57
|
|
|
153
|
-
|
|
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 |
|
|
65
|
+
| `libpetri/doclet` | TypeDoc integration |
|
|
154
66
|
|
|
155
|
-
|
|
156
|
-
import { SmtVerifier, deadlockFree } from 'libpetri/verification';
|
|
67
|
+
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.
|
|
157
68
|
|
|
158
|
-
|
|
159
|
-
.initialMarking(m => m.tokens(input, 1))
|
|
160
|
-
.property(deadlockFree())
|
|
161
|
-
.verify();
|
|
69
|
+
## Build and test
|
|
162
70
|
|
|
163
|
-
|
|
71
|
+
```bash
|
|
72
|
+
npm install
|
|
73
|
+
npm run build
|
|
74
|
+
npm run check
|
|
75
|
+
npm test
|
|
164
76
|
```
|
|
165
77
|
|
|
166
|
-
##
|
|
78
|
+
## Project links
|
|
167
79
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
```
|
|
80
|
+
- [Language-agnostic specification](https://github.com/debe/libpetri/blob/main/spec/00-index.md)
|
|
81
|
+
- [Lean soundness and backend-refinement proofs](https://github.com/debe/libpetri/blob/main/lean/README.md)
|
|
82
|
+
- [Changelog](https://github.com/debe/libpetri/blob/main/CHANGELOG.md)
|
|
83
|
+
- [Apache License 2.0](https://github.com/debe/libpetri/blob/main/LICENSE)
|
|
@@ -3,6 +3,55 @@ import {
|
|
|
3
3
|
latest
|
|
4
4
|
} from "./chunk-ATT7U5H5.js";
|
|
5
5
|
|
|
6
|
+
// src/core/in.ts
|
|
7
|
+
function one(place) {
|
|
8
|
+
return { type: "one", place };
|
|
9
|
+
}
|
|
10
|
+
function exactly(count, place) {
|
|
11
|
+
if (count < 1) {
|
|
12
|
+
throw new Error(`count must be >= 1, got: ${count}`);
|
|
13
|
+
}
|
|
14
|
+
return { type: "exactly", place, count };
|
|
15
|
+
}
|
|
16
|
+
function all(place) {
|
|
17
|
+
return { type: "all", place };
|
|
18
|
+
}
|
|
19
|
+
function atLeast(minimum, place) {
|
|
20
|
+
if (minimum < 1) {
|
|
21
|
+
throw new Error(`minimum must be >= 1, got: ${minimum}`);
|
|
22
|
+
}
|
|
23
|
+
return { type: "at-least", place, minimum };
|
|
24
|
+
}
|
|
25
|
+
function requiredCount(spec) {
|
|
26
|
+
switch (spec.type) {
|
|
27
|
+
case "one":
|
|
28
|
+
return 1;
|
|
29
|
+
case "exactly":
|
|
30
|
+
return spec.count;
|
|
31
|
+
case "all":
|
|
32
|
+
return 1;
|
|
33
|
+
case "at-least":
|
|
34
|
+
return spec.minimum;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function consumptionCount(spec, available) {
|
|
38
|
+
if (available < requiredCount(spec)) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Cannot consume from '${spec.place.name}': available=${available}, required=${requiredCount(spec)}`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
switch (spec.type) {
|
|
44
|
+
case "one":
|
|
45
|
+
return 1;
|
|
46
|
+
case "exactly":
|
|
47
|
+
return spec.count;
|
|
48
|
+
case "all":
|
|
49
|
+
return available;
|
|
50
|
+
case "at-least":
|
|
51
|
+
return available;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
6
55
|
// src/core/out.ts
|
|
7
56
|
function and(...children) {
|
|
8
57
|
if (children.length === 0) {
|
|
@@ -97,6 +146,80 @@ function crossProduct(a, b) {
|
|
|
97
146
|
return result;
|
|
98
147
|
}
|
|
99
148
|
|
|
149
|
+
// src/core/transition-action.ts
|
|
150
|
+
function passthrough() {
|
|
151
|
+
return PASSTHROUGH;
|
|
152
|
+
}
|
|
153
|
+
var PASSTHROUGH = async () => {
|
|
154
|
+
};
|
|
155
|
+
function isPassthrough(action) {
|
|
156
|
+
return action === PASSTHROUGH;
|
|
157
|
+
}
|
|
158
|
+
function transform(fn) {
|
|
159
|
+
return async (ctx) => {
|
|
160
|
+
const result = fn(ctx);
|
|
161
|
+
for (const outputPlace of ctx.outputPlaces()) {
|
|
162
|
+
ctx.output(outputPlace, result);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function fork() {
|
|
167
|
+
return transform((ctx) => {
|
|
168
|
+
const inputPlaces = ctx.inputPlaces();
|
|
169
|
+
if (inputPlaces.size !== 1) {
|
|
170
|
+
throw new Error(`Fork requires exactly 1 input place, found ${inputPlaces.size}`);
|
|
171
|
+
}
|
|
172
|
+
const inputPlace = inputPlaces.values().next().value;
|
|
173
|
+
return ctx.input(inputPlace);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function transformFrom(inputPlace, fn) {
|
|
177
|
+
return transform((ctx) => fn(ctx.input(inputPlace)));
|
|
178
|
+
}
|
|
179
|
+
function transformAsync(fn) {
|
|
180
|
+
return async (ctx) => {
|
|
181
|
+
const result = await fn(ctx);
|
|
182
|
+
for (const outputPlace of ctx.outputPlaces()) {
|
|
183
|
+
ctx.output(outputPlace, result);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function produce(place, value) {
|
|
188
|
+
return async (ctx) => {
|
|
189
|
+
ctx.output(place, value);
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function withTimeout(action, timeoutMs, timeoutPlace2, timeoutValue) {
|
|
193
|
+
return (ctx) => {
|
|
194
|
+
return new Promise((resolve, reject) => {
|
|
195
|
+
let completed = false;
|
|
196
|
+
const timer = setTimeout(() => {
|
|
197
|
+
if (!completed) {
|
|
198
|
+
completed = true;
|
|
199
|
+
ctx.output(timeoutPlace2, timeoutValue);
|
|
200
|
+
resolve();
|
|
201
|
+
}
|
|
202
|
+
}, timeoutMs);
|
|
203
|
+
action(ctx).then(
|
|
204
|
+
() => {
|
|
205
|
+
if (!completed) {
|
|
206
|
+
completed = true;
|
|
207
|
+
clearTimeout(timer);
|
|
208
|
+
resolve();
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
(err) => {
|
|
212
|
+
if (!completed) {
|
|
213
|
+
completed = true;
|
|
214
|
+
clearTimeout(timer);
|
|
215
|
+
reject(err);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
100
223
|
// src/verification/marking-state.ts
|
|
101
224
|
var MARKING_STATE_KEY = /* @__PURE__ */ Symbol("MarkingState.internal");
|
|
102
225
|
var MarkingState = class _MarkingState {
|
|
@@ -1400,6 +1523,17 @@ var StateClass = class {
|
|
|
1400
1523
|
}
|
|
1401
1524
|
};
|
|
1402
1525
|
|
|
1526
|
+
// src/core/internal/output-action-check.ts
|
|
1527
|
+
function requireOutputProducingActions(net) {
|
|
1528
|
+
for (const t of net.transitions) {
|
|
1529
|
+
if (t.outputSpec !== null && isPassthrough(t.action)) {
|
|
1530
|
+
throw new Error(
|
|
1531
|
+
`Transition '${t.name}' declares an output spec but carries passthrough(), which produces no tokens. Every firing would fail output validation (IO-015) and the declared output would never arrive. Bind an action that produces it \u2014 fork() moves the input token across \u2014 or drop the output spec if the transition is meant to be a sink.`
|
|
1532
|
+
);
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1403
1537
|
// src/verification/analysis/state-class-graph.ts
|
|
1404
1538
|
var StateClassGraph = class _StateClassGraph {
|
|
1405
1539
|
net;
|
|
@@ -1430,8 +1564,13 @@ var StateClassGraph = class _StateClassGraph {
|
|
|
1430
1564
|
}
|
|
1431
1565
|
}
|
|
1432
1566
|
}
|
|
1433
|
-
/**
|
|
1567
|
+
/**
|
|
1568
|
+
* Builds the state class graph for a Time Petri Net.
|
|
1569
|
+
*
|
|
1570
|
+
* @throws Error if the net violates CORE-043 — analysis rejects the same nets execution rejects.
|
|
1571
|
+
*/
|
|
1434
1572
|
static build(net, initialMarking, maxClasses, environmentPlaces, environmentMode) {
|
|
1573
|
+
requireOutputProducingActions(net);
|
|
1435
1574
|
const envMode = environmentMode ?? ignore();
|
|
1436
1575
|
const envPlaces = /* @__PURE__ */ new Set();
|
|
1437
1576
|
if (environmentPlaces) {
|
|
@@ -1644,18 +1783,8 @@ function inputRequiredCount(spec) {
|
|
|
1644
1783
|
return spec.minimum;
|
|
1645
1784
|
}
|
|
1646
1785
|
}
|
|
1647
|
-
function inputConsumeCount(spec) {
|
|
1648
|
-
|
|
1649
|
-
case "one":
|
|
1650
|
-
return 1;
|
|
1651
|
-
case "exactly":
|
|
1652
|
-
return spec.count;
|
|
1653
|
-
case "all":
|
|
1654
|
-
return 1;
|
|
1655
|
-
// Analysis: consume minimum (1 token)
|
|
1656
|
-
case "at-least":
|
|
1657
|
-
return spec.minimum;
|
|
1658
|
-
}
|
|
1786
|
+
function inputConsumeCount(spec, available) {
|
|
1787
|
+
return consumptionCount(spec, available);
|
|
1659
1788
|
}
|
|
1660
1789
|
function checkPlaceEnabled(place, required, marking, environmentPlaces, environmentMode) {
|
|
1661
1790
|
if (!environmentPlaces.has(place)) {
|
|
@@ -1673,7 +1802,11 @@ function checkPlaceEnabled(place, required, marking, environmentPlaces, environm
|
|
|
1673
1802
|
function fireTransition(marking, transition, outputPlaces, environmentPlaces, environmentMode) {
|
|
1674
1803
|
const builder = MarkingState.builder().copyFrom(marking);
|
|
1675
1804
|
for (const spec of transition.inputSpecs) {
|
|
1676
|
-
const
|
|
1805
|
+
const available = marking.tokens(spec.place);
|
|
1806
|
+
if (available < inputRequiredCount(spec)) {
|
|
1807
|
+
continue;
|
|
1808
|
+
}
|
|
1809
|
+
const toConsume = inputConsumeCount(spec, available);
|
|
1677
1810
|
consumeFromPlace(builder, spec.place, toConsume, environmentPlaces, environmentMode);
|
|
1678
1811
|
}
|
|
1679
1812
|
for (const arc of transition.resets) {
|
|
@@ -2298,11 +2431,11 @@ var NameMarking = class _NameMarking {
|
|
|
2298
2431
|
return syms ? [...syms.keys()] : [];
|
|
2299
2432
|
}
|
|
2300
2433
|
liveSymbols() {
|
|
2301
|
-
const
|
|
2434
|
+
const all2 = /* @__PURE__ */ new Set();
|
|
2302
2435
|
for (const syms of this.perPlace.values()) {
|
|
2303
|
-
for (const s of syms.keys())
|
|
2436
|
+
for (const s of syms.keys()) all2.add(s);
|
|
2304
2437
|
}
|
|
2305
|
-
return [...
|
|
2438
|
+
return [...all2];
|
|
2306
2439
|
}
|
|
2307
2440
|
/**
|
|
2308
2441
|
* Symmetry-canonical key over `colouredOrder` (the finiteness mechanism). Two
|
|
@@ -2775,8 +2908,11 @@ var SmtVerifier = class _SmtVerifier {
|
|
|
2775
2908
|
}
|
|
2776
2909
|
/**
|
|
2777
2910
|
* Runs the verification pipeline.
|
|
2911
|
+
*
|
|
2912
|
+
* @throws Error if the net violates CORE-043 — verification rejects the same nets execution rejects.
|
|
2778
2913
|
*/
|
|
2779
2914
|
async verify() {
|
|
2915
|
+
requireOutputProducingActions(this.net);
|
|
2780
2916
|
const start = performance.now();
|
|
2781
2917
|
const report = [];
|
|
2782
2918
|
report.push("=== IC3/PDR SAFETY VERIFICATION ===\n");
|
|
@@ -2982,7 +3118,7 @@ var SmtVerifier = class _SmtVerifier {
|
|
|
2982
3118
|
report.push("=== RESULT ===\n");
|
|
2983
3119
|
report.push(`PROVEN (IC3/PDR): ${propDesc}`);
|
|
2984
3120
|
report.push(" Z3 Spacer proved no reachable state violates the property.");
|
|
2985
|
-
report.push(" NOTE: Verification ignores timing constraints
|
|
3121
|
+
report.push(" NOTE: Verification ignores timing constraints.");
|
|
2986
3122
|
report.push(" An untimed proof is STRONGER than a timed one (timing only restricts behavior).");
|
|
2987
3123
|
return this.applyNuGuard(buildResult(
|
|
2988
3124
|
{
|
|
@@ -3015,7 +3151,6 @@ var SmtVerifier = class _SmtVerifier {
|
|
|
3015
3151
|
}
|
|
3016
3152
|
report.push("\n WARNING: This counterexample is in UNTIMED semantics.");
|
|
3017
3153
|
report.push(" It may be spurious if timing constraints prevent this sequence.");
|
|
3018
|
-
report.push(" JS guards are also ignored in this analysis.");
|
|
3019
3154
|
return this.applyNuGuard(buildResult(
|
|
3020
3155
|
{ type: "violated" },
|
|
3021
3156
|
report.join("\n"),
|
|
@@ -3159,6 +3294,12 @@ function isViolated(result) {
|
|
|
3159
3294
|
}
|
|
3160
3295
|
|
|
3161
3296
|
export {
|
|
3297
|
+
one,
|
|
3298
|
+
exactly,
|
|
3299
|
+
all,
|
|
3300
|
+
atLeast,
|
|
3301
|
+
requiredCount,
|
|
3302
|
+
consumptionCount,
|
|
3162
3303
|
and,
|
|
3163
3304
|
andPlaces,
|
|
3164
3305
|
xor,
|
|
@@ -3169,6 +3310,14 @@ export {
|
|
|
3169
3310
|
forwardInput,
|
|
3170
3311
|
allPlaces,
|
|
3171
3312
|
enumerateBranches,
|
|
3313
|
+
passthrough,
|
|
3314
|
+
isPassthrough,
|
|
3315
|
+
transform,
|
|
3316
|
+
fork,
|
|
3317
|
+
transformFrom,
|
|
3318
|
+
transformAsync,
|
|
3319
|
+
produce,
|
|
3320
|
+
withTimeout,
|
|
3172
3321
|
MarkingState,
|
|
3173
3322
|
MarkingStateBuilder,
|
|
3174
3323
|
deadlockFree,
|
|
@@ -3199,10 +3348,11 @@ export {
|
|
|
3199
3348
|
encode,
|
|
3200
3349
|
DBM,
|
|
3201
3350
|
StateClass,
|
|
3351
|
+
requireOutputProducingActions,
|
|
3202
3352
|
StateClassGraph,
|
|
3203
3353
|
decode,
|
|
3204
3354
|
SmtVerifier,
|
|
3205
3355
|
isProven,
|
|
3206
3356
|
isViolated
|
|
3207
3357
|
};
|
|
3208
|
-
//# sourceMappingURL=chunk-
|
|
3358
|
+
//# sourceMappingURL=chunk-5W6SVYPD.js.map
|