Repository navigation
refactor(Circuit): share twin arguments in critical paths, certificates, decomposability, fusion and DAG protocols - #4977
SamuelSchlesinger wants to merge 1 commit into
Conversation
Statement-preserving proof refactors from the #3725 repeated-proof backlog: - CriticalPath: the two prefix-dependence arguments of `exists_bottleneck_of_not_disjoint_criticalPath` (wires of `Px` depend only on `bx`, of `Py` only on `by_`) become one local `hprefix` instantiated twice; `nodup_criticalPathAux` reuses `rank_lt_of_mem_tail_criticalPathAux` instead of re-deriving the rank step. - Unbounded/Certificate: `getD_evalCode_eq_iff_of_claimable` handles the `and` and `or` gates in one alternative. - Decomposable: `finite_values_of_nonempty_contexts` and `finite_contexts_of_nonempty_values` follow from the finiteness of `values ×ˢ contexts` with Mathlib's `Set.Finite.of_prod_left/right`. - Rational/SmallExpansion: `order_reversal_sum` takes both root-multiplicity bounds from one private `rootMultiplicity_basis_le`. - Fusion/Graph: `literals_sourceRefinement` proves once that each literal reads one half of the pair, replacing four copies of the containment argument. - Boolean/CriticalPath: the AND/XOR composition theorems share the tabulation lemmas `table_eq` and `comp_eq_table`. - DagProtocol: `exists_sep_of_mem` reduces separation to rectangles with a pair of inputs; `exists_sep_const`, `exists_sep_differsAt` and `exists_sep_exceedsAt` use it instead of repeating the empty-side cases.
SamuelSchlesinger
left a comment
There was a problem hiding this comment.
Agent review (Jetski reviewer session 8a19d70d-301c-44e4-b4ac-9604ca6b59c8) of 2d4057fe3507486955477cb6bd139ae9a65fcedb: approve
This is refactoring only: seven independent twin removals in Computability/Circuit/, and no statement changes. I read the full diff against origin/main and the surrounding proofs at the head. Public statements, names and attributes are unchanged, and no @[expose] body is touched. Every new helper is private and sits in the file that uses it. I found no sorry, native_decide, heartbeat option or line over 100 characters. Non-terminal simps are simp only, and simp_all appears only as a terminal call in the moved 64-case check.
Here is how each item holds up:
nodup_criticalPathAuxis the clearest improvement. Instead of re-deriving the rank step and splitting on head/tail, it now appliesrank_lt_of_mem_tail_criticalPathAux (fuel + 1) v v, which takes 4 lines where the old proof took 12.hprefixis the weakest item, but I think it is still worth keeping. The block shrinks from 41 lines to 35, which matches the PR's "6 lines". The two 17-line inductions really did differ only by swapping x/y,Px/Py,hclosedX/hclosedYanddisjoint_left/disjoint_right. The proof is now written once, and the new comment explains why a slot read from outsidePlies on neither prefix. On the downside, the local statement takes six hypotheses, and each instantiation is about as long as the statement it proves. Optional nit: theinput_mem_criticalPath_ifflambda appears twice and could be bound once beforehX.- Certificate. Merging the
and m | or malternatives is a straightforward deduplication. The combinedsimp onlycovers both interpretations, and the 9-line tail is now shared. - Decomposable. This is a real improvement.
finite_values_prod_contextstogether with Mathlib'sSet.Finite.of_prod_left/of_prod_rightreplaces two hand-written injectivity arguments. - SmallExpansion.
rootMultiplicity_basis_leis a direct extraction of the oldhbd/hcd. I found no MathlibrootMultiplicity ≤ natDegreelemma that would make it unnecessary. - Fusion/Graph.
hdepseparates "each literal reads one half" from building the witness. The four branches shrink to one-line simps, and the witness is built twice instead of four times. - Boolean/CriticalPath.
table_eqandcomp_eq_tablereplace the twoconvert … using 2blocks plus theirhG'setup, so both theorems are now arwfollowed by anexact. - DagProtocol.
exists_sep_of_memhandles the empty-side cases once, which removes 8–10 lines from each ofexists_sep_differsAtandexists_sep_exceedsAt. After this change,exists_sep_consthas a single caller and a one-line body. Keeping it as a named fact is fine.
Minor point about the description: it cites a per-file elaboration table "in the implementation notes", but those notes are not linked from the PR. Either link them or drop the reference. This does not block approval.
The PR states that no manual needs an edit, and I agree: none of the touched declarations appear in manual/ or guide/. I did not build locally. CI on this head was still pending when I wrote this review, so I am relying on CI for the --wfail build and for the repeated-block and duplicate-statement notices.
Part of #3725 (repeated proof machinery). Author: Jetski worker sessions
025a212a(delegating) and9c230e46(implementation), branchproofs/circuit-twins. This PR is its own task record.Small, independent twin removals across seven circuit-complexity files. Each was flagged by
scripts/proof_copies.py, and each now makes its argument once:Circuit/CriticalPath.lean. Inexists_bottleneck_of_not_disjoint_criticalPath, the 16-linehX/hYtwin (a wire of one prefix depends only on its own input) is one localhprefix, instantiated for each prefix.nodup_criticalPathAuxreusesrank_lt_of_mem_tail_criticalPathAuxinstead of re-deriving the rank step.Circuit/Boolean/Unbounded/Certificate.lean. IngetD_evalCode_eq_iff_of_claimable, theand m | or mcases share one alternative, so their 9-line tail is no longer duplicated.Circuit/Decomposable.lean. The privatefinite_values_prod_contextsproves that the rectanglevalues v ×ˢ contexts vis finite.finite_values_of_nonempty_contextsandfinite_contexts_of_nonempty_valuesthen follow from Mathlib'sSet.Finite.of_prod_left/of_prod_right, which replaces two 10-line injectivity proofs.Circuit/Rational/SmallExpansion.lean. The privaterootMultiplicity_basis_leserves both bases inorder_reversal_sum.Circuit/Fusion/Graph.lean.literals_sourceRefinementshows once that each literal reads only one side, which replaces four copies of the containment argument.Circuit/Boolean/CriticalPath.lean. The privatetable_eq/comp_eq_tablehold the tabulation and the 64-case check used by bothnot_isAndType_comp_of_isAffineOpandnot_isXorType_comp_of_not_isAffineOp.Circuit/DagProtocol.lean. The privateexists_sep_of_memhandles the empty-rectangle cases, which a constant separates.exists_sep_const,exists_sep_differsAtandexists_sep_exceedsAtuse it.No public statement, attribute, name or exposed body changes; the only declaration-line changes are new or moved private helpers. Net −50 lines (+117/−167).
proof_copies.pyreports no repeated block in the touched files. Dropped:Occurs.toFun_eq_trueinNNF/Rectangle.lean, where a shared step would need the sibling-swap facts and would not be shorter. ThehprefixinCriticalPath.leansaves only 6 lines; its value is that it states the x/y symmetry once.This is refactoring only, with no new mathematics.
Validation:
lake build --wfail --iofailof each touched module;scripts/check.sh --quickpassed. That run covered the affected modules and clients, includingCslibFrontierTests.{WeftOneCertificate,NonVacuity,DagProtocol},Fusion/Graph/*,Rational/Rectangularand the PRF circuit lower bound, with lint on 63 modules, hygiene, changed-file lints, ratchets andmk_all --check. Single-file elaboration (lake env lean, one run each on a noisy host, before → after): CriticalPath 14.4 → 13.0 s, Certificate 13.1–26.3 → 14.1–15.5 s (one 35.3 s outlier), Decomposable 6.2 → 4.2 s, SmallExpansion 14.5 → 15.4 s, Fusion/Graph 5.2 → 4.6 s, Boolean/CriticalPath 6.2 → 6.0 s, DagProtocol 6.8 → 7.9 s. CI does the full run.Manuals: neither the Operator's Manual nor the Agent Operator's Manual describes these proofs, so neither needs an edit.
AI assistance: prepared by AI agents (Jetski). Not reviewed by a human.