Skip to content

Repository files navigation

Λs: a calculus for units of measure with conversion

CI Docs

API documentation: ericeallen.github.io/lambda-s, generated by doc-gen4 on every push to main.

Λs is a typed lambda calculus in which conversion between units of the same dimension is a primitive, and the price of admitting it is characterized exactly. This repository is the full mechanization: statics, dynamics, denotational semantics, two abstraction theorems, adequacy, erasure, and the Pi theorem of dimensional analysis, in Lean 4.

The theoretical literature on units, beginning with Kennedy, obtains parametricity theorems for calculi in which no operation can observe a unit. The practical literature provides conversion, which is what programmers ask of units, and no invariance theory, because conversion breaks the parametricity such theories rest on. Λs has both. Every parametric term is invariant under the rescalings that respect dimension, and a first-order program with nonzero denotation is invariant under all rescalings precisely when its accumulated conversion ratio is trivial: a decidable condition, which the development turns into a compiler diagnostic.

The development is 9,400 lines of definitions and proofs and 5,900 lines of documentation (17,700 lines of source in all; scripts/count_lines.py is the method, and CI checks these figures and the table below against it), and stays that small because of one representational decision: units and dimensions are exponent vectors over ℚ, so substitution is a linear map, every substitution lemma is a reordering of finite sums, and no normalization pass over unit syntax exists anywhere in the system.

Status

Lean 4.33.0 (pinned in lean-toolchain)
mathlib pinned in lake-manifest.json
sorry / admit none
lines of definitions and proofs 9,400
lines of documentation 5,900
theorem and lemma declarations 484
axioms propext, Classical.choice, Quot.sound

Examples.lean, QM.lean, and Algorithms.lean run the checker, the drift analysis, and the evaluator at build time through #guard; if a stated result were different, the library would not compile. The two demonstrations whose arithmetic reaches the BLAS stubs (the particle in a box and the two-state system, both in QM.lean) cannot run at build time, so the compiled binary checks them instead, and CI asserts its output.

Build

Prerequisites: elan (which installs the pinned Lean toolchain on first use) and a C compiler.

lake exe cache get     # fetch prebuilt mathlib oleans (multi-GB, needs network)
lake build             # build the library and check every proof
lake exe lambdas       # print the worked reports with their numeric self-checks

lake exe cache get is the slow step; with the cache in place, a full build of this library takes a few minutes on a laptop. The BLAS shim in c/ links against Accelerate's cblas on macOS (through the Command Line Tools SDK's libblas, since Lean's bundled linker has no framework search path; if your Mac has only Xcode, adjust moreLinkArgs in lakefile.lean) and falls back to portable C loops elsewhere; no separate BLAS installation is required, and the binary reports which backend it is running.

What is in here

The algebra. Uom defines a unit as a ℚ-valued exponent vector and proves the group laws. Scaling gives rescalings and the pullback laws that make substitution commute with them. Unify verifies elimination and solution preservation for rational unit equations. It has no assembled unifier or principal-type inference theorem; inference with conversion's dimension constraints remains open in this development. Space, Map, and Density give dimensioned vectors, Hart-style rank-one matrices, and densities.

Statics. Syntax gives types and terms, scope-indexed so ill-scoped syntax is unrepresentable. Typing gives both the declarative judgment HasTy and the checker, and the checker returns derivations: soundness holds by construction, and completeness and decidability are proved. Notation makes programs readable.

Dynamics. Dynamics is a definitional interpreter instrumented with units. Soundness is type soundness, and Normalization is strong normalization by Tait reducibility on type skeletons, so the fuel a definitional interpreter carries is produced by a theorem rather than assumed.

Semantics. Parametricity builds the logical relation, Fundamental proves both abstraction theorems and that coherence is the exact price of conversion. Adequacy joins the declaration oracle to the evaluator, and Erasure strips units and every dynamic check from run-time values without moving the numbers.

Conversion. Conversion gives the operator, Declare the consistency criterion for declaration sets, proved in both directions in exact rational arithmetic, Ratio the first-order syntax of accumulated ratios, and Twist the drift analysis and its decision procedure.

Dimensional analysis. Pi and PiTheorem derive Buckingham factorization and descent to n - rank A rational dimensionless coordinates. The factorization allows arbitrary signed outputs on positive inputs. PiCoherent supplies the dimension-level law for converting programs in closed external unit/dimension scope, including internal polymorphism. The stronger unit-level law applies to parametric convert-free or drift-free programs. Definability and NonDefinability prove that rational powers must be primitive.

Programs. Examples, QM, and Algorithms are the worked examples, including the yard/foot/meter declarations end to end and the pendulum.

Each module carries a header docstring explaining what it is for and why it exists; those are the intended entry points for a reader, and the groups above are the intended reading order.

Theorem index

THEOREMS.md maps every artifact identifier the accompanying paper cites to its Lean name, file, and line. Line numbers are re-derived from the sources by scripts/verify_theorems_index.py (CI fails on drift; --fix repairs the index in place). scripts/count_lines.py is the method behind the size figures above (--check fails CI when the status table stops matching the sources; --fix rewrites it).

Auditing the trust base

lake env lean scripts/Audit.lean

prints the axiom dependencies of every declaration THEOREMS.md indexes (scripts/verify_theorems_index.py fails if any indexed declaration is missing from the audit). CI builds the library, greps the sources for sorry, fails if any audited theorem depends on more than the three standard axioms, and runs the compiled binary, asserting its numeric self-checks and the declared-conversion report.

Trusted base

A reader who believes a theorem trusts the Lean kernel and the three axioms above. A reader who believes a number the binary prints trusts, in addition, Lean's compiler and runtime, the Float carrier, and the three C functions in c/lambdas_blas.c (lambdas_ddot, lambdas_dgemv, lambdas_blas_backend) that reach BLAS. The abstraction and adequacy theorems use real arithmetic and do not equate it with compiled floating-point arithmetic. Rounding affects defined operations. The carriers also totalize partial operations differently: for example, Float.pow returns NaN on negative bases with non-integer exponents, while Real.rpow uses the real part of the principal complex power. Concrete #guard checks execute through Lean's compiler; they are distinct from kernel-checked theorem proofs. The binary checks selected arithmetic and boundary cases, not a general correspondence.

License

Apache-2.0; see LICENSE.

About

A calculus of units of measure with conversion, mechanized in Lean 4

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages