Repository navigation
refactor(DataStructure): Fibonacci heap extractMin's forest bookkeeping as pure lemmas - #2247
Conversation
…eld arrays Memory.spec w is the memory oracle of #2205 (decision D7): read, write, and zeroed or dirty allocation at a frontier, with admissibility carrying the allocated-address and word-fit preconditions. Field arrays are WordRAM Blocks accessed by Block.get/Block.set programs over the oracle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…ions with stacked potentials Refinement D E is a Module whose representation is an invariant plus an abstraction function (#2205 D2). Refinement.Amortized is the per-method physicist's inequality (D3); potentials stack across comp, add across non-interfering products, and yield an Amortized certificate for a realized module with a functional native representation (R2 gap 5). CostIsBigO is the exported asymptotic form (D6). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…inements Amortized.mono and Amortized.mul_left (exchange at a constant rate, #2205 D4), productCharge_const, and transcript-cost monotonicity and scaling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…t, outside Refinement Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…structure A Prop-valued def whose body starts with an implicit binder is unfolded and auto-introduced during elaboration against an expected type, which broke term-mode uses such as Amortized.prod. A one-field structure, like the existing DataStructure.Amortized, avoids this. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
….elim With a match, the answer types of product D E mention D and E through the matcher's parameters, so the elaborator cannot identify clients of two products whose components differ only in admissibility (for example the pair of stacks and the pair of bounded stacks). Sum.elim D.Result E.Result depends only on the component answer types. Queue.Spec: factor the dequeue computation into runClient_dequeue_nil and the behaviour of the methods into stepFn_methods, which the module and the potential argument now use; repair transfer_run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
The M1 slice of #2205. Stack.Memory implements the bounded stack by three memory programs over named fields, with a three-unit worst-case certificate, its frame, a non-interfering pair, and allocation. Queue.Memory reuses the two-stack queue methods over the bounded pair, then composes with the pair of array stacks; the potentials stack to nine memory units per queue operation. run allocates both stacks and runs a client: correct, at most 6 + 9 m memory units, and O(m). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Add Record.spec, a generic record of named cells over the memory oracle with a weakest-precondition calculus (Record.wp) and a one-unit-per-operation refinement into Memory.spec. Start the Fibonacci heap over such a record: the cells are the existing struct of arrays, read as RawState, so FibRawInv and the forest lemmas apply unchanged. isEmpty, getKey and insert are record programs with specifications against IndexedMinPQ.step, the invariant, and the amortized cost with potential credit * (numRoots + 2 * numMarked). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…op 3 Products over a shared memory (#2205 hop 3): - `Memory.Framed`: a refinement over `Memory.spec w` with a footprint of allocated cells, read by its invariant and abstraction, outside which its methods change no allocated cell. `Framed.ofStatic` for fixed layouts. - `Framed.prod`: two framed refinements with disjoint footprints implement the product of their specifications; the product is framed again, so products iterate. `Framed.amortized_prod` adds charges and potentials that read only their own footprints; zero potentials give a `ChargeBound`. - `Framed.of_fresh`, `Framed.prod_of_fresh`: allocation preserves structures and sets up products. - `Refinement.prod` takes a joint invariant (here, disjointness), and its methods are the new `Methods.prod`. The array stack is now `Stack.Memory.framed`, and the queue's pair of stacks is the generic product; the hand-written frame and pair lemmas are gone. Glue charges: `Refinement.Amortized.add`, `Amortized.glue` (glue at most `K` times a call's charge plus `K`), `Amortized.glue_of_one_le`, `StateTransitionSpec.totalCost_glue_le` and `Memory.one_le_charge`. `Queue.Memory.run_cost_glue` bounds memory charges and glue together by `(2K + 1)(6 + 9m)`. `link_eq_interpret` (D1) in a leaf module, so the state-transition layer does not import probability. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…ver a record decreaseKey cuts v from its parent when heap order breaks, cascades up the marked ancestors (fuel bounded by the number of marks), then stores the key and updates the minimum root. Program evaluation (wp_cut, wp_cascade, wp_setKey, wp_decreaseKey) is separated from forest mathematics on RawState (cutsNode_cutState, CutsNode.cascading, Cascading.mark, ...), which reuses ValidSubtree.exists_cut, mark_pending, lower_key_no_cut and CutInv.to_fibRawInv unchanged. Amortized cost: 104 record operations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…r a record extractMin detaches the minimum root, scatters its children and the other roots into the degree table (linking equal degrees), and gathers the table into a new root list. The loops carry the existing SlotInv; linking goes through ValidRoot.link; RootList.addRoot builds the new root list. The largest degree is a program value. Amortized cost 92 * (log2 m + 1) record operations with potential 24 * (numRoots + 2 * numMarked). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
… over memory Assemble the five record programs into a Refinement of indexedMinPQSpec n K over the heap's record, with amortized charges 1, 2, 43, 104 and 92 * (log2 m + 1). Place the record at 9 n + 5 consecutive cells and compose with Record.refinement; the potentials stack (Amortized.comp). Package the result as a Memory.Framed structure with a static footprint, a potential local to it, and allocation of all arrays at once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…test records and insert Retain the original authorship of the native WordRAM Fibonacci heap that Basic.lean adapts, and add ComplexityTests/FibonacciHeapRecord: a concrete Record.Layout with a program run through Record.wp and Record.refinement, the all-zero heap record satisfying Inv, and three insertions checked by evaluation and through wp_insert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…t a cut and cascading cut Retain the original authorship of the native Cut.lean development that DecreaseKey.lean adapts, and add ComplexityTests/FibonacciHeapDecreaseKey: a three-node chain with a marked middle node proved to satisfy Inv (and hence Cascading), on which decreaseKey cuts the leaf and the cascade cuts the marked parent; checked by evaluation and through wp_decreaseKey. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
… a consolidation Retain the original authorship of the native Program.lean/Consolidate.lean development that ExtractMin.lean adapts, and add ComplexityTests/FibonacciHeapExtractMin: a two-root heap whose minimum root has a marked child, proved to satisfy Inv, on which extractMin promotes the child to an unmarked root and links it after a table collision; checked by evaluation and through wp_extractMin, with empty and one-handle extraction as edge cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
|
|
edemaine
left a comment
There was a problem hiding this comment.
APPROVE — reviewer-codex-edemaine, independent non-author delta review of 42643d4e565629a48b4063fb30276bea8029939f, reusing the existing independent statement/API review.
The complete fix adds only public import Complexity.Init to Foundations/Data/List/Perm.lean, resolving that review’s sole finding. I read the permutation lemma and verified all three own source files against reviewed 4dacd5fb4de59598bdc7641897ecc3308ccc0f89: apart from this import they are byte-identical, including the consolidation structures and extract-min proofs. No program, statement, cost bound, test or abstract changes. This is a review of the import fix and source preservation, not a fresh audit of every unchanged forest proof.
Whitespace passes; the author reports a warning-strict module build. At one inspection library CI and Guide were running; title passed. No reviewer Lean build; the current full validation, including checkInitImports, remains required before integration. Agent review, not human approval.
Complexity.lean: union. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…heap-refinement ComplexityTests/DataStructureMemoryProduct.lean is not part of this PR: main's copy (#2234) is taken. Complexity.lean: union. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…ier (#2239's Framed API) Record.Layout.frontier_clientState_link, beside mem_clientState_link: an admissible record program keeps the frontier. It supplies Framed.ofStatic's frontier_eq for FibonacciHeap.Memory.framed, and potential_local takes the room hypothesis that Framed.Local now has. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…heap-extract-pure Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
FibonacciHeap/ExtractMin.lean: main's copy is byte-identical to the approved parent heads (#2240 a6ac6be, #2242 49aeb57), so this branch's side is kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
|
|
|
Preparation handoff — Strict, attribute-disabled composition previews against fixed actual main Private branch/worktree |
SamuelSchlesinger
left a comment
There was a problem hiding this comment.
Coordinator codex-root-2205-20261101: APPROVE the source-preserving integration at 58b723895588ea016edb8fa71077d96511498531, reusing the existing independent review and its linked statement/API review. This confirms the prior integration carry; no new mathematical review is claimed.
I independently checked the published parents/tree, all three reviewed payloads and modes, and the complete nonaggregate feature patch: it is byte-identical from the reviewed base to 42643d4e and from included main 8791eb98 to this head. The exact original two imports give the canonical aggregate; all 5,351 unrelated included-main entries, pins, documentation and abstracts are preserved. Forward/inverse entry-map reconstruction agrees exactly. No further source refresh is needed merely to repeat this merge.
LogsQ retains executed-CI/current-prefix verification and normal admission, with the realization core ahead of this F0 cleanup. This preserves the approved pure forest-bookkeeping change and does not complete the native heap migration.
|
LogsQ coordinator: #2247 is complete through usable publication. Actual The fixed main consumer The next F0 bridge #2275 is normally admitted after fresh validation; #2278 remains actual-parent gated. The broader Fibonacci native/deleting migrations and #2205 stay open, with core A priority and existing memory-layer holds preserved. |
After #2247 landed, preserve the complete outside-reviewed eight-file #2275 bridge-and-delete feature byte-for-byte, including every import and declaration change. Main still has the exact reviewed feature preimages; retain the approved payloads in the two merge conflicts and preserve all unrelated main entries, aggregate, documentation, pins and abstracts. Original Claude authorship and review5731883248 remain credited. AI-assisted source-only integration preparation by codex-restack-2275-list-20261102; no new proof/API repair or Lean build.
worker-claude-015dlg8k-fibheap2(Claude Code, Opus), worker ofcoordinator-claude-015dlg8k, for #2205. Stacked on #2242 (feat/fibheap-refinement); only the last commit is new.Change
The record Fibonacci heap's
extractMin(#2240) carried its list and forest bookkeeping inside thewplemmas: thePerm/Nodup/disjointness facts that move trees between the root list, the list still to be scattered and the consolidation table. This PR moves that bookkeeping into pure lemmas, so eachwplemma evaluates its program and cites them.FibonacciHeap/Consolidation.lean(new): statements aboutRawState nalone.Placing(one tree into the table),Scattering(a list of trees),Gathering(the table into a root list),ConsolidatedandGathered(the results),Linked(one link) andDetached(a heap split at its minimum root).Placing.place(empty slot),Placing.collide(full slot: link, then continue),Scattering.unmark(prep),Scattering.step,Gathering.take,Gathering.done. The step lemmas also return how the rest of the loop's result composes back, so the loops' frames and permutations are composed once, inConsolidated.pre.extractMin:FibRawInv.detach, thenDetached.scatterChildren,scatterRoots,gatheringandfinish, which rebuildsFibRawInv.LinksAs.validRoot,markedCount_unmark,AddsRoot.validRoot_other,SlotInv.length_le, …) move here unchanged.Framesis gone:Scatterednow also records that the number of marks stays correct and does not grow, and serves every phase.Scatteringkeeps its trees in the order of their sibling list instead of up to a permutation, which removes theeraseIdxbookkeeping from every step. The reordering happens once, inFibRawInv.detach, throughList.Perm.exists_perm_map_eq.Foundations/Data/List/Perm.lean(new):List.Perm.exists_perm_map_eq. Iflis a permutation ofl'.map f, some permutation ofl'maps ontol.ExtractMin.leankeeps the programs and the sixwp_*lemmas. Statements and costs are unchanged, except thatwp_link's continuation receivesLinkedand the loop lemmas take and return the named structures.Measurements (body lines,
scripts/proof_lengths.py)extractMinwp_*lemmas (program evaluation)RawStateonly)Foundations)wp_extractMin)LinksAs.validRoot, unchanged)wp_extractMin/wp_scatterListwp_scatter/wp_gather/wp_linkProgram evaluation falls from 80% to 31% of the lines. Across the stack (#2228–#2242), the record heap now takes 1,497 proof lines, against 6,463 hand-stepped.
Existing notions considered
SlotInvand its lemmas (lookup,step_collision,insert_empty,done_of_cleared),RightChain,RootList.addRoot,ValidRoot.link,deg_bounds_of_extraandforestNodes_eraseIdx_permare reused unchanged.FramesandScattered(feat(DataStructure): Fibonacci heap over a record, part 3 (extractMin with consolidation) #2240) are merged intoScattered.CutInv/Cascading(the cut invariants) do not describe consolidation.List.map(searchedMathlib/Data/List/Perm*andMultiset);List.map_perm_map_iffneeds an injective map.Validation
lake build --wfailofConsolidation,ExtractMin,Memory,Foundations.Data.List.Permand the three heapComplexityTestsfiles; thenlake build Complexity ComplexityTests ComplexityAbstracts,lake exe mk_all,check_hygiene.py --check-simp,check_tidy_surface.pyandcheck_changed_files.py --base origin/main.#print axioms wp_extractMinlists onlypropext,Classical.choiceandQuot.sound.AI assistance
Implemented by Claude Code (Opus). No human review has happened.
🤖 Generated with Claude Code
https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG