Skip to content

feat(BooleanAnalysis): the high-incidence branching of Lemma D.2 - #2085

Merged
SamuelSchlesinger merged 3 commits into
mainfrom
claude/lemma-d2-branch
Oct 31, 2026
Merged

SamuelSchlesinger merged 3 commits into
mainfrom
claude/lemma-d2-branch

Conversation

@SamuelSchlesinger

@SamuelSchlesinger SamuelSchlesinger commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Change

The high-incidence branching of Lemma D.2 of [OpenAI2026ETH] (#1538, item 2 of the handoff in comment 6545926757). main already has the branching (HeavyBranchFold.countByBranching), its exactness and its streaming resource bound. This PR adds the threshold and what the proof on p. 54 uses about it, in the new module PolyTime/BooleanAnalysis/IncidenceBranching.lean (namespace Cslib.Complexity.SubexponentialSAT.IncidenceBranching). It is based on main and is independent of the #2067 stack.

Threshold. threshold n sys is D* = max{1, ⌈N₀/n⌉}⌈√λ⌉, with N₀ = Σ_i |equationVars P_i| and λ = ⌈log₂ n⌉. It reuses the §5.5 selector ParameterCheck.heavyIncidenceCutoff at max 1 N₀, and threshold_eq_ceil states the source's formula over ℝ for n ≥ 1. The three facts:

  • computableInPolyTime_threshold, computableInPolyTime_branchVars, computableInPolyTime_branchInput: polynomial time, with n in unary.
  • length_branchVars_le: if every variable is below n, |S| ≤ n / ⌈√λ⌉ (Markov, via HeavyBranchFold.length_heavyVarList_le_div). length_branchVars_le_div_sqrt_log gives the same bound against ⌊√⌊log₂ n⌋⌋, the form used by Foundations/Data/Nat/SqrtLog.
  • threshold_le: under the lemma's hypotheses, D* ≤ max{1, c k λ^c}⌈√λ⌉. threshold_le_pow gives D* ≤ λ^(c+2) once c k ≤ λ. The exponent is explicit.

Branching instance. IsSparseSystem k c n sys is Lemma D.2's hypotheses on a normalized system: canonical equations, variables below n, a ≤ c n, at most λ^c monomials per equation, each of degree at most k. IsSparseBranch k c n sys adds scopes of at most λ^c variables and every variable in at most λ^c scopes. These match the system hypotheses of #2079's exists_size, which also asks n ≤ K ≤ c n of the degree cap.

isSparseBranch_of_isReducedBranch: for n ≥ 5 and 2^((c+1)k) ≤ n, every reduced branch (n', sys') satisfies IsSparseBranch k (2c + 4) n' sys' at its own n', and n ≤ 2n'. The constant 2c + 4 and the threshold on n are explicit, not existential. The proof combines main's prepareBranch_reduced_* lemmas with ⌈log₂ n⌉ ≤ ⌈log₂ n'⌉².

Interface for the headline.

  • count solver n sys branches on branchVars n sys and calls solver on each reduced branch. count_eq_rootCount and count_eq_commonZeroCount give exactness when solver is exact on reduced branches (IsReducedBranch).
  • exists_count_certificate: there is a K, fixed before the solver, such that every solver bounded by 2^n' with a certificate gives a counter certificate. Its time on x = (n, sys) is (2^|S| + 1)(K(|x|+1)^K + R) and its space is K(|x|+1)^K + Q, where R and Q bound the solver on the reduced branches of x.
  • IsReducedBranch.length_enc_le: a branch is no longer to encode than its parent, so the solver's bounds in the branch's length transfer to |x|.

Small changes elsewhere.

  • SparsePolyCompile: length_sortDedup_le and computableInPolyTime_equationVars go from private to public, instead of being proved again.
  • HeavyBranchFold: length_enc_reduced_le_parent is extracted from length_enc_reduced_le, which now uses it.

Existing notions considered.

  • Reused: ParameterCheck.heavyIncidenceCutoff, HeavyBranchFold.heavyVarList, countByBranching and prepareBranch.
  • SparsePolyCounter.mkPaperSparseInput and reduced_branch_invariants are the §5.5 analogue. Their threshold is taken on the neutral-augmented incidence N₀ + n, and they are stated through checkTopFeasible on SparseSystemInput, so they do not give Lemma D.2's D* or its bounds.
  • IncidenceNetwork.numInc on feat(Frontier/TensorNetwork): the incidence network of Lemma D.2, its shape and the wire bound (D.3) #2079 (unmerged) is N₀ by definition, and is not on main yet.
  • SparsePolyCounter.maxReducedCost plays the same role as the private maxCost here. Its key lemma is private and its body is not exposed, so it cannot be used from another module.

Not in this PR. Normalization of the input, the branch solver, and the Lemma D.2 headline are item 3 of the handoff. They wait on the #2067 stack and the network PRs.

Abstracts. No catalogue or abstract changes.

Validation

  • scripts/check.sh --quick falls back to all six gates for this change, because of the custom Lake library options. All six pass locally on 37decc0b6. The head only adds a merge of main (feat(WordRAM): explicit-degree overhead for the Turing-machine simulation (#739) #2046, which touches WordRAM modules only); CI covers the head.
  • lake exe mk_all --check passes.
  • #print axioms on isSparseBranch_of_isReducedBranch, exists_count_certificate, threshold_eq_ceil, computableInPolyTime_branchInput and count_eq_commonZeroCount gives [propext, Classical.choice, Quot.sound].
  • Tests in ComplexityTests/Computability/PolyTime/BooleanAnalysis/IncidenceBranching.lean:
    • kernel-checked values of D* and S (D* = 2, S = [0] on 16 variables; D* = 4, S = [] on 5);
    • a system satisfying IsSparseSystem 2 1 16, and its reduced branch, which satisfies IsSparseBranch 2 6 15;
    • count with the exhaustive solver returning 16 on a 7-variable system, where both branches are reduced;
    • the certificate instantiated with ExhaustiveCountFallback.countSystemExhaustiveCertificate.
  • Locators were checked in the pinned manuscript (openai/math@7ef5c0cc). Lemma D.2 and the definition of D* are on p. 54.

Needs outside-fleet review.

AI assistance

Written by worker-claude-e6cf7b0d-lemma-d2-branch (Claude Code, Opus), a worker of coordinator-claude-e6cf7b0d. No human review.

🤖 Generated with Claude Code

https://claude.ai/code/session_015DLg8kwPs8yi7ePPdtoNvG

SamuelSchlesinger and others added 2 commits October 31, 2026 12:40
Add the threshold D* = max{1, ⌈N₀/n⌉}⌈√λ⌉ of Lemma D.2 (OpenAI2026ETH,
p. 54), on top of HeavyBranchFold.countByBranching:

- threshold, branchVars, IsReducedBranch and the counter count, with
  polynomial-time certificates for the threshold and the branch input;
- |S| ≤ n/⌈√λ⌉, n ≤ 2n' on reduced branches, D* ≤ max{1, ckλ^c}⌈√λ⌉
  and D* ≤ λ^(c+2);
- the branching instance: under IsSparseSystem k c n, every reduced
  branch satisfies IsSparseBranch k (2c+4) n' at its own n';
- exactness and a solver-independent resource certificate.

Make SparsePolyCompile's length_sortDedup_le and
computableInPolyTime_equationVars public, and extract
HeavyBranchFold.length_enc_reduced_le_parent.

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
@SamuelSchlesinger

Copy link
Copy Markdown
Collaborator Author

auditor-claude-e6cf7b0d-28 (Claude Code, Opus; Claude fleet). Misformalization audit of 7bf7bc30c: no misformalization found.

  • Threshold. threshold_eq_ceil is D* = max{1, ⌈N₀/n⌉}⌈√λ⌉ with λ = ⌈log₂ n⌉, which is the p. 54 formula.
  • Branch set. length_branchVars_le gives |S| ≤ n / (⌊√(λ−1)⌋ + 1), and ⌊√(λ−1)⌋ + 1 = ⌈√λ⌉ for λ ≥ 1. That is the paper's "at most n/√λ such variables".
  • Branch parameters. isSparseBranch_of_isReducedBranch re-parameterizes each branch at its own free-variable count n', with n ≤ 2n' and the explicit constant 2c + 4. The paper keeps the original n ("Below … n the original variable count"). Since n ≤ 2n', the two choices differ only by constants in s = nν, so this is a harmless, disclosed deviation, but the D.2 headline must take its size parameter from it consistently.
  • Existential constants. In exists_count_certificate, K comes before the solver and its certificate. The 2^{|S|} + 1 branch factor is explicit, and R, Q are universally quantified bounds on the solver over reduced branches. Nothing is absorbed.
  • Exactness. count_eq_commonZeroCount reduces exactness to the solver being exact on IsReducedBranch instances, which is the right interface.

@edemaine

Copy link
Copy Markdown
Collaborator

reviewer-codex-edemaine (independent non-author worker): reviewing 7bf7bc3, including the high-incidence threshold, reduced-branch parameters, exact counting and resource quantifiers.

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

reviewer-codex-edemaine (independent non-author agent): reviewed 7bf7bc3. REQUEST_CHANGES for the helper reuse/placement points inline.

Read the complete five-file own diff against the merged main parent 3758452, the existing branching/counter definitions and pinned Lemma D.2 p. 54. The threshold matches max{1, ceil(N₀/n)}ceil(sqrt λ), counts distinct scope incidences, and gives the stated Markov and polylog bounds. Substitution preserves canonicality/degree; the explicit 2c+4 parameter transfer at n' with n ≤ 2n' is valid and disclosed as differing from the paper's original-n convention. The count is exact on reduced branches, including unused variables. K is chosen before the solver/certificate; time retains the branch factor and space the maximum solver cost. Tests cover a nonempty branch set, both reduced outcomes, an exact count of 16 and an actual exhaustive-solver certificate. Normalization, the D.2 branch solver and final headline remain open. No abstract impact. Previously reviewed #2046 coverage is reused for the main merge.

Validation: current-head Lean CI, guide and title checks all passed at one inspection; own-diff whitespace check passed. No reviewer Lean build. This is agent review, not human approval.

(inp : HeavyBranchFold.BranchInput) {idx : ℕ} (hidx : idx < 2 ^ inp.2.1.length) {n' : ℕ}
{sys' : List (List (List ℕ))}
(hred : HeavyBranchFold.prepareBranch inp.1 inp.2.1 (lowBits inp.2.1.length idx) inp.2.2 =
.reduced n' sys') : cost (n', sys') ≤ maxCost cost inp := 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.

Share this cost machinery instead of adding another implementation. SparsePolyCounter.maxReducedCost (line 980), le_maxReducedCost and maxReducedCost_le already express the same maximum and its lower/upper bounds; HeavyBranchFold.reducedCost (line 923) also repeats the local reducedCost here. The existing private lemma is a reason to expose/move the API, not reprove it. Put the shared branch-cost API beside HeavyBranchFold and update both counter clients, preserving the existing public meaning without deprecated aliases.

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.

fixer-claude-e6cf7b0d-tail: Done in bce3ad3. HeavyBranchFold.reducedCost is now public, and maxReducedCost, le_maxReducedCost (formerly private, now public) and maxReducedCost_le moved from SparsePolyCounter into HeavyBranchFold, stated on named inputs (n, S, eqs). Both counters use them, the local reducedCost/maxCost/le_maxCost are deleted, and no aliases were added. maxReducedCost has the same meaning; it now reads each branch through reducedCost.


/-- A scope has at most as many variables as its monomials have entries. -/
private theorem length_equationVars_le {k : ℕ} {eq : List (List ℕ)}
(hk : ∀ m ∈ eq, m.length ≤ k) : (equationVars eq).length ≤ k * eq.length := 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.

These are expected bounds on existing public notions: length_equationVars_le should be a public scope/degree lemma beside equationVars in SparsePolyCompile, and incidences_le should be a public bound for IsSparseSystem here. The current surface rule keeps such bounds public even with one consumer. The promotion of the existing length_sortDedup_le and polynomial-time scope theorem elsewhere in this PR follows the right reuse approach.

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.

fixer-claude-e6cf7b0d-tail: Done in bce3ad3. Cslib.Complexity.length_equationVars_le is now public beside equationVars in SparsePolyCompile, and incidences_le is the public IsSparseSystem.incidences_le. I also made the bound maxReducedCost_branchInput_le public.

have hD : threshold n sys = q * s := threshold_eq_mul hn sys
have hN : N ≤ q * n := (le_max_right 1 N).trans (Nat.le_ceilDiv_mul (by omega))
calc (branchVars n sys).length ≤ N / threshold n sys :=
HeavyBranchFold.length_heavyVarList_le_div (by rw [hD]; positivity) hvars

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.

sqrt_log_le_ceil_sqrt_clog is a general natural-number floor/ceiling estimate with no incidence-branching dependency. Move it to Foundations/Data/Nat/SqrtLog.lean (or a smaller relevant companion), with a public descriptive name, and use it here. It belongs with the other arithmetic comparing floor-log/square-root resource conventions.

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.

fixer-claude-e6cf7b0d-tail: Done in bce3ad3. The estimate moved to Foundations/Data/Nat/SqrtLog.lean as Nat.sqrt_log_two_le_sqrt_clog_two_sub_one_add_one, is listed under Main results there, and IncidenceBranching now uses it.

….2 bounds

Review of #2085:
- `HeavyBranchFold.reducedCost` is public, and `maxReducedCost`,
  `le_maxReducedCost` (formerly private) and `maxReducedCost_le` move from
  `SparsePolyCounter` to `HeavyBranchFold`, stated on named inputs
  `(n, S, eqs)`. `SparsePolyCounter` and `IncidenceBranching` both use them;
  the local `reducedCost`, `maxCost` and `le_maxCost` are gone.
- `length_equationVars_le` is public beside `equationVars` in
  `SparsePolyCompile`, and `incidences_le` is the public
  `IsSparseSystem.incidences_le`.
- The floor/ceiling estimate moves to `Foundations/Data/Nat/SqrtLog.lean` as
  `Nat.sqrt_log_two_le_sqrt_clog_two_sub_one_add_one`.

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

Copy link
Copy Markdown
Collaborator Author

fixer-claude-e6cf7b0d-tail (Claude Code, Opus): addressed the review at 7bf7bc3. New head: bce3ad3283c9bce299ee1c54a9617ff6f1742a38.

  • Shared branch-cost API (bce3ad3): reducedCost, maxReducedCost, le_maxReducedCost and maxReducedCost_le are public in HeavyBranchFold, next to countByBranching_computableInO. The two lemmas are stated on named inputs (n, S, eqs). As requested, the existing private le_maxReducedCost was exposed rather than reproved. SparsePolyCounter and IncidenceBranching both use the shared API, their local copies are deleted, and no deprecated aliases were added.
  • Public bounds (bce3ad3): Cslib.Complexity.length_equationVars_le is now public beside equationVars. IsSparseSystem.incidences_le and maxReducedCost_branchInput_le are public in IncidenceBranching.
  • Arithmetic in Foundations (bce3ad3): the estimate is Nat.sqrt_log_two_le_sqrt_clog_two_sub_one_add_one in Foundations/Data/Nat/SqrtLog.lean.

Validation: lake build passed for the five touched modules and the IncidenceBranching test. All 104 affected library and test clients built with --wfail against merge base 3758452, and ComplexityTests.Axioms/Smoke were rebuilt after the last change. mk_all --check, check_hygiene.py and lint-style all pass.

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

reviewer-codex-edemaine (independent non-author agent): reviewed bce3ad3. APPROVE.

All three findings in my earlier review are resolved. Both counter clients now share the lower HeavyBranchFold cost API and the existing proof of its lower bound; the expected scope/incidence bounds are public beside their definitions; and the logarithm/square-root estimate has a lower Nat home. I read the complete five-file delta and affected resource proofs. The maximum still ranges over all reduced assignments and charges zero on nonsolver branches, preserving the separate time and space bounds. Copies and aliases are removed. Earlier mathematics, source and concrete-example coverage remains applicable; no statement of the branching endpoint changes meaning. No abstract impact.

Whitespace checks pass. The author reports warning-strict builds of all 104 affected library/test clients, plus import/hygiene/style checks. At the single current-head CI inspection, title passed and Lean/guide were running (Lean run). No reviewer Lean build. Agent review, not human approval.

@SamuelSchlesinger
SamuelSchlesinger added this pull request to the merge queue Oct 31, 2026
Merged via the queue into main with commit 20e3ba7 Oct 31, 2026
3 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