feat(Units): parameterize the typed unit side (UnitSystem, LTMCTUnitChoices, SIUnitChoices) - #1481
Conversation
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>
|
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 |
Closes #1480.
Finishes the unit-side counterpart to #1447 (which parameterized
Dimensionover a basis and added the magnitude twinUnitScale B). The typed unit choice was still welded toLTMCTDimensionBase; 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)
feat(Units): additive core —class UnitSystem B(Unit : B → Type,mag,mag_pos),TypedChoice B := (b : B) → UnitSystem.Unit b,TypedChoice.toScale : TypedChoice B → UnitScale B, theLTMCTDimensionBaseinstance,LTMCTUnitChoices ≃ TypedChoice LTMCTDimensionBase, anddimScale_eq_toScale_dimScale(the hand-rolled five-factordimScaleequals the genericFinset.prodfold — one source of truth).@[ext]added toUnitScale. No existing call site changes.refactor(Units): renameUnitChoices → LTMCTUnitChoices— it is inherently the unit choice forLTMCTDimensionBase(its fields hardcode the five…Unittypes), 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 underPhyslib/Units/.feat(Units):SIUnitChoices—SIUnitChoices := TypedChoice ISQDimensionBase, the typed SI unit choice over the seven ISQ base quantities, from the same machinery. AddsCurrentUnit/AmountUnit/LuminousIntensityUnit(ampere / mole / candela),instance : UnitSystem ISQDimensionBase, the coherentSIUnitChoices.SI(m, kg, s, A, K, mol, cd), and adimScalereused from the generic fold. PairsISQDimensionBase ↔ SIUnitChoicesbesideLTMCTDimensionBase ↔ LTMCTUnitChoices, with the existingltmctToISQ/isqToLTMCTalready bridging the bases.(A fourth commit wraps two signatures the rename pushed past 100 columns.)
Acceptance criteria (from #1480)
UnitSystem,TypedChoice,TypedChoice.toScaleadded and building, indexed inPhyslib.lean.instance : UnitSystem LTMCTDimensionBaserecovering the five typed unit names, with au .length : LengthUnittype-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.UnitChoicesrenamed toLTMCTUnitChoices(record kept; ergonomics unchanged).SIUnitChoices := TypedChoice ISQDimensionBasewithUnitSystem ISQDimensionBase, the three new ISQ typed unit types,SIUnitChoices.SI, and au .current : CurrentUnittype-safety check; itsdimScalereuses the generic fold.Physlibbuild green; axioms classical-only on the new results.Verification
Ran the
build.ymlgate locally on this branch — all green:lake build -KCI— 9266 jobscheck_file_imports,check_dup_tags,sorry_lint— passrunPhyslibLinters— Physlib + QuantumInfo passscripts/lint-style.sh,api_map_linter.py,codespell— passpropext,Classical.choice,Quot.soundonly (nosorryAx).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 theLengthUnitconvention, can be a follow-up. Happy to split this into separate PRs (core / rename / second basis) if that's easier to review.