Skip to content

benchgraph: survival plot + trimmed head-to-head report - #13

Merged
gaperez64 merged 12 commits into
mainfrom
verdict-trust-fixes
Jun 25, 2026
Merged

benchgraph: survival plot + trimmed head-to-head report#13
gaperez64 merged 12 commits into
mainfrom
verdict-trust-fixes

Conversation

@gaperez64

Copy link
Copy Markdown
Owner

Reframe the preprocessor section of BENCHGRAPH.md around the direct
head-to-head: ltlsynt vs preprocessor+ltlsynt.

  • Add a cactus/survival plot (docs/benchgraph/survival.png): per engine, the
    i-th fastest definitive solve (SOLVED or UNREAL), log-time, timeout line,
    solved counts in the legend. Curve further right = solves more; lower = faster.
  • Trim write_report to the essentials: run params, self-contained %, a
    solved-within-timeout table with the net gain, both-solved speedup, the
    embedded plot, and a correctness line (false-UNREAL / false-REAL vs the
    ltlsynt oracle). Drops the verbose residual-reduction/complexity prose.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV

gaperez64 and others added 12 commits June 24, 2026 13:34
Reframe the preprocessor section of BENCHGRAPH.md around the direct
head-to-head: ltlsynt vs preprocessor+ltlsynt.

- Add a cactus/survival plot (docs/benchgraph/survival.png): per engine, the
  i-th fastest definitive solve (SOLVED or UNREAL), log-time, timeout line,
  solved counts in the legend. Curve further right = solves more; lower = faster.
- Trim write_report to the essentials: run params, self-contained %, a
  solved-within-timeout table with the net gain, both-solved speedup, the
  embedded plot, and a correctness line (false-UNREAL / false-REAL vs the
  ltlsynt oracle). Drops the verbose residual-reduction/complexity prose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
Both bugs are under-approximations (strengthenings): sound for a REALIZABLE
verdict, but their UNREALIZABLE verdict is not trustworthy. Found via
lily/lilydemo19 and lily/lilydemo23 in the corpus benchgraph.

1. certify_reachability / certify_persistence pinned a controllable output to a
   constant (o:=true) for `F o` / `FG o` even when the output was NOT free —
   despite the comment saying "free controllable output". For an output coupled
   via a mutex `!(hl&&fl)`, pinning `hl:=true` collapsed it to `!fl`, falsely
   making the `fl` response cluster UNREALIZABLE. They now decline when the
   output is referenced by any other constraint (output_constrained_elsewhere).
   The mutex there is an INVARIANT (no explicit G), so a CAND_MUTEX check would
   miss it — the direct support check is the right level. Updates the
   reach_blocked golden, which had documented the bug (its own description says
   "not free -> residual" yet it certified).

2. cluster_assumption_mask drops a liveness assumption from a safety-only
   cluster; its comment proves that sound for REALIZABLE only. So when a SAFETY
   cluster reports UNREAL and the spec has a liveness assumption, re-solve the
   cluster with all assumptions kept (prune=false) via the authoritative
   ltlsynt; flip to REAL only if ltlsynt produces a controller (cannot introduce
   a false-REAL). Gated on !has_liveness so it never re-runs the slow liveness
   tail.

lilydemo19/lilydemo23 now SOLVE; inv_decline/cluster_assume/amba_unreal stay
UNREAL; 194/194 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
Audit and classify every certifier by which verdict it is sound for, so the
under-approximations are explicit and the composition can flag them.

- VerdictTrust { TRUST_EXACT, TRUST_UNDER } + block_trust(Block*) registry.
  UNDER (strategy commitment, strengthens the residual; REAL sound, UNREAL not):
  reachability, persistence, response/server, arbiter, round-robin,
  global-recurrence-switch, safety-invariant.  EXACT (forced-value substitution,
  equivalence-preserving): definition, delayed-definition, reaction, set-reset,
  toggle, fixed-delay, guarded-next, and the mutex safety invariant.  No
  certifier OVER-approximates (false-REALs would be an OVER path; the --verify
  controller model-check is their guard).
- CsnfComposition.may_strengthen: set when an accepted block is UNDER.

Audit result: every UNDER certifier is soundly guarded against output coupling —
reachability/persistence by output_constrained_elsewhere (the false-UNREAL fix),
safety-invariant by output_is_free, and the (non-combinational) scheduler
families by the compose CONFLICT_SHARED_OUTPUT ejection.  The marking documents
this and gives a hook for future under-approximations.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
The OxiDD W/R-safety game encoding is NOT exact — it can WEAKEN the spec and so
emit a wrong controller (false-REAL), surfaced by the corpus benchgraph on the
robot-motion family (box/evasion/follow/square): tlsfcompose called them
realizable while ltlsynt (and Spot) say unrealizable.

