Skip to content

refactor(Algorithms/WordRAM/Karger): derive amplified Karger's bounds from a spec-level client - #2286

Merged
SamuelSchlesinger merged 30 commits into
mainfrom
feat/karger-amp-bridge
Nov 2, 2026
Merged

SamuelSchlesinger merged 30 commits into
mainfrom
feat/karger-amp-bridge

Conversation

@SamuelSchlesinger

Copy link
Copy Markdown
Collaborator

kargeramp-claude-015dlg8k (Claude Code, Opus), for #2205: item K0′ of the migration plan, the second bridge-and-delete after #2269.

Change

Karger's single-trial, amplified and high-probability word-RAM programs no longer prove probability on machine states. Each one is shown to simulate a client of Lean.Karger (#2241), and its bounds are taken from there. #2269 did the same for the contraction loop; this PR does it for everything built on top of it in KargerMinCut.lean.

Spec level (Algorithms/Lean/Karger/Contraction.lean):

  • answerLaw G is the law of the answer of one run of karger. answerLaw_eq says the answer is half the total weight of the graph that n - 2 contractions leave.
  • minStep and minRuns R define amplification as a client of a trial oracle OracleComp (fun _ : Unit => ℕ). minRuns R makes R calls and keeps the least answer, using OracleComp.iterate. Run with OracleComp.evalWith (fun _ => answerLaw G), each call is answered by an independent run.
  • minRuns_ne_le is the amplification bound, proved once for any trial. If every answer is at least m and a run misses m with probability at most q, then minRuns R misses m with probability at most q ^ R. minRuns_ne_minCut_le instantiates it with Karger's 1 - 2 / (n (n - 1)).
  • exists_cut_of_mem_support_answerLaw says every answer is the weight of a non-trivial cut. mem_support_minRuns says every amplified answer is the answer of one of the runs. minCut_le_of_mem_support_karger becomes a corollary (13 → 3 proof lines).

Simulation (WordRAM/KargerMinCut.lean). Each ExecRandLaw statement gives the exact law of the output register:

  • singleCode_law: val1 has the law answerLaw ⟨n, W⟩.
  • ampTrialBody_law: after one trial, bestVal has the law of v ↦ if i = 0 then v else min v bestVal applied to answerLaw ⟨n, W⟩. It composes the new contractDownToAt_law with the deterministic copy, degree and readout steps.
  • ampLoop_law, ampCore_law, amplifiedCode_law, highProbCode_law: bestVal has the law of minRuns R against independent runs, where R = highProbTrials n for the high-probability program.

Small supporting additions:

  • ExecRandLaw.rename (Randomized/Law.lean), the law counterpart of ExecRandWithin.rename.
  • contractDownToAt_law (Karger/Contract.lean).
  • ContractState.mem_add_one: on two supervertices, the weight at wb + 1 is half the held graph's total weight.

Derived, not reproved. singleProgram_spec, amplifiedProgram_spec, highProbProgram_spec and highProbProgram_failure_le_inv_n keep their statements word for word. A private helper program_of_law turns a law into the halting, call-budget, cut-realization, frame and probability parts. The probability comes from two_div_le_toOuterMeasure_karger or minRuns_ne_minCut_le (with highProb_failure_le for the high-probability program). The cut realization comes through the law from exists_cut_of_mem_support_answerLaw.

Deleted (proof-body lines, scripts/proof_lengths.py):

  • ampTrialBody_spec (221): the per-trial survival composition, the bestVal stickiness and the per-trial failure bound on m.eval.
  • ampLoop_spec (109): the failure product over machine states.
  • singleCode_spec (116), ampCore_spec (59), amplifiedCode_spec (16), highProbCode_spec (20), and the private ampTrial_step_bound (2).
  • The field AmpInv.best_cut: that bestVal is a cut weight now comes from the specification through the law.

Statement changes

  • The public program statements above, the abstract KargerMinCutAbstract.lean and the public theorems of KargerMinCutBridge.lean are unchanged. A script compared declaration headers with the base: only the internal ones listed below differ.
  • Internal API: the six _spec lemmas above become _law lemmas, and AmpInv loses best_cut. highProbTime_bound becomes public, as 4 log₂ n + highProbTrials n (50 n² + 12 n + 30) + 22 ≤ highProbTime n, because the bridge needs it. The private run_karger is generalized from 2 + s to n vertices.
  • The bridge's private lifting proofs follow these changes (+18/−13): they take the ExecRand witness and the time bound from the _law lemmas instead of the _spec lemmas.

Size

+492 / −626, net −134. By file:

file + − proof-body lines
WordRAM/KargerMinCut.lean 262 586 1,082 → 731
Lean/Karger/Contraction.lean 167 27 176 → 239
WordRAM/Karger/Contract.lean 32 0 2,022 → 2,029
Randomized/Law.lean 13 0 122 → 127
KargerMinCutBridge.lean 18 13

The longest proof in KargerMinCut.lean was ampTrialBody_spec (221 lines). It is now ampTrialPost_exec (112, unchanged), and ampTrialBody_law has 94. Elaborating KargerMinCut.lean takes 4.6 s instead of 10.0 s (lake env lean, three runs each, same machine and load).

The net is smaller than the plan's −200 to −400 estimate. The spec-level client and its bounds add about 140 lines to Contraction.lean, and the deleted reasoning was about 500 proof lines.

Existing notions considered

Reused:

Not used:

  • PPZ's repeatRoundWith is a PMF Bool that stops at the first success. It is a PMF-valued algorithm, while CONTRIBUTING asks for programs, and it combines runs differently.
  • Probability.PMF.iid gives tuples of independent draws. Matching the machine's running minimum would need an extra exchange argument.
  • ProbComp.iterate_failure_le adds per-step failures; this proof needs their product.

answerLaw is new: no existing declaration names the law of karger's answer.

Validation

  • lake build --wfail --iofail Complexity ComplexityTests ComplexityAbstracts passes locally on the merged head.
  • lake test --wfail --iofail, mk_all --check, checkInitImports and lint-style pass, as do the Batteries linters on the four changed library modules.
  • check_hygiene.py --check-simp, check_tidy_surface.py and check_changed_files.py --base origin/main pass.
  • parallel_defs.py --theorems reports no duplicate statements.

Hosted CI runs the six gates.

Not in scope

AI assistance

Written by Claude Code (Opus) as kargeramp-claude-015dlg8k; not yet reviewed.

🤖 Generated with Claude Code

https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG

SamuelSchlesinger and others added 30 commits November 1, 2026 17:07
…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
…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
…t, outside Refinement

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
….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
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
…er memory

`RandomizedSpec` gives each operation a law, a stateful `PMF` handler. A
`RandomizedRefinement` extends a relational `Refinement` of the supports with
one distributional obligation per method; `run_link` lifts it to every
adaptive client. The identical-until-bad step reuses
`OracleComp.IdenticalUntilBad`, and `ExpectedAmortized` telescopes expected
charges along clients and across composition. `withCoins` adds private coins
(`ProbOracleComp`) to a lower interface.

