1 Introduction

Geometric Algebra provides a language for manipulating geometry algebraically, which unifies many geometric applications of complex numbers, quaternions, and linear algebra into a single mathematical language.

There are software packages in various languages today which support working with and developing intuition for Geometric Algebra. Most of these packages are designed for numerical computation, typically targeted somewhere along the spectrum with ease of use at one end and efficiency at the other. However, it is the packages designed for symbolic manipulation which are most relevant to the topic of this paper, such as the packages for Python [4], Maple [1], and Mathematica [2]. These packages are built on top of computer algebra systems (CAS), and typically consist of definitions of the objects and operators of GA, and sometimes some specialized routines to simplify expressions.

A key feature in a CAS is the ability to simplify expressions to save the user from doing so manually, which can be slow and error-prone. Such a system is preloaded with a set of rules, such as \(x(y + z) = xy + xz\) which can be used to manipulate expressions. These rules are in a sense axiomatic; a CAS does not provide proofs of these rules, and so trust has to be placed in both the author of the rules, and in the procedures used to apply them.

Theorem provers take quite a different approach—the base set of axioms is very small (for example, those of Zermelo–Fraenkel set theory), and every other “rewrite rule” must be proven from these. This approach drastically reduces the amount of trust needed from the user—instead of having to place trust in every single rewrite rule, their trust can be concentrated onto: the theorem prover itself, its choice of axioms, and the fact that the definitions used in the rewrite rule correspond to their established meaningFootnote 1.

One such theorem prover is Lean [5], developed by Microsoft Research. We choose to use this theorem prover for our formalization not because we believe it is objectively better, but because of the rapidly growing library and community forming around it, which we describe more in Sect. 5.

This paper will start in Sect. 4 by introducing the Lean language and syntax, in order to provide a reader unfamiliar with either theorem provers or Lean with the basic tools needed to understand relevant code snippets. It will then summarize the scope of the Lean mathematics library mathlib [19], and how we intend this work to fit within it. With these preliminaries in place, it will outline in Sect. 6 the approach taken by previous formalizations of Geometric Algebra in other languages, and summarize their strengths and shortcomings. At this point, we introduce our own Lean formalization, contrasting its foundations to those of prior work, and demonstrating its strengths and weaknesses by example. We conclude by outlining gaps in mathlib’s API which, if filled, would help to tie together our formalization with other branches of mathematics, as well as how ongoing work in mathlib will open doors to further formalization goals.

2 Geometric Algebra

Geometric algebra (GA)Footnote 2 provides a mechanism to extend a vector space with a metric-dependent product operator, the geometric product. This product combines and generalizes the properties of the conventional dot and cross product used in 3D euclidean space, while inheriting their geometric interpretations; as an example, for two vectors a and b, the product decomposes as

$$\begin{aligned} ab = a\cdot b + a \wedge b \end{aligned}$$

where \(a\cdot b\) is a scalar and \(a \wedge b\) is a bivector analogous to \(a \times b\).

A geometric algebra is characterized by its metric, a quadratic form Q(x) assigning a scalar value to the square of each vector x. It is typicalFootnote 3 for our vectors to be a module over \(\mathbb {R}\), where the action of the quadratic form can be characterized by its action on a set of orthogonal basis vectors \(e_i\). Specifically, the quadratic form can be encoded a 3-tuple “signature” of natural numbers (pqr), indicating that p of the basis vectors satisfy \(Q(e_i) = 1, q\) satisfy \(Q(e_i) = -1\), and r satisfy \(Q(e_i) = 0\). For these real vector spaces, we use the notation \(\mathcal {G}(\mathbb {R}^{p,q,r})\) to denote an algebra of a given signature. Some commonly used geometric algebras for 3D geometry are \(\mathcal {G}(\mathbb {R}^{4, 1, 0})\), Conformal Geometric Algebra (CGA); and \(\mathcal {G}(\mathbb {R}^{3, 0, 1})\), Plane based Geometric Algebra (PGA). These are particularly valuable to applications in computer graphics and robotics, as “blade” elements of the algebra represent 3D primitives like lines, planes, and circles, while “rotor” elements of the algebra represent translations, rotations, and reflections. Many other familiar algebras are isomorphic to a geometric algebra, like the complex numbers \(\mathcal {G}(\mathbb {R}^{0,1,0})\) and the exterior algebra \(\mathcal {G}(\mathbb {R}^{0,0,n})\).

A key advantage to using GA for geometric problems is that it is rarely necessary to explicitly separate coordinates when doing geometry, as would be done for instance when constructing a rotation matrix or computing the intersection of two planes. In a numerical software package, internally representing coordinates is unavoidable; but for symbolic manipulation, coordinates can just be a distraction. For this reason, we would prefer a formalization that avoids coordinates entirely.

3 Theorem Proving Software

