Skip to content

perf: reduce Ehrhart volume proof elaboration - #697

Open
Vilin97 wants to merge 1 commit into
mainfrom
codex/optimize-20261020T1615
Open

Vilin97 wants to merge 1 commit into
mainfrom
codex/optimize-20261020T1615

Conversation

@Vilin97

@Vilin97 Vilin97 commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

Reduce proof elaboration work in the 56k-line EhrhartVolumeInequality project while preserving every existing statement and definition.

The mathematical changes replace a variance expansion with Jensen's inequality for the normalized bump measure, derive first-moment integrability from the second moment, factor repeated closed-span and self-adjoint range-closure arguments, reuse the spatial basis decomposition through a continuous linear map, and remove redundant L² representative conversions in the Brascamp proof. The engineering pass narrows arithmetic hypotheses, uses direct proofs of elementary facts where diagnostic builds succeed, and retains explicit type annotations where profiling shows they are cheaper. AnalysisSupport keeps the implementation dependencies of the new support lemmas private. Explicit shake: keep annotations retain the MatrixOrder scope and the scalar inner-product instances that occur in the original elaborated types.

Base: 79b42a12c43b772728b8b2d88ec19f295f48446b (current main at cycle start). Head: 6d9af8f2ae775c28d393a5e3e7742efcdeb7162d.
Toolchain: the repository's unchanged Lean v4.35.0-rc3 and Mathlib c55e6e786f49471c72fbddbec5415808896aec1e.

Invariant audit

A native Lean environment exporter serializes each original constant's fully elaborated type, universe parameters, safety, declaration metadata, and all non-theorem values as a constructor-level expression DAG. It omits theorem proof values only. The comparison includes private and generated constants, plus the private/exported environment views and the original exported-name set. A separate source audit checks all 2,372 original declaration signatures and all original definitions, instances, notation and scope commands.

PASS: all 3,578 original constant records and all 3,787 original private/exported constant views are identical; no original declaration or exported name was removed or changed. The original 307,164 exported names remain available. The head adds ten supporting public lemmas and one generated private congruence helper (3,589 owned constants total). All 2,372 original source signatures and all non-proof declarations/scope commands are unchanged. Every manifest difference is one of those explicitly accounted-for additions.

The SHA256 of the unchanged original 3,578-record manifest subset is 55740d87820809cb40eed5947ea5f161ac9975ad3b3433dda98a6d788031458b.

Measurements

Final exact-source clean-project ABBA runs:

Run Revision Wall seconds User CPU seconds Maximum child RSS (KiB)
1 base 192.85 302.43 1,995,612
2 head 210.96 314.88 1,977,236
3 head 208.71 313.57 1,979,832
4 base 234.91 338.62 2,003,156

Means: wall 213.880 → 209.835 seconds (1.891% lower); user CPU 320.525 → 314.225 seconds (1.966% lower); maximum child RSS 1,999,384 → 1,978,534 KiB (1.043% lower).

The 10% wall-time/RAM target was not reached. Optimization continued through the six-hour timebox (2026-10-20 16:15:08–22:15:08 UTC); final measurement and publication followed. These small wall-time differences are observations on a shared VM, not evidence of a reliable 1.891% speedup. VM load rose from about 32 to 38 during this final batch. The proof simplifications and lower profiled elaboration work are the main reasons to retain this change for review.

Controlled builds remove only this project's build products under .lake/build/{lib/lean,ir}/LeanPool/, retain the same warm dependency artifacts, use LEAN_NUM_THREADS=8, and run sequentially in base/head/head/base order. /usr/bin/time records wall time, user CPU time and maximum child RSS. Source hashes are checked before and after each run; no profiling or validation jobs overlap the timed builds. The VM is shared, so wall-time differences have that limitation.

Synchronous command profiles (Elab.async=false, command/profiler traces using heartbeats) cover all seven original proof modules and the new support module. Summed raw command counters fall from 4,691,501,026 to 4,508,682,406 (3.8968%), including the new helpers. This measures declaration elaboration work, not dependency loading or complete build wall time. The product-space basis proof falls from 12,702,018 to 6,116,649 in an isolated comparison; the normalized-bump Jensen proof replaces the original variance expansion. Candidates that changed original generated helpers or regressed materially were restored.

Validation

PASS: four warning-free clean-project builds; Mathlib linters over ten selected modules (3,589 declarations); style; lake shake; native and independent full-environment manifest comparisons; source-signature/non-proof audit; selected-project quality/trust checks; project card and canonical generated-index checks; and git diff --check. Dependency fingerprints match before/after every timed run, including the actual Mathlib checkout revision. All checks used the frozen final source hashes.

Commands include:

