Skip to content

feat(Units): parameterize the typed unit side (UnitSystem, LTMCTUnitChoices, SIUnitChoices) - #1481

Open
NicolasRouquette wants to merge 4 commits into
leanprover-community:masterfrom
NicolasRouquette:parametrize-unit
Open

feat(Units): parameterize the typed unit side (UnitSystem, LTMCTUnitChoices, SIUnitChoices)#1481
NicolasRouquette wants to merge 4 commits into
leanprover-community:masterfrom
NicolasRouquette:parametrize-unit

Conversation

@NicolasRouquette

Copy link
Copy Markdown
Contributor

Closes #1480.

Finishes the unit-side counterpart to #1447 (which parameterized Dimension over a basis and added the magnitude twin UnitScale B). The typed unit choice was still welded to LTMCTDimensionBase; this makes it basis-generic while keeping typed-unit safety, following Option D from the #1447 review. Full rationale, the blast-radius map, and the "why not A/B/C" analysis are in #1480.

What's here (three reviewable commits)

  1. feat(Units): additive coreclass UnitSystem B (Unit : B → Type, mag, mag_pos), TypedChoice B := (b : B) → UnitSystem.Unit b, TypedChoice.toScale : TypedChoice B → UnitScale B, the LTMCTDimensionBase instance, LTMCTUnitChoices ≃ TypedChoice LTMCTDimensionBase, and dimScale_eq_toScale_dimScale (the hand-rolled five-factor dimScale equals the generic Finset.prod fold — one source of truth). @[ext] added to UnitScale. No existing call site changes.
  2. refactor(Units): rename UnitChoices → LTMCTUnitChoices — it is inherently the unit choice for LTMCTDimensionBase (its fields hardcode the five …Unit types), so the name now mirrors the dimension basis. Stays a record: { SI with length := … }, u.length, ⟨…⟩, @[ext] all unchanged. Whole-word rename, all ~112 references under Physlib/Units/.
  3. feat(Units): SIUnitChoicesSIUnitChoices := TypedChoice ISQDimensionBase, the typed SI unit choice over the seven ISQ base quantities, from the same machinery. Adds CurrentUnit / AmountUnit / LuminousIntensityUnit (ampere / mole / candela), instance : UnitSystem ISQDimensionBase, the coherent SIUnitChoices.SI (m, kg, s, A, K, mol, cd), and a dimScale reused from the generic fold. Pairs ISQDimensionBase ↔ SIUnitChoices beside LTMCTDimensionBase ↔ LTMCTUnitChoices, with the existing ltmctToISQ / isqToLTMCT already bridging the bases.

(A fourth commit wraps two signatures the rename pushed past 100 columns.)

Acceptance criteria (from #1480)

  • UnitSystem, TypedChoice, TypedChoice.toScale added and building, indexed in Physlib.lean.
  • instance : UnitSystem LTMCTDimensionBase recovering the five typed unit names, with a u .length : LengthUnit type-safety check.
  • LTMCTUnitChoices ≃ TypedChoice LTMCTDimensionBase.
  • LTMCTUnitChoices.dimScale = UnitScale.dimScale ∘ toScale (law-unification), a single source of truth for the scaling law on the magnitude layer.
  • UnitChoices renamed to LTMCTUnitChoices (record kept; ergonomics unchanged).
  • SIUnitChoices := TypedChoice ISQDimensionBase with UnitSystem ISQDimensionBase, the three new ISQ typed unit types, SIUnitChoices.SI, and a u .current : CurrentUnit type-safety check; its dimScale reuses the generic fold.
  • Full Physlib build green; axioms classical-only on the new results.

Verification

Ran the build.yml gate locally on this branch — all green:

  • lake build -KCI — 9266 jobs
  • check_file_imports, check_dup_tags, sorry_lint — pass
  • runPhyslibLinters — Physlib + QuantumInfo pass
  • scripts/lint-style.sh, api_map_linter.py, codespell — pass
  • Axioms of the new results: propext, Classical.choice, Quot.sound only (no sorryAx).

Notes for reviewers: the three new unit types (CurrentUnit / AmountUnit / LuminousIntensityUnit) are minimal (positive-real magnitude + division); their full scale/relation API, and relocation to the appropriate physics directories following the LengthUnit convention, can be a follow-up. Happy to split this into separate PRs (core / rename / second basis) if that's easier to review.

NicolasRouquette and others added 4 commits August 1, 2026 17:45
Add the typed layer over the basis-generic magnitude twin `UnitScale B`:

* `class UnitSystem (B)` — a typed unit type per base dimension, with a
  positive-real magnitude (`Unit`, `mag`, `mag_pos`).
* `def TypedChoice (B) [UnitSystem B] := (b : B) → UnitSystem.Unit b` — a
  typed unit choice over any basis, the basis-generic form of `UnitChoices`.
* `TypedChoice.toScale : TypedChoice B → UnitScale B` — project the typed
  layer onto the magnitude layer that already carries the proved scaling laws.

For the default basis:

* `instance : UnitSystem LTMCTDimensionBase` recovers the five named typed unit
  types (`u .length : LengthUnit`, …), with type-safety `example`s.
* `UnitChoices ≃ TypedChoice LTMCTDimensionBase` (`equivTypedChoice`) and
  `toScale_equivTypedChoice` exhibit the bespoke record as that instance.
* `UnitChoices.dimScale_eq_toScale_dimScale` proves the hand-rolled five-factor
  `UnitChoices.dimScale` equals the generic `UnitScale.dimScale` `Finset.prod`
  fold at `toScale` — a single source of truth for the scaling law.

`UnitScale` gains `@[ext]`. Additive: no existing `UnitChoices` call site changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The bespoke five-field unit-choice record is inherently the unit choice for
the `LTMCTDimensionBase` dimension basis (its fields hardcode `LengthUnit`,
`TimeUnit`, `MassUnit`, `ChargeUnit`, `TemperatureUnit`). Rename it to
`LTMCTUnitChoices` so the name mirrors `LTMCTDimensionBase`, freeing the plain
`UnitChoices` name for a basis-generic reading and pairing naturally with the
forthcoming `SIUnitChoices` over `ISQDimensionBase`.

Pure whole-word rename across the Units subtree (structure stays a record, so
`{ SI with length := … }`, `u.length`, `⟨…⟩`, `@[ext]` are all unchanged);
`LTMCTUnitChoices ≃ TypedChoice LTMCTDimensionBase` still bridges to the
generic layer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Demonstrate the basis-generic typed-unit machinery on a second, seven-quantity
basis. `SIUnitChoices := TypedChoice ISQDimensionBase` is the typed SI unit
choice (current-based, seven slots), the sibling of the charge-based five-slot
`LTMCTUnitChoices`, produced by the same `UnitSystem` / `TypedChoice` layer.

* New typed unit types for the ISQ base quantities not already present —
  `CurrentUnit` (ampere), `AmountUnit` (mole), `LuminousIntensityUnit`
  (candela) — following the `LengthUnit` positive-real convention.
* `instance : UnitSystem ISQDimensionBase` assigning each of the seven ISQ base
  quantities its typed unit.
* `SIUnitChoices.SI` — the coherent SI choice (m, kg, s, A, K, mol, cd) — with a
  `u .current : CurrentUnit` type-safety check.
* `SIUnitChoices.dimScale` is obtained for free from `UnitScale.dimScale`; no
  per-basis scaling law is hand-rolled (`dimScale_self` reuses the generic proof).

Registered in `Physlib.lean`. Axioms are classical-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The `UnitChoices → LTMCTUnitChoices` rename (+4 chars) pushed two signatures
over the 100-column limit flagged by `scripts/lint-style.py`. Wrap them; no
logic change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Thank you for this PR, which will now be reviewed. If submitting to ./Physlib or ./QuantumInfo, please see our review guidelines if you are not familiar with the process. You should expect a back and forth with a reviewer before your PR is merged. See also that link for how to add appropriate labels to your PR. The PR will also go through a number of automated checks. You can learn more about these here, including how to run them locally.

If you are submitting to ./PhyslibAlpha there will be a lighter review process, though your PR must still pass the automated checks.

If you want to bring attention to this PR, please write a message on this thread of the Lean Zulip.

Important: If a reviewer adds an awaiting-author label to your PR, once you have addressed the review comments, please remove that label by adding a comment with -awaiting-author. This helps us keep track of reviews.

@github-actions github-actions Bot added the t-units Units label Aug 2, 2026
@nateabr nateabr self-assigned this Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

t-units Units

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix UnitChoices' basis asymmetry: parametrize the typed unit side

2 participants