Theorem proving software must do more than simply encode and verify mathematical truth; it must make doing so ergonomic for the user, and minimize the inevitable friction when converting a pen and paper argument into a machine-readable one. The typical workflow for this conversion is split into two parts—translating the theorem statement, and then translating the proof.

The use of dependent type theory (as opposed to the set theory typically used by mathematicians) helps with the theorem statements, as it provides a mechanism to reject nonsensical statements like \(1 = (2 < 3)\) (with a type error like “\(2 < 3\) is a Prop, expected an \(\mathbb {N}\)”). Flexible notation is also valuable in theorem statements, as mathematics is symbol-heavy; for instance, being able to write \(\sum \) instead of “sum” makes it easier to align paper with screen.

Where the software can really shine though is in the proofs, via interactive and automated theorem proving. The former is about showing unresolved “goals” as the proof progresses, to help the user as they write and to guide them what to do next. The latter is invaluable for discharging goals the user views as trivial, such as \((a + b) + c = (b + c) + a\)—while the user could manually apply associativity and commutativity lemmas, automation prevents them having to waste time thinking about this. The scale of automation can vary from filling in the blanks (converting a proof of \(x < x + 1\) into a proof of \(2 < 3\)), to performing a CAS-like simplification, to applying a sophisticated machine-learning model [18]. Since automation is typically implemented as proof-generation, it doesn’t impact the trustworthiness of the prover—the generated proof is subject to the same mechanical scrutiny as a hand-written one. The line between interactive and automated is frequently blurred.

The Lean 3 language used in this paper is just one of many theorem proving languages, and while it has all of the properties described above, it is not unique in that it does so. Its use of dependent types is very similar to Coq, and its heavy use of notation similar to Agda. Its automation tools are currently less powerful than those of Isabelle/HOL, without an equivalent to Isabelle/HOL’s powerful tactic [17].

4 A Quick Primer on Lean

In this section, we will give a very brief introduction to the Lean language, in order to aid with reading the fragments of Lean codeFootnote 4 in the rest of this paper. The Lean community website provides a much more in-depth set of reference materials [12], as well as an in-browser Lean 3 environmentFootnote 5 [13].

We’ll start with a simple definition, showing how to define a value with a given name and type. Here, we define the name to refer to the natural number () 2:

figure d

Function types are declared with a separating the types of their inputs and outputs. Function values introduce their variable binders using a followed by variable names. Here, we define a function that takes a natural number and doubles it:

figure g

For convenience, the language lets us introduce the variable and declare its type in one place; so we could also have written this:

figure h

Function application is notated with juxtaposition, which has higher precedence than most operators. Note that sometimes a is used in place of parentheses.

figure j

What makes Lean a language for theorem proving, and not just a regular functional programming language, is its , which holds mathematical statements.

figure l

Mathematical statements are themselves types (are permitted to appear to the right of a colon), whose values constitute their proofs. We use the keyword when providing proofs, but the syntax is otherwise identical:

figure n

We can prove by definition . However, while we are free to make the , Lean does not allow us to prove it. Instead, it grants us an escape with the keyword, which is used to mark proofs as omitted. Using sets a contagious flag that marks a proof and all its dependencies as incomplete, ensuring that the user eventually goes back to fill in the missing proof. In this paper, we will use in code examples to indicate proofs not interesting to the reader, but present in our formalization.

Usually we do not separate our statements and proof as we did for . The example below shows a slightly longer proof, using our earlier definition of :

figure pa

This can be read as a function, that takes a number and emits a proof of a statement about that specific . This is what it means for Lean to be dependently-typed; the type of the result of a function can depend on its input. When the inputs of a function are themselves proofs, this concept of proofs as values leads naturally to the Howard-Curry correspondence; an implication of the form \(P \implies Q\) is represented as a function that converts proofs of P into proofs of Q.

The second line of this proof enters tactic mode using the keyword. Once within this mode, tactics can be used. These tactics are often themselves Lean programs, and this mode is what makes Lean an “interactive” theorem prover. When in this mode, compatible text editors will show what is left to be proven after each tactic has been applied.

The logical foundation of Lean is the Calculus of Inductive Constructions. The following example demonstrates a typical inductive construction; an inductive type used to represent the logical or of two propositions:

figure w

This reads as “there are two ways to construct a proof of \(P \vee Q\); by providing a proof of P), and by providing a proof of Q)”. From this definition, Lean provides us with an induction principle which allows this procedure to be reversed, as “To proveFootnote 6\(P \vee Q \rightarrow R\), it is sufficient to prove \(P \rightarrow R\) and \(Q \rightarrow R\)”.

These “inductive” types are used to build almost every object needed in formalized mathematics and computer science; examples include the integers, lists, logic operators, and existential quantifiers. Sometimes we need one more fundamental building block, “quotient” types. These allow associating an equivalence relation with a type, for instance to ensure that \(\frac{1}{2} = \frac{2}{4}\). Lean supports these too, and we will see more of them in Sect. 7.2.