lake build LeanPool.EhrhartVolumeInequality.Imports
lake env lean --run scripts/ci/lint-project.lean <all selected project modules>
lake exe lint-style LeanPool.EhrhartVolumeInequality.Imports
lake shake --force --keep-public LeanPool.EhrhartVolumeInequality.Imports

The unchanged repository quality/trust routines were also run with the selected project's files and modules, including axiom closure, all-constant option/backdoor audit, headers, forbidden constructs, size limits, project-card declarations and the generated project aggregate. Whole-pool CI remains required. No gates, configuration, waivers, dependency pins, registry cards or unrelated projects are changed; LeanPool.lean is unchanged.

Limitations: full-pool and current-main merge-queue CI were not run locally and remain required, as do the independent refactor review and normal repository protections. Per-declaration costs can shift with the import environment; this PR does not claim every declaration became cheaper. No merge, queue entry or auto-merge action is requested or performed.

This PR is for review only; no merge or auto-merge is enabled.

@greptile-apps

greptile-apps Bot commented Oct 20, 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.

RetriggerView in Greptile

[Low impact] No actionable defect was found in the reviewed refactor; the normal repository checks remain required before merging.

Summary

This refactor adds ten support lemmas and shortens proofs without changing the original statements or definitions.

  • The Ehrhart volume proofs use less elaboration work to reach the same results.

Vilin97 explicitly acknowledges that the 10% performance target was not reached and that the small wall-time difference is not a reliable speedup. Vilin97 also states that retained type annotations and imports intentionally preserve elaboration cost and original inferred types.

Review limits: builds, timing runs, and the reported environment-manifest comparison were not independently rerun. External source fidelity, upstream license evidence, and repository-wide prior art were not independently verified.

Reviews (1) · Last reviewed commit: "perf: reduce Ehrhart volume proof elabor..." · Reviewed by Greptile

@github-actions

Copy link
Copy Markdown
Contributor

Proof profile (new / modified Lean files)

lake build wall time (changed modules): 18.29 s (= 0.30 min) — user 7.49 s, sys 5.22 s.

This build covers the added modules and their dependency cones on top of the measurement environment; modified files are measured without rebuilding the pool.

Statement changes

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

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: 606,714 → 586,964 (-19,750, -3.3%). Commands: 507 → 507.

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

Files: 1 compared — 1 cheaper, 0 costlier, 0 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 disjoint root command traces with trace.profiler.useHeartbeats and synchronous elaboration, converted to maxHeartbeats units. Failed measurements are not classified as cheaper or costlier. Δ lines counts added/deleted lines from this PR diff.

File Δ lines HB base HB head Δ HB Δ HB % Wall base (s) Wall head (s)
LeanPool/EhrhartVolumeInequality/Convexity.lean +95/-230 606,714 586,964 -19,750 -3.3% 77.49 73.28
Total +95/-230 606,714 586,964 -19,750 -3.3% 77.5 73.3

New files — absolute profile

Total heartbeats: 26,717 maxHeartbeats units across 1 valid file (706 added LOC).

Sum of lean --profile: 4304.1 ms (= 4.30 s) across 1 valid file. Import-excluded time: 1574.1 ms (= 1.57 s).

Count-heartbeats wall-clock total: 6.05 s. Repeated import cost inside lean --profile: 2730.0 ms (= 2.73 s).

Heartbeat values sum disjoint root command traces with trace.profiler.useHeartbeats and synchronous elaboration, converted from raw allocations to maxHeartbeats units by dividing by 1000. They include command elaboration and kernel checking, exclude imports, and include profiler overhead; they are not comparable to the deprecated linter's totals. Per-file wall clocks are measured under parallel load and are noisier than heartbeats.

LOC counts added lines in the profiled Lean files from this PR diff.

File LOC Heartbeats (maxHB) Count wall (s) lean --profile (s) Without import (s) Import (s) Commands Errors
LeanPool/EhrhartVolumeInequality/AnalysisSupport.lean 164 26,717 6.05 4.30 1.57 2.73 17 0
LeanPool/EhrhartVolumeInequality/Convergence.lean 23 — — — — — 141 1
LeanPool/EhrhartVolumeInequality/Foundations.lean 146 — — — — — 0 1
LeanPool/EhrhartVolumeInequality/FourierAnalysis.lean 87 — — — — — 560 1
LeanPool/EhrhartVolumeInequality/Imports.lean 1 — — — — — 0 1
LeanPool/EhrhartVolumeInequality/Regularization.lean 124 — — — — — 661 1
LeanPool/EhrhartVolumeInequality/Resolvent.lean 92 — — — — — 585 1
LeanPool/EhrhartVolumeInequality/Variation.lean 69 — — — — — 629 1
Total 706 26,717 6.05 4.30 1.57 2.73 2593 7

