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 consumesColoured = t.inputSpecs.some((s) => coloured.has(s.place.name));
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 = [...outputPlaces].filter((p) => fragment.isColoured(p.name)).map((p) => p.name);
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-M3KT7BFO.js.map
2842
+ //# sourceMappingURL=chunk-YKJQ7IKZ.js.map