5 Lean’s Mathematical Library mathlib

By itself, Lean is very much “batteries not included”. Its standard library is not opinionated on whether you use it for mathematics or software verification, and as a result comes with little beyond basic data types and constructive logic. Notably, it does not contain proofs of statements like “the integers form a ring”, nor even the definition of “ring” required to make such a statement! This is not a short-coming in Lean—it’s just a choice of division of responsibility.

The mathematically interesting statements come from mathlib, which is “a community-driven effort to build a unified library of mathematics formalized in the Lean proof assistant” [19], spanning topics like linear algebra, topology, and analysis. The library is constantly growing [14], with over 100 contributors whose backgrounds are widely spread across both fields and seniority, with valuable contributions coming from undergraduates and professors alike. Perhaps a particularly notable property of mathlib is that one of its goals is to formalize the entirety of a particular undergraduate mathematics curriculum [15].

The coherency and breadth of this library makes formalization work in Lean particularly attractive, as new structures can often be built as a thin layer on top of existing structures. Furthermore, it reduces the effort needed to bring formalizations in different branches of mathematics together—for instance, in the process of formalizing statements about the wedge product in this work (Sect. 7.8), the mathlib definition of the matrix determinant was shown to be an alternating map.

Lean is not unique in having a standard library of mathematics—two obvious contenders are the math-comp of Coq, and the stdlib of Agda. A thorough comparison of the three libraries is beyond the scope of this paper, but a very rough estimate of breadth and accessibility to new users can be obtained by counting the lines of code, comments, and contributors, as shown in Table 1. This estimate is a poor one, as differences between the languages themselves could easily result in the same idea taking a different number of lines to express—but it’s sufficient to demonstrate that Lean is at least on-par with its competitors. For reference we also include Hol-light and Isabelle’s “Archive of Formal Proofs” (AFP) in Table 1, but as noted in the table caption these are not suited for direct comparison.

Table 1 Comparison of metrics between standard libraries of popular provers using data from their GitHub repositories as of July 2021

Our intent in formalizing Geometric Algebra is for our formalization to not only interface well with mathlib, but also for certain portions to ultimately end up a part of it. Contributing code into mathlib ensures its ongoing maintenance [20], and has numerous advantages: community review by Lean experts, automated detection of bad practices by software tools, and generated documentation published to the web. Perhaps most important though is that the community as a whole takes on the responsibility of keeping our contributions compatible with the rest of mathlib as it evolves. The quality bar for inclusion into mathlib is high, and as is common in software development, the review process favors lots of small contributions over one giant contribution. In practice this means it works best to develop larger formalizations outside mathlib, while in parallel continually shifting parts of their foundations back into mathlib; this allow rapid iteration unimpeded by reviewer delay, while still insuring against the formalization diverging irrecoverably from mathlib.

In the rest of this section, we will introduce the elementary parts of mathlib that will be essential to both translating existing formalizations and constructing our own.

5.1 Algebraic Structures

Some of the simplest definitions provided by mathlib are those of the algebraic structure hierarchy—statements like “the type M is a monoid if it is a semi-group, has an identity 1, and \(\forall m : M, m \cdot 1 = 1 \cdot m = 1\)”. These definition are intended to be used through type-classes, which are a mechanism for associating structure with a type. This mechanism comes in two parts: a syntax using for finding type-classes,

figure ad

and the keyword for registering an instance of a type-class to custom types.

figure af

Combined, these declarations allow our

Of particular interest to formalization of geometric algebra are type-classes,Footnote 7 which respectively describe an R-module structure on V (roughly a vector space) and an R-algebra structure on A. The former is of interest as it characterizes an arbitrary vector space over which we wish to define the geometric algebra, while the latter is a minimum requirement which our definition must meet in order to be considered useful.

5.2 Homomorphisms

In mathematics, it is frequently useful to talk about structure-preserving morphisms, such as an R-linear map; a function \(f(x) : A \rightarrow B\) that \(f(x + y) = f(x) + f(y)\) and \(\forall c \in R, f(cx) = cf(x)\). In mathlib this is represented by the type that “bundles” the map itself with proofs of the aforementioned properties. Since such bundled maps are quite common in mathlib, shorthand notation is provided. Table 2 summarizes mathlib’s bundled maps and their notations used in this paper.

Table 2 Notation for homomorphisms in mathlib

6 Existing Formalizations of GA

While there has been no published use of Lean to formalize geometric, Clifford, or Grassman–Cayley algebras, there are already formalizations in other theorem proving languages. To aid the reader, when describing these other formalizations this section presents code snippets translated into their (roughly) equivalent Lean code.

Of particular interest in these existing formalizations is the underlying definition used to define a multivector, and how this definition can be used to define a product of some kind. While proofs are obviously important to a formalization, every proof has to start with a theorem statement, the expressivity of which is limited by the definitions at hand.

We present them roughly in order of generality.

6.1 Fixed-Dimension Representations

In [11], a formalization in Isabelle/HOL specific to \(\mathcal {G}(\mathbb {R}^3)\) is presented that enumerates all the r-vectors explicitly by assigning a name to each grade:

figure ak

From here, the operations of an abelian group can be defined componentwise:

figure al

and shown to satisfy its axioms using the are equal if their four components are equal”:

figure am

Already we can see that this approach inevitably leads to a lot of repetition, as while it would be easy to generalize over the integer grades 0, 1, 2, 3, it is challenging to generalize over the names .

The problem only becomes worse when defining the geometric product, as now we have four terms in each of the components. As in [11], the full definition is omitted below.

figure ao

From here, [11] goes on to prove that multivectors form a ring, by showing that multiplication associates and distributes, and operates as expected with one. Again, this would have to be done component-wise, and the trivial but presumably verbose proofs are omitted from [11].

The tedium of the component-wise definitions and proofs can be reduced by generation from CAS implementations and automation features within the theorem provers, but this scales poorly to more complex statements, which may need to be tackled by hand. Needless to say, this formalization does not scale at all to other dimensions and signature of algebra, as no part of it is generalized.

6.2 Recursive Tree Representations

A convenient way to escape this death-by-cases is to use a recursive definition of a multivector. This is the approach taken by the Coq formalization of Grassmann–Cayley algebra in [7] (and resembles the computational approach used by Garamon  [3]). There, the definition is built as a balanced binary tree, where each branch indicates the presence or absence of a basis blade, and the leafs contain the corresponding coefficient.

figure ap

In this Lean translation, the syntax is used to pattern match against an integer representing the remaining depth of the tree, while captures the branching. For instance, \(a + a_1e_1 + a_2e_2 + a_{12}e_{12}\) is represented as a term of type as \(((a, a_2), (a_1, a_{12}))\).

The recursive data definition leads naturally to a recursive operator definition, which resembles the following:Footnote 8

figure at

Here, the pattern-matching is against the depth of the tree, and for non-root elements, the two branches. This elegantly avoids having to deal with coefficient-wise proofs, and results in a definition that works on algebras of arbitrary dimension .

While [7] does not extend to defining a metric or the geometric product it infers, their follow-up work [8] does so. This design still shares a shortcoming of the previous design—it imbues the definition with a canonical and orthogonal basis, which is at odds with our goal of being coordinate-free.

6.3 Indexed Coordinate Representations

The HOL light formalization in [16] offers the same generality as the one in Sect. 6.2, but slightly more abstractly describing a multivector as a set of coefficients indexed by the IDs of its basis vectors.

figure au

[16] goes on to define the geometric product and various derived products for arbitrary metrics, which means their formalizations can be used for both CGA and PGA. A rough translation of their generalized product formalization is as follows.

figure av

Here is the symmetric difference. This is then used to derive the wedge and other products as

figure ax

Overall, the formalization that follows in [16] is expansive, covering topics ranging from the existence of inverses to outermorphisms. However, the initial definition of ingrains a preferred choice of orthogonal (finite) basis, which while in line with many numerical packages for Clifford algebras, is at odds with how vector spaces are formalized in mathlib. mathlib’s approach is typically axiomatic, introducing explicit sets of basis vectors only when needed; often, only the proof of the existence of a set of basis vectors is used.

To mesh well with mathlib, our formalization will need to support algebras over a variety of vector spaces, not just those with coefficients in \(\mathbb {R}^n\). We are of course free to take on extra assumptions should we need them (such as the scalars forming a field, or the dimension of the space being finite), but by making the initial definitions more general we leave the door open to future researchers interested in other algebras which do not satisfy these assumptions.

7 Our Formalization of GA

In this section, we present a variety of definitions and theorems for GA that we formalized in Lean. For reasons described in Sect. 5, some of these formalizations have been integrated into mathlib, while the rest are available in our source code repository (linked in Sect. 9). We won’t attempt to distinguish where the line is drawn, as ultimately the result is the same; users of our source repository will automatically get a compatible version of mathlib.

7.1 Remarks on Type Theory

While it is typical on paper to avoid distinguishing “the multivectors of grade zero” from “the scalars”, or “the multivectors of grade 1” from “the vectors”, the strict dependent typing of Lean forces us to treat these separately. Instead of saying that the multivectors \(\mathcal {G}(V)\) “contain” the scalars R and vectors V, we need to provide explicit mappings between these distinct types. Respectively, these come in the form of a ring homomorphism \(\mathtt {algebra\_map} : R \rightarrow \mathcal {G}(V)\) and a linear map \(\mathtt {\iota } : V \rightarrow \mathcal {G}(V)\)Footnote 9.