Aggregate phase totals

Phase Time
import 2730.0 ms (= 2.73 s)
typeclass inference 787.0 ms (= 0.79 s)
interpretation 331.0 ms (= 0.33 s)
tactic execution 127.0 ms (= 0.13 s)
elaboration 98.7 ms (= 0.10 s)
type checking 94.1 ms (= 0.09 s)
initialization 35.9 ms (= 0.04 s)
tacticAnalysis 30.8 ms (= 0.03 s)
linting 18.5 ms (= 0.02 s)
overlappingInstancesLinter 13.1 ms (= 0.01 s)
parsing 11.1 ms (= 0.01 s)
process pre-definitions 8.5 ms (= 0.01 s)

Slowest changed modules (from lake build)

Changed module Lake time
LeanPool.EhrhartVolumeInequality.AnalysisSupport 5.00 s
Per-file `lean --profile` output

LeanPool/EhrhartVolumeInequality/AnalysisSupport.lean

import took 2.73s
cumulative profiling times:
	attribute application 0.112ms
	congr simp thm 1.47ms
	elaboration 98.7ms
	fix level params 1.48ms
	import 2.73s
	initialization 35.9ms
	instantiate metavars 0.774ms
	interpretation 331ms
	let-to-have transformation 0.328ms
	linting 18.5ms
	module linting 0.00141ms
	norm_num 3.24ms
	overlappingInstancesLinter 13.1ms
	parsing 11.1ms
	process pre-definitions 8.51ms
	share common exprs 3.83ms
	simp 7.19ms
	tactic execution 127ms
	tacticAnalysis 30.8ms
	type checking 94.1ms
	typeclass inference 787ms
real 4.30
user 2.64
sys 1.26

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

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

{
"reviewed_head": "6d9af8f2ae775c28d393a5e3e7742efcdeb7162d",
"summary": "The refactor extracts reusable analytic interfaces and replaces repeated closed-span, self-adjoint range and basis calculations with named lemmas. The normalized-bump Jensen argument proves its probability and integrability obligations, and the remaining proof edits use explicit arithmetic facts or remove redundant elaboration scaffolding.",
"assessment": {
"scope": "analytic helper extraction and proof elaboration cleanup",
"introduces_tech_debt": false,
"maintainability": "improved",
"brittleness": "more_robust",
"risk": "low",
"assessment_one_sentence": "The complete nine-file change preserves readable mathematical mechanisms while reducing repetition and broad proof search."
},
"verdict": "approve",
"findings": [],
"validation": {
"source_scope": "All816 changed hunks covered across the team, including the full164-line AnalysisSupport module. Exact full source pairs, Git hashes and optional current-main projection verified.",
"performance": "The public ABBA arithmetic is consistent, but the small shared-VM wall-time difference does not establish a reliable speedup. Profile6303244091 has a valid Convexity comparison and new-support profile; seven other comparisons are unavailable. No10percent acceptance gate is introduced.",
"limits": "No independent build, compiled-manifest reproduction or private benchmark-artifact inspection. Existing configured2240 and own CI39507124813/core118918948609 remain pending."
},
"owner_scope": "Review only. Preserve no-queue/no-auto instructions; this favorable source assessment does not request integration."
}

@Vilin97

Vilin97 commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 LLM review — refactor (gpt-6.1-sol)

Reviewed head: 6d9af8f2ae775c28d393a5e3e7742efcdeb7162d

Verdict: ✅ approve

The refactor centralizes analytic helpers, replaces the variance expansion with Jensen, and reuses the spatial decomposition while preserving readable proof steps. Arithmetic changes narrow tactic inputs or use direct lemmas; all new helpers have callers. I found no actionable maintainability regression. Independent compilation was blocked by missing Mathlib dependencies, and the advisory comparison successfully profiles only Convexity, leaving the overall performance claim unverified.

Aspect Value
Scope proof refactor and helper extraction
Introduces tech debt ✅ no
Maintainability ✅ improved
Brittleness ✅ more_robust
Risk ✅ low

Reusable arguments and explicit arithmetic dependencies improve maintenance without obscuring the proofs or introducing broader automation.


Tokens: 2,487,455 in / 6,821 out · Tier: codex-subscription · Effort: xhigh · Billing: Codex subscription quota (no API credits) · Estimated cost: $10.0521 (Standard API equivalent; uncached input) (long-context rate)
Automated review against .github/REFACTOR_REVIEW_RULES.md. Disagree? Reply on the PR; rules can be updated in a PR of their own.

This branch has not been deployed

No deployments
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