libpetri 2.10.5 → 2.11.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.
|
@@ -1925,7 +1925,7 @@ function encodeViolation(ctx, plan, lay, flat, property, cur) {
|
|
|
1925
1925
|
}
|
|
1926
1926
|
|
|
1927
1927
|
// src/verification/analysis/name-fragment.ts
|
|
1928
|
-
function classify(net) {
|
|
1928
|
+
function classify(net, mode, carrierPlaces) {
|
|
1929
1929
|
const coloured = /* @__PURE__ */ new Set();
|
|
1930
1930
|
let anyMatch = false;
|
|
1931
1931
|
for (const t of net.transitions) {
|
|
@@ -1935,9 +1935,18 @@ function classify(net) {
|
|
|
1935
1935
|
}
|
|
1936
1936
|
}
|
|
1937
1937
|
if (!anyMatch || coloured.size === 0) return null;
|
|
1938
|
+
if (mode === "extended") {
|
|
1939
|
+
for (const c of carrierPlaces) coloured.add(c);
|
|
1940
|
+
}
|
|
1941
|
+
for (const t of net.transitions) {
|
|
1942
|
+
if (t.resets.some((r) => coloured.has(r.place.name)) || t.reads.some((r) => coloured.has(r.place.name)) || t.inhibitors.some((i) => coloured.has(i.place.name))) {
|
|
1943
|
+
return null;
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1938
1946
|
const roles = /* @__PURE__ */ new Map();
|
|
1939
1947
|
for (const t of net.transitions) {
|
|
1940
|
-
const
|
|
1948
|
+
const colouredInputs = t.inputSpecs.filter((s) => coloured.has(s.place.name));
|
|
1949
|
+
const consumesColoured = colouredInputs.length > 0;
|
|
1941
1950
|
let producesColoured = false;
|
|
1942
1951
|
if (t.outputSpec !== null) {
|
|
1943
1952
|
for (const branch of enumerateBranches(t.outputSpec)) {
|
|
@@ -1958,11 +1967,16 @@ function classify(net) {
|
|
|
1958
1967
|
}
|
|
1959
1968
|
colouredIn.sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
|
|
1960
1969
|
role = { type: "join", colouredIn };
|
|
1970
|
+
} else if (consumesColoured) {
|
|
1971
|
+
if (mode === "base") return null;
|
|
1972
|
+
if (colouredInputs.length !== 1) return null;
|
|
1973
|
+
const spec = colouredInputs[0];
|
|
1974
|
+
const countOne = spec.type === "one" || spec.type === "exactly" && spec.count === 1;
|
|
1975
|
+
if (!countOne) return null;
|
|
1976
|
+
role = { type: "consume", colouredInput: spec.place.name };
|
|
1961
1977
|
} else if (producesColoured) {
|
|
1962
|
-
if (consumesColoured) return null;
|
|
1963
1978
|
role = { type: "mint" };
|
|
1964
1979
|
} else {
|
|
1965
|
-
if (consumesColoured) return null;
|
|
1966
1980
|
role = { type: "ordinary" };
|
|
1967
1981
|
}
|
|
1968
1982
|
roles.set(t.name, role);
|
|
@@ -2165,12 +2179,15 @@ var NameStateClassGraph = class _NameStateClassGraph {
|
|
|
2165
2179
|
this._successors[from].push(to);
|
|
2166
2180
|
}
|
|
2167
2181
|
};
|
|
2182
|
+
function colouredOutputs(outputPlaces, fragment) {
|
|
2183
|
+
return [...outputPlaces].filter((p) => fragment.isColoured(p.name)).map((p) => p.name);
|
|
2184
|
+
}
|
|
2168
2185
|
function nameSuccessors(role, names, outputPlaces, fragment, sym) {
|
|
2169
2186
|
switch (role.type) {
|
|
2170
2187
|
case "ordinary":
|
|
2171
2188
|
return [names.copy()];
|
|
2172
2189
|
case "mint": {
|
|
2173
|
-
const colouredOut =
|
|
2190
|
+
const colouredOut = colouredOutputs(outputPlaces, fragment);
|
|
2174
2191
|
const nm = names.copy();
|
|
2175
2192
|
if (colouredOut.length > 0) {
|
|
2176
2193
|
const fresh = sym.next++;
|
|
@@ -2187,6 +2204,17 @@ function nameSuccessors(role, names, outputPlaces, fragment, sym) {
|
|
|
2187
2204
|
}
|
|
2188
2205
|
return result;
|
|
2189
2206
|
}
|
|
2207
|
+
case "consume": {
|
|
2208
|
+
const colouredOut = colouredOutputs(outputPlaces, fragment);
|
|
2209
|
+
const result = [];
|
|
2210
|
+
for (const s of names.symbolsIn(role.colouredInput)) {
|
|
2211
|
+
const nm = names.copy();
|
|
2212
|
+
nm.remove(role.colouredInput, s, 1);
|
|
2213
|
+
for (const p of colouredOut) nm.add(p, s, 1);
|
|
2214
|
+
result.push(nm);
|
|
2215
|
+
}
|
|
2216
|
+
return result;
|
|
2217
|
+
}
|
|
2190
2218
|
}
|
|
2191
2219
|
}
|
|
2192
2220
|
function enablingSymbols(names, colouredIn) {
|
|
@@ -2210,8 +2238,8 @@ function enablingSymbols(names, colouredIn) {
|
|
|
2210
2238
|
|
|
2211
2239
|
// src/verification/nu-scg-verifier.ts
|
|
2212
2240
|
var NOTE_EXACT = "\nNote: \u03BD-join correlation decided exactly via the state-class-graph name-partition quotient \u2014 the symbolic graph closed, so the verdict is sound AND complete (no spurious different-name counterexample; quiescence is name-aware), beyond the bounded-budget fragment (NU-050, Route B).\n";
|
|
2213
|
-
function verifyViaNameScg(net, initial, property, sinkPlaces, environmentPlaces, environmentMode, maxClasses) {
|
|
2214
|
-
const fragment = classify(net);
|
|
2241
|
+
function verifyViaNameScg(net, initial, property, sinkPlaces, environmentPlaces, environmentMode, maxClasses, fragmentMode, carrierPlaces) {
|
|
2242
|
+
const fragment = classify(net, fragmentMode, carrierPlaces);
|
|
2215
2243
|
if (fragment === null) return null;
|
|
2216
2244
|
for (const p of initial.placesWithTokens()) {
|
|
2217
2245
|
if (fragment.isColoured(p.name)) return null;
|
|
@@ -2322,6 +2350,8 @@ var SmtVerifier = class _SmtVerifier {
|
|
|
2322
2350
|
_environmentMode = alwaysAvailable();
|
|
2323
2351
|
_timeoutMs = 6e4;
|
|
2324
2352
|
_nuMaxClasses = 1e5;
|
|
2353
|
+
_fragmentMode = "base";
|
|
2354
|
+
_carrierPlaces = /* @__PURE__ */ new Set();
|
|
2325
2355
|
static forNet(net) {
|
|
2326
2356
|
return new _SmtVerifier(net);
|
|
2327
2357
|
}
|
|
@@ -2381,6 +2411,38 @@ var SmtVerifier = class _SmtVerifier {
|
|
|
2381
2411
|
this._nuMaxClasses = max;
|
|
2382
2412
|
return this;
|
|
2383
2413
|
}
|
|
2414
|
+
/**
|
|
2415
|
+
* Selects the ν-net coloured-place fragment for Route B (NU-051). `base`
|
|
2416
|
+
* (default) admits the shipped mint → matched-join fragment only; `extended`
|
|
2417
|
+
* additionally admits the opt-in coloured-consumer (drain/relay) role and the
|
|
2418
|
+
* declared {@link carrierPlaces}. When `extended` is requested but the net
|
|
2419
|
+
* falls outside the coloured-consumer fragment, Route B declines and a short
|
|
2420
|
+
* note is appended to the report before falling back to the sound
|
|
2421
|
+
* over-approximation.
|
|
2422
|
+
*/
|
|
2423
|
+
fragmentMode(mode) {
|
|
2424
|
+
this._fragmentMode = mode;
|
|
2425
|
+
return this;
|
|
2426
|
+
}
|
|
2427
|
+
/**
|
|
2428
|
+
* Declares ν-net *carrier* places (NU-051, EXTENDED only): intermediate places
|
|
2429
|
+
* that carry a fresh name from the minting fork onward to a ν-join input. Under
|
|
2430
|
+
* {@link fragmentMode} `extended` they are unioned into the coloured set so the
|
|
2431
|
+
* existing mint co-mints one fresh name into all of them; under `base` they are
|
|
2432
|
+
* ignored. Accumulating. Throws if a declared place is not in the net — a
|
|
2433
|
+
* mistyped carrier name would let two fork branches mint independent names, so
|
|
2434
|
+
* the join never becomes name-enabled and the verifier would otherwise report a
|
|
2435
|
+
* confident false deadlock; it must surface, never silently proceed.
|
|
2436
|
+
*/
|
|
2437
|
+
carrierPlaces(...places) {
|
|
2438
|
+
for (const p of places) {
|
|
2439
|
+
if (![...this.net.places].some((np) => np.name === p.name)) {
|
|
2440
|
+
throw new Error(`declared carrier place '${p.name}' not in the net`);
|
|
2441
|
+
}
|
|
2442
|
+
this._carrierPlaces.add(p.name);
|
|
2443
|
+
}
|
|
2444
|
+
return this;
|
|
2445
|
+
}
|
|
2384
2446
|
/**
|
|
2385
2447
|
* Runs the verification pipeline.
|
|
2386
2448
|
*/
|
|
@@ -2403,7 +2465,9 @@ var SmtVerifier = class _SmtVerifier {
|
|
|
2403
2465
|
this._sinkPlaces,
|
|
2404
2466
|
this._environmentPlaces,
|
|
2405
2467
|
this._environmentMode,
|
|
2406
|
-
this._nuMaxClasses
|
|
2468
|
+
this._nuMaxClasses,
|
|
2469
|
+
this._fragmentMode,
|
|
2470
|
+
this._carrierPlaces
|
|
2407
2471
|
);
|
|
2408
2472
|
if (outcome !== null) {
|
|
2409
2473
|
report.push("=== \u03BD-net Route B: name-aware state-class graph (NU-050) ===");
|
|
@@ -2428,6 +2492,11 @@ var SmtVerifier = class _SmtVerifier {
|
|
|
2428
2492
|
}
|
|
2429
2493
|
);
|
|
2430
2494
|
}
|
|
2495
|
+
if (this._fragmentMode === "extended") {
|
|
2496
|
+
report.push(
|
|
2497
|
+
"\u03BD-net Route B (EXTENDED) declined: net outside coloured-consumer fragment (a coloured place consumed count != 1 or by multiple inputs, carries a reset/read/inhibitor arc, or a join re-mints a coloured place); verified via sound over-approximation instead."
|
|
2498
|
+
);
|
|
2499
|
+
}
|
|
2431
2500
|
}
|
|
2432
2501
|
report.push("Phase 1: Flattening net...");
|
|
2433
2502
|
const flatNet = flatten(this.net, this._environmentPlaces, this._environmentMode);
|
|
@@ -2770,4 +2839,4 @@ export {
|
|
|
2770
2839
|
isProven,
|
|
2771
2840
|
isViolated
|
|
2772
2841
|
};
|
|
2773
|
-
//# sourceMappingURL=chunk-
|
|
2842
|
+
//# sourceMappingURL=chunk-YKJQ7IKZ.js.map
|