Typically we would assume these mappings are injective, but we can obtain many results without needing to do so. As it turns out, the definitions outlined below permit these maps to be non-injective, for particularly pernicious choices of R and V [9]Footnote 10.

7.2 The Quotient Definition

A Clifford algebra over the vector space V with quadratic form \(Q : V \rightarrow R\) can be defined as a quotient of the tensor algebra T(V) by the two-sided ideal \(I_Q\) generated from the set \(\{ v \otimes v - Q(v) \,\vert \, v \in V \}\). Generating an ideal from this set amounts to taking the smallest superset of it that is closed under left- and right- multiplication and addition by elements of T(V). When we take a quotient by an ideal, we are saying that two elements are considered equivalent if their subtraction is in that ideal. It follows then that we have \(v \otimes v \approx Q(v)\), and therefore our construction ensures that vectors square to scalars.

As of writing, mathlib does not have direct support for two-sided ideals, but it does support the equivalent operation of taking the quotient by a suitable closure of a relation like \(v \otimes v \approx Q(v)\). As such, the quotient definition still translates fairly naturally into Lean:

figure ay

What makes this definition particularly attractive is that thanks to the attribute (a Lean metaprogram built into mathlib), the structure can be automatically proved by Lean using its knowledge of . Note that it is structure which provides

The operations described in Sect. 7.1 also fall out with minimal effort: the derived structure provides the map from the scalars while the map from the vectors is obtained by first mapping the vectors into the tensor algebra (using , the analogous \(\iota \) for the tensor algebra), and then embedding them within the quotient using the API around . Putting these together, we can verify that our construction does indeed square vectors to scalars:

figure hi

The remaining code to explain is our definition, which demonstrates how types can be use for propositions, as was introduced briefly in Sect. 4. Here, we declare as a proposition over pairs of elements in T(V), but provide only one way to construct it, . In essence, this means that a proof of is a proof that there exists some v such that \(T_1 = {\iota }(v) \otimes {\iota }(v)\) and \(T_2 = Q(v)\). Note that mathlib uses not for the product in the tensor algebra.

While not written by the authors, a better understanding of the power of inductive types can be obtained by looking inside mathlib’s definition of . The inductive type used by this definition to extend our definition to its closure under ring operations is roughly as follows:

figure bp

This reads as “A pair of elements are satisfied by the closure of a relation if:”

  • “They satisfy the relation

  • “They can each be split into an addition with the same right , and with left operands satisfying the closure of the relation.”

  • “They can each be split into an multiplication with the same left/right operand, and with a right/left operand satisfying the closure of the relation.”

One might remark that something still seems odd about this relation, as neither this nor our imply reflexivity, symmetry, or transitivity — however, these properties follow from the axiomatization of Lean’s type, and are provided as part of the Lean prelude as .

7.3 The Universal Property

While convenient to define, the quotient can be hard to state further definitions and prove theorems about. When defining operations over a quotient, the approach is almost always to operate on the data within the quotient, and then prove that for any operands that are considered equal under the quotient, the output of the operation is unchanged.

Such proofs can be very challenging, especially given some short-comings in Lean when it comes to recursing over nested inductive types (such as which wraps our above). Another approach is to work with the universal property from category theory. The universal property of the Clifford algebra is shown diagrammatically in Eq. (7.1)—given a linear map f from V to an algebra A satisfying \(f(v)f(v) = Q(v)\cdot 1_{A}\), there is a unique addition-and-multiplication-preserving map from \(\mathcal {G}(Q)\) to A that satisfies \(f = ({\text {lift}} f) \circ \iota \). Since \({\text {lift}}\) provides a unique mapping, it has an inverse and we can also state this property in reverse in terms of g.

(7.1)

The universal property can be stated in Lean as

figure bv

which with the help of Table 2, reads piecewise as:

  • “lift” is an equivalence between...

  • ... R-linear maps from the vector space V to the algebra A...

  • ... whose output squares to the metric ...

  • ... and maps between \(\mathcal {G}(Q)\) and A which are R-linear and preserve multiplication.

The implementation of (as opposed to just its type) is not included in this paper, but consists largely of invoking uninteresting machinery around already in mathlib. This machinery within mathlib encapsulates the task of working under the quotient, so that we don’t have to

Note that if we apply this equivalence in reverse to the identity algebra automorphism \(\mathcal {G}(Q) \rightarrow \mathcal {G}(Q)\) (that is, evaluate ), then we recover a linear map from V to \(\mathcal {G}(Q)\) whose results square to scalars. IntuitivelyFootnote 11, this is \(\iota (v)\).

The type of alone is enough for us to prove statements like \(({\text {lift}} f) (a + b * c) = f(a) + f(b)f(c)\), while its composition with \(\iota \) gives us the remaining interesting properties.

For the rest of our formalization, our proofs and definitions depend only on the properties of , and never on the quotient construction from Sect. 7.2. In principle, this would enable future work to transfer proofs of theorems about our construction to any other construction, such as those in Sect. 6, provided that those definitions are equipped with their own

7.4 Conjugations

Beyond the identity mapping , the next simplest operation we can use it to define is the grade involution \({\hat{X}}\), which flips the sign of every component vector. In Lean, we write that

figure cf

where is producing the trivial proof that . Just as we saw earlier with , the type of alone is enough to prove statements about involutions of addition and multiplication. This time, we also get from the type the fact that involute acts as the identity on scalars. All that remains is to prove that involution negates vectors, which get almost for free using some lemmas about the universal property (not shown):

figure cj

To check that the Lean simplifier is suitably trained for , we show that taking the involution of a product of n vectors () is equivalent to scaling by \((-1)^{n}\):

figure cl

A similar approach can be performed to define grade reversion \({\tilde{X}}\), although this time instead of inserting a minus sign for each vector, we need to flip the multiplication order. mathlib provides us an mapping for exactly that, which by definition satisfies . Applying this to each of our vectors will then give , which we can map back into . It can be trivially shown that this mapping is linear and invertible (), which combined with some rather ugly boilerplate gives us a complete definition for grade reversal.

figure cr

Unlike , so we need to prove how it acts on scalars and multiplication ourselves. Once again, makes short work of this.

figure ct

While the above definitions of give us proofs about their operations on sums and products essentially for free, they miss one key property of these conjugations; the fact that they are involutive, . Proving these becomes much easier once we build an inductive principle.

7.5 Induction

The induction principle we seek can be stated “If a property and is preserved under addition and multiplication, then it holds for all of ”. Perhaps surprisingly, the universal property alone is enough for us to construct this principle. An a outline of the approach is:

  1. 1.

    Show that collectively, the inputs to our inductive principle define a of precisely the elements that satisfy ; that is, a subset of the full Clifford algebra which contains zero and one and is closed under addition and multiplication. By doing this, Lean provides us with a type which bundles each element of the subalgebra with a proof that it belongs to that subalgebra.

  2. 2.

    Restrict the codomain of , and show that doing so still preserves the fact that vectors square to scalars.

  3. 3.

    Lift this restricted map from .

  4. 4.

    Apply this lifted map to our input . We show that the value part of this lifting is just , meaning the proof part is , our proof for an arbitrary element.

The full Lean implementation is shown below.

figure de

Armed with our new hammer, we find a lot of nail-like lemmas we can easily prove. Below, we show that involution and reverse commute, and each is involutive; that is, \(\tilde{{\hat{x}}} = \hat{{\tilde{x}}}\), \(\hat{{\hat{x}}} = x\), and \(\tilde{{\tilde{x}}} = x\).

figure fx

7.6 \(\mathbb {Z}_2\)-grading

An algebra A is said to be graded by an additive monoid I if there exists a family of I-indexed submodules \(A_i\) such that \(x \in A_i,\ y \in A_j \rightarrow xy \in A_{i + j}\), \(1 \in A_0\), and every element \(a \in A\) has a unique decompositionFootnote 12\(a = \sum _i a_i\) where \(a_i \in A_i\). If we adjust this definition to use a wedge product instead of a regular product, then we can obtain the familiar \(\mathbb {N}\)-grading used in Geometric Algebra. However, we haven’t formalized the wedge product yet!

Instead, we can show that the Clifford algebra permits a \(\mathbb {Z}_2\) grading, that is a grading by the integers modulo two. Intuitively, this maps to the notion of even- and odd-graded r-vectors. Again, we get there via the universal property; this time, mapping into is built into mathlib. This type can be thought of as somewhat analogous to a polynomial, where the coefficients are the even and odd multivectors themselves, and the variable is either \(x = x^3 = \cdots \) (odd) or \(1 = x^2 = \cdots \) (even), where multiplication behaves as addition does in \(\mathbb {Z}_2\). We write this in Lean as follows, where the name indicates constructing an object of a single grade.

figure di

Thanks to the universal property, and the fact it produces an for us, we get obvious properties like for free.

To finish this definition of the grading, we show that there is in the other direction forming a left inverse (by simply summing components), and we show that the grades are disjoint. We state this latter fact as

figure dm

which reads “If you take the grade i part of x (\(x_i\)), and then split \(x_i\) into its constituent grades, it will consistent of a single grade i”. The Lean proof is omitted in this paper for brevity, but it once again falls out after application of the induction principle from Sect. 7.5.

7.7 Versors

The versors can be described as a set of multivectors closed under multiplication and scaling, generated from the set of vectors . We write this formally as:

figure dp

where is a wrapper for a set of elements, built on top of the structures in mathlib that respectively carry proofs of closure under multiplication and scaling.

