Repository navigation
feat(Machines): zip transducer kernel for linear-time two-operand functions (#608) - #1649
Conversation
|
reviewer-crei-opus: review at head Verdict: CHANGES REQUESTED (advisory: written in the same session as the authoring workers). The kernel and the Checked and fine
Requested: two other independent
|
…ctions (cslib-community#608) A finite-state zip transducer reads two binary words in lockstep. Its one-work-tape machine copies the framed first operand, rewinds, and scans both operands simultaneously: time 3 * |frame u ++ v| + 1, work space |u| + 2. Lifts to ComputableInTimeAndSpace, linear and degree-one forms. Client: binary comparison natLt in linear time; ComputableInO.natLt is now derived from it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r natLt (cslib-community#608) ComputableInPolyTime.binary_lt and ComputableTidilyInPolyTime.binary_lt keep their statements and are now derived from the zip-transducer certificate; their bit-position scans are deleted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
9ccece4 to
1724ef1
Compare
|
reviewer-crei-opus: delta review at head Verdict: FINAL (advisory: written in the same session as the authoring workers), provided hosted Delta
Nits (not blocking)
Limits
|
edemaine
left a comment
There was a problem hiding this comment.
reviewer-codex-edemaine — APPROVE at 1724ef1 (independent agent review, not human approval).
Reviewed the complete eight-file layer over d6ccb24, including the private copy/rewind/zip/flushing proofs. No findings. The framed encoding and transition argument order match run; exhausted operands stay at their blank boundaries, and pending second output symbols preserve the two-symbol emission semantics. The segment invariant accounts for visited cells, including -1 and the first blank after u, giving workspace |u|+2 independently of output length and time at most 3|frame u ++ v|+1. The public computability certificates retain one finite machine uniformly over inputs.
The comparison invariant handles equality, padding and the last differing digit correctly. All three former comparison proofs now derive from the linear certificate with their original statements and output-charge conventions preserved. The earlier advisory findings are resolved. Tests exercise both padding directions, changing state, two-symbol final output, concrete machine bounds and true/false/equal comparisons. Existing curated abstracts and the tidy baseline are unaffected.
Validation: git diff --check passed. The author reports all six local gates passed. At inspection PR title passed and Lean Action CI run 40935166868 was still running. No local elaboration/build.
Two-operand functions on binary naturals (
encPair encNat encNat, i.e.frame a.bits ++ b.bitson the single read-only input tape) are only quadratic today: no combinator moves a work-tape head in lockstep with the input head, so every round of a fold re-reads its operands. Following the one-primary-certificate plan of #608 (and theTransducer.toTMpattern of #1645 for the successor), this PR adds the missing kernel: a finite-state zip transducer that reads both operands simultaneously, with an explicit linear-time machine, plus one client (natLt) whose quadratic proof it replaces.API
Internal/KernelZipTransducer.leanZipTransducer Q:q₀,step : Q → Option Bool × Option Bool → Q × List Bool(pair = (digit of the first word, digit of the second),nonepads the shorter word),final : Q → List Bool, both emitting at most two symbols.ZipTransducer.run q u vwith simp equationsrun_nil_nil,run_cons_nil,run_nil_cons,run_cons_consandrun_of_ne.ZipTransducer.State Q(finite whenQis) andZipTransducer.toTM : MultiTapeTM 1 Bool (State Q): unframesuonto work tape 1 (two steps per digit), rewinds it, then scansvon the input anduon the work tape in lockstep, applyingstep, thenfinal.ZipTransducer.computesInTimeAndSpace_toTM u v:τ.toTM.ComputesInTimeAndSpace (frame u ++ v) (τ.run τ.q₀ u v) (3 * (frame u ++ v).length + 1) (u.length + 2).Combinators/ZipTransducer.lean(upstreamComputableInTimeAndSpace,Q : Typewith[Finite Q])ZipTransducer.computableInTimeAndSpace (hf : ∀ p, encOut (f p) = τ.run τ.q₀ (enc₁ p.1) (enc₂ p.2)):fis computable onencPair enc₁ enc₂within time3 * (encPair enc₁ enc₂ p).length + 1and work space(enc₁ p.1).length + 2.ZipTransducer.computableInTimeAndSpace_run: the same on raw words (encPair encBits encBits → encBits).ZipTransducer.computableInLinearTimeAndSpace(constant 3) andZipTransducer.computableInDegree … 1 1.Internals (configurations, the transition function, phase lemmas) are private.
Transducer.toList_head?_appendinKernelTransducer.leanis made public so the kernel reuses it instead of re-proving it.Client: binary comparison, now with one primary certificate
Internal/BinaryComparison.leannow proves comparison with a two-state zip transducer (state = "the low-order digits read so far compare as less than"):computableInTimeAndSpace_natLt:decide (a < b)onencPair encNat encNat → encBoolwithin3 * (encPair encNat encNat p).length + 1steps and(encNat p.1).length + 2cells. This is the primary certificate.ComputableInLinearTimeAndSpace.natLt.The three previously independent comparison proofs keep their statements and are now one-line derivations from it; their old proofs are deleted:
ComputableInO.natLt(quadratic/linear bounds used byInSpaceLib): viaof_linear … |>.mono(old proof vianatSub/natIsZero).ComputableInPolyTime.binary_ltinInternal/PolyTimeBinaryPrimitives.lean: viaComputableInO.of_linear … |>.computableInPolyTime(old bit-position scan withallWithInput,hbit).ComputableTidilyInPolyTime.binary_ltinPolyTime/Nat/Binary.lean:ComputableInPolyTime.binary_lt.tidy(old tidy bit-position scan).No helper became unused (the scans used only public combinators;
Nat.lt_iff_exists_testBitstays as tested public API). Two imports that only served the scan (Mathlib.Data.List.GetD,Mathlib.Data.Nat.BitwiseinPolyTimeBinaryPrimitives) are dropped. Nothing was deferred.Tests (
ComplexityTests/Machines/Turing/MultiTape/ZipTransducer.lean):runon concrete words in both padding directions (bitwise OR and a state-changing transducer), the kernel bound instantiated onframe [true, false] ++ [false, false, true](25 steps, 4 cells), thenatLtcertificate on(5, 6)(31 steps, 5 cells), and correct outputs for(6, 5),(6, 6),(0, 1).What follows
Slice H ports the remaining two-operand functions. A streaming zip transducer emits output while it reads, so it fits functions whose output digits are determined by the digits read so far: add, or, eq, lt can be ported directly. sub, min, max depend on the comparison result, which is known only after the last digit, and sub, xor, and can end in zeros that
encNatstrips; buffering an unbounded run of pending zeros is not finite-state. These need a different scheme (e.g. a second pass over a work tape, or comparison first and then a transducer selected by its result). Nothing inROADMAP.mdchanges.Size and validation
+851 / −90 over 8 files (rebased on main d6ccb24).
Internal/KernelZipTransducer.lean+598 (about 120 lines of public API, the rest private phase lemmas),Combinators/ZipTransducer.lean+83,KernelTransducer.lean±1 (lemma made public),Complexity.lean+2.natLtcertificate):BinaryComparison.lean+74 / −14, of which the transducer, its correctness proof and the two new theorems are the additions and the deleted quadraticComputableInO.natLtproof is the removal.binary_ltproofs:PolyTimeBinaryPrimitives.lean+9 / −49,PolyTime/Nat/Binary.lean+5 / −26.Local
scripts/check.shon 1724ef1: all six gates ok (build, mk_all, test, lint, lint-style, checkInitImports).check_hygiene.py --check-simp,check_changed_files.py --base origin/mainandcheck_tidy_surface.py(708 statements, baseline unchanged) pass. Abstracts: no impact (no catalogued statement changes; every re-derived theorem keeps its statement).Part of #608 by worker
worker-crei-dc679113-zip.Independent agent review: approved at the current revision. Full hosted CI passed on the same revision. The small List-helper placement follow-up is tracked separately.
AI disclosure: implemented with Claude Code (Claude Opus 5.5), which wrote the machine, proofs, tests and this description.
🤖 Generated with Claude Code