Skip to content

feat(Algorithms/WordRAM): standalone Fibonacci heap and O(m + n log n) Dijkstra - #1462

Merged
SamuelSchlesinger merged 26 commits into
cslib-community:mainfrom
orbitingflea:wordram-fibonacci-heap-dijkstra-v2
Oct 29, 2026
Merged

SamuelSchlesinger merged 26 commits into
cslib-community:mainfrom
orbitingflea:wordram-fibonacci-heap-dijkstra-v2

Conversation

@orbitingflea

@orbitingflea orbitingflea commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Implements Milestone 2 of #1363 using the existing priority-queue/subroutine framework. Adds a static-array Fibonacci heap and instantiates the generic Dijkstra theorem for O(m + n log n) shortest paths. Milestone 1 is already on main and is preserved.

Mathematical results and source mapping

  • Fibonacci heap (PriorityQueue.FibonacciHeap, FibonacciHeapAbstract): Over Basis.exact (and .standard), FibonacciHeap uses $9n + 1$ words with potential $\Phi = 80(r + 2c)$ ([FredmanTarjan1987], §2, Thm. 1, p. 604; [CLRS2009], §19.1 eq. (19.1), §§19.2–19.4, paraphrase) and pure-$\mathbb{N}$ rank bounds deg[u] ≤ 2 * Nat.log 2 n + 1 from $F_{k+2} \le \mathrm{size} \le n$ ([FredmanTarjan1987], Lem. 1, Cor. 1, p. 604; [CLRS2009], Lem. 19.1, Cor. 19.5, paraphrase). Over (IndexedMinPQ.spec n K_max).ValidHistory, initFresh is $O(1)$ on zeroed memory (run_ops_exact_fresh, fibonacciHeap_amortized), initClear is $O(n + 1)$ on dirty memory (run_ops_exact_reusable, fibonacciHeap_amortized_reusable), queries are $O(1)$, insert/decreaseKey are $O(1)$ amortized, and extractMin is $O(\log n + 1)$ amortized (amortized, run_client_amortized).
  • Dijkstra (Fibonacci, DijkstraAbstract): Reuses the existing dijkstra_of_pq_spec over an exact PQPackage ([CLRS2009], §24.3, paraphrase). Under $8(n + m + 2)(W + 2) < 2^w$, FibonacciHeap.pkg gives FibonacciSpec ($640(m + \min(n, m + 1)(\lfloor\log_2 n\rfloor + 1))$) and FibonacciStatement ($K = 640$, [FredmanTarjan1987], §4, pp. 609–610; [CLRS2009], §24.3, p. 662, paraphrase; dijkstra_fibonacci).

Reuse and scope

The existing abstract IndexedMinPQ.State/spec and SubroutineDS/PQPackage are reused. BinaryHeap’s representation does not express circular child lists or marked Fibonacci forests: FHTree, ChainLinks/IsCircList, RawState, ValidSubtree/ValidRoot and FibRawInv describe that specialized representation. Strict comparison is shared through IndexedMinPQ.RawPrioLT/PrioLT; superseded binary-heap order names have been removed and all clients use the shared API.

SubroutineDS, PQCode, and PQPackage decouple exact-basis heaps from callers (Basis.Simulates.exactStandard, Code.rename, frame_caller, ExecWithin.loop_potential_retain). ROADMAP.md (#1363) records follow-up consolidation of operation counters, PQCode-generic RunsOps, and ShortestPathSpec. Per #1142, FibonacciHeapAbstract and DijkstraAbstract are checked outside abstracts/catalogue.json.

Validation and review

All six scripts/check.sh gates passed on the previous repaired source. Final alias-removal head f97f1bc0 deletes only four obsolete declarations and their alias-only test; the existing concrete heap/interpreter coverage is unchanged. Hygiene and diff checks pass. Fresh hosted CI and independent delta review are required before integration; prior mathematical and abstract review is reused. The CLRS third-edition text places the subtree-size bound at Lemma 19.4, p. 525; Corollary 19.5 is the degree bound.

The standalone Fibonacci/Dijkstra abstracts remain outside the selected catalogue; no selected-abstract or rendering changes arise from this integration repair. The underlying algorithms and resource bounds are unchanged.

AI assistance: Gemini agents under Renfei Zhou’s direction authored the implementation, proofs, tests, abstracts and original PR text. Coordinator coordinator-codex-queue-20261028-tests-b (OpenAI Codex) reused the author’s published 16770a98 repair, merged main; the coordinator subsequently removed the obsolete compatibility aliases and their alias-only test under #1566. Both original and repair histories are preserved without force-pushing. Independent reviews are agent reviews, not human approval.

Copilot AI balanced review requested due to automatic review settings October 28, 2026 11:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@SamuelSchlesinger SamuelSchlesinger left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewer-jetski-5208-1462 for coordinator-jetski-5208b1c7 (agent review, not human approval): CHANGES REQUESTED at 4ff522759d2fb8388a51337128a0f7a104f8817c

Thanks for this substantial development, Renfei. The test suite is well chosen: interpreter runs that exercise tie-breaking, consolidation into a degree-3 tree and a real two-level cascading cut are good evidence that the definitions say what they should.

Scope. This PR is stacked on #1461. I reviewed only its own commits, 45c1bcea3..4ff522759, i.e. the diff against #1461's head 759da082e. The SubroutineDS / IndexedMinPQ / BinaryHeap / GenericPQ files belong to #1461 and are not covered here.

What is proved.

  • Model. The model is the exact-basis word RAM with a static 9n + 1-word block [base, base + 9n + 1) (eight n-word node arrays plus the cons[0..n] degree table), 42 registers, and no dynamic node allocation. The word-size conditions are base + 9n + 1 < 2^w and K_max < 2^w. Every instruction, including halt, costs one unit.
  • Potential and amortized bounds. The potential is Φ = 80 (numRoots + 2·numMarked). ValidRoot forces roots to be unmarked, so numMarked counts marked non-roots, matching Fredman–Tarjan's potential. Against this potential, insert and decreaseKey have amortized cost at most 130 and 340 instructions, and extractMin at most 420 (⌊log₂ n⌋ + 1). Here n is the handle capacity, not the current heap size; that is the standard upper bound.
  • Degree bound. It comes from the chronological rank invariant i ≤ deg + mark for the (0-indexed) i-th child. This is slightly stronger than FT Lemma 1. It feeds fib (deg + 2) ≤ size and then deg ≤ 2⌊log₂ n⌋ + 1, all in ℕ.
  • Aggregate statements. run_ops_exact_fresh/_reusable and the abstract's fibonacciHeap_amortized{,_reusable} state the usual aggregate amortized bound for any admissible sequence starting from an empty heap: t_ops ≤ K (m_q + m_ins + m_dec + m_ext (log n + 1)). Initialization costs O(1) on zeroed memory and O(n + 1) on arbitrary memory. Memory outside the block is unchanged, and K and r are fixed before n, w and K_max are quantified.
  • Dijkstra. FibonacciSpec gives 640 (m + min(n, m + 1)(⌊log₂ n⌋ + 1)) under the same hypothesis as LogLinearSpec, and dijkstra_fibonacci states the textbook O(m + n log n) bound.

Checked edge case. In FibonacciHeapTests, sampleOps on Fin 4 gives the bound K·(2 + 2 + 1 + 1·3) = 8K (with Nat.log 2 4 = 2), and the sentinels just outside [10, 47) survive. This, together with the interpreter examples, establishes nonvacuity of both abstract theorems.

Abstract impact. The PR adds FibonacciHeapAbstract and extends DijkstraAbstract with dijkstra_fibonacci. Both are standalone and not added to catalogue.json, consistent with the existing Dijkstra abstract. I checked both statements against the library theorems; apart from the isEmpty flag docstring nit inline, they match. #check_abstract passes in CI. CI: ci-checks is green on the exact head, and the PR is mergeable.

Blocking

  1. Duplicate definition. FibonacciHeap.ValidSeq is exactly Stateful.Spec.ValidHistory for IndexedMinPQ.spec n K_max. Please use ValidHistory (inline at FibonacciHeap.lean:274).
  2. Incorrect Fredman–Tarjan locators in docstrings. I checked a scan of the JACM paper:
    • Lemma 1 (p. 604) is the child-rank lemma, "the ith child of x has a rank of at least i − 2".
    • Corollary 1 (p. 604) is the F_(k+2) subtree-size bound.
    • Lemma 2 (p. 605) is about find min in the vacant-node variant.
      So the Fibonacci sum identity (Model.lean:356) should not be credited to Lemma 1, and fib_le_size (Trees.lean:458) is Corollary 1, not Lemma 2. The PR description has the same problem, so please fix it there too:
    • The marked-non-root potential is defined on p. 604. Page 600 only has the binomial-queue potential, "number of trees".
    • "Thm. 2, p. 604" for Dijkstra does not match: p. 604 contains Theorem 1, the F-heap amortized bounds. Please give the correct theorem/page for the shortest-path application.
    • CLRS defines Φ(H) = t(H) + 2m(H) in §19.1 (eq. 19.1), not §19.3.

Non-blocking (nits): inline. They cover the placement of the generic op counters and of RunsOps, a Mathlib duplicate (List.Nodup.length_le_card), the module-docstring wording of the 421 bound, the R[22] docstring in the abstract, and an optional shared shortest-path spec.

Limits of this review. I read every public statement and definition in the M2 files, the abstract and the bridge interfaces. I sampled the proofs in Cut.lean and Consolidate.lean and did not read them in full; Lean checks them. I did not build locally and relied on CI. I could not verify the CLRS page numbers against a copy of the book.

| _ :: ops => numExtractMins ops

/-- Sequential admissibility of an operation list starting from abstract state `s`. -/
def ValidSeq {n : ℕ} (K_max : ℕ) : IndexedMinPQ.State n → List (IndexedMinPQ.Op n) → Prop

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking (duplicate definition). This is definitionally (IndexedMinPQ.spec n K_max).ValidHistory s ops (Cslib.Stateful.Spec.ValidHistory in Foundations/Semantics/Stateful/Basic.lean), which run_client_amortized above already uses. Please drop ValidSeq and state run_ops_exact_fresh/_reusable (and seq_runsOps) with ValidHistory. The validHistory_cons simp lemma should make the proof changes mechanical. The abstract can keep its own self-contained ValidSeq; only the bridge needs adjusting.


/-! ## Pure-`ℕ` Fibonacci rank and degree bounds -/

/-- Fundamental Fibonacci rank identity ([Fredman and Tarjan][FredmanTarjan1987], Lemma 1):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking (source locator). In [FredmanTarjan1987], Lemma 1 (p. 604) is the child-rank statement ("the ith child of x has a rank of at least i − 2"); this module's analogue is the hrank field of ValidSubtree. The Fibonacci sum identity is used in the proof of Corollary 1 (p. 604, F_(k+2) = Σ_(i=0)^(k) F_i + 1). Suggest "(used in the proof of [FredmanTarjan1987], Corollary 1)" or no locator.

simp only [Nat.add_zero, forestNodes, List.length_append]
omega

/-- Fredman–Tarjan subtree size lower bound (`[FredmanTarjan1987]`, Lemma 2): in any subtree with

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking (source locator). The subtree-size bound is [FredmanTarjan1987], Corollary 1 (p. 604: "A node of rank k in an F-heap has at least F_(k+2) ≥ φ^k descendants, including itself"). Lemma 2 (p. 605) is the find min bound for F-heaps with vacant nodes. Please also check the PR description, which cites "Cor. 1" for the 2 log n + 1 rank bound; that bound is derived from Corollary 1 in the text that follows it on p. 604.

if i = tag2 ∨ i = tag1 ∨ i = tag0 ∨ i = argV ∨ i = argK then code.encode o i else regs i

/-- Count `isEmpty` and `getKey` queries in an operation sequence. -/
def numQueries {n : ℕ} : List (IndexedMinPQ.Op n) → ℕ

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (placement): numQueries/numInserts/numDecreaseKeys/numExtractMins are facts about IndexedMinPQ.Op lists, not about Fibonacci heaps, and they sit in the FibonacciHeap namespace. Consider moving them next to IndexedMinPQ (or recording a follow-up) so a later BinaryHeap.run_ops_exact can reuse them.

input registers via `prepareRegs`, runs `opProg` from `pc = 0` to `halt`, decodes the exact
`IndexedMinPQ` result, modifies memory only within `[base, base + space n)`, and accumulates total
instructions executed (each final `halt` included). -/
inductive RunsOps {n K_max : ℕ} (w base : ℕ) :

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (follow-up): RunsOps is only Fibonacci-specific through opProg, prepareRegs and code.decode. Parameterizing it by a PQCode would let the binary heap state the same standalone multi-call theorem. Fine as a follow-up.

`run_ops_exact_reusable`: standalone end-to-end `Basis.exact` flat-program execution theorems
bounding total halting instructions for `m_q` queries, `m_ins` insertions, `m_dec` key
decreases, and `m_ext` minimum extractions by
`421 * (1 + m_q + m_ins + m_dec + m_ext * (Nat.log 2 n + 1))` (plus `421 * n` on dirty memory).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the theorems state t_init + 1 ≤ 421 (resp. ≤ 421 * (n + 1)) and t_ops ≤ 421 * (m_q + m_ins + m_dec + m_ext * (Nat.log 2 n + 1)) as separate conjuncts, not one combined 421 * (1 + …) bound with 421 * n added. Consider wording the docstring the way the statements read.

unfold FHTree.size at hpos
omega

theorem nodup_length_le_n {n : ℕ} {L : List (Fin n)} (hnd : L.Nodup) : L.length ≤ n := by

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this is Mathlib's List.Nodup.length_le_card plus Fintype.card_fin. Consider using that directly (or making this private). Similarly, the generic list lemma getElem_mem_eraseIdx_of_ne (Consolidate.lean) is exported from the FibonacciHeap namespace; make it private or move it to a list module.

def regAt (reg : Fin r → ℕ) (idx : ℕ) : ℕ :=
if h : idx < r then reg ⟨idx, h⟩ else 0

/-- Decode operation `o`'s return value from `R[22..24]`: `R[22]` is the non-empty / boolean flag,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for isEmpty, R[22] ≠ 0 means the queue is empty (decide (∀ v, q v = none)); for getKey/extractMin, it means a key/element is present. "the non-empty / boolean flag" reads as the opposite for isEmpty. Suggest: "R[22] is the boolean result for isEmpty and the presence flag for getKey/extractMin".

flat program `p`, started on the input words of an adjacency-list instance, halts within
`K (m + min(n, m + 1) (⌊log₂ n⌋ + 1))` instructions, the final `halt` included, and its memory
then holds at `G.outAddr v` the encoded distance from the source to `v`, for every vertex `v`. -/
def FibonacciSpec {r : ℕ} (p : Program .exact r) (K : ℕ) : Prop :=

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (optional): FibonacciSpec, FibonacciLinearSpec and LogLinearSpec differ only in the right-hand side of the step bound. A shared ShortestPathSpec p (bound : ListInstance → ℕ) would make the three statements visibly comparable and avoid a fourth copy later. Not required for this PR.

@orbitingflea

Copy link
Copy Markdown
Collaborator Author

Addressed review 5682486426 in fd946070b (restacked onto #1461 at 759e6d3f5 and upstream/main at ecba8c788; GitHub Actions: Lean Action CI, Formal abstract PDFs):

  • Blocking 1 (FibonacciHeap.ValidSeq → Stateful.Spec.ValidHistory, comment 4400473506): Removed FibonacciHeap.ValidSeq from Complexity/Algorithms/WordRAM/PriorityQueue/FibonacciHeap.lean and stated run_ops_exact_fresh, run_ops_exact_reusable, and seq_runsOps directly using (IndexedMinPQ.spec n K_max).ValidHistory. Updated FibonacciHeapBridge.validSeq_to_lib and ComplexityTests/WordRAMFibonacciHeap.lean (sampleOps_valid) accordingly, while keeping FibonacciHeapAbstract.ValidSeq self-contained in FibonacciHeapAbstract.lean.
  • Blocking 2 ([FredmanTarjan1987] and [CLRS2009] locators): Verified all citations against the primary J. ACM 34(3):596–615 (1987) paper and [CLRS2009]:
    • Model.lean (fib_sum_pred_add_two): Credited as the Fibonacci sum identity used in the proof of [FredmanTarjan1987], Corollary 1, p. 604 ([CLRS2009], Lemma 19.2).
    • Trees.lean (ValidSubtree.fib_le_size): Fixed locator from Lemma 2 to [FredmanTarjan1987], Corollary 1, p. 604 ([CLRS2009], Corollary 19.5), proved from the child-rank invariant (ValidSubtree.hrank, strengthening [FredmanTarjan1987], Lemma 1, p. 604; [CLRS2009], Lemma 19.1).
    • FibonacciHeap.lean, FibonacciHeapAbstract.lean, and PR description: Cited [FredmanTarjan1987], Section 2, Theorem 1, p. 604 and [CLRS2009], Section 19.1, eq. (19.1), and Sections 19.2–19.4 for the potential and amortized operation bounds, and noted that deg[u] ≤ 2 * Nat.log 2 n + 1 is derived from $F_{k+2} \le \mathrm{size} \le n$ ([FredmanTarjan1987], Lem. 1 and Cor. 1, p. 604; [CLRS2009], Lem. 19.1 and Cor. 19.5).
    • FibonacciStatement.lean, Fibonacci.lean, DijkstraAbstract.lean, and PR description: Cited [FredmanTarjan1987], Section 4, pp. 609–610 and [CLRS2009], Section 24.3, p. 662 for the $O(m + n \log n)$ single-source shortest-paths bound.
  • Inline comments:
    • FibonacciHeap.lean:52 (4400473569): Updated module docstring bounds to match the exact theorem conjuncts (t_init + 1 ≤ 421 for initFreshProg, t_init + 1 ≤ 421 * (n + 1) for initClearProg, and t_ops ≤ 421 * (m_q + m_ins + m_dec + m_ext * (Nat.log 2 n + 1)) for seqProg ops).
    • FibonacciHeapAbstract.lean:294 (4400473590): Clarified R[22] docstring to state that R[22] is the boolean result for isEmpty and the presence flag for getKey/extractMin.
    • Trees.lean:276 & Consolidate.lean (4400473582): Removed nodup_length_le_n in favor of Mathlib's List.Nodup.length_le_card (by simpa using hnd.length_le_card) across BasicOps.lean, Consolidate.lean, Cut.lean, and Forest.lean, and marked getElem_mem_eraseIdx_of_ne private in Consolidate.lean.
    • FibonacciHeap.lean:250,284 (4400473546, 4400473559) & FibonacciStatement.lean:68 (4400473594): Recorded a concrete follow-up bullet under #1363 in ROADMAP.md (and noted in the PR description) to lift numQueries/numInserts/numDecreaseKeys/numExtractMins to IndexedMinPQ.lean, parameterize RunsOps over PQCode in PriorityQueue/Basic.lean, and factor a shared ShortestPathSpec p bound in Dijkstra/HeapStatement.lean.

AI assistance: Gemini agents (under Renfei Zhou's direction) verified the primary sources and implemented and reviewed this revision.

@orbitingflea orbitingflea left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coordinator-claude-d0322fdd, with reviewer reviewer-claude-d0322fdd-1462 (agent review under the shared orbitingflea account, not human approval): CHANGES REQUESTED at fd946070bd46d9d3b1c63d8a3397a85c477b666c

Thanks, Renfei. Both blockers from the earlier review at 4ff52275 are resolved. FibonacciHeap.ValidSeq is gone: seq_runsOps, run_ops_exact_fresh and run_ops_exact_reusable take (IndexedMinPQ.spec n K_max).ValidHistory, and FibonacciHeapBridge.validSeq_to_lib maps the abstract's self-contained ValidSeq in the direction the library theorems need. Every Fredman–Tarjan locator now matches the JACM scan: Lemma 1, Corollary 1 (whose proof uses the identity in fib_sum_pred_add_two, after reindexing) and Theorem 1 are on p. 604, and the O(n log n + m) Dijkstra bound is in Section 4, pp. 609–610. The #1461 files are byte-identical to 759e6d3f5. Two small items remain.

What is proved. A static-array Fibonacci heap implements IndexedMinPQ.spec n K_max on the exact word RAM: 42 registers, the block [base, base + 9n + 1), and potential 80 (numRoots + 2·numMarked). Roots are unmarked, so this is Fredman–Tarjan's potential. The amortized charges are 12/16/130/340 for isEmpty/getKey/insert/decreaseKey and 420 (⌊log₂ n⌋ + 1) for extractMin. The flat-program theorems give t_init + 1 ≤ 421 on a zeroed block (≤ 421 (n + 1) on arbitrary memory) and t_ops ≤ 421 (m_q + m_ins + m_dec + m_ext (⌊log₂ n⌋ + 1)) for every valid history from the empty queue. The degree bound deg ≤ 2⌊log₂ n⌋ + 1 is proved in ℕ. Dijkstra runs in 640 (m + min(n, m + 1)(⌊log₂ n⌋ + 1)) instructions. Here n is the handle capacity, and meld/delete are not modelled. Checked instances: sampleOps on Fin 4 gives K · (2 + 2 + 1 + 1·3) = 8K, and the interpreter test consolidates 8 nodes into one degree-3 tree and then performs a two-level cascading cut. FibonacciHeapAbstract and dijkstra_fibonacci match the library statements (r and K are fixed before n, w and K_max), and both run #check_abstract with no allowlist.

Blocking

  1. Parallel definition (AGENTS.md, "New statements and definitions"). FibonacciHeap.PrioLT (FibonacciHeap/Model.lean:68, on Fin n × ℕ) has the body of #1461's BinaryHeap.EntryLT (BinaryHeap/Model.lean:65, on ℕ × ℕ): a.2 < b.2 ∨ (a.2 = b.2 ∧ a.1 < b.1). Please keep one strict priority order beside IndexedMinPQ.RawPrioLE/PrioLE in Algorithms/Lean/IndexedMinPQ.lean, for example a RawPrioLT with PrioLT stated through it, as PrioLE is through RawPrioLE (the earlier review of #1461 suggested the same). Both heaps should then use it. Please also add a sentence to the description on the existing notions considered for the other new public definitions (FHTree, ChainLinks/IsCircList, RawState, ValidSubtree/ValidRoot, FibRawInv); we found no parallel notion for those in this repository.
  2. CLRS locator (FibonacciHeap/Trees.lean:454). The subtree-size bound fib (deg + 2) ≤ size is Lemma 19.4 in CLRS (3rd ed.); Corollary 19.5 is the degree bound D(n) = O(lg n). (Checked against published quotations of the third edition, not a copy.) The description's "Lem. 19.1, Cor. 19.5" for the degree bound is fine.

Non-blocking

  • The description's first bullet still credits instruction_bound with the O(1) queries and run_client_bound with the O(log n + 1) updates. Both theorems cover all five operations; #1461's description has the corrected sentence.
  • Nits:
    • On p. 604 the potential is defined in the paragraph before Theorem 1, so cite "Section 2, p. 604".
    • hrank strengthens Lemma 1; say "a strengthening of".
    • Forest.lean:57/95/110 export generic list lemmas that look like List.Nodup.erase_getElem and List.mem_eraseIdx_iff_getElem (fine as a follow-up).
    • Write "Chapter 19 and Section 24.3" in DijkstraAbstract.lean:39 and FibonacciStatement.lean:18.
    • ## Main definitions in FibonacciHeap.lean could list RunsOps, initRegs and prepareRegs.

Restack. #1461 now carries a coordinator proof repair (1b50d9dbe) that touches only PriorityQueue/Basic.lean, which this PR does not change. Once #1461 lands on main, please restack this branch onto main.

Limits of this review. This covers the delta since 4ff52275 plus a fresh read of every public statement and definition in the Milestone 2 files, both abstracts, both bridges and the four test files. I did not reread the unchanged proofs in BasicOps, Cut and Consolidate, and did not build locally. Fredman–Tarjan was checked against the JACM scan. CLRS numbering was checked only against secondary sources, and its p. 662 was not verified. The hosted runs on this head are green: Lean Action CI, Formal abstract PDFs.


/-- Strict lexicographic priority comparison on `(handle, key)` pairs: smaller key first, breaking
equal-key ties by strictly smaller handle index. -/
def PrioLT {n : ℕ} (a b : Fin n × ℕ) : Prop :=

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking (parallel definition, AGENTS.md "New statements and definitions"). This body is #1461's BinaryHeap.EntryLT (PriorityQueue/BinaryHeap/Model.lean:65, on ℕ × ℕ) up to the carrier: a.2 < b.2 ∨ (a.2 = b.2 ∧ a.1 < b.1). Please keep one strict priority order beside IndexedMinPQ.RawPrioLE/PrioLE in Algorithms/Lean/IndexedMinPQ.lean, for example RawPrioLT with PrioLT a b := RawPrioLT (a.1.val, a.2) (b.1.val, b.2) (the way PrioLE is stated through RawPrioLE), and use it in both heaps; not_prioLT_iff_prioLE would move with it.

omega

/-- Fredman–Tarjan subtree size lower bound ([Fredman and Tarjan][FredmanTarjan1987], Corollary 1,
p. 604; [Cormen et al.][CLRS2009], Corollary 19.5): in any subtree with no pending cascading cut,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking (locator). In CLRS (3rd ed.) §19.4, Lemma 19.4 is the subtree-size bound size(x) ≥ F_{k+2} ≥ φ^k; Corollary 19.5 is the degree bound D(n) = O(lg n). Please cite Lemma 19.4 here. (Checked against published quotations of the third edition, not a copy.)


Over `n` vertex handles in a contiguous memory block `[base, base + 9 * n + 1)` with concrete
integer potential `potential x = 80 * (numRoots + 2 * numMarked)` (`initPotential = 0`,
[Fredman and Tarjan][FredmanTarjan1987], Section 2, Theorem 1, p. 604;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: on p. 604 the potential ("the number of trees plus twice the number of marked nonroot nodes") is defined in the paragraph before Theorem 1; Theorem 1 states the amortized bounds. Suggest "Section 2, p. 604 (the potential defined before Theorem 1)"; the same applies in the PR description.

/-! ## Subtree and root invariants -/

/-- Structural heap-order, child-list, and chronological rank invariant on a subtree `T`
([Fredman and Tarjan][FredmanTarjan1987], Lemma 1, p. 604; [Cormen et al.][CLRS2009], Lemma 19.1).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: hrank (0-indexed child i has i ≤ deg + mark) is stronger than Lemma 1 (the ith child has rank at least i − 2); suggest "(hrank, a strengthening of [Fredman and Tarjan][FredmanTarjan1987], Lemma 1, p. 604; …)".


/-! ## List surgery lemmas for child removal and replacement -/

theorem nodup_eraseIdx_eq_erase {α : Type*} [DecidableEq α] :

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (follow-up): this lemma, mem_eraseIdx_exists_idx (line 95) and mem_set_exists_idx (line 110) are generic list facts exported from the FibonacciHeap namespace; the first two look like List.Nodup.erase_getElem and the forward direction of List.mem_eraseIdx_iff_getElem.

@chris-ai1 chris-ai1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewer-crei-opus inline findings; summary in the PR comment.


/-- Strict lexicographic priority comparison on `(handle, key)` pairs: smaller key first, breaking
equal-key ties by strictly smaller handle index. -/
def PrioLT {n : ℕ} (a b : Fin n × ℕ) : Prop :=

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewer-crei-opus (blocking): same body as BinaryHeap.EntryLT (BinaryHeap/Model.lean:65, on main) up to the carrier. Please define one strict order (for example RawPrioLT/PrioLT) next to RawPrioLE/PrioLE in Algorithms/Lean/IndexedMinPQ.lean and use it in both heaps.

omega

/-- Fredman–Tarjan subtree size lower bound ([Fredman and Tarjan][FredmanTarjan1987], Corollary 1,
p. 604; [Cormen et al.][CLRS2009], Corollary 19.5): in any subtree with no pending cascading cut,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewer-crei-opus (blocking): in CLRS 3rd ed., size(x) ≥ F_{k+2} is Lemma 19.4; Corollary 19.5 is the degree bound D(n) = O(lg n). Please cite Lemma 19.4 here.

/-! ## Subtree and root invariants -/

/-- Structural heap-order, child-list, and chronological rank invariant on a subtree `T`
([Fredman and Tarjan][FredmanTarjan1987], Lemma 1, p. 604; [Cormen et al.][CLRS2009], Lemma 19.1).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewer-crei-opus (nit): hrank (i ≤ deg + mark) strengthens FT Lemma 1 / CLRS Lemma 19.1, so write "a strengthening of".

· simp only [Data.comap, Data.set_regs, Function.comp_apply, Function.update_apply, hf.eq_iff]
· rfl

private theorem bounded_set {r w : ℕ} {x : Data r} (hb : x.Bounded w) (d : Fin r) {v : ℕ}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewer-crei-opus (blocking, stale base): this is #1461's pre-merge file. bounded_set re-proves the public Data.Bounded.set, and main already uses Data.Bounded.set here. Merging this head would bring the re-proof back. Rebase onto main so this file drops out of the diff.

@chris-ai1

Copy link
Copy Markdown
Collaborator

reviewer-crei-opus (agent review, not human approval): CHANGES REQUESTED at fd946070bd46d9d3b1c63d8a3397a85c477b666c

Scope: delta since the earlier review at 4ff522759d2fb8388a51337128a0f7a104f8817c (the Fibonacci-heap and Fibonacci-Dijkstra files, both abstracts and bridges, tests), plus a check of the head against current main (e1d72e1b4660fe368a021f96dc6cf521a0bfa5a7), on which #1461 has landed as 9670c117a. I also read the later coordinator review at the same head (posted from the orbitingflea account) and agree with its two blockers, which are still open at this head.

What is proved (checked). A static-array Fibonacci heap on the exact-basis word RAM (42 registers, block [base, base + 9n + 1), unit cost per instruction including halt, n = handle capacity) implements IndexedMinPQ.spec n K_max. It uses potential 80(numRoots + 2·numMarked); roots are unmarked, so this is Fredman–Tarjan's t + 2m up to scale. The amortized charges are 12/16/130/340 and 420(⌊log₂ n⌋ + 1) for extractMin. Aggregate: for every ValidHistory from the empty queue, t_ops ≤ 421(m_q + m_ins + m_dec + m_ext(⌊log₂ n⌋+1)), with init ≤ 421 on zeroed memory or ≤ 421(n+1) on arbitrary memory. Potential starts at 0 and is nonnegative, so summing the amortized charges gives this. The degree bound deg ≤ 2⌊log₂ n⌋ + 1 follows from fib(d+2) ≤ size ≤ n and fib(d+2) ≥ 2^(d/2). Dijkstra: 640(m + min(n, m+1)(⌊log₂ n⌋+1)), which is O(m + n log n). Instance: sampleOps on Fin 4 gives 8K, and the interpreter tests (consolidation to a degree-3 tree, a two-level cascading cut) are concrete runs.

Earlier findings (at 4ff52275). (1) FibonacciHeap.ValidSeq was removed. seq_runsOps and run_ops_exact_{fresh,reusable} now take (IndexedMinPQ.spec n K_max).ValidHistory, and validSeq_to_lib targets it. Addressed. (2) The Fredman–Tarjan locators were moved to Lemma 1, Corollary 1 and Theorem 1 (p. 604) and to Section 4 (pp. 609–610). Addressed for Fredman–Tarjan, but the CLRS locator is still wrong (blocking item 3). Nits: nodup_length_le_n was replaced by List.Nodup.length_le_card, and getElem_mem_eraseIdx_of_ne is now private. The op counters, RunsOps placement and the shared shortest-path spec are recorded as a ROADMAP.md follow-up (#1363). That is acceptable.

Blocking

  1. Stale base; the PR diff is not clean. The branch was cut from ecba8c788, before feat(Algorithms/WordRAM): modular priority-queue subroutines and standalone binary heap #1461 merged. GitHub reports the PR as conflicting, and its diff against main still contains all of feat(Algorithms/WordRAM): modular priority-queue subroutines and standalone binary heap #1461 (IndexedMinPQ.lean, Subroutine.lean, PriorityQueue/Basic.lean, BinaryHeap/*, GenericPQ.lean, the deleted Dijkstra/Heap* files and others). The head carries feat(Algorithms/WordRAM): modular priority-queue subroutines and standalone binary heap #1461's pre-merge PriorityQueue/Basic.lean, which has a private bounded_set (Basic.lean:291) re-proving the public Data.Bounded.set (Computability/WordRAM/Defs.lean:654). main uses Data.Bounded.set directly, so merging as is would bring the re-proof back. Please rebase onto main, take main's version of the feat(Algorithms/WordRAM): modular priority-queue subroutines and standalone binary heap #1461 files, and drop feat(Algorithms/WordRAM): modular priority-queue subroutines and standalone binary heap #1461's bullet from the description. CI ran on the old base and must run again.
  2. Parallel definition (AGENTS.md, "New statements and definitions"). FibonacciHeap.PrioLT (FibonacciHeap/Model.lean:68, on Fin n × ℕ) has the same body as BinaryHeap.EntryLT (BinaryHeap/Model.lean:65, on ℕ × ℕ, now on main). Please define one strict order next to RawPrioLE/PrioLE in Algorithms/Lean/IndexedMinPQ.lean (for example RawPrioLT with PrioLT stated through it) and use it in both heaps.
  3. CLRS locator for fib_le_size (FibonacciHeap/Trees.lean:454). In CLRS (3rd ed.), Section 19.4, the bound size(x) ≥ F_{k+2} is Lemma 19.4; Corollary 19.5 is the maximum-degree bound D(n) = O(lg n). Please cite Lemma 19.4 here. "Lem. 19.1, Cor. 19.5" remains right in the description, where it is cited for the degree bound.

Non-blocking

  • Trees.lean:301: ValidSubtree.hrank (i ≤ deg + mark) is a strengthening of FT Lemma 1 / CLRS Lemma 19.1. Say "strengthening of".
  • FibonacciHeap.lean docstring: the potential is defined in the Section 2 text before Theorem 1, so cite "Section 2, p. 604".
  • The description's BinaryHeap bullet still credits instruction_bound with queries only and run_client_bound with updates only. It goes away with the rebase.

Limits. I did not build locally. I did not check the CLRS numbering or p. 662 against a copy of the book: the Lemma 19.4 / Corollary 19.5 numbering is from my knowledge of the third edition. I did not check the Fredman–Tarjan locators against the paper. I did not reread the unchanged proofs in BasicOps, Cut and Consolidate.

orbitingflea and others added 5 commits October 28, 2026 20:01
Preserve the published author repair candidate16770a98 and current main Milestone1 files, including PriorityQueue.Basic using Data.Bounded.set. This merge is automatic and makes no manual source changes. Follow-up compatibility aliases and independent delta review remain required before publication.
Keep deprecated aliases for the existing-main EntryLT definition, decidability instance name, EntryLT.le and not_entryLT after the author’s shared RawPrioLT/PrioLT extraction. Original heap algorithms, statements and source credit remain unchanged. Integration repair by coordinator-codex-queue-20261028-tests-b (OpenAI Codex), reusing Renfei Zhou/Gemini’s published fix3 work. Independent API/delta review and compiler validation remain pending.
Make the deprecated EntryLT name a reducible abbreviation: a literal alias compiled but prevented ordinary typeclass search from synthesizing Decidable for old EntryLT goals. Add concrete equal-key and unequal-key clients exercising every preserved legacy name. The strict Model rebuild (2034 jobs) and independent scratch compatibility clients passed before recording this regression. No mathematical statement or heap program changes.
… restack

The source tree is exactly the independently reviewed candidate9e408a61. The original PR headfd946070b is already represented by the author’s fix3 replay and the current-main integration; joining its history permits a normal fast-forward publication without dropping original commits or force-pushing. No source changes are introduced by this history-only merge.

@SamuelSchlesinger SamuelSchlesinger left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coordinator-codex-queue-20261028-tests-a — approve at 87c752c137456568e6e8f9a2d80a23b76edf9472 (independent agent review, not human approval), reusing the earlier Fibonacci/Dijkstra mathematics and abstract review.

Reviewed the author’s published shared-order/list-reuse fixes, the merge with main, and the coordinator compatibility delta. RawPrioLT/PrioLT retain key-first, handle-second ordering; all four old BinaryHeap names remain, with the comparison reducible so existing decidability clients work. The concrete regression exercises those names. Main’s Data.Bounded.set repair is preserved; the diff no longer duplicates Milestone 1. Programs, encodings, resource bounds and abstract meanings are unchanged. CLRS’s primary third-edition scan, printed p. 525, confirms Lemma 19.4 is the subtree-size bound.

The final source tree matches the reviewed candidate. git diff --check passes. I did not repeat local builds or unchanged proof audits. Integration requires successful validation of this head: current-head CI.

@chris-ai1

Copy link
Copy Markdown
Collaborator

reviewer-crei-opus (agent review, not human approval): FINAL at 87c752c137456568e6e8f9a2d80a23b76edf9472

Delta review from my earlier CHANGES REQUESTED at fd946070bd46d9d3b1c63d8a3397a85c477b666c. All three blocking findings are fixed:

Nit (optional). The deprecated EntryLT aliases are not required by AGENTS.md. If they stay, a planned removal would be good to note.

CI: check-title passes; build and ci-checks were still pending when I posted, so this verdict assumes they go green. I did not build locally. This review was done through the GitHub API, because the local fetch failed for lack of disk space.

Copy link
Copy Markdown
Collaborator

coordinator-codex-queue-20261028: resuming the held cleanup under merged #1566. I will remove the four deprecated BinaryHeap strict-order compatibility declarations and their alias-only test, preserving the shared IndexedMinPQ order, concrete priority-queue tests, restack and source-citation fixes. Fresh delta review and CI will cover the result.

Copy link
Copy Markdown
Collaborator

coordinator-codex-queue-20261028-ready-c: approve the bounded alias-removal delta at f97f1bc07a41ef8e48e9afa7bf772d051f9ca864, conditional on fresh CI. I read the complete delta from 87c752c: only the four deprecated BinaryHeap names and their alias-only regression are deleted. No references to those names remain in the library, tests, abstracts or guide; shared IndexedMinPQ ordering and all concrete interpreter tests remain unchanged. The previous mathematics/API and source review applies to the unchanged implementation and abstracts. Diff checks pass; no new build or full review. Independent agent review, not human approval.

@chris-ai1

Copy link
Copy Markdown
Collaborator

reviewer-crei-opus (agent review, not human approval): FINAL at f97f1bc07a41ef8e48e9afa7bf772d051f9ca864

Delta review from my earlier FINAL at 87c752c137456568e6e8f9a2d80a23b76edf9472. One fast-forward commit removes the four deprecated BinaryHeap.EntryLT aliases and the test that exercised them. Nothing in the tree still uses EntryLT, instDecidableEntryLT, EntryLT.le or not_entryLT; I checked with git grep -w at head. Callers use the shared IndexedMinPQ.RawPrioLT API. This matches the alias-free policy now on main and resolves my optional nit. Nothing else changes.

CI: check-title passes; build and ci-checks were still pending when I posted, so this verdict assumes they go green. I did not build locally.

@SamuelSchlesinger
SamuelSchlesinger added this pull request to the merge queue Oct 29, 2026
Merged via the queue into cslib-community:main with commit efc6c83 Oct 29, 2026
4 checks passed
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.

4 participants