Lean provides some useful syntax for working with sub-objects like this. Instead of working with , we can write as a shorthand . The advantage of “bundling” the multivector with its proof of being a versor like this is that operations can be defined to automatically produce a bundle containing a proof that their result is also a versor; and indeed, does just that.

Armed with our definition, the next step is to once again construct an induction principle. Most of the heavy lifting is done by the principle in mathlib, which was developed as part of this paper. The statement of this principle is:

figure dx

The induction principle lets us once again bash out some useful statements with uninteresting proofs. This time, we scratch the surface of Lean’s meta-programming framework to avoid repeating a trivial proof:

figure dy

A more interesting application of our induction principle is to prove that the product of a versor and its reverse is a scalar:

figure dz

Here we use some more verbose Lean syntax to clearly indicate each branch of the induction. From here, we go on to show that versors have an inverse, and that for a non-trivial algebra over a field in an anistropic metric, they form a group with zero (i.e. all elements but zero have an inverse):

figure ea

7.8 Wedge Products and \(\mathbb {N}\)-Grading

Formalizing the wedge product of n vectors can be done as follows,

figure eb

The definitions and API for alternating maps, and crucially their construction from the alternatization of a multilinear map were some of the many contributions to mathlib as part of the work in this paper. Through this API, we can easily prove statements like (i.e. \(a \wedge b \wedge a = 0\) for all vectors ab), or more generally that the wedge product of linearly dependent vectors is zero.

Of course, a crucial use of the wedge product is between arbitrary multivectors, not just basis vectors. The ideal way to define this wedge product would be to find a linear isomorphism by transferring the arguments along the isomorphism, computing the product in the exterior algebra, and transferring back:

figure ef

The advantage of this approach is that theorems about multiplication in exterior algebras can be transferred easily to theorems about the wedge product in Clifford algebras.

Our work does not go as far as defining the , although in collaboration with members of the Lean community the authors contributed a definition of to mathlib using a similar approach to that described in Sects. 7.2 and 7.3. Constructing the isomorphism from the universal property alone is difficult.

One way to do so would be to first show that the Clifford algebra is a filtered algebra, in that it can be split into subsets \(X_0 \subseteq X_1 \subseteq X_2 \subseteq \cdots \) such that \(a \in X_i, b \in X_j \implies ab \in X_{i+j}\). From here, the associated graded algebra can be constructed with grades \(Y_0 = X_0, Y_{n + 1} = \tfrac{X_{n+1}}{X_n}\) where division indicates the quotient submodule. Finally, a variant of the Poincaré–Birkhoff–Witt theorem can be applied to find the isomorphism.

The definition of a filtered algebra, along with a proof that a Clifford algebra satisfies it with \(X_i\) as “the multivectors of at most grade i” was formalized in Lean by the authors. The associated graded algebra proved challenging to encode in dependent type theory, as the type of each grade becomes a function of the type of the grade before it. This obstacle is not insurmountable, but the authors feel it best left to future work.

Interestingly, it can be shown that such an isomorphism does not always exist; as mentioned in Sect. 7.1, there exist Clifford algebras under our definition where the “algebra map” is not injective. However, we show in our formalization that the “algebra map” of the exterior algebra is always injective. Since only one of the two maps is always injective, these pathological Clifford algebras cannot be isomorphic to the corresponding exterior algebra.

7.9 Constructing Specific Algebras

In Sect. 2, we draw attention to some particularly useful geometric algebras over the real numbers, which until this point our formalization has been too general to mention. In this section, we show how to use our general formalization with specific algebras. It is worth noting that our formalization does not permit us to make statements like “the complex numbers are a geometric algebra”, instead requiring us to rephrase to “the complex numbers are isomorphic to a geometric algebra”. We state this isomorphism in Lean as follows:

figure eg

The full details are provided in our source repository, as well as a similar construction for the quaternions. This choice to work with isomorphisms is pragmatic one; it’s consistent with how mathlib handles the tensor algebra, and it doesn’t force us to declare one particular isomorphism as canonical; in the example above, we could just as easily mapped .

For a more illustrative example than the complex numbers, we will use the rest of this section to outline how to set up a definition of Conformal Geometric Algebra, \(\mathcal {G}(\mathbb {R}^{n+1, 1, 0})\), which augments the initial vector space \(\mathbb {R}^{n}\) with two extra dimensions spanned by the orthogonal vectors \(e_{+}\) and \(e_{-}\) where \(e_{+}^2 = 1\) and \(e_{-}^2 = -1\). In practice it can be algebraically convenient to span these extra dimensions instead with null basis vectors \(n_o, n_\infty \) where \(n_o\cdot n_\infty = 1\), and \(n_o^2 = n_\infty ^2 = 0\), as is done in [6, Table 13.1]. This approach is desirable because these basis vectors have more geometric meaning, with \(n_o\) being associated with the origin, and \(n_\infty \) associated with the point at infinity.