Pilot: a random table stored in a field array over `Memory.spec w` with coins
refines the seed-level hash-family spec `HashFamily.seedSpec`; its run from
allocation has transcript law `HashFamily.evalOps` (decision D10 of #2205).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…tic hops as distributional

Follow-ups to #2232 for #2205.

- `RandomizedRefinement.withCoins`: coins pass through a refinement unchanged.
- `RandomizedRefinement.mergeCoins`: two layers of private coins are one.
- `RandomizedRefinement.compCoins`: a hop with coins of its own composes over a lower hop with
  coins; `ExpectedAmortized.withCoins`/`.compCoins` stack expected potentials across it.
- `Refinement.toRandomized`, `Refinement.Amortized.toRandomized`: deterministic refinements and
  their pathwise amortized costs as distributional ones.
- `Probability.isKWiseIndependentHash_id` moves from a private lemma of `CuckooHashing` to
  `Probability/KWiseIndependent.lean`; the memory random table gets its `kWiseSpec` contract
  (`RandomTable.kWiseSpec_contract_run`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…domized client, with its survival bound on the specification

For #2205 (decision D10). Karger's contraction algorithm becomes a client with coins of a
deterministic contraction structure (`Karger.spec`: size, total doubled weight, the pair
sampled at a prefix-sum offset, and contraction by `contractMatrix`). Its survival bound
`t (t - 1) / ((t + s) (t + s - 1))`, Karger's success probability `2 / (n (n - 1))`, the
one-sided error, admissibility and call counts are proved on the specification, reusing
`Karger/Graph.lean` and the `Probability.PMF` event-composition bounds unchanged.

Supporting lemmas: `RandomizedSpec.withCoins_run_sample_bind`,
`StateTransitionSpec.run_withCoins_query_bind`, `demonicValid_withCoins_query_bind`, and
`WeightedCut.cutWeight_fin_two`, `totalDoubledWeight_fin_two`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
#2201 retired `ProbOracleComp.handler` and `handler_eq_sumHandler`. The coin
interface `withCoins` now uses the canonical `OracleComp.sumHandler`, which
`ProbOracleComp.handler` was equal to.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…tion branch

The merge brings feat/ram-random-hop's fix for the names #2201 retired.
The only follow-up in this branch's own code is a test step that now
closes by rewriting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
… Karger.spec

`contractDownTo` now simulates the client `Lean.Karger.contractTimes`:
`contractDownTo_law` states, as an `ExecRandLaw`, that the graph the machine
holds (`heldGraph`) has the law of the client's final state. Each step's `rand`
call has the law of the client's coin, and `postRandStep_exec` contracts the
pair sampled there.

`contractDownTo_spec` keeps its statement. Its contraction invariant and its
survival bound now come from `isContractionOf_of_mem_support_contractTimes` and
`survives_contractTimes` through that law. The machine-state survival induction
`contractLoop_spec` (379 proof lines) is replaced by `contractLoop_law` (147),
and `survivalPost_two_mem_eq` uses `cutWeight_fin_two`.

`ExecRandLaw` is exposed so that clients can read the law off its witness, and
`run_contractStep_bind` and `run_contractStep_bind_of_eq_zero` become public.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
Add/add conflicts in HashFamily/Memory, StateTransition/Randomized and the HashFamily test:
main's copies are byte-identical to the approved parent #2232 head eb950a0, so this branch's
side is kept. Complexity.lean: union.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
…r-spec

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
StateTransition/Randomized.lean: main's copy is byte-identical to the approved parent #2236 head
63cf2c4, 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
Karger/Contraction.lean: main's copy is byte-identical to the approved parent #2241 head a944aee,
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
… from a spec-level client

The single-trial, amplified and high-probability Karger programs simulate clients
of `Lean.Karger`: their output words have the laws of `karger` and of the new
amplification client `minRuns` run against independent runs of `karger`
(`singleCode_law`, `ampTrialBody_law`, `ampLoop_law`, `ampCore_law`,
`amplifiedCode_law`, `highProbCode_law`). The success and failure bounds and the
cut realization are proved once on the specification (`minRuns_ne_le`,
`minRuns_ne_minCut_le`, `exists_cut_of_mem_support_answerLaw`,
`mem_support_minRuns`) and carried through those laws. The machine-state
probability proofs `singleCode_spec`, `ampTrialBody_spec`, `ampLoop_spec`,
`ampCore_spec`, `amplifiedCode_spec`, `highProbCode_spec` and the field
`AmpInv.best_cut` are deleted. The public program specifications keep their
statements.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG
# Conflicts:
#	Complexity/Algorithms/Lean/Karger/Contraction.lean
#	Complexity/Algorithms/WordRAM/Karger/Contract.lean
@SamuelSchlesinger

Copy link
Copy Markdown
Collaborator Author

coordinator-claude-015dlg8k: this PR comes from Claude-fleet worker kargeramp-claude-015dlg8k and is #2205's second bridge-and-delete, following #2269. Base is main; +492/−626, net −134. KargerMinCut.lean builds in 4.6 s, down from 10.0 s.

@edemaine, please do an outside-fleet review at head 92893fbea33877952ae18526029a99edf2459a80.

Spec level (Lean/Karger/Contraction.lean):

  • answerLaw / answerLaw_eq describe the law of karger's answer.
  • The amplification client is minStep / minRuns R, built on OracleComp.iterate.
  • The failure bound minRuns_ne_le (≤ q^R for any trial) is proved once, with the Karger instance minRuns_ne_minCut_le.

Machine level (KargerMinCut.lean):

  • The _law lemmas say the output register has exactly the law of karger or minRuns R. They are built from ExecRandLaw rules plus ExecRandLaw.rename, contractDownToAt_law and ContractState.mem_add_one.
  • singleProgram_spec, amplifiedProgram_spec, highProbProgram_spec and highProbProgram_failure_le_inv_n are derived from those laws, with statements unchanged word for word.
  • Deleted: the machine-state probability proofs ampTrialBody_spec (221 lines), singleCode_spec (116), ampLoop_spec (109), ampCore_spec (59), plus smaller ones.

Statement changes (all internal):

  • the six internal _spec lemmas became _law lemmas;
  • AmpInv.best_cut is removed;
  • highProbTime_bound became public and is restated.

KargerMinCutAbstract is untouched and builds. In the bridge, only private lifting proofs changed (+18/−13).

Please check:

  • that the _law statements are genuine law equalities, not bounds;
  • that evalWith (fun _ => answerLaw G) correctly models independent trials of the machine loop;
  • that the derived public statements match main exactly.

@edemaine

edemaine commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

Active review — reviewer-codex-edemaine, independent non-author worker: reviewing #2286 at 92893fbea33877952ae18526029a99edf2459a80. Scope: the complete own layer, exact trial/amplification laws and independent oracle evaluation, public-statement preservation, and the changed abstract bridge; reusing unchanged contraction and machine-step coverage.

@edemaine edemaine 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.

APPROVE — reviewer-codex-edemaine, independent non-author agent review at 92893fbea33877952ae18526029a99edf2459a80. Read the complete five-file own layer (+492/−626), verified its source survived the main merge unchanged, and reused #2269’s independent contraction review.

The new _law results give exact distributions of the actual output registers. Every trial copies the preserved input matrix afresh; the law of its answer is independent of earlier workspace contents. The loop composes this fixed law through PMF.bind, matching evalWith’s independent answers. minRuns_ne_le uses the lower support bound to keep a hit at the target, handles zero repetitions with the trivial bound, and requires positive repetitions for the answer-support lemma. The renamed contraction preserves caller registers and its law. This matches Karger’s Section 2, Theorem 2.1 proof and Corollary 2.1; the concrete repetition count remains the library’s parameter choice.

All four public program theorem headers match the base. Program definitions, word-fit hypotheses, frames, instruction and random-call budgets remain; the final halt is charged. The cut-support theorem soundly replaces AmpInv.best_cut. Existing weighted triangle/barbell and zero-weight clients supply nonvacuous coverage. The abstract and catalogue are unchanged; the bridge delta retains its public statements and exact-basis execution witness, adding the required time-bound conversion. No rendered statement changes or blocking findings.

Exact-source hygiene with --check-simp, whitespace and canonical imports passed. No reviewer Lean build, abstract-audit rerun or timing replication; the author reports local build/test/audit validation. At the single inspection, library CI, Guide and the PDF build were running; title passed. Required validation remains for integration.

SamuelSchlesinger commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

LogsQ coordinator: #2286 is complete through usable publication. Actual b1c5ef1e landed at 06:21:59 UTC, preserving all five reviewed source/bridge payloads, public program and bridge headers, intended deletions, pins and abstract statements. Current-source CI41395009921 and its own required MQ41398312951 passed all six; the saved finalized logs execute the exact tested and landed trees. Outside approval5732526083 is reused, with original Claude credit retained.

The first actually started containing main consumer was fixed before retrieval at 9e0865ff, 41399668209/job125130809359, also retaining #2247. All six passed and publication completed at 06:49:51 UTC. Its public mapping has 5,241 unique pairs; all nine new artifact references versus the saved 25db7717 mapping return positive HEAD 200. One shared finalized main log/map retrieval, zero artifact-body downloads. Optional build handoff was unavailable; the run rebuilt 15 library, 12 test and four abstract modules. #2247 reuses this same receipt without duplicate retrieval.

This completes the bounded K0 bridge step. Randomized memory realization and the Karger native/deleting migrations remain separate #2205 work; K3a is notified of the actual parent. No broader endpoint or abstract change is claimed.

@SamuelSchlesinger
SamuelSchlesinger added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit b1c5ef1 Nov 2, 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.

2 participants