Verdict-trust: an over-approximation's REALIZABLE verdict is not trustworthy.

- ComposeRoute.over_approx + exact=false on ROUTE_WR_SAFETY (the marking).
- When the W/R OxiDD path returns a controller and no --verify model-check is
  configured, confirm it with the authoritative ltlsynt before trusting it: if
  ltlsynt produces a controller use that, if ltlsynt says UNREAL report UNREAL,
  and if ltlsynt is unavailable/inconclusive keep the OxiDD controller (so the
  Spot-verified /bin/false W/R tests still solve self-contained). With --verify
  set, the existing self-verification gate already covers it.

box0/box1/evasion0/square5x5* now correctly report UNREALIZABLE; correct W/R
specs still solve; 194/194 tests green (route-stats goldens updated for
exact 1->0). (follow0/follow1 remain REAL in BOTH split and non-split and ltlsynt
agrees on the cluster — a separate tlsfcompose-vs-syfco translation discrepancy,
not this bug.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
Full 2545-spec head-to-head, ltlsynt vs preprocessor+ltlsynt, 30s/run. With the
verdict-trust fixes: 0 false-UNREAL across the corpus. At a 30s budget the
preprocessor net-loses on completeness (the decomposition/OxiDD overhead costs
the timeout race), so this captures the no-verify pipeline before the W/R
over-approx fix (which removes the false-REALs it shows).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
A large cluster's LTL formula (hundreds of KB) exceeds the per-argument exec
limit (Linux MAX_ARG_STRLEN, 128 KiB), so a `--formula=<huge>` spawn fails with
E2BIG.  That silently disabled the ltlsynt fallback / re-validation / verifier
on big specs, so tlsfcompose kept whatever the (possibly wrong) in-process
backend produced — surfacing as false-REALs on the big robot-motion specs
(follow0/follow1) where the W/R over-approx re-validation could not reach ltlsynt
to refute the bogus controller.

Switch every formula-to-subprocess path to a file:
- run_ltlsynt: write the formula to a temp file, invoke `ltlsynt -F FILE`.
- controller_violates_spec (--verify gate): `--formula-file FILE`.
- the generated compose.sh driver: `ltlsynt -F FILE`.

follow0/follow1 now correctly report UNREALIZABLE; 194/194 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
The existing --input-signals/--output-signals print the *declared* signals (bus
notation like g[0..0], parameters unresolved) on the raw spec — not the scalar
atoms a synthesizer needs.  Add --expanded-ins/--expanded-outs, which expand()
the spec (buses unrolled, parameters resolved) and emit a comma-separated,
space-free list ready to paste into `ltlsynt --ins=…/--outs=…`, matching syfco
--print-*-signals.

  tlsfinfo --expanded-outs full_arbiter.tlsf  ->  g_0,g_1

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
…section)

- Replace the command-line `ltlsynt --formula=…` / `-f "$(…)"` examples with the
  file-based `-F` form: a large cluster formula overflows the exec arg limit
  (E2BIG), matching the in-tool fix.
- Use the new `tlsfinfo --expanded-ins/--expanded-outs` for the synthesizer
  interface (the old `--input-signals | lc` left bus notation like g[0..0]
  unexpanded, breaking parametric specs); document the flags under "inspect".
- Point the benchgraph reference at the actual section name
  ("ltlsynt vs preprocessor + ltlsynt"); the old "Preprocessor speed &
  complexity" heading no longer exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
# Conflicts:
#	src/templates.c
#	test/cases/reach_blocked.residual
…nded-*

- clang-format the merged compose_*/templates/main_tlsfcompose sources.
- Regenerate test/cases/reach_blocked.csnf: the false-UNREAL fix makes the
  reachability certifier skip an output constrained elsewhere, so the block is
  now `candidate safety-invariant`, not `solved reachability` (the old golden
  predated the fix; it only runs in the research-tools build, which build-oxidd
  doesn't enable, so the local suite missed it).
- Add info_expanded_ins/info_expanded_outs golden tests covering the new
  tlsfinfo --expanded-ins/--expanded-outs flags.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
The verdict-trust additions (may_strengthen, VerdictTrust/block_trust) were not
clang-formatted; format only checked the .c files locally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
Replace the old 31.8%/×35/151 baseline with the current run (16.5%
self-contained, 0 false-UNREAL, 0 false-REAL, net +12) and add the verdict-trust
framework, W/R over-approx false-REAL fix, E2BIG file-based formula passing, and
tlsfinfo --expanded-ins/--expanded-outs to the Done list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvbjHkBHLYwxrFrvHae2xV
@gaperez64
gaperez64 merged commit baed1ea into main Jun 25, 2026
10 checks passed
@gaperez64
gaperez64 deleted the verdict-trust-fixes branch June 26, 2026 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant