A framework to formalize units (such as length, time, mass, velocity, etc.) in Lean.
- Dimensions : Type u_1
- addCommGroup : AddCommGroup Dimensions
Instances
The two key types here are Formal and Scalar d. Scalar d is the space of scalar
quantities whose units are given by d:Dimensions. Collectively, they generate a graded commutative
ring Formal, which can be conveniently described using the existing Mathlib structure
AddMonoidAlgebra. Algebraic manipulations of scalar quantities will be most conveniently
handled by casting these quantities into the commutative ring Formal, where one can use
standard Mathlib tactics such as ring.
In principle one could also develop vector-valued quantities with dimension, but for now we restrict attention to scalar quantities only.
Instances For
We will encounter a technical issue with Lean's type system, namely that the type Scalar d
and Scalar d' are not identical if d' and d are merely propositionally equal (as opposed
to definitionally equal); for instance, Scalar (d₁+d₂) and Scalar (d₂+d₁) are distinct types.
Technically, this renders multiplication on scalar types noncommutative. To get around this, we
create a casting operator, where the propositional equality is attempted to be resolved by the Lean
tactic module whenever possible. Unfortunately, the casting operator from Scalar d to Scalar d'
cannot be captured by standard Lean coercion classes such as Coe or CoeOut as each of the types
here contain parameters not present in the other.
Instances For
This is a variant of Scalar.val_inj that handles casts.
The existing Mathlib method AddMonoidAlgebra.single is perfect for embedding each type of
scalar into the formal graded ring Formal.
Equations
- ↑q = AddMonoidAlgebra.single d q.val
Instances For
Equations
Many identities involving several types of Scalars can be dealt with by applying
simp [←toFormal_inj] to move everything to Formal. A large number of further simp lemmas
in this file are then designed to simplify such Formal expressions, often by pushing casting
operators inward back to the Scalar types. As such, there will be significant overlap between
the simp and norm_cast tags.
Conveniently, casts from one scalar to another will automatically disappear when moving to
Formal.
We will use the NeZero class to tag some scalars as non-zero; this becomes relevant when
using such scalars as units. One could also introduce API to tag some scalars as positive, but
we currently are not implementing this.
Note how the simp lemma is in the direction of pushing casts inward.
Equations
- UnitsSystem.Scalar.instNeg = { neg := fun (q : UnitsSystem.Scalar d) => { val := -q.val } }
Equations
- UnitsSystem.Scalar.instSub = { sub := fun (q₁ q₂ : UnitsSystem.Scalar d) => { val := q₁.val - q₂.val } }
Equations
- UnitsSystem.Scalar.instSMul = { smul := fun (c : α) (q : UnitsSystem.Scalar d) => { val := c • q.val } }
Equations
Equations
The dimensionless scalars Scalar 0 can be identified with real numbers.
Instances For
Equations
We are finally able to view Scalar as a vector space over ℝ as promised.
Equations
- UnitsSystem.Scalar.instModule = { toSMul := UnitsSystem.Scalar.instSMul, one_smul := ⋯, mul_smul := ⋯, smul_zero := ⋯, smul_add := ⋯, add_smul := ⋯, zero_smul := ⋯ }
One can multiply a Scalar d₁ and Scalar d₂ quantities to obtain a Scalar (d₁+d₂) quantity,
in a manner compatible with multiplication in Formal.
Equations
- UnitsSystem.Scalar.instHMul = { hMul := fun (q₁ : UnitsSystem.Scalar d₁) (q₂ : UnitsSystem.Scalar d₂) => { val := q₁.val * q₂.val } }
Similarly, one can raise a Scalar d quantity to a natural number power n to obtain a Scalar (n • d) quantity. One could also implement exponentiation to an integer, but I have elected
not to do this, implementing an inversion relation instead.
Instances For
One cannot use the Mathlib classes Pow or HPow here because the output type Scalar (n • d) depends on the input n. As the symbol ^ is reserved for such classes, we use the symbol ** isntead.
Equations
- UnitsSystem.«term_**_» = Lean.ParserDescr.trailingNode `UnitsSystem.«term_**_» 80 81 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "**") (Lean.ParserDescr.cat `term 81))
Instances For
Multiplication and inversion combine to give division in the usual fashion.
Equations
- UnitsSystem.Scalar.instHDiv = { hDiv := fun (q₁ : UnitsSystem.Scalar d₁) (q₂ : UnitsSystem.Scalar d₂) => { val := q₁.val / q₂.val } }
Equations
- UnitsSystem.Scalar.instHDiv' = { hDiv := fun (q : UnitsSystem.Scalar d) (r : ℝ) => { val := q.val / r } }
Equations
- UnitsSystem.Scalar.instHDiv'' = { hDiv := fun (q : UnitsSystem.Scalar d) (n : ℕ) => q / ↑n }
Equations
- UnitsSystem.Scalar.instHDiv''' = { hDiv := fun (q : UnitsSystem.Scalar d) (n : ℤ) => q / ↑n }
Equations
- UnitsSystem.Scalar.instLE d = { le := fun (x y : UnitsSystem.Scalar d) => x.val ≤ y.val }
Equations
- One or more equations did not get rendered due to their size.
unit.in q is q:Scalar d measured in terms of unit:Scalar d.