We start by defining the conformalized vector space of a real vector space as the triple of (original vector space V, \(n_0\) coefficient, \(n_\infty \) coefficient). Note that by doing this we are choosing a preferred basis (something we generally wanted to avoid) over the extra dimensions, but we continue to avoid doing so over V.

figure ei

We proceed by providing linear maps to extract each component:

figure ej

and some definitions to construct conformal vectors:

figure ek

Finally, we can define the up mapping \({\text {up}}(v) = n_0 + v + \tfrac{1}{2}{\Vert v\Vert }^2n_\infty \) and the conformal metric Q, the final pieces needed to construct the Clifford algebra:

figure el

With our definitions out of the way, our next job is to train the Lean simplifier about trivial combinations of these functions

figure em

From this, we can prove that has the form we’d expect, that correctly produces null vectors, and that the metric between two conformal points is proportional to their distance:

figure hq

Note that while at a glance this last result appears off by a factor of two from the “usual” result that \({\text {up}}(x)\cdot {\text {up}}(y) = -\frac{1}{2}\left\| x - y\right\| \), this is because Lean’s is defined as twice the value of the inner product \(x \cdot y\).

A construction of PGA in Lean can be done in very much the same way, and is included in our source repository.

8 Future Work

In Sect. 7, we formalized a variety of elementary GA operations, and showed how to leverage various existing definitions supplied in mathlib to do so in a way that is concise and integrates with the rest of the library. Our work however, is not yet at the point to be ready for use in formalizing results at the edge of research in Clifford Algebras, as some important elementary definitions are still absent. In this section, we will outline the absent areas of formalization which would contribute significantly to closing this gap.

8.1 Graded Modules and Algebras

To date, mathlib does not have a reusable definition for graded modules and algebras, making it difficult to make definitions that can be reused across tensor, exterior, and Clifford algebras. In Sect. 7.6, we present a definition that represents the \(\mathbb {Z}_2\)-gradation using a injective map into . This representation is flawed, as there are terms of this type that do not represent a valid grading result such as , which falsely claims that the scalars are a grade one element. This can be partially resolved by restricting this injective map to its range to form an equivalence, but the resulting object becomes awkward to work with.

A better solution would be to use mathlib’s , as this allows us to put a different restriction upon each grade. Unfortunately, unlike the latter, the former is not equipped with a multiplicative structure needed to use it with the universal property. Designing the API for equipping such a structure was deemed out of scope for this paper, but will be essential for conveniently working with the grades of geometric, exterior, and tensor algebras in Lean.

8.2 Isomorphisms from Clifford to Exterior Algebras

As mentioned in Sect. 7.8, this work was not able to define the wedge product on multivectors, largely due to desiring a coordinate-free approach. While this makes our formalization less useful than the other formalizations in Sect. 6, it should be noted that those formalizations require an explicit coordinate parametrization. To make progress in this direction, mathlib needs to acquire definitions and API for working with filtered algebras and their associated graded algebra. Linking up the definitions in mathlib of the Clifford algebra with the definition of the universal enveloping Lie algebra would help with applying the Poincaré–Birkhoff–Witt theorem, which itself would need formalizing.

8.3 Geometric Calculus

Parallel to our efforts to formalize geometric algebra, mathlib has been making great progress in the field of analysis, with slowly improving support for multivariate calculus. A notable result in the last few months was the formalization of variations of the Fundamental Theorem of Calculus.

As this part of mathlib matures, it should be possible to formalize the Geometric Calculus described by [10]. This will however not be a simple task—many of the results are stated in terms of an typeclass, which in practice means they apply only to the reals or the complex numbers. The next step towards formalizing Geometric Calculus would be to generalize some of these results to the quaternions (which are in mathlib), which would inform how to sensibly break apart the structure into smaller pieces.

9 Conclusions

We have shown how Lean can be used to formalize Geometric Algebra in a variety of ways. Of these ways, we chose to develop the formalization using a quotient definition, as this offered greater generality than any previous formalization. We demonstrate how to use the universal property of the Clifford algebra that this definition provides to recover additional definitions and operators, and how to prove that these constructions behave as we intend. To demonstrate the generality of our approach, we show how to specialize it to a Conformal Geometric Algebra over a vector space of arbitrary dimension. Throughout, we make liberal use of the mathlib library for Lean, demonstrating the convenience of having an expansive body of formalized mathematical terminology stated coherently in a single place.

A complete archive consisting of our formalization, our translations of parts of existing formalizations, the precise versions of Lean and mathlib that our code is compatible with, and a summary of the various contributions to mathlib made as part of this work can be found on GitHub at

https://github.com/pygae/lean-ga

mathlib is not only growing quickly, but changes quickly too. Through having contributed the key definitions from our work back into mathlib, we ensured these definitions will change with it, and can be built upon in future by others.