Skip to content

perf: speed up Burkholder majorant proofs - #454

Merged
Vilin97 merged 6 commits into
mainfrom
claude/daily-optimize-2026-09-18
Sep 19, 2026
Merged

Vilin97 merged 6 commits into
mainfrom
claude/daily-optimize-2026-09-18

Conversation

@Vilin97

@Vilin97 Vilin97 commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Daily optimization cycle, target project: LeanPool/Burkholder (Burkholder's sharp martingale-transform inequality, provenance AI). Base: b2041a8152d6667dc61e9119b8654d36d77aa391 (origin/main at the start of the cycle; LeanPool/Burkholder, the toolchain and the manifest are unchanged on main since then).

Why this project: among nine candidates built and timed from cold (CompactnessAndDegeneracy, Burkholder, NonSoficGroup, Vlasov, EhrhartVolumeInequality, SpherePacking, PhaseRetrieval, HadwigerNelsonBounds, QuantumParallelRepetition), Burkholder had the densest cost: 95 % of its 242 CPU-seconds sit in two twin 10k-line files (MajorantPG2, MajorantPL2, the p > 2 and 1 < p < 2 regimes) made of ~330 private lemmas each that re-prove the same elementary facts inline hundreds of times. PhaseRetrieval has a larger total (694 CPU-s) but spread over 43 measure-theoretic files with many public declarations.

Only MajorantPG2.lean and MajorantPL2.lean change. No definition, statement, name, universe list, safety level, instance/simp/reducibility attribute or import changes; no gate, waiver, set_option, sorry, native_decide or new axiom.

Invariant audit

Method: a Lean script (importModules LeanPool.Burkholder, run against a copied olean directory so rebuilds cannot race it) prints, for every constant whose module starts with LeanPool.Burkholder: kind, safety, reducibility hints, universe params, reducibility status, instance flag/priority, simp flag, protected/private flags, inductive/ctor/recursor metadata, the type hash and the fully explicit pretty-printed type (pp.explicit, pp.universes, pp.privateNames, pp.instances, ...), plus value hashes for defs; theorem proof hashes go to a side file. Run at the base commit and at the head, then diffed.

Result: base 997 declarations, head 1015.

  • 0 removed, 0 changed real declarations. Every one of the 997 pre-existing declarations has an identical type/universes/safety/attributes row, including the public API (Majorants.exists_majorant_geTwo, Majorants.exists_majorant_leTwo, Majorants.exists_majorant_p_eq_2, Majorants.exists_majorant_p_g_1, MeasureTheory.Lp_Burkholder_inequality_martingaleTransform, all defs and notations).
  • The only non-additive rows are compiler-generated simp auxiliaries (<lemma>._simp_1_N): 22 removed and 1 with a different type, all children of private lemmas whose simp calls were replaced. All def value hashes are unchanged.
  • 40 added rows: the 39 new private lemmas below and 1 _simp_ auxiliary.
  • Proof terms differ for 257 private theorems and one public theorem (exists_majorant_geTwo, whose have-level linarith one-liners now use the helpers); its statement is byte-identical.

What changed (both files, same patterns)

  • continuity → explicit terms (42 sites). In a scratch file continuity takes 0.1 s, inside these proofs 1.5–3.5 s (aesop normalising a context with ~30 hypotheses and let-bound sets). Continuous (fun z => (-z.1, -z.2)) is now continuous_fst.neg.prodMk continuous_snd.neg, fun t => (t, y) is continuous_id.prodMk continuous_const, etc.
  • Shared private helpers instead of inline re-proofs. MajorantPL2 re-proved 0 < a p 57 times (rw [a_eq_leTwo]; exact div_pos (by linarith) (by linarith)), y < y / a p 33 times (with nlinarith), a p * y < y 40 times (simpa using mul_lt_mul_of_pos_right), boundary-point sector membership 50+ times; MajorantPG2 re-derived y < x from A2, ¬ QuarterPlane/¬ QuarterPlane2 facts (54 sites), t ∈ Set.Ioo from interior (Icc) (90 sites in both files), and the derivative of vGeTwo on closureA2 (11 sites). These are now single private lemmas (a_pos_of_one_lt_of_lt_two, lt_self_div_a_leTwo, mul_a_lt_of_lt_div_a, closureA2_diag_leTwo, quarterPlane3_mul_a_leTwo, lt_of_lt_mul_a, not_quarterPlane_of_neg, mem_Ioo_of_mem_interior_Icc, hasDerivAt_vGeTwo_x_DxauxFunction1, ...). Elementary consequences of 2 ≤ p / 1 < p < 2 (0 < p, 0 < p - 1, p ≠ 1, ...) are stated once and used as terms at 177 sites instead of by linarith in contexts whose division-heavy hypotheses make each linarith call cost 50–300 ms of cancelDenoms preprocessing. In MajorantPG2 the three a p lemmas moved above their first use so the earlier lemmas could use them.
  • Derivative bookkeeping. HasDerivAt (fun s => (s + y) / 2) (1 / 2) t is ((hasDerivAt_id' (x := t)).add_const y).div_const 2 instead of simpa [div_eq_mul_inv, mul_comm, mul_left_comm, mul_assoc] using ...; rpow derivatives use Real.hasDerivAt_rpow_const/HasDerivAt.rpow_const with congr_deriv (by ring) (or a rw [show p - 1 - 1 = p - 2 by ring]) instead of AC-normalising simpa and convert ... using 2 (95 blocks).
  • Cheaper closers. 84 nlinarith → linarith where linear reasoning suffices (each kept only when it compiles); simpa using mul_lt_mul_of_pos_right h hx → mul_lt_of_lt_one_left hx h; dsimp [c]; field_simp → mul_div_cancel₀; two hand-rewritten steps in vLeTwo_A2_second_bracket_nonpos_leTwo (mul_div_cancel₀, mul_le_mul_of_nonneg_right instead of field_simp/linarith [...]).

Net: −1069 lines (PG2 10682 → 10213, PL2 10023 → 9423); continuity 42 → 0, nlinarith 105 → 21, linarith 1369 → 1114, simpa 838 → 553, field_simp 141 → 111.

Measurements

Machine: 32-core WSL2 host, otherwise idle; Lean v4.34.0 / Mathlib 5ed29652 as pinned by the repository. Clean builds delete .lake/build/{lib/lean,ir}/LeanPool/Burkholder* first; base and head were built back to back on the same oleans.

lake build LeanPool.Burkholder (clean) wall s user CPU s
base b2041a81 23.84 243.3
head 19.35 188.1
change −18.8 % −22.7 %

Per file, sequential lake env lean -DmaxSynthPendingDepth=3 -Dweak.linter.mathlibStandardSet=true <file> (user CPU s, base → head): MajorantPG2 121.5 → 93.8 (−22.8 %), MajorantPL2 131.1 → 80.3 (−38.8 %); Definitions, MajorantPEq2, Majorants, MartingaleTransforms, Burkholder unchanged (1.2–6.5 s each). Profiling used -Dtrace.profiler=true -Dtrace.profiler.threshold=20; the biggest single items were continuity (aesop) and the repeated inline blocks listed above.

Checks run (all green)

  • lake build LeanPool.Burkholder — 0 warnings, 0 errors (the three info: Try this: ring_nf notes are pre-existing on main).
  • lake exe runLinter LeanPool.Burkholder — "Linting passed".
  • lake exe lint-style LeanPool — no output.
  • lake exe mk_all --check — "No update necessary".
  • python -m lean_pool.quality pieces scoped to the project: textual gates (headers, forbidden text, sizes, proof sizes, cards) — 0 errors for Burkholder; #print axioms audit of the project declarations — 0 errors (only propext/Classical.choice/Quot.sound); environment option-backdoor audit over LeanPool.Burkholder — 0 errors.
  • Declaration manifest diff as described above.

Limitations

  • The remaining cost is diffuse: ~1100 linarith calls at 20–200 ms each (dominated by cancelDenoms preprocessing of / 2 hypotheses) and ~550 simpa calls; the next step would be per-site linarith only [...], which is not safely automatable.
  • Whole-pool linting was not rerun locally (single-project worktree); CI will run it.
  • Only LeanPool/Burkholder is touched; generated indexes needed no change.

🤖 Generated with Claude Code

Optimize the two 10k-line majorant files of the Burkholder project
(`MajorantPG2`, `MajorantPL2`) without changing any declaration.

- Replace 42 `continuity` calls (aesop, 1.5-3.5 s each inside these
  crowded contexts) by explicit continuity terms.
- Factor 38 private helper lemmas for facts that were re-proved inline
  dozens of times (`0 < a p`, `y < y / a p`, `a p * y < y`, sector
  membership of boundary points, denominator clearing, consequences of
  `2 ≤ p` / `1 < p < 2`, interior of `Icc`, quarter-plane exclusions,
  sector derivatives) and use them at ~600 sites.
- Rewrite the `HasDerivAt` bookkeeping in the derivative lemmas with
  `hasDerivAt_id'`/`div_const`/`rpow_const` plus `congr_deriv (by ring)`
  instead of AC-normalising `simpa` calls.
- Downgrade 84 `nlinarith` calls to `linarith` where that suffices, and
  drop `simpa` in favour of direct lemmas (`mul_lt_of_lt_one_left`, ...).

Clean `lake build LeanPool.Burkholder`: 243 -> 188 user CPU seconds
(-23%), 23.8 s -> 19.4 s wall. Declaration manifest (types, universes,
safety, names of all 997 pre-existing declarations) unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Advisory cross-file review against Lean Pool's supervisory rubric. This is not by itself a significance, source-verification, or merge verdict.

Retrigger

The PR appears safe to merge because the proof-only refactors preserve the public contracts and no actionable regression remains.

Summary

The PR refactors the two Burkholder majorant developments to reduce elaboration cost without changing their mathematical interfaces.

  • Replaces repeated arithmetic, sector-membership, continuity, and derivative proof work with private helper lemmas and explicit proof terms.
  • Converts the files to the Lean module system while preserving the public majorant theorem surface.
  • Reduces the combined source size and reports substantial focused-build CPU and wall-time improvements.
  • No actionable correctness, integration, security, or repository-rule violations were identified.

Reviews (5) · Last reviewed commit: "Merge remote-tracking branch 'origin/mai..."

@github-actions

Copy link
Copy Markdown
Contributor

Proof profile (new / modified Lean files)

Statement changes

✅ No statements changed — all 702 tracked declarations across 2 modified files kept their type; only proofs / definition bodies changed.

Also: 39 declarations added, 0 removed. A reorganization moves declarations between files, which shows up here as an add in one file and a remove in another.

➕ Declarations added (39)
  • Majorants.MajorantPG2.half_p_nonneg_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.hasDerivAt_vGeTwo_x_DxauxFunction1 — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.hasDerivAt_vGeTwo_y_DyauxFunction1 — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.lt_of_lt_mul_a — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.mem_Ioo_of_mem_interior_Icc — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.not_quarterPlane2_of_gt — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.not_quarterPlane2_of_lt — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.not_quarterPlane_of_lt — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.not_quarterPlane_of_neg — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.one_le_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.one_le_sub_one_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.one_lt_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.p_ne_zero_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.p_nonneg_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.p_pos_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.sub_one_ne_zero_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.sub_one_nonneg_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPG2.sub_one_pos_of_two_le — LeanPool/Burkholder/Majorants/MajorantPG2.lean
  • Majorants.MajorantPL2.a_pos_of_one_lt_of_lt_two — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.closureA1_mul_a_leTwo — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.closureA2_diag_leTwo — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.half_p_nonneg_of_one_lt — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.lt_mul_a_of_div_a_lt — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.lt_self_div_a_leTwo — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.mem_Ioo_of_mem_interior_Icc — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.mul_a_le_of_le_div_a — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.mul_a_lt_of_lt_div_a — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.p_ne_one_of_one_lt — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.p_ne_zero_of_one_lt — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.p_nonneg_of_one_lt — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.p_pos_of_one_lt — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.quarterPlane3_mul_a_leTwo — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.quarterPlane_diag_of_pos — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.quarterPlane_div_a_leTwo — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.sub_one_le_one_of_lt_two — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.sub_one_ne_zero_of_one_lt — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.sub_one_nonneg_of_one_lt — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.sub_one_pos_of_one_lt — LeanPool/Burkholder/Majorants/MajorantPL2.lean
  • Majorants.MajorantPL2.sub_two_neg_of_lt_two — LeanPool/Burkholder/Majorants/MajorantPL2.lean

Statements are compared textually against the merge base (comments and whitespace ignored; by proof terms embedded in a type are treated as proof-irrelevant), the same method as physlib's /check-golf. Anonymous instances and examples are not tracked.

Compile cost of modified files — base → head

Heartbeats: 2,652 → 2,808 (+156, +5.9%). Declarations: 663 → 702.

Per-file wall sum: 141.0 s → 132.4 s (-6.1%). Wall clock is measured under parallel load and is noisy; heartbeats are deterministic and are the regression signal.

Files: 2 compared — 0 cheaper, 0 costlier, 2 within noise (threshold: |Δ heartbeats| ≥ 1,000 and ≥ 1%).

Both sides are elaborated against the merge-base build of the pool — sound when only proofs and definition bodies change; a file whose statements changed may fail there and is flagged ⚠. Heartbeats come from Mathlib's linter.countHeartbeats, in maxHeartbeats units. Δ lines counts added/deleted lines from this PR diff.

File Δ lines HB base HB head Δ HB Δ HB % Wall base (s) Wall head (s)
LeanPool/Burkholder/Majorants/MajorantPL2.lean +516/-1116 1,324 1,408 +84 +6.3% 70.85 64.97
LeanPool/Burkholder/Majorants/MajorantPG2.lean +534/-1003 1,328 1,400 +72 +5.4% 70.13 67.44
Total +1,050/-2,119 2,652 2,808 +156 +5.9% 141.0 132.4

Advisory only — never blocks merge. Full log uploaded as the proof-profile artifact.

@Vilin97

Vilin97 commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator Author

Exact-head review at 8b72eb19ef (refactor standard, 2026-09-18; equivalent approval comment — GitHub does not permit self-approval on an automation-authored PR). The head is the branch after an update-branch merge of main; relative to main the diff is exactly Burkholder/Majorants/MajorantPG2.lean and MajorantPL2.lean (+1050/−2119).

What changes. Proof bodies only: 42 new private helper lemmas (elementary consequences of 2 ≤ p / 1 < p < 2, quarter-plane non-membership, interior-of-Icc, the three a p bounds moved to the top of the file) replace hundreds of inline re-derivations; continuity (aesop) is replaced by explicit Continuous.* terms (32 → 0), nlinarith by linarith/positivity with the right hypothesis in hand (84 → 0), linarith calls drop from 360 to 105, field_simp from 32 to 2. No open, set_option, attribute, import, section, or docstring-structure changes; no forbidden constructs. The /profile report confirms no statement changed across all 702 tracked declarations (39 added, 0 removed), matching the author's declaration-manifest audit (997 pre-existing declarations identical in type/universes/safety/attributes).

Maintainability. Improved: explicit continuity terms and named elementary lemmas are more robust to Mathlib drift than continuity/nlinarith searches, and the argument structure is preserved line for line. Measured on the author's host: clean project build 23.8 s → 19.4 s wall (−18.8 %), 243 → 188 CPU-s; per file MajorantPG2 −22.8 %, MajorantPL2 −38.8 %. Greptile: no actionable finding. Author-side checks (project build, runLinter, lint-style, mk_all --check, scoped axiom and option audits) reported green.

Disposition. Nothing is requested of the author. Merge waits only for the required checks on this head: the Lean CI run is a cold ten-shard build because #450's new cache namespaces are still being seeded by main's own run, so Build project will take roughly two hours; repository auto-merge is disabled, so the merge will be done by the next cycle (or the maintainer) once it is green and the head is still current.

@Vilin97

Vilin97 commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator Author

Head moved to cc1ad3fd8c by the update-branch merge of main (metadata commit only); the Burkholder tree is identical to 8b72eb19, so the review above applies unchanged. Required checks restart on this head.

@github-actions

Copy link
Copy Markdown
Contributor

Auto-rebase stopped: this PR conflicts with main outside the two
mechanically resolvable files (LeanPool.lean, LeanPool/projects.yml),
so the overlap needs a human. Remove the needs-manual-rebase label once
resolved to re-enable automatic updates.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

Auto-rebase stopped: this PR conflicts with main outside the two
mechanically resolvable files (LeanPool.lean, LeanPool/projects.yml),
so the overlap needs a human. Remove the needs-manual-rebase label once
resolved to re-enable automatic updates.

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

Independent refactor review at af9b64a739944724ab6d842149924eb73f5ea5bb: approve the content, quality 4/5. Shared parameter and region lemmas, explicit continuity terms and focused arithmetic replace repeated heavy solver setup while preserving proof structure. The prior profile reports all 702 tracked types preserved; its +5.9% heartbeat change is below the profiler's material threshold, and noisy per-file wall time fell 141.0 → 132.4 s. No material regression established.

This cycle repaired the main/module migration conflict in an isolated worktree, preserving the public-import layout and the explicit arithmetic proofs already on main. The final 3,036-job project build, semantic lint, full-root style, index, repository static scans and axiom/environment audit pass. The remote head was checked before the fast-forward push. Fresh whole-pool CI is now running its quality checks. The configured LLM workflow dispatch returned HTTP 422 (disabled); this is the independent exact-head refactor review, not a claim that workflow ran. Equivalent approval comment because GitHub forbids self-approval. Normal protected merge remains conditional on final exact-head CI/mergeability checks; no override.

@Vilin97 Vilin97 added the needs-maintainer Actual human decision required: licensing, mathematical scope, policy, or reviewer disagreement. label Sep 19, 2026
@Vilin97

Vilin97 commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator Author

Disposition: merged at reviewed head af9b64a739944724ab6d842149924eb73f5ea5bb. Full protected CI completed successfully, including the complete quality/trust checks. Removed the temporary needs-maintainer label and used the normal protected squash merge: 4c5b9ae4d41acdf90cd1d8a8a053bebf89224d2a. The earlier pending-CI boundary is resolved. Independent review.

@Vilin97 Vilin97 removed the needs-maintainer Actual human decision required: licensing, mathematical scope, policy, or reviewer disagreement. label Sep 19, 2026
@Vilin97
Vilin97 merged commit 4c5b9ae into main Sep 19, 2026
13 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.

1 participant