├── .github └── workflows │ ├── lean_build.yml │ └── lean_doc.yml ├── .gitignore ├── .gitpod.yml ├── LICENSE ├── README.md ├── docs └── misc │ ├── buchholz2005.md │ ├── goals.md │ ├── many_faces.md │ └── related.md ├── export.lean ├── leanpkg.toml └── src ├── examples └── recursors.lean ├── for_mathlib ├── README.md ├── algebra │ ├── algebra_operations.lean │ ├── center_submonoid.lean │ ├── filtration.lean │ └── monoid_algebra.lean └── linear_algebra │ ├── bilinear_form │ └── tensor_product.lean │ ├── quadratic_form │ ├── isometric_map.lean │ └── prod.lean │ └── tensor_product │ └── inner_product_space.lean └── geometric_algebra ├── from_mathlib ├── basic.lean ├── category_theory.lean ├── concrete │ ├── cga.lean │ ├── default.lean │ └── pga.lean ├── conjugation.lean ├── contract.lean ├── default.lean ├── even_odd.lean ├── even_odd_equiv.lean ├── fold.lean ├── mathoverflow.lean ├── versors.lean └── zmod_grading.lean ├── nursery ├── chisolm.lean ├── graded.lean └── instances.lean └── translations ├── README.md ├── hol_light.lean ├── ida.lean ├── ida_derived.lean └── laurents.lean /.github/workflows/lean_build.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | pull_request: 4 | 5 | jobs: 6 | update_lean_xyz_branch_and_build: 7 | runs-on: ubuntu-latest 8 | name: Build project 9 | steps: 10 | 11 | - name: checkout project 12 | uses: actions/checkout@v3 13 | with: 14 | fetch-depth: 0 15 | 16 | - name: update branch 17 | if: github.ref == 'refs/heads/master' 18 | uses: leanprover-contrib/update-versions-action@master 19 | 20 | - name: Install elan 21 | run: | 22 | set -o pipefail 23 | curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh -s -- --default-toolchain none -y 24 | ~/.elan/bin/lean --version 25 | echo "$HOME/.elan/bin" >> $GITHUB_PATH 26 | 27 | - name: install Python 28 | uses: actions/setup-python@v1 29 | with: 30 | python-version: 3.8 31 | 32 | - name: Install leanproject 33 | run: | 34 | python3 -m pip install --user pipx 35 | python3 -m pipx ensurepath 36 | source ~/.profile 37 | pipx install mathlibtools 38 | 39 | - name: Set up olean cache 40 | uses: actions/cache@v3 41 | with: 42 | path: _cache 43 | key: oleans 44 | 45 | - name: Configure 46 | run: | 47 | leanpkg configure 48 | leanproject get-mathlib-cache 49 | leanproject get-cache --fallback=download-first || true 50 | 51 | - name: Build 52 | run: | 53 | set -o pipefail 54 | # TODO: allow noisy files in a better way 55 | lean --json --make src | (python3 _target/deps/mathlib/scripts/detect_errors.py || true) 56 | 57 | - name: Save olean cache 58 | run: | 59 | leanproject mk-cache 60 | 61 | - name: Export symbols 62 | run: | 63 | leanproject mk-all 64 | lean --run export.lean > lean-decl-info.tex 65 | 66 | - uses: actions/upload-artifact@v3 67 | with: 68 | name: lean-decl-info 69 | path: lean-decl-info.tex 70 | -------------------------------------------------------------------------------- /.github/workflows/lean_doc.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | 4 | jobs: 5 | build_docs: 6 | runs-on: ubuntu-latest 7 | name: Build docs 8 | environment: 9 | name: documentation 10 | url: https://pygae.github.io/lean-ga-docs 11 | steps: 12 | 13 | - name: 📁 Checkout project 14 | uses: actions/checkout@v2 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: 🔧 Install elan 19 | run: | 20 | set -o pipefail 21 | curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh -s -- --default-toolchain none -y 22 | ~/.elan/bin/lean --version 23 | echo "$HOME/.elan/bin" >> $GITHUB_PATH 24 | 25 | - name: 🐍 Install Python 26 | uses: actions/setup-python@v1 27 | with: 28 | python-version: 3.8 29 | 30 | - name: 📁 Checkout Lean's doc-gen 31 | uses: actions/checkout@v2 32 | with: 33 | fetch-depth: 0 34 | repository: leanprover-community/doc-gen 35 | path: doc-gen 36 | 37 | - name: 🐍 Install Python dependencies 38 | run: | 39 | python -m pip install --upgrade pip 40 | pip install -r doc-gen/requirements.txt 41 | ls doc-gen 42 | 43 | - name: ✏️ Mangle paths for doc-gen 44 | run: | 45 | lean_version="$(sed '/^lean_version/!d;s/.*"\(.*\)".*/\1/' leanpkg.toml)" 46 | mathlib_git_hash="$(sed '/rev/!d;s/.*"\([a-z0-9]*\)".*/\1/' leanpkg.toml)" 47 | cd doc-gen 48 | sed -i "s/rev = \"\S*\"/rev = \"$mathlib_git_hash\"/" leanpkg.toml 49 | 50 | # Force doc_gen project to match the Lean version used in CI. 51 | # If they are incompatible, something in doc_gen will fail to compile, 52 | # but this is better than trying to recompile all of mathlib. 53 | elan override set "$lean_version" 54 | 55 | leanproject get-mathlib-cache 56 | echo -e "path ../src" >> leanpkg.path 57 | cat leanpkg.path 58 | (cd ../src; 59 | find "." -name \*.lean -not -name all.lean \ 60 | | sed 's,^\./,,;s,\.lean$,,;s,/,.,g;s,^,import ,' \ 61 | | sort >./all.lean) 62 | 63 | cp _target/deps/mathlib/docs/references.bib ../docs 64 | 65 | cat ../src/all.lean 66 | lean --path 67 | 68 | - name: 🔧 Build the lean code 69 | run: | 70 | cd doc-gen 71 | lean -v 72 | lean --make src/entrypoint.lean 73 | 74 | - name: 📝 Export Lean symbol information 75 | run: | 76 | cd doc-gen 77 | lean --run src/entrypoint.lean > export.json 78 | 79 | - name: 📚 Build HTML docs 80 | run: | 81 | cd doc-gen 82 | python3 \ 83 | -c "import print_docs; del print_docs.extra_doc_files[:]; print_docs.copy_yaml_bib_files = lambda p: None; print_docs.library_link_roots['lean-ga'] = 'https://github.com/pygae/lean-ga/blob/$GITHUB_SHA/src/'; print_docs.main()" \ 84 | -r .. -w 'https://pygae.github.io/lean-ga-docs/' -t built-docs 85 | 86 | - name: 🔑 Install SSH Client 87 | uses: webfactory/ssh-agent@v0.4.1 88 | with: 89 | ssh-private-key: ${{ secrets.DEPLOY_KEY }} 90 | 91 | - name: 🚀 Deploy 92 | uses: JamesIves/github-pages-deploy-action@3.7.1 93 | with: 94 | SSH: true 95 | SINGLE_COMMIT: true 96 | REPOSITORY_NAME: pygae/lean-ga-docs 97 | BRANCH: gh-pages # The branch the action should deploy to. 98 | FOLDER: doc-gen/built-docs # The folder the action should deploy. 99 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.olean 2 | /_target 3 | /leanpkg.path 4 | src/all.lean -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: leanprovercommunity/mathlib:gitpod 2 | 3 | vscode: 4 | extensions: 5 | - jroesch.lean 6 | 7 | tasks: 8 | - before: . /home/gitpod/.profile 9 | - init: | 10 | leanproject get-mathlib-cache 11 | lean --make src 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 pygae 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lean-ga 2 | ======= 3 | 4 | [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/pygae/lean-ga) 5 | [![arXiv](https://img.shields.io/badge/arXiv-2110.03551-b31b1b.svg)](https://arxiv.org/abs/2110.03551) 6 | [![DOI](https://zenodo.org/badge/doi/10.1007/s00006-021-01164-1.svg)](http://dx.doi.org/10.1007/s00006-021-01164-1) 7 | 8 | A partial formalization of Geometric Algebra (GA) in the [Lean formal proof verification system](https://github.com/leanprover-community/lean) and using its [Mathematical Library](https://github.com/leanprover-community/mathlib/). 9 | 10 | A description of the foundations of this work is published as [Formalizing Geometric Algebra in Lean](https://link.springer.com/article/10.1007/s00006-021-01164-1) in _Advances in Applied Clifford Algebras_ (note that the web version has been horrendously typeset by the publisher, but the PDF version is readable). The code in this repository has evolved since that publication to keep up with changes to mathlib. 11 | We presented an early version of this at ICCA 2020 ([slides](https://pygae.github.io/lean-ga/ICCA2020)). 12 | 13 | A semi-interactive viewer for the contents of this project can be found at https://pygae.github.io/lean-ga-docs/. 14 | Of particular interest are: 15 | 16 | * Parts of mathlib contributed as part of this work. These used to live in this repository, but have graduated to mathlib itself. The links below go to the precise version of mathlib `lean-ga` uses, rather than to the latest mathlib docs. 17 | * [`clifford_algebra`](https://pygae.github.io/lean-ga-docs/find/clifford_algebra) 18 | * [`clifford_algebra_ring.equiv`](https://pygae.github.io/lean-ga-docs/find/clifford_algebra_ring.equiv): the real numbers have an isomorphic clifford algebra. 19 | * [`clifford_algebra_complex.equiv`](https://pygae.github.io/lean-ga-docs/find/clifford_algebra_complex.equiv): the complex numbers have an isomorphic clifford algebra. 20 | * [`clifford_algebra_quaternion.equiv`](https://pygae.github.io/lean-ga-docs/find/clifford_algebra_quaternion.equiv): the quaternion numbers have an isomorphic clifford algebra. 21 | * [`clifford_algebra.as_exterior`](https://pygae.github.io/lean-ga-docs/find/clifford_algebra.as_exterior): the exterior algebra has an isomorphic clifford algebra 22 | * [`exterior_algebra`](https://pygae.github.io/lean-ga-docs/find/exterior_algebra) 23 | * [`alternating_map`](https://pygae.github.io/lean-ga-docs/find/alternating_map) 24 | * Translations of other formalizations: 25 | * [`geometric_algebra/translations/hol_light.lean`](https://pygae.github.io/lean-ga-docs/geometric_algebra/translations/hol_light.html) 26 | * [`geometric_algebra/translations/ida.lean`](https://pygae.github.io/lean-ga-docs/geometric_algebra/translations/ida.html) 27 | * [`geometric_algebra/translations/laurents.lean`](https://pygae.github.io/lean-ga-docs/geometric_algebra/translations/laurents.html) 28 | * Additional API on top of the mathlib `clifford_algebra`: 29 | * [`geometric_algebra/from_mathlib/versors.lean`](https://pygae.github.io/lean-ga-docs/geometric_algebra/from_mathlib/versors.html), a formalization of versors 30 | * [`geometric_algebra/from_mathlib/concrete/cga.lean`](https://pygae.github.io/lean-ga-docs/geometric_algebra/from_mathlib/concrete/cga.html), a formalization of CGA 31 | 32 | To get the full experience of using lean-ga without having to install lean, use the GitPod link at the top of this readme. 33 | Wait for the command in the console to finish, then open one of the files referenced above, and wait for compilation to finish (the orange bars to vanish). 34 | At this point, you can move the cursor around to view the proof state, and try adding new statements to the file using our definitions. 35 | 36 | See [this visualization](https://eric-wieser.github.io/mathlib-import-graph/?docs_url=https%3A%2F%2Fpygae.github.io%2Flean-ga-docs%2F) to see which parts of Mathlib are used in this formalization (directly or indirectly). 37 | 38 | Update for [ICACGA](https://icacga.org/) 39 | ---------------------------------------- 40 | This repository has been updated to contain some of the examples in the paper _"Computing with the universal properties of the Clifford algebra and the even subalgebra"_, submitted to the ICACGA conference. 41 | In turn, that paper contains permalinks that lead back to commits within this repository. 42 | Many of the examples in that paper have since graduated to mathlib and are no longer in this repository. 43 | 44 | The main results from that work are: 45 | 46 | * [`clifford_algebra.equiv_even`](https://pygae.github.io/lean-ga-docs/find/clifford_algebra.equiv_even): every clifford algebra is isomorphic to the even subalgebra of a larger algebra. 47 | * [`clifford_algebra.equiv_exterior`](https://pygae.github.io/lean-ga-docs/find/clifford_algebra.equiv_exterior): every clifford algebra over a ring of characteristic not two is isomorphic as a module to the exterior algebra. 48 | 49 | Contributing 50 | ------------ 51 | 52 | We welcome contributions, especially those in the areas outlined in the Future Work section of our paper. In some cases though, your contribution may well be better directed at mathlib itself, especially if it only depends on the parts of our work that have already been integrated into Mathlib. 53 | 54 | Project Structure 55 | ----------------- 56 | 57 | This project is configured for use with [`leanproject`](https://leanprover-community.github.io/leanproject.html), and such can be downloaded with `leanproject get pygae/lean-ga`. 58 | The Lean source files can all be found in the `src` directory, which is structured as follows. 59 | 60 | * [`src/for_mathlib`](https://github.com/pygae/lean-ga/tree/master/src/for_mathlib): non-GA formalizations intended for contribution to mathlib 61 | * [`src/geometric_algebra`](https://github.com/pygae/lean-ga/tree/master/src/geometric_algebra) 62 | * [`nursury`](https://github.com/pygae/lean-ga/tree/master/src/geometric_algebra/nursery): various experiments at formalizations approaches 63 | * [`translations`](https://github.com/pygae/lean-ga/tree/master/src/geometric_algebra/translations): partial translations of formalizations in other languages 64 | * [`from_mathlib`](https://github.com/pygae/lean-ga/tree/master/src/geometric_algebra/from_mathlib): The core of this formalization, building on top of the `clifford_algebra` contributed to Mathlib 65 | 66 | Additionally, there are some miscellaneous resources in [`docs/misc`](https://github.com/pygae/lean-ga/tree/master/docs/misc), which contain a mixture of links to and excepts from related work, and some initial design ideas and goals. 67 | 68 | Naming 69 | ------ 70 | 71 | There is little precedent for naming third-party Lean libraries; we mirror the choice made by [lean-perfectoid-spaces](https://leanprover-community.github.io/lean-perfectoid-spaces/) by prefixing the repo name with `lean-`, and use `ga` to abbreviate `geometric-algebra`. 72 | -------------------------------------------------------------------------------- /docs/misc/buchholz2005.md: -------------------------------------------------------------------------------- 1 | > This file can be previewed with rendered mathematical formulas [here](https://stackedit.io/viewer#!url=https://raw.githubusercontent.com/pygae/lean-ga/master/docs/misc/buchholz2005.md). 2 | 3 | ### Buchholz 2005 4 | 5 | > Source: Chapter 2 Clifford Algebra in [A Theory of Neural Computation 6 | with Clifford Algebras](https://macau.uni-kiel.de/servlets/MCRFileNodeServlet/dissertation_derivate_00001402/d1402.pdf) by Sven Buchholz. 7 | 8 | > The main definition and theorems of Clifford algebras will be presented following mostly I. R. Porteous. **Clifford Algebras and the Classical Groups**. Cambridge University Press, Cambridge, 1995 and P. Lounesto. **Clifford Algebras and Spinors**. Cambridge University Press, 1997. By doing so Clifford algebras will be constructed from quadratic spaces, and, hence, will have a metric structure right from the beginning. 9 | 10 | > There is and will always be an ongoing discussion in the Clifford (Geometric) Algebra community, if this is a good idea and how important metric aspects are for the very first foundation of Clifford (Geometric) Algebra [40]. For our approach, since being heavily based on the idea of transformation groups, they are mandatory. 11 | 12 | #### Definition 2.1 (Real Algebra) 13 | 14 | $A$ real algebra is a real linear space $(\mathcal{A},+, \cdot)$ endowed with a bilinear product 15 | 16 | $$ 17 | \otimes: \mathcal{A} \times \mathcal{A} \rightarrow \mathcal{A},(\mathrm{a}, \mathrm{b}) \mapsto \mathrm{a} \otimes \mathrm{b} 18 | $$ 19 | 20 | Hence, a real algebra is a pair $((\mathcal{A},+, \cdot), \otimes)$ 21 | 22 | #### Definition 2.2 (Types of Algebras) 23 | 24 | An algebra $((\mathcal{A},+, \cdot), \otimes)$ is called 25 | 26 | (i) associative, if for all $\mathrm{a}, \mathrm{b}, \mathrm{c} \in \mathcal{A}:(\mathrm{a} \otimes \mathrm{b}) \otimes \mathrm{c}=\mathrm{a} \otimes(\mathrm{b} \otimes \mathrm{c})$ 27 | (ii) commutative, if for all $\mathrm{a}, \mathrm{b} \in \mathcal{A}: \mathrm{a} \otimes \mathrm{b}=\mathrm{b} \otimes \mathrm{a}$ 28 | (iii) an algebra with identity, if there exists $1 \in \mathcal{A}$ such that for all $\mathrm{a} \in \mathcal{A}$ $1 \otimes \mathrm{a}=\mathrm{a} \otimes 1=1$ 29 | 30 | The real numbers considered as algebra $((\mathbb{R},+, \cdot), \cdot),$ for example, do comprise all the attributes of Definition 2.2 31 | 32 | #### Proposition 2.3 33 | 34 | For any algebra $((\mathcal{A},+, \cdot), \otimes),$ the product $\otimes$ is already uniquely determined given only the products for an arbitrary basis of $\mathcal{A}$. 35 | 36 | #### Proposition 2.4 37 | 38 | Any algebra $((\mathcal{A},+, \cdot), \otimes)$ is distributive by definition, or, equivalently, $(\mathcal{A},+, \otimes)$ is always a ring. 39 | 40 | #### Proposition 2.5 41 | 42 | Two finite dimensional algebras $\mathcal{A}$ and $\mathcal{B}$ are isomorphic, written as $\mathcal{A} \cong \mathcal{B},$ if they are isomorphic as rings, that is if there exists a bijective mapping $\phi: \mathcal{A} \rightarrow \mathcal{B}$ such that, for all $\mathrm{a}, \mathrm{b} \in \mathcal{A}$ 43 | (i) $\phi(a+b)=\phi(a)+\phi(b)$ 44 | (ii) $\phi(\mathrm{a} \otimes \mathrm{b})=\phi(\mathrm{a}) \otimes \phi(\mathrm{b})$ 45 | 46 | #### Definition 2.6 (Tensor Product) 47 | 48 | Let $\mathcal{A}$ be a finite dimensional real associative algebra with identity. If there exist subalgebras $\mathcal{B}$ and $\mathcal{C}$ of $\mathcal{A}$ such that 49 | (i) for any $\mathrm{b} \in \mathcal{B}, \mathrm{c} \in \mathcal{C}, \mathrm{bc}=\mathrm{cb}$ 50 | (ii) $\mathcal{A}$ is generated as an algebra by $\mathcal{B}$ and $\mathcal{C}$ 51 | (iii) $\operatorname{dim} \mathcal{A}=\operatorname{dim} \mathcal{B} \operatorname{dim} \mathcal{C}$ 52 | then $\mathcal{A}$ is said to be the tensor product of $\mathcal{B}$ and $\mathcal{C},$ written as $\mathcal{B} \otimes \mathcal{C}$ 53 | 54 | #### Definition 2.7 (Field) 55 | 56 | Let $(\mathcal{R},+, \otimes)$ be a ring. If $(\mathcal{R} \backslash\{0\}, \otimes)$ is a (non-)commutative $g$roup$,$then $(\mathcal{R},+, \otimes)$ is called a (skew) field. 57 | 58 | #### Definition 2.8 (The Field of Complex Numbers) 59 | 60 | Consider the set of all ordered pairs of real numbers 61 | $$ 62 | \mathbb{R}^{2}=\{z=(a, b) \mid a, b \in \mathbb{R}\} 63 | $$ 64 | together with addition and multiplication defined for all $z_{1}=\left(a_{1}, b_{1}\right), z_{2}=\left(a_{2}, b_{2}\right) \in \mathbb{R}^{2}$ 65 | 66 | as 67 | 68 | $$ 69 | \begin{array}{l} 70 | z_{1}+z_{2}=\left(a_{1}+a_{2}, b_{1}+b_{2}\right) \\ 71 | z_{1} \otimes z_{2}=\left(a_{1} a_{2}-b_{1} b_{2}, a_{1} b_{2}+a_{2} b_{1}\right) 72 | \end{array} 73 | $$ 74 | 75 | Then $\mathbb{C}:=\left(\mathbb{R}^{2},+, \otimes\right)$ is called the field of complex numbers. 76 | 77 | The imaginary unit $i$ is obtained by setting $i:=(0,1) .$ The $\operatorname{law} \mathfrak{i}^{2}=-1$ then is just a direct consequence of $(2.2) .$ Furthermore, the usual notion of a complex number $z=a+i b$ is easily obtained from the identity 78 | $$ 79 | z=(a, b)=(a, 0)+(0,1) \otimes(b, 0) 80 | $$ 81 | 82 | The complex numbers $\mathbb{C}$, although mostly viewed as a field, comprise yet another algebraic structure. $\mathbb{C}$ contains infinitely many subfields isomorphic to $\mathbb{R}$. Choosing one also defines a real linear structure on $\mathbb{C}$. The obvious choice for that distinguished copy of $\mathbb{R}$ in $\mathbb{C}$ is given by the map 83 | $$ 84 | \alpha: \mathbb{R} \rightarrow \mathbb{C}, \mathfrak{a} \mapsto(a, 0) 85 | $$ 86 | For any $\lambda \in \mathbb{R}$ and any $z=(a, b) \in \mathbb{C}$ we then get 87 | $$ 88 | \alpha(\lambda) \otimes(\mathrm{a}, \mathrm{b})=(\lambda, 0) \otimes(\mathrm{a}, \mathrm{b})=(\lambda \mathrm{a}, \lambda \mathrm{b}) 89 | $$ 90 | which turns $\mathbb{C}$ also into a real algebra. More precisely, $\mathbb{C}$ thereby becomes a real associative and commutative algebra of dimension 2 with (1,0) as identity element. 91 | 92 | #### Definition 2.9 (The Algebra of Quaternions) 93 | 94 | Consider the linear space $\left(\mathbb{R}^{4},+, \cdot\right)$ with standard basis $\left\{1:=\left(1_{\mathbb{R}}, 0,0,0\right), i:=\left(0,1_{\mathbb{R}}, 0,0\right), j:=\left(0,0,1_{\mathbb{R}}, 0\right), k:=\left(0,0,0,1_{\mathbb{R}}\right)\right\}$ and 95 | define a multiplication $\otimes$ on it according to the following table 96 | 97 | | $\otimes$ | $1$ | $\mathrm{i}$ | $\mathrm{j}$ | $\mathrm{k}$ | 98 | |-----------|-----|--------------|--------------|--------------| 99 | | $1$ | $1$ | $\mathrm{i}$ | $\mathrm{j}$ | $\mathrm{k}$ | 100 | | $\mathrm{i}$ | $\mathrm{i}$ | $-1$ | $\mathrm{k}$ | $-\mathrm{j}$ | 101 | | $\mathrm{j}$ | $\mathrm{j}$ | $-\mathrm{k}$ | $-1$ | $\mathrm{i}$ | 102 | | $\mathrm{k}$ | $\mathrm{k}$ | $\mathrm{j}$ | $-\mathrm{i}$ | $-1$ | 103 | 104 | Then $\mathbb{H}:=\left(\left(\mathbb{R}^{4},+, \cdot\right), \otimes\right)$ is a real associative algebra of dimension $4,$ which is called the 105 | algebra of quaternions. Obviously, $1$ is the identity element of $\mathbb{H}$. 106 | 107 | Any quaternion $q \in \mathbb{H}$ can be written in the form 108 | $$ 109 | \mathrm{q}=\mathrm{q}_{0}+\mathrm{i} \mathrm{q}_{1}+\mathrm{j} \mathrm{q}_{2}+\mathrm{k} \mathrm{q}_{3} 110 | $$ 111 | with $\mathrm{q}, \mathrm{q}_{1}, \mathrm{q}_{2}, \mathrm{q}_{3} \in \mathbb{R} .$ Analogously as in $\mathbb{C},$ the basis vectors $\{\mathfrak{i}, \mathfrak{j}, \mathrm{k}\}$ are often named 112 | imaginary units. In particular, the following relations hold among them 113 | $$ 114 | \mathrm{j} \mathrm{k}=-\mathrm{k} \mathrm{j}=\mathrm{i} \quad \mathrm{k} \mathrm{i}=-\mathrm{i} \mathrm{k}=\mathrm{j} \quad \mathrm{i} j=-\mathrm{j} \mathrm{i}=\mathrm{k} 115 | $$ 116 | 117 | $(\mathbb{H},+, \otimes)$ is a skew field. 118 | 119 | #### Definition 2.10 (Division Algebra) 120 | 121 | An algebra $\mathcal{A}$ is called a division algebra if, for all $a \in \mathcal{A} \backslash\{0\},$ both of the following two equations 122 | $$ 123 | \begin{array}{l} 124 | a x=b \\ 125 | y a=b 126 | \end{array} 127 | $$ 128 | are uniquely solvable for all $\mathrm{b} \in \mathcal{A}$. 129 | 130 | #### Definition 2.11 (Zero Divisor) 131 | 132 | Let $\mathcal{A}$ be an algebra. An element a $\in \mathcal{A}$ is called zero divisor, if there exists $\mathrm{b} \in \mathcal{A} \backslash\{0\}$ such that 133 | $$ 134 | a b=0 \text { or } b a=0 135 | $$ 136 | 137 | #### Theorem 2.12 (Frobenius) 138 | 139 | Any finite dimensional real associative division algebra is isomorphic to either $\mathbb{R}, \mathbb{C},$ or $\mathbb{H}$. 140 | 141 | #### Proposition 2.13 142 | 143 | Let $\mathcal{A}$ be a finite-dimensional algebra. Then $\mathcal{A}$ is a division algebra, if and only if, $\mathcal{A}$ is free of zero divisors. 144 | 145 | #### Definition 2.14 (Quadratic Form) 146 | 147 | Let X be a real linear space endowed with a scalar product, i.e. with a symmetric bilinear form, 148 | $$ 149 | F: X \times X \rightarrow \mathbb{R},(a, b) \mapsto a \cdot b 150 | $$ 151 | Then the map 152 | $$ 153 | \mathrm{Q}: X \rightarrow \mathbb{R}, \mathrm{a} \mapsto \mathrm{a} \cdot \mathrm{a} 154 | $$ 155 | is called the quadratic form of $F$. Furthermore, the pair $(X,Q)$ is called a real quadratic space. 156 | 157 | $Q$ is uniquely determined by $F$, and vice versa, in virtue of 158 | $$ 159 | \mathrm{F}(\mathrm{a}, \mathrm{b})=\frac{1}{2} \cdot(\mathrm{Q}(\mathrm{a}+\mathrm{b})-\mathrm{Q}(\mathrm{a})-\mathrm{Q}(\mathrm{b})) 160 | $$ 161 | Thus, one can arbitrarily switch between $\mathrm{Q}$ and $\mathrm{F}$. 162 | 163 | #### Proposition 2.1 164 | 165 | Let$(\mathrm{X}, \mathrm{Q})$ be an $\mathrm{n}$-dimensional real quadratic space. Then there exists a basis $\left\{e_{1}, \ldots, e_{n}\right\}$ of $(X, Q)$ and uniquely determined $p, q, r \in\{0, \ldots, n\}$ such that, for all $i, j \in\{1, \ldots, n\},$ the following two conditions are fulfilled 166 | 167 | (i) $\mathrm{Q}\left(e_{i}\right)=\left\{\begin{array}{cc}1, & i \leq p \\ -1, & p+1 \leq i \leq p+q \\ 0, & p+q+1 \leq i \leq p+q+r=n\end{array}\right.$ 168 | (ii) $\mathrm{Q}\left(e_{i}+e_{j}\right)-\mathrm{Q}\left(e_{i}\right)-\mathrm{Q}\left(e_{j}\right)=0$ 169 | 170 | A basis with the above properties is called an orthonormal basis of $(\mathrm{X}, \mathrm{Q}),$ and the triple $(p, q, r)$ is called the signature of $(X, Q)$. 171 | 172 | #### Definition 2.15 (Degenerate Space) 173 | 174 | Let $(\mathrm{X}, \mathrm{Q})$ be a finite dimensional real quadratic space. Then $(\mathrm{X}, \mathrm{Q})$ is said to be a degenerate space if 175 | $$ 176 | \{a \in X \mid Q(a)=0\} \neq \emptyset 177 | $$ 178 | and to be a non-degenerate space otherwise. 179 | 180 | #### Definition 2.16 (Clifford Algebra) 181 | 182 | Let $(\mathrm{X}, \mathrm{Q})$ be an arbitrary finite dimensional real quadratic space and let $\mathcal{A}$ be a real associative algebra with identity. Furthermore, let 183 | $\alpha: \mathbb{R} \rightarrow \mathcal{A}$ and $v: \mathrm{X} \rightarrow \mathcal{A}$ be linear injections such that 184 | (i) $\mathcal{A}$ is generated as an algebra by its distinct subspaces $\{v(v) \mid v \in X\}$ and $\{\alpha(a) \mid a \in \mathbb{R}\}$ 185 | (ii) $\forall v \in X:(v(v))^{2}=\alpha(Q(v))$ 186 | 187 | Then $\mathcal{A}$ is said to be a Clifford algebra for $(\mathrm{X}, \mathrm{Q})$. The elements of a Clifford algebra are 188 | called multivectors. The product of a Clifford algebra is named geometric product. The signature of the quadratic space is also the signature of the algebra. 189 | 190 | #### Theorem 2.17 191 | 192 | Any Clifford algebra is isomorphic to some matrix algebra. 193 | 194 | Since any Clifford algebra is a real associative algebra by definition, the above important theorem holds. 195 | 196 | #### Proposition 2.18 197 | 198 | Let$(\mathrm{X}, \mathrm{Q})$ be an $\mathrm{n}$ -dimensional real quadratic space with an orthonormal basis $\left\{e_{i} \mid 1 \leq i_{\mathrm{k}}: C_{\mathrm{p}, \mathrm{q}, \mathrm{r}} \rightarrow C_{\mathrm{p}, \mathrm{q}, \mathrm{r}}, \mathrm{x} \mapsto \sum_{\mathrm{I} \in \mathcal{I} \atop|\mathrm{I}|=\mathrm{k}} x_{\mathrm{I}} e_{\mathrm{I}} 286 | $$ 287 | for any $\mathrm{k} \in\{0, \cdots, n\}$. 288 | 289 | Using the grade operator any multivector can be written as 290 | $$ 291 | x=\sum_{k=0}^{n}_{k} 292 | $$ -------------------------------------------------------------------------------- /docs/misc/goals.md: -------------------------------------------------------------------------------- 1 | Formalization Goals 2 | =================== 3 | 4 | TL;DR: 5 | 6 | The primary goal is to have a series of loosely coupled definitions of GA, some are constructive, some the algorithmic, some are mathematical, but they can all be shown to be an instance of one or a few general type classes focusing on the behaviors and propertie rather than representations and thus a lot of theorems/identities proven for the general type classes will automatically apply. During the process, keep the formalization as readable as the math in the usual GA literature, and in a coordinate-free fashion as long as possible. 7 | 8 | The full version: 9 | 10 | 1. Formalize Geometric Algebra in a generic way that 11 | - doesn't depend on data structures, not even canonical structures 12 | - contains only how the algebra works and its natural relations to other abstract mathematical structures by leveraging the power of Type Class in Lean 13 | - is deeply rooted in its mathematical foundation while keeping its accessibility to common GA users 14 | 2. Formalize geometric objects (in PGA, CGA, for example) based on the generic formalization 15 | 3. Verify the equivalence or explore the relations of various formalisms of Geometric Algebra 16 | 4. Verify the correctness and computational properties of various Geometric Algebra data structures and algorithms 17 | 5. Develops tactics and automations specific to Geometric Algebra using Lean's powerful metaprogramming framework 18 | 6. Formalize important or interesting applications of Geometric Algebra 19 | - such as the ones demonstrated by https://enkimute.github.io/ganja.js/examples/coffeeshop.html 20 | 7. Numerical GA Code generator for various programming languages with a rich set of options from various verified Geometric Algebra data structures and algorithms 21 | - inspired by https://github.com/vincentnozick/garamon and https://github.com/enkimute/ganja.js 22 | 8. Symbolic rewrite rule generator for Rule-based rewriting languages 23 | - e.g. https://github.com/JuliaSymbolics/SymbolicUtils.jl 24 | 9. Verify GA libraries by pluggable bridges with them 25 | - e.g. https://github.com/chakravala/Grassmann.jl , https://github.com/jeremyong/gal , https://github.com/RobinKa/tfga , to name a few interested but really challenging ones 26 | - using tools/APIs summarized in https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/Examples.20of.20communicating.20with.20Lean 27 | 10. Formalize Geometric Calculus 28 | 29 | Besides all of the above, the code and documentation should be readable for common users and provide references for further reading. 30 | 31 | Proposed project structure 32 | -------------------------- 33 | 34 | ```bash 35 | # Github actions like https://github.com/leanprover-community/mathlib/blob/master/.github/workflows/build.yml 36 | ├── .github 37 | # VSCode settings like https://github.com/leanprover-community/mathlib/blob/master/.vscode/settings.json 38 | ├── .vscode 39 | # Docs like https://github.com/leanprover-community/mathlib/tree/master/docs using https://github.com/leanprover-community/doc-gen and possibly https://github.com/leanprover-community/format_lean and https://github.com/leanprover-community/lean-client-python 40 | # also docs like https://github.com/avigad/mathematics_in_lean_source 41 | ├── docs 42 | # The accompanying paper like https://arxiv.org/abs/1910.09336 and https://arxiv.org/abs/1910.12320 43 | # Possibly will be written using https://manubot.org/ 44 | ├── paper 45 | # Scripts like https://github.com/leanprover-community/mathlib/blob/master/scripts/deploy_docs.sh 46 | ├── scripts 47 | # Source 48 | ├── src 49 | # The root of Geometric Algebra formalization 50 | # Following the layout in mathlib e.g. https://github.com/leanprover-community/mathlib/tree/master/src/linear_algebra 51 | │ ├── geometric_algebra 52 | # Goal 1 53 | │ │ ├── generic 54 | # Goal 2 55 | │ │ ├── geometry 56 | # Goal 3 57 | │ │ ├── formalism 58 | # Goal 4 59 | │ │ ├── data 60 | │ │ ├── algorithm 61 | # Goal 5 62 | │ │ ├── tactic 63 | # Goal 6 64 | │ │ ├── application 65 | # Goal 7 66 | │ │ ├── codegen 67 | # Goal 8 68 | │ │ ├── rulegen 69 | # Goal 9 70 | │ │ ├── libraries 71 | # Goal 10 72 | │ │ ├── calculus 73 | # Experimental code 74 | │ │ ├── _nursery 75 | # Deprecated code that was part of the formalization 76 | │ │ └── _deprecated 77 | # Potential changes to the other directories in mathlib 78 | │ └── ... 79 | # Tests like https://github.com/leanprover-community/mathlib/tree/master/test 80 | └── test 81 | ``` 82 | -------------------------------------------------------------------------------- /docs/misc/many_faces.md: -------------------------------------------------------------------------------- 1 | # The Many Faces of Geometric Algebra 2 | 3 | > This file can be previewed with rendered mathematical formulas [here](https://stackedit.io/viewer#!url=https://raw.githubusercontent.com/pygae/lean-ga/master/docs/misc/many_faces.md). 4 | 5 | Geometric Algebra (GA) or Clifford Algebra can be defined in many ways. We summarize the definitions here to inspire proper ways to formalize GA. 6 | 7 | Some definitions are very elementary but hard to make rigorous. Some may seem rigorous but still hard to formalize. Some are very rigorous and can be formalized but fail to remain intuitive or elegant. 8 | 9 | Definitions are grouped by similarity. The definitions in the same group would have subtle yet important differences, that's why they deserve to be listed here. 10 | 11 | Definitions are mostly direct quotes from the source, with slight modifications for readability or brevity. 12 | 13 | > The following are work-in-progress and not necessarily well organized. 14 | 15 | ### Hestenes 1984 16 | 17 | > Source: Hestenes, David, and Garret Sobczyk. Clifford algebra to geometric calculus: a unified language for mathematics and physics. Vol. 5. Springer Science & Business Media, 2012. 18 | 19 | An element of the Geometric Algebra $\mathscr{G}$ will be called a multivector. We assume that $\mathscr{G}$ is algebraically closed, that is, that the sum or product of any pair of multivectors is a unique multivector. The geometric sum and product of multivectors $A, B, C, \ldots$ have the following properties: 20 | 21 | Addition is commutative; 22 | $$ 23 | A+B=B+A 24 | $$ 25 | Addition and multiplication are associative; 26 | $$ 27 | \begin{array}{l} 28 | (A+B)+C=A+(B+C) \\ 29 | (A B) C=A(B C) 30 | \end{array} 31 | $$ 32 | Multiplication is distributive with respect to addition; 33 | $$ 34 | A(B+C)=A B+A C 35 | $$ 36 | $$ 37 | (B+C) A=B A+C A 38 | $$ 39 | There exist unique additive and multiplicative identities 0 and 1 40 | $$ 41 | \begin{array}{l} 42 | A+0=A \\ 43 | 1 A=A 44 | \end{array} 45 | $$ 46 | Every multivector $A$ has a unique additive inverse $-A$ 47 | $$ 48 | A+(-A)=0 49 | $$ 50 | 51 | Geometric algebra is set apart from other associatve algebras by a few additional axioms which classify multivectors into different types or, as we shall say, grades. We assume that any multivector $A$ can be written as the sum 52 | $$ 53 | A=\langle A\rangle_{0}+\langle A\rangle_{1}+\langle A\rangle_{2}+\cdots=\sum_{r}\langle A\rangle_{r} 54 | $$ 55 | 56 | The quantity $\langle A\rangle_{r}$ is called the $r$ -vector part of $A .$ If $A=\langle A\rangle_{r}$ for some positive integer $r,$ then $A$ is said to be homogeneous of grade $r$ and will be called an $r$ -vector. The terms scalar, vector, bivector, trivector,.... are often used as alternatives to the terms 0 -vector, 1 -vector, 2 -vector, 3 -vector, $\ldots$ respectively. The grade operator $\langle\ldots .\rangle_{r}$ enjoys the properties 57 | 58 | $$ 59 | \begin{array}{l} 60 | \langle A+B\rangle_{r}=\langle A\rangle_{r}+\langle B\rangle_{r} \\ 61 | \langle\lambda A\rangle_{r}=\lambda\langle A\rangle_{r}=\langle A\rangle_{r} \lambda, \quad \text { if } \lambda=\langle\lambda\rangle_{0} \\ 62 | \left\langle\langle A\rangle_{r}\right\rangle_{r}=\langle A\rangle_{r} 63 | \end{array} 64 | $$ 65 | 66 | Axioms (1.10) and (1.11) (i.e. the 1st one and 2nd one immediately above) imply that the space $\mathscr{G}^{r}$ of all $r$ -vectors is a linear subspace of $\mathscr{G},$ and, indeed, that $\mathscr{G}$ itself is a linear space. Axiom (1.11) also implies that the scalars compose a commutative subalgebra of $\mathscr{G}$. Without further ado, we assume that the space $\mathscr{G}^{0}$ of all scalars is identical with the set of real numbers. As argued elsewhere in this book, we regard any wider definition of the scalars (for example as the complex numbers) to be entirely unnecessary and, indeed, inimical to the purposes of geometric algebra. 67 | 68 | Equation (1.12) (i.e. the 3rd one immediately above) exhibits the characteristic property of a projection operator, so $\langle A\rangle_{r}$ can be regarded as the projection of $A$ into the space $\mathscr{G}^{r}$. Actually, (1.12) need not be regarded as an axiom, because it can be derived with the help of our remaining axioms which fix the relations among multivectors of different grade. Multiplication of vectors is related to scalars by the assumption that the 'square' of any nonzero vector $a$ is equal to the square of a unique positive scalar lal called the magnitude of $a$, that is 69 | 70 | $$ 71 | A_{r}=a_{1} a_{2} \ldots a_{r} 72 | $$ 73 | where 74 | $$ 75 | \begin{array}{c} 76 | a_{j} a_{k}=-a_{k} a_{j} \\ 77 | \text { for } j, k=1,2, \dots, r, \text { and } j \neq k 78 | \end{array} 79 | $$ 80 | As a final axiom, we assume that for every nonzero $r$ -blade $A_{r},$ there exists a nonzero vector $a$ in $\mathscr{G}$ such that $A_{r} a$ is an $(r+1)$ -blade. This guarantees the existence of nontrivial blades of every finite grade. In fact, it implies that each $\mathscr{G}$ r and, of course, all of $\mathscr{G}$ is a linear space of infinite dimension. This leads ultimately to delicate questions of convergence for homogeneous multivectors with infinite grade. But we will not be concerned with such questions in this book. 81 | 82 | ### Lawson 1989 83 | 84 | > Source: H.B. Lawson and M.-L. Michelsohn. Spin Geometry. Princeton University Press, Princeton NJ, 1989. But the quote and the comments come from Doran 1994. 85 | 86 | One starts with a vector space $V$ over a commutative field $k$, and supposes that $q$ is a quadratic form on $V$. The tensor algebra of $V$ is defined as 87 | $$ 88 | \mathcal{T}(V)=\sum_{r=0}^{\infty} \otimes^{r} V 89 | $$ 90 | where $\otimes$ is the tensor product. One next defines an ideal $\mathcal{I}_{q}(V)$ in $\mathcal{T}(V)$ generated by all elements of the form $v \otimes v+q(v) 1$ for $v \in V$. The Clifford algebra is then defined as the quotient 91 | $$ 92 | C l(V, q) \equiv \mathcal{T}(V) / \mathcal{I}_{q}(V) 93 | $$ 94 | 95 | This definition is mathematically correct, but has a number of drawbacks: 96 | 97 | 1. The definition involves the tensor product, $\otimes$, which has to be defined initially. 98 | 2. The definition uses two concepts, tensor algebras and ideals, which are irrelevant to the properties of the resultant geometric algebra. 99 | 3. Deriving the essential properties of the Clifford algebra from this definition requires further work, and none of these properties are intuitively obvious from the axioms. 100 | 4. The definition is completely useless for introducing geometric algebra to a physicist or an engineer. It contains too many concepts that are the preserve of pure mathematics. 101 | 102 | The above considerations lead us propose the following principle: 103 | The axioms of an algebraic system should deal directly with the objects 104 | of interest. 105 | 106 | That is to say, the axioms should offer some intuitive feel of the properties of the system they are defining. 107 | 108 | ### Doran 1994 109 | 110 | > Source: Doran, Christopher John Leslie. Geometric algebra and its application to mathematical physics. Diss. University of Cambridge, 1994. http://geometry.mrao.cam.ac.uk/wp-content/uploads/2015/02/DoranThesis.pdf 111 | 112 | A geometric algebra $\mathcal{G}$ is a graded linear space, the elements of which are called multivectors. The grade- 0 elements are called scalars and are identified with the field of real numbers (we will have no cause to consider a geometric algebra over the complex field). The grade-1 elements are called vectors, and can be thought of as directed line segments. The elements of $\mathcal{G}$ are defined to have an addition, and each graded subspace is closed under this. A product is also defined which is associative and distributive, though non-commutative (except for multiplication by a scalar). The final axiom (which distinguishes a geometric algebra from other associative algebras) is that the square of any vector is a scalar. Given two vectors, $a$ and $b$, we find that 113 | $$ 114 | \begin{aligned} 115 | (a+b)^{2} &=(a+b)(a+b) \\ 116 | &=a^{2}+(a b+b a)+b^{2} 117 | \end{aligned} 118 | $$ 119 | It follows that 120 | $$ 121 | a b + b a = (a +b)^{2} - a^{2} - b^{2} 122 | $$ 123 | 124 | and hence that $(a b+b a)$ is also a scalar. The geometric product of 2 vectors $a, b$ can therefore be decomposed as 125 | $$ 126 | a b=a \cdot b+a \wedge b 127 | $$ 128 | where 129 | $$ 130 | a \cdot b \equiv \frac{1}{2}(a b + b a) 131 | $$ 132 | is the standard scalar, or inner, product (a real scalar), and 133 | $$ 134 | a \wedge b \equiv \frac{1}{2}(a b - b a) 135 | $$ 136 | is the antisymmetric outer product of two vectors, originally introduced by Grassmann. 137 | 138 | ### Lynn 139 | 140 | > Source: [All Hail Geometric Algebra!](https://crypto.stanford.edu/~blynn/haskell/ga.html) by [Ben Lynn](https://crypto.stanford.edu/~blynn/) 141 | 142 | We can trivially define a product with nice properties on any set: just take [the free monoid](https://en.wikipedia.org/wiki/Free_monoid). Similarly, we can define a vector product with nice properties thanks to [free algebras](https://en.wikipedia.org/wiki/Free_algebra). 143 | 144 | By constraining our free algebra with one simple relation, we obtain the vaunted geometric algebra. We define the geometric product by subjecting the free product to the following constraint: for any vector $\mathbf{v}$, 145 | 146 | $$ \mathbf{v v} = \mathbf{v} \cdot \mathbf{v}$$ 147 | 148 | We could [generalize by replacing the dot product with any quadratic form, and by considering any vector space over any field](https://en.wikipedia.org/wiki/Geometric_algebra), but we focus on the standard dot product on $\mathbb{R}^{n},$ where the resulting geometric algebra is denoted $\mathbb{G}^{n}$ 149 | 150 | We could have instead written $\mathbf{v}^{2}=|\mathbf{v}|^{2},$ but this hides our need for the [polarization identity](https://en.wikipedia.org/wiki/Polarization_identity): 151 | 152 | $$ 153 | \mathbf{u} \cdot \mathbf{v}=\frac{1}{2}((\mathbf{u}+\mathbf{v}) \cdot(\mathbf{u}+\mathbf{v})-\mathbf{u} \cdot \mathbf{u}-\mathbf{v} \cdot \mathbf{v}) 154 | $$ 155 | 156 | From our constraint, this is: 157 | 158 | $$ 159 | \mathbf{u} \cdot \mathbf{v}=\frac{1}{2}\left((\mathbf{u}+\mathbf{v})^{2}-\mathbf{u}^{2}-\mathbf{v}^{2}\right) 160 | $$ 161 | 162 | By elementary algebra, this implies: 163 | 164 | $$ 165 | \mathbf{u} \cdot \mathbf{v}=\frac{1}{2}(\mathbf{u} \mathbf{v}+\mathbf{v} \mathbf{u}) 166 | $$ 167 | 168 | Hence when $\mathbf{u}$ and $\mathbf{v}$ are orthogonal, we have $\mathbf{u v}=-\mathbf{v u}$ . 169 | 170 | ### Chisolm 2012 171 | 172 | A geometric algebra is a set $\mathcal{G}$ with two composition laws, addition and multiplication (also called the geometric product$),$ that obey these axioms. 173 | 174 | Axiom 1. $\mathcal{G}$ is a ring with unit. The additive identity is called 0 and the multiplicative identity is called 1. 175 | 176 | Axiom 2. $\mathcal{G}$ contains a field $\mathcal{G}_0$ of characteristic zero which includes 0 and 1. 177 | 178 | Axiom 3. $\mathcal{G}$ contains a subset $\mathcal{G}_1$ closed under addition, and $\lambda \in \mathcal{G}_0$, $v \in \mathcal{G}_1$ implies $\lambda v = v \lambda \in \mathcal{G}_1$. 179 | 180 | Axiom 4. The square of every vector is a scalar. 181 | 182 | Axiom 5. The inner product is nondegenerate. 183 | 184 | Axiom 6. If $\mathcal{G}_0 = \mathcal{G}_1$, then $\mathcal{G} = \mathcal{G}_0$. Otherwise, $\mathcal{G}$ is the direct sum of all the $\mathcal{G}_r$. 185 | 186 | For each $r$, let the grade operator $\left< \right>_r : \mathcal{G} \to \mathcal{G}_r$ project each $A \in \mathcal{G}$ onto its unique grade-$r$ component. 187 | Then 188 | (a) $A$ is an $r$-vector iff $A = \left_r$. 189 | (b) $\left_r$ = $\left_r$ + $\left_r$. 190 | (c) $\left< \lambda A \right>_r$ = $\left< A \lambda \right>_r$ = $\lambda \left_r$. 191 | (d) $\left<\left_r\right>_s = <\left_r\delta_{rs}$. (Thus the $\left< \right>_r$ are independent projection operators.) 192 | (e) $\sum_r \left_r = A$ for any $A \in \mathcal{G}$. (Thus the $\left< \right>_r$ are a complete set of projection operators.) 193 | (f) $\left_r = 0$ if $r \lt 0$ for all $A \in \mathcal{G}$. 194 | Because we take the scalar part of multivectors so often, I will let $\left$ mean $\left_0$. 195 | 196 | ### Buchholz 2005 197 | 198 | > Source: Chapter 2 Clifford Algebra in [A Theory of Neural Computation 199 | with Clifford Algebras](https://macau.uni-kiel.de/servlets/MCRFileNodeServlet/dissertation_derivate_00001402/d1402.pdf) by Sven Buchholz. See also [the full version](./buchholz2005.md). 200 | 201 | Let $(\mathrm{X}, \mathrm{Q})$ be an arbitrary finite dimensional real quadratic space and let $\mathcal{A}$ be a real associative algebra with identity. Furthermore, let 202 | $\alpha: \mathbb{R} \rightarrow \mathcal{A}$ and $v: \mathrm{X} \rightarrow \mathcal{A}$ be linear injections such that 203 | (i) $\mathcal{A}$ is generated as an algebra by its distinct subspaces $\{v(v) \mid v \in X\}$ and $\{\alpha(a) \mid a \in \mathbb{R}\}$ 204 | (ii) $\forall v \in X:(v(v))^{2}=\alpha(Q(v))$ 205 | 206 | Then $\mathcal{A}$ is said to be a Clifford algebra for $(\mathrm{X}, \mathrm{Q})$. The elements of a Clifford algebra are 207 | called multivectors. The product of a Clifford algebra is named geometric product. The signature of the quadratic space is also the signature of the algebra. 208 | 209 | ### Clifford 1882 210 | 211 | > Source: 14.1 Clifford's original defintion in **Clifford Algebras and Spinors** by P. Lounesto 212 | 213 | Grassmann's exterior algebra $\wedge \mathbb{R}^{n}$ of the linear space $\mathbb{R}^{n}$ is an associative algebra of dimension $2^{n} .$ In terms of a basis $\left\{\mathbf{e}_{1}, \mathbf{e}_{2}, \ldots, \mathbf{e}_{n}\right\}$ for $\mathbb{R}^{n}$ the exterior algebra $\wedge \mathbb{R}^{n}$ has a basis 214 | 215 | $$ 216 | 217 | \begin{array}{l} 218 | 1 \\ 219 | \mathbf{e}_{1}, \mathbf{e}_{2}, \ldots, \mathbf{e}_{n} \\ 220 | \mathbf{e}_{1} \wedge \mathbf{e}_{2}, \mathbf{e}_{1} \wedge \mathbf{e}_{3}, \ldots, \mathbf{e}_{1} \wedge \mathbf{e}_{n}, \mathbf{e}_{2} \wedge \mathbf{e}_{3}, \ldots, \mathbf{e}_{n-1} \wedge \mathbf{e}_{n} \\ 221 | \vdots \\ 222 | \mathbf{e}_{1} \wedge \mathbf{e}_{2} \wedge \ldots \wedge \mathbf{e}_{n} 223 | \end{array} 224 | $$ 225 | 226 | The exterior algebra has a unity 1 and satisfies the multiplication rules 227 | $$ 228 | \begin{array}{l} 229 | \mathbf{e}_{i} \wedge \mathbf{e}_{j}=-\mathbf{e}_{j} \wedge \mathbf{e}_{i} \quad \text { for } \quad i \neq j \\ 230 | \mathbf{e}_{i} \wedge \mathbf{e}_{i}=0 231 | \end{array} 232 | $$ 233 | Clifford 1882 kept the first rule but altered the second rule, and arrived at the multiplication rules 234 | $$ 235 | \begin{array}{l} 236 | \mathbf{e}_{i} \mathbf{e}_{j}=-\mathbf{e}_{j} \mathbf{e}_{i} \quad \text { for } \quad i \neq j \\ 237 | \mathbf{e}_{i} \mathbf{e}_{i}=1 238 | \end{array} 239 | $$ 240 | This time $\left\{\mathbf{e}_{1}, \mathbf{e}_{2}, \ldots, \mathbf{e}_{n}\right\}$ is an orthonormal basis for the positive definite Euclidean space $\mathbb{R}^{n} .$ An associative algebra of dimension $2^{n}$ so defined is the Clifford algebra $\mathcal{C} \ell_{n}$. 241 | 242 | ### Basis-free version of Clifford's definition 243 | 244 | > Source: 14.2 Basis-free version of Clifford's definition in **Clifford Algebras and Spinors** by P. Lounesto 245 | 246 | Here we consider as an example the exterior algebra $\wedge \mathbb{R}^{4}$ of the 4 -dimensional real linear space $\mathbb{R}^{4}$. Provide the linear space $\mathbb{R}^{4}$ with a quadratic form 247 | $$ 248 | Q(\mathbf{x})=x_{0}^{2}-x_{1}^{2}-x_{2}^{2}-x_{3}^{2} 249 | $$ 250 | and associate to $Q$ the symmetric bilinear form 251 | $$ 252 | \langle\mathbf{x}, \mathbf{y}\rangle=\frac{1}{2}[Q(\mathbf{x}+\mathbf{y})-Q(\mathbf{x})-Q(\mathbf{y})] 253 | $$ 254 | This makes $\mathbb{R}^{4}$ isometric with the Minkowski space-time $\mathbb{R}^{1,3}$. Then define the left contraction $u \mathrm{J} v \in \wedge \mathbb{R}^{1,3}$ by 255 | (a) $\mathbf{x}\rfloor\mathbf{y}=\langle\mathbf{x}, \mathbf{y}\rangle$ 256 | (b) $\mathbf{x}\rfloor(u \wedge v)=(\mathbf{x}\rfloor u) \wedge v + \hat{u} \wedge(\mathbf{x} \rfloor v)$ 257 | (c) $(u \wedge v)\rfloor w=u\rfloor(v \perp w)$ 258 | 259 | for $\mathbf{x}, \mathbf{y} \in \mathbb{R}^{1,3}$ and $u, v, w \in \wedge \mathbb{R}^{1,3}$, where $\hat{u}$ is the grade involute of $u \in \bigwedge V$, defined for a k-vector $u \in \bigwedge^k V$ by $\hat{u} = (-1)^k u$ 260 | 261 | The identity (b) says that $x$ operates like a derivation and the identity (c) makes $\bigwedge \mathbb{R}^{1,3}$ a left module over $\bigwedge \mathbb{R}^{1,3}$ Then introduce the Clifford product of $\mathbf{x} \in \mathbb{R}^{1,3}$ and $u \in \bigwedge \mathbb{R}^{1,3}$ by the formula 262 | $$ 263 | \mathbf{x} u = \mathbf{x} \rfloor u + \mathbf{x} \wedge u 264 | $$ 265 | 266 | and extend this product by linearity and associativity to all of $\bigwedge \mathbb{R}^{1,3}$. Provided with the Clifford product (the linear space underlying) the exterior algebra $\bigwedge \mathbb{R}^{1,3}$ becomes the Clifford algebra $\mathcal{C} \ell_{1,3}$ 267 | 268 | ### Definition by generators and relations 269 | 270 | > Source: 14.3 Definition by generators and relations in **Clifford Algebras and Spinors** by P. Lounesto 271 | 272 | The following definition is favored by physicists. It is suitable for non-degenerate quadratic forms, especially the real quadratic spaces $\mathbb{R}^{p, q}$. 273 | 274 | Definition. An associative algebra over $\mathbb{F}$ with unity 1 is the Clifford algebra $\mathcal{C} \ell(Q)$ of a non-degenerate $Q$ on $V$ if it contains $V$ and $\mathbb{F}=\mathbb{F} \cdot 1$ as distinct subspaces so that 275 | (1) $\mathbf{x}^{2}=Q(\mathbf{x})$ for any $\mathbf{x} \in V$ 276 | (2) $V$ generates $\mathcal{C} \ell(Q)$ as an algebra over $\mathbb{F}$ 277 | (3) $\mathcal{C} \ell(Q)$ is not generated by any proper subspace of $V$ 278 | 279 | ### Universal object of quadratic algebras 280 | 281 | > Source: 14.4 Universal object of quadratic algebras in **Clifford Algebras and Spinors** by P. Lounesto 282 | 283 | The Clifford algebra $\mathcal{C} \ell(Q)$ is the universal associative algebra over $\mathbb{F}$ generated by $V$ with the relations $\mathbf{x}^{2}=Q(\mathbf{x}), \mathbf{x} \in V$ 284 | 285 | Let $Q$ be the quadratic form on a linear space $V$ over a field $\mathbb{F}$, and let $A$ be an associative algebra over $\mathbb{F}$ with unity $1_{A} .$ A linear mapping $V \rightarrow A$, $\mathbf{x} \rightarrow \varphi_{\mathbf{x}}$ such that 286 | $$ 287 | \left(\varphi_{x}\right)^{2}=Q(x) \cdot 1_{A} \quad \text { for all } x \in V 288 | $$ 289 | is called a Clifford map. 290 | 291 | The subalgebra of $A$ generated by $\mathbb{F}=\mathbb{F} \cdot 1_{A}$ and $V$ (or more precisely by the images of $\mathbb{F}$ and $V$ in $A$ ) will be called a quadratic algebra. 292 | 293 | The Clifford algebra $\mathcal{C} \ell(Q)$ is a quadratic algebra with a Clifford $\operatorname{map} V \rightarrow \mathcal{C} \ell(Q), \quad \mathbf{x} \rightarrow \gamma_{\mathbf{x}}$ such that for any Clifford map $\varphi: V \rightarrow A$ there 294 | exists a unique algebra homomorphism $\psi: \mathcal{C} \ell(Q) \rightarrow A$ making the following diagram commutative: 295 | $$ 296 | \begin{array}{c} 297 | V \stackrel{\gamma}{\longrightarrow} \mathcal{C} \ell(Q) \\ 298 | \varphi \searrow \quad \downarrow \psi \\ 299 | \quad A 300 | \end{array} \quad \varphi_{\mathbf{x}}=\psi\left(\gamma_{\mathbf{x}}\right) 301 | $$ 302 | This definition says that all Clifford maps may be obtained from $\gamma: V \rightarrow \mathcal{C} \ell(Q)$ which is thereby universal. 303 | 304 | ### Clifford algebra as a quotient of the tensor algebra 305 | 306 | > Source: 14.5 Clifford algebra as a quotient of the tensor algebra in **Clifford Algebras and Spinors** by P. Lounesto 307 | 308 | Chevalley 1954 p. 37 constructs the Clifford algebra $\mathcal{C} \ell(Q)$ as the quotient algebra $\otimes V / I(Q)$ of the tensor algebra $\otimes V$ with respect to the two-sided ideal $I(Q)$ generated by the elements $\mathbf{x} \otimes \mathbf{x}-Q(\mathbf{x})$ where $\mathbf{x} \in V .$ See also $N .$ Bourbaki 1959 p. 139 and $T . Y .$ Lam 1973 p. $103 .$ The tensor algebra approach gives a proof of existence by construction - suitable for an algebraist who is interested in rapid access to the main properties of Clifford algebras over commutative rings. 309 | 310 | In characteristic zero we may avoid quotient structures by making the exterior algebra $\bigwedge V$ concrete as the subspace of antisymmetric tensors in $\otimes V .$ For example, if $\mathbf{x}, \mathbf{y} \in V,$ then $\mathbf{x} \wedge \mathbf{y}=\frac{1}{2}(\mathbf{x} \otimes \mathbf{y}-\mathbf{y} \otimes \mathbf{x}) \in \bigwedge^{2} V .$ 311 | 312 | More generally, a simple $k$ -vector $\mathbf{x}_{1} \wedge \mathbf{x}_{2} \wedge \ldots \wedge \mathbf{x}_{k}$ is identified with 313 | $$ 314 | Alt\left(\mathbf{x}_{1} \otimes \mathbf{x}_{2} \otimes \ldots \otimes \mathbf{x}_{k}\right)=\frac{1}{k !} \sum_{\pi} \operatorname{sign}(\pi) \mathbf{x}_{\pi(1)} \otimes \mathbf{x}_{\pi(2)} \otimes \ldots \otimes \mathbf{x}_{\pi(k)} 315 | $$ 316 | where the linear operator $Alt: \otimes V \rightarrow \wedge V$, called alternation, is a projection operator $Alt(\bigotimes V)=\bigwedge V$ satisfying $u \wedge v=Alt(u \otimes v)$. 317 | 318 | Similarly, we may obtain an isomorphism of linear spaces $\wedge V \rightarrow \mathcal{C} \ell(Q)$ by identifying simple $k$ -vectors with antisymmetrized Clifford products 319 | 320 | $$ 321 | \mathbf{x}_{1} \wedge \mathbf{x}_{2} \wedge \ldots \wedge \mathbf{x}_{k} \rightarrow \mathbf{x}_{1} \dot{\wedge} \mathbf{x}_{2} \dot{\wedge} \ldots \dot{\wedge} \mathbf{x}_{k}=\frac{1}{k !} \sum_{\pi} \operatorname{sign}(\pi) \mathbf{x}_{\pi(1)} \mathbf{x}_{\pi(2)} \ldots \mathbf{x}_{\pi(k)} 322 | $$ 323 | 324 | thus splitting the Clifford algebra $\mathcal{C} \ell(Q)$ into fixed subspaces of $k$ -vectors $\bigwedge^{k} V \subset \mathcal{C} \ell(Q)$. Any orthogonal basis $\mathbf{e}_{1}, \mathbf{e}_{2}, \ldots, \mathbf{e}_{n}$ of $V$ gives a correspon- 325 | dence 326 | $$ 327 | \mathbf{e}_{i_{1}} \wedge \mathbf{e}_{i_{2}} \wedge \ldots \wedge \mathbf{e}_{i_{k}} \rightarrow \mathbf{e}_{i_{1}} \dot{\wedge} \mathbf{e}_{i_{2}} \dot{\wedge} \ldots \dot{\wedge} \mathbf{e}_{i_{k}}=\mathbf{e}_{i_{1}} \mathbf{e}_{i_{2}} \ldots \mathbf{e}_{i_{k}} 328 | $$ 329 | of bases for $\wedge V$ and $\mathcal{C} \ell(Q)$ 330 | 331 | ### Mother Algebra 332 | 333 | > Source: Doran, Chris, David Hestenes, Frank Sommen, and Nadine Van Acker. "Lie groups as spin groups." Journal of Mathematical Physics 34, no. 8 (1993): 3642-3669. 334 | 335 | > Grassmannian argue that GA is more fundamental than CA, because it makes no assumptions about a metric on the vector space that generates it. On the contrary, Cliffordians argue that CA is more fundamental than GA, because it contains GA as a subalgebra. 336 | 337 | To reconcile the contemporary views of Grassmann and Clifford algebras, we begin with a standard definition of the Grassmann algebra $\Lambda_{n}=\Lambda\left(\mathcal{V}^{n}\right)$ of an $n$ -dimensional real vector space $\mathcal{V}^{n} .$ This associative algebra is generated from $\mathcal{V}^{n}$ by Grassmann's outer product under the assumption that the product of several vectors vanishes if and only if the vectors are linearly dependent. With the notation in Eq. (2.1) for the outer product, the outer product 338 | $$ 339 | v_{1} \wedge v_{2} \wedge \ldots \wedge v_{k} 340 | $$ 341 | of $k$ linearly independent vectors is called a $k$ -blade, and a linear combination of $k$ -blades is called a $k$ -vector. The set of all $k$ -vectors is a linear space 342 | $$ 343 | \Lambda_{n}^{k}=\Lambda^{k}\left(\mathcal{V}^{n}\right) 344 | $$ 345 | with dimension given by the binomial coefficient $\left(\begin{array}{l}n \\ k\end{array}\right) .$ With the notations $\Lambda_{n}^{1}=\mathcal{V}^{n}$ and $\Lambda_{n}^{0}=\Re$ for the real scalars, the entire Grassmann algebra can be expressed as a $2^{n}-$ dimensional linear space 346 | $$ 347 | \Lambda_{n}=\sum_{k=0}^{n} \Lambda_{n}^{k} 348 | $$ 349 | This completes our description of Grassmann's "exterior algebra," but ore mathematical structure is needed for applications. Standard practice is to introduce this structure by defining the space of linear forms on $\Lambda_{n} .$ However, we think there is a better procedure which is closer to Grassmann's original approach. 350 | 351 | We introduce an $n$ -dimensional vector space $\mathcal{V}^{n *}$ dual to $\mathcal{V}^{n}$ with "duality" defined by the following condition: If $\left\{w_{i}\right\}$ is a basis for $\mathcal{V}^{n},$ then there is a basis $\left\{w_{i}^{*}\right\}$ for $\mathcal{V}^{n *}$ defining unique scalar-valued mappings denoted by 352 | 353 | $$ 354 | \mathcal{V}_{i}^{n *} \cdot \mathcal{V}_{j}^{n}=\frac{1}{2} \delta_{i, j}, \quad \text { for } i, j=1,2, \ldots, n 355 | $$ 356 | The dual space generates its own Grassmann algebra 357 | $$ 358 | \Lambda^{*}\left(\mathcal{V}^{n}\right)=\Lambda_{n}^{*}=\sum_{k=0}^{n} \Lambda_{n}^{k^{*}} 359 | $$ 360 | The inner product (2.5) can be extended to a product between $k$ -vectors, so that each $k$ vector in $\mathcal{V}^{n *}$ determines a unique $k$ -form on $\mathcal{V}^{n},$ that is, a linear mapping of $\Lambda_{n}^{k}$ into the scalars. In other words, $\Lambda_{n}^{k^{*}}$ can be regarded as the linear space of all $k$ -forms. 361 | 362 | This much is equivalent to the standard theory of linear forms, though Eq. (2.5) is not a standard notation defining one-forms. The notation has been adopted here so Eq. (2.5) can be interpreted as Grassmann's inner product, and $\Lambda_{n}$ and $\Lambda_{n}^{*}$ can be imbedded in a single geometric algebra with a single central product defined by Eq. $(2.1) .$ One way to do that is by identifying $\Lambda_{n}$ with $\Lambda_{n}^{*}$ but then Eq. (2.5) defines a nondegenerate metric on $\mathcal{V}^{n},$ and Grassmannians claim that that is a loss in generality. Cliffordians counter that the loss is illusory, for the interpretation of Eq. (2.5) as a metric tensor is not necessary if it is not wanted; with one variable held fixed, it can equally well be interpreted as a "contraction" defining a linear form. Be that as it may, there really is an advantage to keeping $\Lambda_{n}$ and $\Lambda_{n}^{*}$ distinct, in fact maximally distinct, as we see next. We turn $\Lambda_{n}$ and $\Lambda_{n}^{*}$ into geometric algebras by defining the inner products 363 | $$ 364 | w_{i} \cdot w_{j}=0 \quad \text { and } \quad w_{i}^{*} \cdot w_{j}^{*}=0 365 | $$ 366 | so Eq. (2.1) gives 367 | $$ 368 | w_{i} \wedge w_{j}=w_{i} w_{j}=-w_{j} w_{i} \quad \text { and } \quad w_{i}^{*} \wedge w_{j}^{*}=w_{i}^{*} w_{j}^{*}=-w_{j}^{*} w_{i}^{*} 369 | $$ 370 | Also we assume that the $w_{i}$ and the $w_{i}^{*}$ are linearly independent vectors spanning a $2 n-$ dimensional vector space 371 | $$ 372 | \mathcal{R}^{n, n}=\mathcal{V}^{n} \otimes \mathcal{V}^{n *} 373 | $$ 374 | with an inner product defined by Eqs. (2.5) and $(2.7 \mathrm{a}) .$ This generates a $2^{2 n}$ -dimensional geometric algebra which we denote by 375 | $$ 376 | \mathcal{R}_{n, n}=\mathcal{G}\left(\mathcal{R}^{n, n}\right)=\sum_{k=0}^{n} \mathcal{R}_{n, n}^{k} 377 | $$ 378 | with $k$ -vector subspaces $\mathcal{R}_{n, n}^{k}=\mathcal{G}^{k}\left(\mathcal{R}^{n, n}\right)=\mathcal{G}^{k}\left(\mathcal{R}_{n, n}\right) .$ Anticipating the conclusion that it will prove to be an ideal tool for characterizing linear and multilinear functions on an $n$ -dimensional vector space, let us refer to $\mathcal{R}_{n, n}$ as the mother algebra. 379 | 380 | ### Geometric Algebra Coordinate Frames 381 | 382 | > Source: Eid, A.H.: An extended implementation framework for geometric algebra operations on systems of coordinate frames of arbitrary signature. Adv. Appl. Clifford Algebras 28(1), 16 (2018) 383 | > But the quoted construction here (which is better summarized) came from Eid, Ahmad Hosny. "A Low-Memory Time-Efficient Implementation of Outermorphisms for Higher-Dimensional Geometric Algebras." Advances in Applied Clifford Algebras 30.2 (2020): 1-20. 384 | 385 | A GACF is completely defined using two components: 386 | 387 | 1. An ordered set of $n$ basis vectors $\boldsymbol{F}_{1}^{n}=\left\langle f_{0}, f_{1}, \ldots, f_{n-1}\right\rangle$ defining the dimensions of the GACF's base vector space. 388 | 2. A symmetric real bilinear form $\mathbf{B}: \boldsymbol{F}_{1}^{n} \times \boldsymbol{F}_{1}^{n} \rightarrow \mathbb{R}, \mathbf{B}\left(f_{i}, f_{j}\right)=\mathbf{B}\left(f_{j}, f_{i}\right)=$ 389 | $f_{i} \cdot f_{j}$ determining the inner product of basis vectors and given by a symmetric $n \times n$ bilinear form matrix $\mathbf{A}_{\mathcal{F}}=\left[f_{i} \cdot f_{j}\right]$ called the Inner Product Matrix (IPM) of the GACF. 390 | 391 | A GACF can be of two types: orthogonal or non-orthogonal. The IPM of an orthogonal GACF is diagonal $\left(f_{i} \cdot f_{i}=d_{i}, f_{i} \cdot f_{j}=0 \forall i \neq j\right)$ while the IPM of a non-orthogonal GACF is non-diagonal $\left(f_{i} \cdot f_{j}=f_{j} \cdot f_{i}=b_{i j} \exists i \neq j: b_{i j} \neq 0\right)$ 392 | 393 | A Euclidean GACF is orthogonal with all $d_{i}=1$ We construct three additional components to serve GA computations within the GACF: 394 | 395 | 1. The ordered set of $2^{n}$ basis blades of all grades $\boldsymbol{F}^{n}=\left\langle F_{0}, F_{1}, \cdots, F_{2^{n}-1}\right\rangle$ This set is automatically determined by the set of basis vectors $\boldsymbol{F}_{1}^{n}$. This component is independent of the metric represented by $\mathbf{A}_{\mathcal{F}}$ as they are created using the metric-independent outer product of basis vectors in $\boldsymbol{F}_{1}^{n}$ 396 | $F_{i}=\prod_{\wedge}\left(\boldsymbol{F}_{1}^{n}, i\right)$ 397 | $=\left\{\begin{array}{ll}1, & i=0 \\ f_{m}, & i=2^{m}, m \in\{0,1, \ldots, n-1\} \\ f_{i_{1}} \wedge f_{i_{2}} \wedge \cdots \wedge f_{i_{r}}, \quad i=2^{i_{1}}+2^{i_{2}}+\cdots+2^{i_{r}} & i_{i} Source: Macdonald, Alan. "A survey of geometric algebra and geometric calculus." Advances in Applied Clifford Algebras 27.1 (2017): 853-891. http://www.faculty.luther.edu/~macdonal/GA&GC.pdf 406 | 407 | The geometric algebra $\mathbb{G}^{n} .$ The geometric algebra $\mathbb{G}^{n}$ is an extension of the inner product space $\mathbb{R}^{n},$ with more objects and operations. First, $\mathbb{G}^{n}$ is an associative algebra with a $1 .$ That is, it is a vector space with a product satisfying properties $\mathrm{G} 1-\mathrm{G} 4$ for all scalars $a$ and $A, B, C \in \mathbb{G}^{n}:$ 408 | $\mathrm{G} 1 . A(B+C)=A B+A C,(B+C) A=B A+C A$ 409 | $\mathrm{G} 2 .(a A) B=A(a B)=a(A B)$ 410 | G3. $(A B) C=A(B C)$ 411 | $\mathrm{G} 4.1 A=A 1=A$ 412 | The product is called the geometric product. It is not commutative. Members of $\mathbb{G}^{n}$ are called multivectors. This allows us to reserve the term "vector" for vectors in $\mathbb{R}^{n} .$ (They are also multivectors.) This is a convenient terminology. Vectors are denoted in lower case bold. We list two more properties. 413 | G5. The geometric product of $\mathbb{G}^{n}$ is linked to the algebraic structure of $\mathbb{R}^{n}$ $\mathrm{by}$ 414 | $$ 415 | \mathbf{u u}=\mathbf{u} \cdot \mathbf{u}=|\mathbf{u}|^{2} \text { for all } \mathbf{u} \in \mathbb{R}^{n} 416 | $$ 417 | This shows that nonzero vectors have an inverse in $\mathbb{G}^{n}: \mathbf{u}^{-1}=\mathbf{u} /|\mathbf{u}|^{2}$ 418 | 419 | G6. Every orthonormal basis for $\mathbb{R}^{n}$ determines a canonical basis (defined below $)$ for the vector space $\mathbb{G}^{n}$ 420 | 421 | That's it! That's the geometric algebra. We have not proved that the mathematical structure just described exists. For that, see [14] (A. Macdonald, An Elementary Construction of the Geometric Algebra. Adv. Appl. 422 | Cliff. Alg. 12 (2002), 1-6. (Improved version: http://www.faculty.luther.edu/~macdonal/GAConstruct.pdf ).). 423 | 424 | Before proceeding, we need Eq. (1.2) below. In the next equation, Step is a polarization identity. Verify it by multiplying out the inner product on the right side. Step (2) follows from Eq. (1.1). Verify Step (3) by multiplying out the geometric product on the left side. 425 | $$ 426 | \begin{aligned} 427 | \mathbf{u} \cdot \mathbf{v} & \stackrel{1}{=} \frac{1}{2}((\mathbf{u}+\mathbf{v}) \cdot(\mathbf{u}+\mathbf{v})-\mathbf{u} \cdot \mathbf{u}-\mathbf{v} \cdot \mathbf{v}) \\ 428 | & \stackrel{2}{=} \frac{1}{2}\left((\mathbf{u}+\mathbf{v})^{2}-\mathbf{u}^{2}-\mathbf{v}^{2}\right) \stackrel{3}{=} \frac{1}{2}(\mathbf{u v}+\mathbf{v} \mathbf{u}) 429 | \end{aligned} 430 | $$ 431 | If $\mathbf{u}$ and $\mathbf{v}$ are orthogonal, then this gives 432 | $$ 433 | \mathbf{v} \mathbf{u}=-\mathbf{u v} . \quad(\mathbf{u}, \mathbf{v} \text { orthogonal }) 434 | $$ 435 | $$ 436 | \text { Example: }\left(1+\mathbf{e}_{1} \mathbf{e}_{2}\right)\left(\mathbf{e}_{1}-2 \mathbf{e}_{2}\right)=-\mathbf{e}_{1}-3 \mathbf{e}_{2} 437 | $$ 438 | If $\mathbf{u}$ and $\mathbf{v}$ are orthogonal and nonzero, then from Eq. (1.2) 439 | $$ 440 | (\mathbf{u v})^{2}=\mathbf{u v u v}=-\mathbf{u u v v}=-|\mathbf{u}|^{2}|\mathbf{v}|^{2}<0 441 | $$ 442 | Therefore $\mathbf{u v}$ is not a scalar or a vector. It is something new. 443 | 444 | ### Elementary Construction 445 | 446 | > Source: A. Macdonald, An Elementary Construction of the Geometric Algebra. Adv. Appl. Cliff. Alg. 12 (2002), 1-6. http://www.faculty.luther.edu/~macdonal/GAConstruct.pdf 447 | > The deinition in it is not actually included due to lack of generality. Here we're only interested in the desciption of the motivation to have an elementary construction and the comparisons of constructions, plus listing axioms of vector space and algebra for easy potential reference. 448 | 449 | My goal is to provide a construction of $\mathrm{GA}(n)$ suitable for someone with only an elementary knowledge of $\mathbf{R}^{n} .$ The construction is simple, elementary, direct, and motivated. Two features of the construction help make this so. First, the construction uses only elementary properties of $\mathbf{R}^{n}$. Some constructions use more advanced mathematical structures, such as tensor products. (Our construction is compared to others in Section 7.) **The geometric algebra $\mathrm{GA}(n)$ is a fundamental mathematical structure which is part of the essence of Euclidean space. It therefore deserves a construction not using less fundamental structures than $\mathbf{R}^{n}$.** 450 | 451 | Second, the construction is based directly upon the two fundamental identities which distinguish $\operatorname{GA}(n):$ If $e$ and $f$ are orthonormal vectors in $\mathbf{R}^{n},$ then 452 | $$ 453 | \begin{array}{l} 454 | e e=1 \\ 455 | e f=-f e 456 | \end{array} 457 | $$ 458 | Eqs. 459 | (1) and (2) motivate our construction. $\mathrm{GA}(n)$ is a $2^{n}$ dimensional vector space containing $\mathbf{R}^{n}$ which is also an associative algebra with identity. Its vectors are called multivectors. In addition, Eqs. 460 | (1) and (2) are satisfied. We list the vector space and algebra axioms for reference. Let $a$ and $b$ be scalars and $u, v,$ and $w$ be multivectors. Then 461 | 462 | V1. $u+v=v+u$ 463 | V2. $(u+v)+w=u+(v+w)$ 464 | V3. $u+0=u$ 465 | V4. $u+(-u)=0$ 466 | V5. $1 u=u$ 467 | V6. $a(b u)=(a b) u$ 468 | V7. $a(u+v)=a u+a v$ 469 | V8. $(a+b) u=a u+b u$ 470 | 471 | A1. $u(v w)=(u v) w$ 472 | A2. $u(v+w)=u v+u w \quad (v+w) u=v u+w u$ 473 | A3. $(a u) v=u(a v)=a(u v)$ 474 | A4. $1 u=u 1=u$ 475 | 476 | 7 Other Constructions. Emil Artin has given an elegant and simple elementary construction of $\mathrm{GA}(n)$ [2, p .186]. Our construction is better motivated and, I think, somewhat simpler. 477 | 478 | Marcel Riesz' construction in his Maryland lectures [6, Sec. 1.2-1.4] is incomplete. Riesz introduces products of the form Eq. 479 | (3) for orthonormal basis vectors $\left\{e_{i}\right\}$ and stipulates that $e_{i} e_{i}=1$ and $e_{i} e_{j}=-e_{j} e_{i}$ for $i \neq j .$ (Our Eqs. (1) and (2) But to show that these rules can be consistently applied, he needs something analogous to our lemma, which he does not supply. And once it is supplied, the associativity of the geometric product is trivial, as we have seen. Then Riesz's proof of the associativity in Sec. 1.3 becomes superfluous. 480 | 481 | Ambjorn Naeve and Lars Svensson have given a construction which uses concepts from abstract algebra (rings, totally ordered sets, ideals) [5], although it could be reexpressed in more elementary terms. 482 | R.D. Arthan has given a "minmalist" construction of the geometric algebra 483 | [1]. 484 | Pertti Lounesto has catalogued several nonelementary constructions of $\mathrm{GA}(n)$ including those using a Grassman algebra, a tensor product, and a universal algebra [4]. **These constructions obscure the simplicity and elementary nature of the geometric algebra.** 485 | 486 | ### Bromborsky 2014 487 | 488 | > Source: Bromborsky, Alan. "An introduction to geometric algebra and calculus." (2014). 489 | 490 | Let $\mathcal{V}(p, q)$ be a finite dimensional vector space of signature $(p, q)^{1}$ over $\Re .$ Then $\forall a, b, c \in \mathcal{V}$ there exists a geometric product with the properties - 491 | $$ 492 | \begin{aligned} 493 | (a b) c &=a(b c) \\ 494 | a(b+c) &=a b+a c \\ 495 | (a+b) c &=a c+b c \\ 496 | a a & \in \Re 497 | \end{aligned} 498 | $$ 499 | 500 | If $a^{2} \neq 0$ then $a^{-1}=\frac{1}{a^{2}} a$. 501 | 502 | ### Perwass 2009 503 | 504 | > Source: Perwass, Christian, et al. Geometric algebra with applications in engineering. Vol. 4. Berlin: Springer, 2009. 505 | 506 | Let $\mathbb{R}^{p, q}$ denote a $(p+q)$ -dimensional vector space over the reals $\mathbb{R} .$ Furthermore, let a commutative scalar product be defined as $\ast : \mathbb{R}^{p, q} \times \mathbb{R}^{p, q} \rightarrow \mathbb{R}$ That is, for $\boldsymbol{a}, \boldsymbol{b} \in \mathbb{R}^{p, q}$ 507 | $$ 508 | \boldsymbol{a} * \boldsymbol{b}=\boldsymbol{b} * \boldsymbol{a} \quad \in \mathbb{R} 509 | $$ 510 | 511 | Axiom 3.1 (Geometric Algebra) 512 | 513 | Let $\mathbb{A}\left(\mathbb{R}^{p, q}\right)$ denote the associative algebra over the quadratic space $\left(\mathbb{R}^{p, q}, \ast\right)$ and let o denote the algebraic product. 514 | 515 | Note that the field $\mathbb{R}$ and the vector space $\mathbb{R}^{p, q}$ can both be regarded as subspaces of $\mathbb{A}\left(\mathbb{R}^{p, q}\right)$. The algebra $\mathbb{A}\left(\mathbb{R}^{p, q}\right)$ is said to be a geometric algebra if for 516 | $\boldsymbol{a} \in \mathbb{R}^{p, q} \subset \mathbb{A}\left(\mathbb{R}^{p, q}\right), \boldsymbol{a} \circ \boldsymbol{a}=\boldsymbol{a} \ast \boldsymbol{a}$ 517 | 518 | The geometric algebra over $\mathbb{R}^{p, q}$ is denoted by $\mathbb{G}\left(\mathbb{R}^{p, q}\right)$ or simply $\mathbb{G}_{p, q}$ and the algebra product is called the Clifford or geometric product. Although the geometric product is denoted here by $\circ$, it is represented later by juxtaposition for brevity. 519 | 520 | In the following, all axioms of a geometric algebra are given explicitly. First of all, the elements of $\mathbb{G}_{p, q},$ which are called multivectors, satisfy the axioms of a vector space over the field $\mathbb{R}$ 521 | 522 | Axiom 3.2 The following two operations exist in $\mathbb{G}_{p, q}$ : 523 | 1. Multivector addition. For any two elements $\boldsymbol{A}, \boldsymbol{B} \in \mathbb{G}_{p, q}$ there exists an element $\boldsymbol{C}=\boldsymbol{A}+\boldsymbol{B} \in \mathbb{G}_{p, q},$ their sum. 524 | 2. Scalar multiplication. For any element $\boldsymbol{A} \in \mathbb{G}_{p, q}$ and any scalar $\alpha \in \mathbb{R}$ there exists an element $\alpha \boldsymbol{A} \in \mathbb{G}_{p, q},$ the $\alpha$ -multiple of $\boldsymbol{A}$ 525 | Axiom 3.3 (Vector Space) Let $\boldsymbol{A}, \boldsymbol{B}, \boldsymbol{C} \in \mathbb{G}_{p, q}$ and $\alpha, \beta \in \mathbb{R}$ 526 | 1. Associativity of multivector addition: 527 | $$ 528 | (\boldsymbol{A}+\boldsymbol{B})+\boldsymbol{C}=\boldsymbol{A}+(\boldsymbol{B}+\boldsymbol{C}) 529 | $$ 530 | 2. Commutativity: 531 | $$ 532 | \boldsymbol{A}+\boldsymbol{B}=\boldsymbol{B}+\boldsymbol{A} 533 | $$ 534 | 3. Identity element of addition. There exists an element $0 \in \mathbb{G}_{p, q},$ the zero element, such that 535 | $$ 536 | A+0=A 537 | $$ 538 | 4. Associativity of scalar multiplication: 539 | $$ 540 | \alpha(\beta \boldsymbol{A})=(\alpha \beta) \boldsymbol{A} 541 | $$ 542 | 5. Commutativity of scalar multiplication: 543 | $$ 544 | \alpha \boldsymbol{A}=\boldsymbol{A} \alpha 545 | $$ 546 | 6. Identity element of scalar multiplication. The identity element $1 \in \mathbb{R}$ satisfies 547 | $$ 548 | 1 A=A 549 | $$ 550 | 7. Distributivity of multivector sums: 551 | $$ 552 | \alpha(\boldsymbol{A}+\boldsymbol{B})=\alpha \boldsymbol{A}+\alpha \boldsymbol{B} 553 | $$ 554 | 8. Distributivity of scalar sums: 555 | $$ 556 | (\alpha+\beta) \boldsymbol{A}=\alpha \boldsymbol{A}+\beta \boldsymbol{A} 557 | $$ 558 | 559 | It follows from these axioms that for each $\boldsymbol{A} \in \mathbb{G}_{p, q}$ there exists an element $-\boldsymbol{A}:=(-1) \boldsymbol{A}$ such that 560 | $$ 561 | \boldsymbol{A}-\boldsymbol{A}:=\boldsymbol{A}+(-\boldsymbol{A})=\boldsymbol{A}+(-1) \boldsymbol{A}=(1+(-1)) \boldsymbol{A}=0 \boldsymbol{A}=0 562 | $$ 563 | 564 | Axiom 3.4 The axioms related to the algebraic product, i.e. the geometric product, are as follows. Let $\boldsymbol{A}, \boldsymbol{B}, \boldsymbol{C} \in \mathbb{G}_{p, q}$ and $\alpha, \beta \in \mathbb{R}$ 565 | 1. The algebra is closed under the geometric product: 566 | $$ 567 | \boldsymbol{A} \circ \boldsymbol{B} \in \mathbb{G}_{p, q} 568 | $$ 569 | 2. Associativity: 570 | $$ 571 | (\boldsymbol{A} \circ \boldsymbol{B}) \circ \boldsymbol{C}=\boldsymbol{A} \circ(\boldsymbol{B} \circ \boldsymbol{C}) 572 | $$ 573 | 3. Distributivity: 574 | $$ 575 | \boldsymbol{A} \circ(\boldsymbol{B}+\boldsymbol{C})=\boldsymbol{A} \circ \boldsymbol{B}+\boldsymbol{A} \circ \boldsymbol{C} \quad \text { and } \quad(\boldsymbol{B}+\boldsymbol{C}) \circ \boldsymbol{A}=\boldsymbol{B} \circ \boldsymbol{A}+\boldsymbol{C} \circ \boldsymbol{A} 576 | $$ 577 | 4. Scalar multiplication: 578 | $$ 579 | \alpha \circ \boldsymbol{A}=\boldsymbol{A} \circ \alpha=\alpha \boldsymbol{A} 580 | $$ 581 | All axioms given so far define an associative algebra. What actually separates Clifford algebra from other algebras is the defining equation. 582 | Axiom 3.5 Let $a \in \mathbb{R}^{p, q} \subset \mathbb{G}_{p, q} ;$ then 583 | $$ 584 | \boldsymbol{a} \circ \boldsymbol{a}=\boldsymbol{a} * \boldsymbol{a} \in \mathbb{R} 585 | $$ 586 | That is, the geometric product of a vector (not a multivector in general) with itself maps to an element of the field $\mathbb{R}$ 587 | 588 | -------------------------------------------------------------------------------- /docs/misc/related.md: -------------------------------------------------------------------------------- 1 | Related References 2 | ====================== 3 | 4 | GA & Lean related 5 | -------------------- 6 | 7 | ### Lean/Mathlib Src 8 | 9 | - [init/core](https://github.com/leanprover/lean/blob/master/library/init/core.lean) 10 | - [data/complex/basic](https://github.com/leanprover-community/mathlib/blob/master/src/data/complex/basic.lean) 11 | - [data/matrix/basic](https://github.com/leanprover-community/mathlib/blob/master/src/data/matrix/basic.lean) 12 | - [geometry/euclidean](https://github.com/leanprover-community/mathlib/blob/master/src/geometry/euclidean.lean) 13 | - https://github.com/jsm28/bmo2-2020-lean/ 14 | - [geometry/manifold/real_instances](https://github.com/leanprover-community/mathlib/blob/master/src/geometry/manifold/real_instances.lean) 15 | - [analysis/convex/cone](https://github.com/leanprover-community/mathlib/blob/master/src/analysis/convex/cone.lean) 16 | - [analysis/normed_space/real_inner_product](https://github.com/leanprover-community/mathlib/blob/master/src/analysis/normed_space/real_inner_product.lean) 17 | - [doc](https://leanprover-community.github.io/mathlib_docs/analysis/normed_space/real_inner_product.html#inner_product_space) 18 | 19 | ### Lean/Mathlib PRs 20 | 21 | - [`feat(data/quaternion): define quaternions and prove some basic properties #2339`](https://github.com/leanprover-community/mathlib/pull/2339/) 22 | - [refactor(algebra/module): change module into an abbreviation for semimodule #2848](https://github.com/leanprover-community/mathlib/pull/2848) 23 | - [feat(algebra/add_torsor): torsors of additive group actions #2720](https://github.com/leanprover-community/mathlib/pull/2720/files) 24 | 25 | ### Inspiring Lean Code 26 | 27 | - [Formalizing Euclid's Axioms](https://github.com/vaibhavkarve/leanteach2020/blob/master/src/euclid.lean) 28 | - [commutative differential graded algebras](https://gist.github.com/kbuzzard/f5ee35457c5d257ceec58c66d7da0c38) 29 | - [free module](https://gist.github.com/sflicht/53bdcdb1e3536e668736f7b4eb63cd79) 30 | - [Huber_pair](https://github.com/leanprover-community/lean-perfectoid-spaces/blob/master/src/Huber_pair.lean#L72) 31 | 32 | ### Lean/Mathlib Doc 33 | 34 | - https://leanprover-community.github.io/mathlib-overview.html 35 | - https://leanprover-community.github.io/mathlib_docs/ 36 | - [data/overview.yaml](https://github.com/leanprover-community/leanprover-community.github.io/blob/newsite/data/overview.yaml) 37 | - https://leanprover-community.github.io/undergrad.html 38 | - https://leanprover-community.github.io/undergrad_todo.html 39 | - [style guide](https://github.com/leanprover-community/leanprover-community.github.io/blob/newsite/templates/contribute/style.md) 40 | - https://lean-forward.github.io/ 41 | - [tutorial/category_theory/intro](https://github.com/leanprover-community/mathlib/blob/master/docs/tutorial/category_theory/intro.lean) 42 | 43 | ### Inspiring Papers and Slides 44 | 45 | - [The Lean Mathematical Library](https://arxiv.org/abs/1910.09336) 46 | - [Maintaining a library of formal mathematics](https://lean-forward.github.io/mathlib-maintenance/paper.pdf) 47 | - [Formalising perfectoid spaces](https://arxiv.org/abs/1910.12320) 48 | - "ForTheL texts and Lean texts" in http://www.andrew.cmu.edu/user/avigad/meetings/fomm2020/slides/fomm_koepke.pdf 49 | - [Diagram Chasing in Interactive Theorem Proving](https://pp.ipd.kit.edu/uploads/publikationen/himmel20bachelorarbeit.pdf) 50 | - [Homological algebra in Lean](https://github.com/TwoFX/lean-homological-algebra) 51 | 52 | ### Inspiring Chats 53 | 54 | - [grassmann algebra and clifford algebra](https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/cleaning.20up.20this.20tactic.20proof.20%28regarding.20closures%29/near/193026381) 55 | - [fold notation](https://gitter.im/leanprover_public/Lobby?at=5a5686366117191e614e3ce4) 56 | - `(fold* )` 57 | - [tests/lean/fold](https://github.com/leanprover-community/lean/blob/master/tests/lean/fold.lean) 58 | - [tests/lean/over_notation](https://github.com/leanprover-community/lean/blob/master/tests/lean/over_notation.lean) 59 | - [euclidean_vector_space](https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/Some.20olympiad.20formalisations/near/197858180) 60 | 61 | ### Notation 62 | 63 | - https://github.com/leanprover/vscode-lean/blob/master/translations.json 64 | - https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts 65 | - https://en.wikipedia.org/wiki/List_of_mathematical_symbols_by_subject 66 | 67 | 68 | ### Tactics 69 | 70 | - [Lean Cheatsheet](https://gist.github.com/utensil/dc635f2991255f76d8da797efdabbf15) 71 | - https://www.imo.universite-paris-saclay.fr/~pmassot/enseignement/math114/tactiques.pdf (in French) 72 | - https://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html 73 | - http://www.inf.ed.ac.uk/teaching/courses/tspl/cheatsheet.pdf 74 | - https://leanprover-community.github.io/extras/tactic_writing.html#marios-monadic-symbols-cheat-sheet 75 | 76 | - [A Lean tactic for normalising ring expressions with exponents (short paper)](https://lean-forward.github.io/ring_exp/paper.pdf) 77 | - [Simplifying casts and coercions](https://lean-forward.github.io/norm_cast/norm_cast.pdf) 78 | - https://github.com/lean-forward/field 79 | - https://github.com/lean-forward/ring_exp 80 | 81 | GA Formalization Related 82 | -------------------------- 83 | 84 | - Implementing Geometric Algebra Products with Binary Tree - 2014 85 | - https://github.com/thery/GeometricAlgebra 86 | - Formalization of Geometric Algebra in HOL Light - li2018.pdf 87 | - https://github.com/jrh13/hol-light/tree/master/Geometric_Algebra 88 | - A New Formalization of Origami in Geometric - 2016 89 | - Formalization of Conformal Geometric Algebra and Robot Kinematics 90 | 91 | - Reference manuals 92 | - Coq: https://coq.inria.fr/refman/index.html 93 | - https://github.com/coq/coq/blob/master/doc/tools/coqrst/coqdomain.py 94 | - HOL Light: https://www.cl.cam.ac.uk/~jrh13/hol-light/reference.html 95 | - Isabelle/HOL 96 | - https://isabelle.in.tum.de/documentation.html 97 | - https://isabelle.in.tum.de/dist/library/HOL/index.html 98 | - https://devel.isa-afp.org/browser_info/current/AFP/Quaternions/ 99 | - https://www.isa-afp.org/browser_info/current/AFP/Octonions/ 100 | 101 | GA related 102 | ------------- 103 | 104 | - https://en.wikipedia.org/wiki/Geometric_algebra 105 | - https://en.wikipedia.org/wiki/Sedenion 106 | - [Geometrization of the Real Number System by Garret Sobczyk](https://arxiv.org/abs/1707.02338) 107 | - [Projective Geometric Algebra as a Subalgebra of Conformal Geometric algebra](https://arxiv.org/abs/2002.05993) 108 | - [Versor Cheat Sheet](http://versor.mat.ucsb.edu/masters_appendix.pdf) 109 | - https://github.com/pygae/GAlgebra.jl/blob/master/test/runtests.jl 110 | - Chapter 2 Clifford Algebra in [A Theory of Neural Computation 111 | with Clifford Algebras](https://macau.uni-kiel.de/servlets/MCRFileNodeServlet/dissertation_derivate_00001402/d1402.pdf) 112 | - Chapter 14 Definitions of Clifford Algebra in Clifford Algebras and Spinors by Lounesto 113 | - [All Hail Geometric Algebra!](https://crypto.stanford.edu/~blynn/haskell/ga.html) 114 | - [Chris Doran's Geometric Algebra Haskell Package](https://github.com/ga/haskell) 115 | - http://geometry.mrao.cam.ac.uk/2016/10/geometric-algebra-2016/ 116 | - http://math.uga.edu/~pete/quadraticforms.pdf 117 | 118 | Lean related 119 | ------------------ 120 | 121 | - [lean](https://github.com/leanprover-community/lean) - Lean Theorem Prover 122 | - [format_lean](https://github.com/leanprover-community/format_lean) - A Lean file formatter 123 | - https://sphinx-litprog.readthedocs.io/en/stable/ 124 | - [mathlib-tools](https://github.com/leanprover-community/mathlib-tools) - Development tools for https://github.com/leanprover-community/mathlib 125 | - [lean-client-python](https://github.com/leanprover-community/lean-client-python) - Python talking to the Lean theorem prover 126 | - [doc-gen](https://github.com/leanprover-community/doc-gen) - Generate HTML documentation for mathlib and Lean 127 | - [elan](https://github.com/Kha/elan) - A Lean version manager 128 | - [olean-rs](https://github.com/digama0/olean-rs) - parser/viewer for olean files 129 | - [Lean-game-maker](https://github.com/mpedramfar/Lean-game-maker) - This project converts structured Lean code into an interactive browser game. 130 | 131 | - [The Lean Reference Manual](https://leanprover.github.io/reference/) 132 | - [Theorem Proving in Lean](https://leanprover.github.io/theorem_proving_in_lean/) 133 | - [The Lean Theorem Prover](http://www.contrib.andrew.cmu.edu/~avigad/Talks/lean_ini.pdf) 134 | - [Logic and Proof](https://leanprover.github.io/logic_and_proof/) 135 | - [The Hitchhiker's Guide to Logical Verification](https://github.com/blanchette/logical_verification_2020/raw/master/hitchhikers_guide.pdf) 136 | 137 | - [tutorials](https://github.com/leanprover-community/tutorials) - Some Lean tutorials 138 | - [mathematics_in_lean](https://github.com/leanprover-community/mathematics_in_lean) 139 | - https://github.com/avigad/mathematics_in_lean_source 140 | - [mathlib](https://github.com/leanprover-community/mathlib) - Lean mathematical components library 141 | - [lean-perfectoid-spaces](https://github.com/leanprover-community/lean-perfectoid-spaces) - Perfectoid spaces in the Lean formal theorem prover. 142 | - [natural_number_game](https://github.com/ImperialCollegeLondon/natural_number_game) - Building the natural numbers in Lean. 143 | - [complex-number-game](https://github.com/ImperialCollegeLondon/complex-number-game) - The Complex Number Game. Make the complex numbers in Lean. 144 | - [group-theory-game](https://github.com/ImperialCollegeLondon/group-theory-game) - Building group theory from scratch in Lean 145 | - [real-number-game](https://github.com/ImperialCollegeLondon/real-number-game) - A gamification of the theorems in MATH40002 Analysis 1 146 | - [M1P1-lean](https://github.com/ImperialCollegeLondon/M1P1-lean) - Material from M1P1, formalised in Lean 147 | - [M4000x_LEAN_formalisation](https://github.com/JasonKYi/M4000x_LEAN_formalisation) - Formalising lecture notes from 1st year Imperial Mathematics course. 148 | - [M40001_lean](https://github.com/ImperialCollegeLondon/M40001_lean) 149 | - [Theorem proving hello world: prove a+0=a and 0+a=a](https://www.codewars.com/kata/5c879811bc562909bf65c8e6/train/lean) 150 | - https://leanprover-community.github.io/learn.html 151 | 152 | - [formalabstracts](https://github.com/formalabstracts/formalabstracts) - 153 | - [formal-encoding](https://github.com/IMO-grand-challenge/formal-encoding) - Formal encoding of IMO problems 154 | - [cubical lean](https://github.com/groupoid/lean) - Ground Zero: cubical base library for Lean 3 155 | - [xena](https://github.com/kbuzzard/xena) - Lean Library currently studying for a degree at Imperial College 156 | - http://wwwf.imperial.ac.uk/~buzzard/xena/ 157 | - [xena-UROP-2018](https://github.com/ImperialCollegeLondon/xena-UROP-2018) - A place to put our 2018 Xena project UROP thoughts and programs. 158 | - [Geometry in Lean](https://github.com/ImperialCollegeLondon/xena-UROP-2018/tree/master/src/Geometry) 159 | - [vector space](https://github.com/ImperialCollegeLondon/xena-UROP-2018/blob/master/src/vector_space.lean) 160 | - [The Xena Project summer projects, 2020](http://wwwf.imperial.ac.uk/~buzzard/xena/UROP2020.html) 161 | - [mathematica](https://github.com/robertylewis/mathematica) - Lean-independent implementation of the MM-Lean link 162 | - [mm-lean](https://github.com/minchaowu/mm-lean) - One direction of the MM-Lean link 163 | - [two-level](https://github.com/annenkov/two-level) - Two-Level Type Theory 164 | - [common-sense-lean](https://github.com/own-pt/common-sense-lean) - The initial ideas of a common sense library in Lean based on SUMO Ontology 165 | - [lean-for-hackers](https://github.com/agentultra/lean-for-hackers) 166 | - [tptp-lean-puzzles](https://github.com/FredsoNerd/tptp-lean-puzzles) 167 | - https://github.com/unitb/temporal-logic 168 | 169 | - [chore(*): replace rec_on with induction and match for readability](https://github.com/leanprover-community/mathlib/commit/f02a88b817a86450ce95514851f582dc9bdc460e) 170 | 171 | - [An Infinitely Large Napkin](https://github.com/vEnhance/napkin/) 172 | 173 | Theorem Prover/Type theory related 174 | ------------------------------------- 175 | 176 | - [lean-type-theory](https://github.com/digama0/lean-type-theory) - LaTeX code for a paper on lean's type theory 177 | - https://leanprover-community.github.io/lean-perfectoid-spaces/type_theory.html 178 | - [https://manishearth.github.io/blog/2017/03/04/what-are-sum-product-and-pi-types/](https://manishearth.github.io/blog/2017/03/04/what-are-sum-product-and-pi-types/) 179 | - 4 Defining Codatatypes in [Defining (Co)datatypes and Primitively (Co)recursive Functions in Isabelle/HOL](http://isabelle.in.tum.de/dist/doc/datatypes.pdf) 180 | - [A Tutorial on (Co-)Inductive Types in Coq](https://www.labri.fr/perso/casteran/RecTutorial.pdf) 181 | - [Canonical Structures for the working Coq user](https://hal.inria.fr/hal-00816703/file/main.pdf) 182 | - [Comparison of Two Theorem Provers: Isabelle/HOL and Coq](https://arxiv.org/abs/1808.09701) 183 | - [A Survey of Languages for Formalizing Mathematics](https://arxiv.org/abs/2005.12876) 184 | - [Category theory for scientists](https://arxiv.org/abs/1302.6946) 185 | - [Rethinking set theory](https://arxiv.org/abs/1212.6543) -------------------------------------------------------------------------------- /export.lean: -------------------------------------------------------------------------------- 1 | /- This file exports file and line information for use in LaTeX references. -/ 2 | 3 | import all 4 | 5 | import tactic.core 6 | 7 | open tactic 8 | 9 | meta structure decl_info := 10 | (name : name) 11 | (filename : string) 12 | (line : ℕ) 13 | 14 | meta def process_decl (e : environment) (d : declaration) : tactic (option decl_info) := 15 | do 16 | ff ← d.in_current_file | return none, 17 | let decl_name := d.to_name, 18 | -- allow linking to private names 19 | let (internal, short_name) := if (`_private).is_prefix_of decl_name 20 | then (ff, decl_name.update_prefix decl_name.get_prefix.get_prefix) 21 | else (decl_name.is_internal ∨ d.is_auto_generated e, decl_name), 22 | ff ← pure internal | return none, 23 | some filename ← return (e.decl_olean decl_name) | return none, 24 | let parts := filename.split (= '/'), 25 | some ⟨line, _⟩ ← return (e.decl_pos decl_name) | return none, 26 | return $ some ⟨short_name, filename, line⟩ 27 | 28 | /-- Split a path into an optional parent component and filename -/ 29 | def path_split (path : string) : option string × string := 30 | match (path.split (= '/')).reverse with 31 | | [] := (none, "/") 32 | | [a] := (none, a) 33 | | (a :: as) := ("/".intercalate as.reverse, a) 34 | end 35 | 36 | /-- Split a lean path into a project/parent pair -/ 37 | def project_file_split (path : string) : io (option string × string) := 38 | do 39 | (parent, some rest, tt) ← (io.iterate (some path, (none : option string), ff) $ λ state, do { 40 | (some p, old_rest, ff) ← pure state | pure none, 41 | (parent, rest) ← pure (path_split p), 42 | let rest := (match old_rest with 43 | | some r := rest ++ "/" ++ r 44 | | none := rest 45 | end), 46 | some parent ← pure parent | pure (some (parent, old_rest, tt)), 47 | found ← io.fs.file_exists (parent ++ "/leanpkg.toml"), 48 | if !found && "/lib/lean/library".is_suffix_of p then 49 | pure (some (none, some rest, tt)) 50 | else 51 | pure (some (parent, some rest, found)) }), 52 | pure (parent, rest) 53 | 54 | /-- A version of `list.map` for `io` that does not consume the whole stack -/ 55 | def list.mmap_io {α β : Type*} (f : α → io β) (l : list α) : io (list β) := 56 | do 57 | (_, bs) ← io.iterate (l, ([] : list β)) (λ state, do { 58 | (a :: as, bs) ← pure state | return none, 59 | b ← f a, 60 | return (some (as, b :: bs)) 61 | }), 62 | pure bs 63 | 64 | /-- A version of `list.mfoldl` for `io` that does not consume the whole stack -/ 65 | def list.mfoldl_io {s α : Type*} (f : s → α → io s) (x : s) (l : list α) : io s := 66 | prod.snd <$> io.iterate (l, x) (λ state, do { 67 | (a :: as, x) ← pure state | return none, 68 | x' ← f x a, 69 | return (some (as, x')) 70 | }) 71 | 72 | def project_map (α : Type*) := rbmap (with_bot string) α 73 | 74 | meta def main : io unit := 75 | do 76 | let project_urls : project_map string := rbmap.from_list 77 | [ (some "lean-ga", "https://github.com/pygae/lean-ga") 78 | , (some "mathlib", "https://github.com/leanprover-community/mathlib") 79 | --, (⊥, "https://github.com/leanprover-community/lean") 80 | ], 81 | let project_shas : project_map string := rbmap.from_list [ 82 | (⊥, lean.githash) 83 | ], 84 | 85 | infos ← io.run_tactic $ do 86 | { e ← get_env, 87 | e.get_decls.mmap (process_decl e) }, 88 | io.put_str_ln "\\makeatletter", 89 | io.put_str_ln "", 90 | io.put_str_ln "\\newcommand\\@leandef[4]{%", 91 | io.put_str_ln "\\@namedef{lean-ref-proj@#1}{#2}%", 92 | io.put_str_ln "\\@namedef{lean-ref-file@#1}{#3}%", 93 | io.put_str_ln "\\@namedef{lean-ref-line@#1}{#4}%", 94 | io.put_str_ln "}", 95 | io.put_str_ln "", 96 | project_shas ← infos.mfoldl_io (λ (shas : project_map string) (di : option decl_info), do 97 | { some di ← pure di | pure shas, 98 | (some p_dir, file) ← project_file_split di.filename | pure shas, 99 | (_, p) ← pure (path_split p_dir), 100 | -- skip projects without urls 101 | some url ← pure (project_urls.find p) | pure shas, 102 | io.put_str_ln (format!"\\@leandef{{{di.name}}}{{{p}}}{{{file}}}{{{di.line}}}").to_string, 103 | none ← pure (shas.find p) | pure shas, 104 | sha ← io.cmd { cmd := "git", args := ["rev-parse", "HEAD"], cwd := p_dir }, 105 | let sha := sha.pop_back, -- remove trailing newline 106 | pure (shas.insert p sha) }) 107 | project_shas, 108 | 109 | io.put_str_ln "", 110 | project_shas.to_list.mmap_io (λ sha : option string × string, do 111 | some url ← pure (project_urls.find sha.1) | pure (), 112 | some p ← pure sha.1 | pure (), 113 | io.put_str_ln (format!"\\@namedef{{lean-ref-url@{p}}}{{{url}}}").to_string, 114 | io.put_str_ln (format!"\\@namedef{{lean-ref-sha@{p}}}{{{sha.2}}}").to_string), 115 | 116 | io.put_str_ln "", 117 | io.put_str_ln "\\makeatother" 118 | -------------------------------------------------------------------------------- /leanpkg.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lean-ga" 3 | version = "0.1" 4 | lean_version = "leanprover-community/lean:3.51.1" 5 | path = "src" 6 | 7 | [dependencies] 8 | mathlib = {git = "https://github.com/leanprover-community/mathlib", rev = "bf2428c9486c407ca38b5b3fb10b87dad0bc99fa"} 9 | -------------------------------------------------------------------------------- /src/examples/recursors.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2022 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import algebra.ring.basic 7 | import data.int.basic 8 | 9 | /-! 10 | # Recursors in functional programming 11 | 12 | This file contains the examples from section 2 of "Computing with the universal properties of the 13 | Clifford algebra and the even subalgebra". 14 | 15 | While these are not related to GA at all, they are valuable for building intuition for how to think 16 | about `clifford_algebra.lift` and `clifford_algebra.fold`, along with other more complex recursion 17 | schemes. 18 | 19 | Some quick remarks about Lean syntax from those coming from the paper: 20 | 21 | * $f(a, b)$ or $f(a)(b)$ is written `f a b` 22 | * `x ↦ f(x)` is written `λ x, f x`. 23 | -/ 24 | 25 | variables {R : Type*} [semiring R] 26 | 27 | namespace icacga 28 | 29 | def sum : list R → R 30 | | [] := 0 31 | | (a :: l) := a + sum l 32 | 33 | run_cmd guard $ sum [1, 2, 3] = 6 34 | 35 | def accum_from : list R → R → list R 36 | | [] := λ a, [a] 37 | | (b :: l) := λ a, a :: accum_from l (a + b) 38 | 39 | def accum : list R → list R 40 | | l := accum_from l 0 41 | 42 | run_cmd guard $ accum [1, 2, 3] = [0, 1, 3, 6] 43 | 44 | def rev_accum_aux : list R → R × list R 45 | | [] := (0, []) 46 | | (a :: l) := let (b, l') := rev_accum_aux l in (a + b, b :: l') 47 | 48 | def rev_accum : list R → list R 49 | | l := let (b, l') := rev_accum_aux l in b :: l' 50 | 51 | run_cmd guard $ rev_accum [1, 2, 3] = [6, 5, 3, 0] 52 | 53 | end icacga 54 | -------------------------------------------------------------------------------- /src/for_mathlib/README.md: -------------------------------------------------------------------------------- 1 | # Non-GA code to contribute to Mathlib 2 | 3 | This directory contains definitions and lemmas that the authors consider gaps in mathlib. 4 | Each file in this directory corresponds roughly to the location in mathlib where the contribution should go. 5 | Not every file is "mathlib-ready". 6 | -------------------------------------------------------------------------------- /src/for_mathlib/algebra/algebra_operations.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import algebra.algebra.operations 7 | import algebra.algebra.subalgebra.basic 8 | 9 | /-! # Lemmas for `algebra/algebra/operations.lean` -/ 10 | 11 | namespace submodule 12 | 13 | variables {R : Type*} {A : Type*} [comm_semiring R] [semiring A] [algebra R A] 14 | 15 | def one_eq_algebra_of_id_range : (1 : submodule R A) = (algebra.of_id R A).range.to_submodule := 16 | begin 17 | dunfold has_one.one, 18 | ext, 19 | simp [algebra.of_id_apply], 20 | end 21 | 22 | end submodule 23 | -------------------------------------------------------------------------------- /src/for_mathlib/algebra/center_submonoid.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import algebra.algebra.basic 7 | 8 | /-! # Submonoids including the central ring -/ 9 | 10 | namespace algebra 11 | 12 | set_option old_structure_cmd true 13 | 14 | /-- A `center_submonoid` is a submonoid that includes the central ring of the algebra -/ 15 | structure center_submonoid (R : Type*) (A : Type*) [comm_semiring R] [semiring A] [algebra R A] 16 | extends submonoid A, sub_mul_action R A. 17 | 18 | namespace center_submonoid 19 | 20 | variables {R : Type*} {A : Type*} 21 | 22 | section semiring 23 | 24 | variables [comm_semiring R] [semiring A] [algebra R A] (S : center_submonoid R A) 25 | 26 | instance : set_like (center_submonoid R A) A := 27 | { coe := center_submonoid.carrier, 28 | coe_injective' := λ x y h, by { cases x, cases y, congr' } } 29 | 30 | instance : submonoid_class (center_submonoid R A) A := 31 | { one_mem := λ S, S.to_submonoid.one_mem, 32 | mul_mem := λ S _ _, S.to_submonoid.mul_mem, } 33 | 34 | instance : nonempty S.to_sub_mul_action := ⟨⟨1, S.to_submonoid.one_mem⟩⟩ 35 | 36 | instance : zero_mem_class (center_submonoid R A) A := 37 | { zero_mem := λ S, S.to_sub_mul_action.zero_mem ⟨1, S.to_submonoid.one_mem⟩, } 38 | 39 | lemma smul_mem (r : R) {a : A} : a ∈ S → r • a ∈ S := S.to_sub_mul_action.smul_mem r 40 | protected lemma mul_mem {a b : A} : a ∈ S → b ∈ S → a * b ∈ S := S.to_submonoid.mul_mem 41 | protected lemma one_mem : (1 : A) ∈ S := S.to_submonoid.one_mem 42 | protected lemma zero_mem : (0 : A) ∈ S := S.to_sub_mul_action.zero_mem ⟨1, S.one_mem⟩ 43 | 44 | @[simp] lemma algebra_map_mem (r : R) : algebra_map R A r ∈ S := 45 | by { rw algebra_map_eq_smul_one r, exact S.smul_mem r S.one_mem, } 46 | 47 | variables (R) 48 | def closure (s : set A) : center_submonoid R A := 49 | let c := submonoid.closure (set.range (algebra_map R A) ∪ s) in 50 | { smul_mem' := λ r a h, begin 51 | rw algebra.smul_def r a, 52 | exact c.mul_mem (submonoid.subset_closure $ or.inl $ set.mem_range_self r) h 53 | end, ..c} 54 | 55 | @[simp] lemma subset_closure {s : set A} : s ⊆ closure R s := 56 | λ x hx, submonoid.subset_closure $ or.inr hx 57 | 58 | @[simp] lemma closure_to_submonoid {s : set A} : 59 | (closure R s).to_submonoid = submonoid.closure (set.range (algebra_map R A) ∪ s) := 60 | rfl 61 | 62 | variables {R} 63 | 64 | instance : mul_action R S := S.to_sub_mul_action.mul_action 65 | 66 | instance : monoid_with_zero S := 67 | { zero_mul := λ v, subtype.eq $ zero_mul ↑v, 68 | mul_zero := λ v, subtype.eq $ mul_zero ↑v, 69 | ..S.to_sub_mul_action.has_zero, 70 | ..S.to_submonoid.to_monoid } 71 | 72 | instance [nontrivial A] : nontrivial S := 73 | nontrivial_of_ne 0 1 (subtype.ne_of_val_ne zero_ne_one) 74 | 75 | @[simp, norm_cast] lemma coe_zero : ((0 : S) : A) = 0 := rfl 76 | @[simp, norm_cast] lemma coe_smul (k : R) (v : S) : (↑(k • v) : A) = k • v := rfl 77 | 78 | end semiring 79 | 80 | section ring 81 | 82 | variables [comm_ring R] [ring A] [algebra R A] (S : center_submonoid R A) 83 | 84 | @[simp] lemma neg_mem (S : center_submonoid R A) (v : A) : v ∈ S → -v ∈ S := S.to_sub_mul_action.neg_mem 85 | 86 | instance : has_neg (S) := S.to_sub_mul_action.has_neg 87 | 88 | @[simp, norm_cast] lemma coe_neg (v : S) : (↑-v : A) = -v := rfl 89 | 90 | end ring 91 | 92 | end center_submonoid 93 | 94 | end algebra 95 | -------------------------------------------------------------------------------- /src/for_mathlib/algebra/filtration.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import algebra.algebra.operations 7 | 8 | /-! # Filtrations of an `algebra` -/ 9 | 10 | namespace algebra 11 | 12 | /-- A filtration is an indexed family of submodules such that `i ≤ j → S i ≤ S j` and `S i * S j = S (i + j)` -/ 13 | structure filtration (R : Type*) (A : Type*) (ι : Type*) [preorder ι] [has_add ι] [comm_semiring R] [semiring A] [algebra R A] := 14 | (to_fun : ι → submodule R A) 15 | (mono' : monotone to_fun) 16 | (complete' : ∀ x, ∃ i, x ∈ to_fun i) 17 | (map_add' : ∀ n m, to_fun (n + m) = to_fun n * to_fun m) 18 | 19 | namespace filtration 20 | 21 | variables {R : Type*} {A : Type*} {ι : Type*} [preorder ι] [has_add ι] [comm_semiring R] [semiring A] [algebra R A] 22 | 23 | instance : has_coe_to_fun (filtration R A ι) (λ _, ι → submodule R A) := ⟨to_fun⟩ 24 | 25 | variables (f : filtration R A ι) 26 | 27 | -- the normal bundled function tricks, to hide the `to_fun` 28 | @[simp] lemma to_fun_eq_coe : f.to_fun = f := rfl 29 | @[simp] lemma mk_coe (f : ι → submodule R A) (h1 h2 h3) : ⇑(filtration.mk f h1 h2 h3) = f := rfl 30 | lemma mono : monotone f := f.mono' 31 | lemma map_add {n m} : f (n + m) = f n * f m := f.map_add' n m 32 | lemma complete : ∀ x, ∃ i, x ∈ f i := f.complete' 33 | 34 | lemma supr_eq_top (x : A) : supr f = ⊤ := 35 | begin 36 | rw submodule.supr_eq_span, 37 | suffices : (⋃ (i : ι), (f i : set A)) = ⊤, 38 | { simp [this] }, 39 | refine set.eq_univ_of_forall (λ x, _), 40 | simp only [set.mem_Union, set_like.mem_coe], 41 | exact f.complete' x, 42 | end 43 | 44 | end filtration 45 | 46 | end algebra 47 | -------------------------------------------------------------------------------- /src/for_mathlib/algebra/monoid_algebra.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import algebra.monoid_algebra.basic 7 | 8 | /-! # Lemmas for `algebra/monoid_algebra.lean` 9 | 10 | These are part of upstream PR 11 | https://github.com/leanprover-community/mathlib/pull/4321 -/ 12 | 13 | namespace add_monoid_algebra 14 | 15 | variables (k : Type*) {G : Type*} 16 | /-- 17 | The `alg_hom` which maps from a grading of an algebra `A` back to that algebra. 18 | -/ 19 | noncomputable def sum_id {A : Type*} [comm_semiring k] [semiring A] [algebra k A] [add_monoid G] : 20 | add_monoid_algebra A G →ₐ[k] A := 21 | lift_nc_alg_hom (alg_hom.id k A) ⟨λ g, 1, by simp, λ a b, by simp⟩ (by simp) 22 | 23 | lemma sum_id_apply {A : Type*} [comm_semiring k] [semiring A] [algebra k A] [add_monoid G] (g : add_monoid_algebra A G) : 24 | sum_id k g = g.sum (λ _ gi, gi) := 25 | by simp [sum_id, lift_nc_alg_hom, lift_nc_ring_hom, lift_nc, alg_hom.id, ring_hom.id] 26 | 27 | -- `monoid_algebra` is missing some of the `finsupp` API: 28 | 29 | noncomputable def lsingle {k A : Type*} [semiring k] [semiring A] [module k A] (i : G) : A →ₗ[k] add_monoid_algebra A G := 30 | finsupp.lsingle i 31 | 32 | @[simp] lemma lsingle_apply {k A : Type*} [semiring k] [semiring A] [module k A] (i : G) (a : A) : 33 | (lsingle i : _ →ₗ[k] _) a = finsupp.single i a := rfl 34 | 35 | end add_monoid_algebra 36 | -------------------------------------------------------------------------------- /src/for_mathlib/linear_algebra/bilinear_form/tensor_product.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2023 Eric Wieser. All rights reserved. 3 | Released under Apache 2.0 license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import linear_algebra.bilinear_form.tensor_product 7 | import linear_algebra.quadratic_form.basic 8 | import data.is_R_or_C.basic 9 | 10 | universes u v w 11 | variables {ι : Type*} {R : Type*} {M₁ M₂ : Type*} 12 | 13 | open_locale tensor_product 14 | 15 | namespace bilin_form 16 | 17 | section comm_semiring 18 | variables [comm_semiring R] 19 | variables [add_comm_monoid M₁] [add_comm_monoid M₂] 20 | variables [module R M₁] [module R M₂] 21 | 22 | lemma is_symm.tmul {B₁ : bilin_form R M₁} {B₂ : bilin_form R M₂} 23 | (hB₁ : B₁.is_symm) (hB₂ : B₂.is_symm) : (B₁.tmul B₂).is_symm := 24 | suffices (B₁.tmul B₂).to_lin = (B₁.tmul B₂).to_lin.flip, 25 | begin 26 | intros x y, 27 | have := fun_like.congr_fun (fun_like.congr_fun this x) y, 28 | exact this 29 | end, 30 | tensor_product.ext' $ λ x₁ x₂, tensor_product.ext' $ λ y₁ y₂, 31 | (congr_arg2 (*) (hB₁ x₁ y₁) (hB₂ x₂ y₂) : _) 32 | 33 | end comm_semiring 34 | 35 | end bilin_form 36 | 37 | namespace quadratic_form 38 | variables [add_comm_group M₁] [add_comm_group M₂] 39 | variables [module ℝ M₁] [module ℝ M₂] 40 | 41 | lemma _root_.quadratic_form.pos_def.tmul {B₁ : bilin_form ℝ M₁} {B₂ : bilin_form ℝ M₂} 42 | (hB₁ : B₁.to_quadratic_form.pos_def) (hB₂ : B₂.to_quadratic_form.pos_def) : 43 | (B₁.tmul B₂).to_quadratic_form.pos_def := 44 | sorry 45 | 46 | end quadratic_form 47 | -------------------------------------------------------------------------------- /src/for_mathlib/linear_algebra/quadratic_form/isometric_map.lean: -------------------------------------------------------------------------------- 1 | import linear_algebra.quadratic_form.isometry 2 | 3 | /-! # Isometric (semi)linear maps 4 | 5 | Note that `quadratic_form.isometry` is already taken for isometric equivalences. 6 | -/ 7 | set_option old_structure_cmd true 8 | 9 | variables {ι R R₁ R₂ R₃ R₄ M₁ M₂ M₃ M₄ : Type*} 10 | 11 | namespace quadratic_form 12 | 13 | section semilinear 14 | 15 | variables [semiring R₁] [semiring R₂] [semiring R₃] [semiring R₄] 16 | variables [add_comm_monoid M₁] [add_comm_monoid M₂] [add_comm_monoid M₃] [add_comm_monoid M₄] 17 | variables [module R₁ M₁] [module R₂ M₂] [module R₃ M₃] [module R₄ M₄] 18 | 19 | /-- An isometry between two quadratic spaces `M₁, Q₁` and `M₂, Q₂` over a ring `R`, 20 | is a linear equivalence between `M₁` and `M₂` that commutes with the quadratic forms. -/ 21 | @[nolint has_nonempty_instance] structure isometric_map (σ : R₁ →+* R₂) 22 | (Q₁ : quadratic_form R₁ M₁) (Q₂ : quadratic_form R₂ M₂) extends M₁ →ₛₗ[σ] M₂ := 23 | (map_app' : ∀ m, Q₂ (to_fun m) = σ (Q₁ m)) 24 | 25 | 26 | notation Q₁ ` →qₛₗ[`:25 σ:25 `] `:0 Q₂:0 := isometric_map σ Q₁ Q₂ 27 | notation Q₁ ` →qᵢ `:25 Q₂:0 := isometric_map (ring_hom.id _) Q₁ Q₂ 28 | 29 | namespace isometric_map 30 | 31 | 32 | variables {σ₁₂ : R₁ →+* R₂} {σ₂₃ : R₂ →+* R₃} {σ₃₄ : R₃ →+* R₄} 33 | variables {σ₁₃ : R₁ →+* R₃} {σ₂₄ : R₂ →+* R₄} {σ₁₄ : R₁ →+* R₄} 34 | variables {Q₁ : quadratic_form R₁ M₁} {Q₂ : quadratic_form R₂ M₂} 35 | variables {Q₃ : quadratic_form R₃ M₃} {Q₄ : quadratic_form R₄ M₄} 36 | 37 | instance : semilinear_map_class (Q₁ →qₛₗ[σ₁₂] Q₂) σ₁₂ M₁ M₂ := 38 | { coe := λ f, f.to_linear_map, 39 | coe_injective' := λ f g h, by cases f; cases g; congr', 40 | map_add := λ f, f.to_linear_map.map_add, 41 | map_smulₛₗ := λ f, f.to_linear_map.map_smulₛₗ } 42 | 43 | lemma to_linear_map_injective : 44 | function.injective (isometric_map.to_linear_map : (Q₁ →qₛₗ[σ₁₂] Q₂) → (M₁ →ₛₗ[σ₁₂] M₂)) := 45 | λ f g h, fun_like.coe_injective (congr_arg fun_like.coe h : _) 46 | 47 | @[ext] lemma ext ⦃f g : Q₁ →qₛₗ[σ₁₂] Q₂⦄ (h : ∀ x, f x = g x) : f = g := fun_like.ext _ _ h 48 | 49 | /-- See Note [custom simps projection]. -/ 50 | protected def simps.apply (f : Q₁ →qₛₗ[σ₁₂] Q₂) : M₁ → M₂ := f 51 | 52 | initialize_simps_projections isometric_map (to_fun → apply) 53 | 54 | @[simp] lemma map_appₛₗ (f : Q₁ →qₛₗ[σ₁₂] Q₂) (m : M₁) : Q₂ (f m) = σ₁₂ (Q₁ m) := f.map_app' m 55 | 56 | @[simp] lemma coe_to_linear_map (f : Q₁ →qₛₗ[σ₁₂] Q₂) : ⇑f.to_linear_map = f := rfl 57 | 58 | /-- The identity isometry from a quadratic form to itself. -/ 59 | @[simps] 60 | def id (Q : quadratic_form R₁ M₁) : Q →qᵢ Q := 61 | { map_app' := λ m, rfl, 62 | .. linear_map.id } 63 | 64 | /-- The composition of two isometries between quadratic forms. -/ 65 | @[simps] 66 | def comp [ring_hom_comp_triple σ₁₂ σ₂₃ σ₁₃] (g : Q₂ →qₛₗ[σ₂₃] Q₃) (f : Q₁ →qₛₗ[σ₁₂] Q₂) : Q₁ →qₛₗ[σ₁₃] Q₃ := 67 | { to_fun := λ x, g (f x), 68 | map_app' := λ m, 69 | by rw [←@ring_hom_comp_triple.comp_apply _ _ _ _ _ _ σ₁₂ σ₂₃ σ₁₃, ← f.map_appₛₗ, ← g.map_appₛₗ], 70 | .. (g.to_linear_map : M₂ →ₛₗ[σ₂₃] M₃).comp (f.to_linear_map : M₁ →ₛₗ[σ₁₂] M₂) } 71 | 72 | @[simp] lemma to_linear_map_comp [ring_hom_comp_triple σ₁₂ σ₂₃ σ₁₃] (g : Q₂ →qₛₗ[σ₂₃] Q₃) (f : Q₁ →qₛₗ[σ₁₂] Q₂) : 73 | (g.comp f).to_linear_map = g.to_linear_map.comp f.to_linear_map := rfl 74 | 75 | @[simp] lemma id_comp (f : Q₁ →qₛₗ[σ₁₂] Q₂) : (id Q₂).comp f = f := ext $ λ _, rfl 76 | @[simp] lemma comp_id (f : Q₁ →qₛₗ[σ₁₂] Q₂) : f.comp (id Q₁) = f := ext $ λ _, rfl 77 | lemma comp_assoc 78 | [ring_hom_comp_triple σ₁₂ σ₂₃ σ₁₃] [ring_hom_comp_triple σ₂₃ σ₃₄ σ₂₄] 79 | [ring_hom_comp_triple σ₁₂ σ₂₄ σ₁₄] [ring_hom_comp_triple σ₁₃ σ₃₄ σ₁₄] 80 | (h : Q₃ →qₛₗ[σ₃₄] Q₄) (g : Q₂ →qₛₗ[σ₂₃] Q₃) (f : Q₁ →qₛₗ[σ₁₂] Q₂) : 81 | (h.comp g).comp f = h.comp (g.comp f) := ext $ λ _, rfl 82 | 83 | /-- There is a zero map from any module with the zero form. -/ 84 | instance : has_zero ((0 : quadratic_form R₁ M₁) →qₛₗ[σ₁₂] Q₂) := 85 | { zero := 86 | { map_app' := λ m, (map_zero _).trans (_root_.map_zero _).symm, 87 | ..(0 : M₁ →ₛₗ[σ₁₂] M₂) } } 88 | 89 | /-- There is a zero map from the trivial module. -/ 90 | instance has_zero_of_subsingleton [subsingleton M₁] : has_zero (Q₁ →qₛₗ[σ₁₂] Q₂) := 91 | { zero := 92 | { map_app' := λ m, subsingleton.elim 0 m ▸ (map_zero _).trans $ 93 | (_root_.map_zero σ₁₂).symm.trans $ σ₁₂.congr_arg (map_zero _).symm, 94 | ..(0 : M₁ →ₛₗ[σ₁₂] M₂) } } 95 | 96 | /-- Maps into the zero module are trivial -/ 97 | instance [subsingleton M₂] : subsingleton (Q₁ →qₛₗ[σ₁₂] Q₂) := 98 | ⟨λ f g, ext $ λ _, subsingleton.elim _ _⟩ 99 | 100 | end isometric_map 101 | 102 | end semilinear 103 | 104 | section linear 105 | 106 | namespace isometric_map 107 | 108 | variables [semiring R] 109 | variables [add_comm_monoid M₁] [add_comm_monoid M₂] [add_comm_monoid M₃] [add_comm_monoid M₄] 110 | variables [module R M₁] [module R M₂] [module R M₃] [module R M₄] 111 | 112 | variables {Q₁ : quadratic_form R M₁} {Q₂ : quadratic_form R M₂} 113 | 114 | /-- Isometries are isometric maps -/ 115 | @[simps] 116 | def _root_.quadratic_form.isometry.to_isometric_map (g : Q₁.isometry Q₂) : 117 | Q₁ →qᵢ Q₂ := { ..g } 118 | 119 | @[simp] lemma map_app (f : Q₁ →qᵢ Q₂) (m : M₁) : Q₂ (f m) = Q₁ m := f.map_app' m 120 | 121 | end isometric_map 122 | 123 | end linear 124 | 125 | end quadratic_form 126 | -------------------------------------------------------------------------------- /src/for_mathlib/linear_algebra/quadratic_form/prod.lean: -------------------------------------------------------------------------------- 1 | import linear_algebra.quadratic_form.prod 2 | import for_mathlib.linear_algebra.quadratic_form.isometric_map 3 | 4 | /-! # Extra results using `isometric_map` about `quadratic_form`s on product types -/ 5 | 6 | universes u v w 7 | variables {ι : Type*} {R : Type*} {M₁ M₂ N₁ N₂ : Type*} {Mᵢ Nᵢ : ι → Type*} 8 | variables [semiring R] 9 | variables [add_comm_monoid M₁] [add_comm_monoid M₂] [add_comm_monoid N₁] [add_comm_monoid N₂] 10 | variables [module R M₁] [module R M₂] [module R N₁] [module R N₂] 11 | variables [Π i, add_comm_monoid (Mᵢ i)] [Π i, add_comm_monoid (Nᵢ i)] 12 | variables [Π i, module R (Mᵢ i)] [Π i, module R (Nᵢ i)] 13 | 14 | open_locale big_operators 15 | 16 | namespace quadratic_form 17 | 18 | namespace isometric_map 19 | 20 | section prod 21 | variables [fintype ι] (QM₁ : quadratic_form R M₁) (QM₂ : quadratic_form R M₂) 22 | variables (QN₁ : quadratic_form R N₁) (QN₂ : quadratic_form R N₂) 23 | 24 | /-- `linear_map.inl` as an `isometric_map`. -/ 25 | @[simps] def inl [decidable_eq ι] (i : ι) : QM₁ →qᵢ QM₁.prod QM₂ := 26 | { map_app' := λ x, by simp, 27 | .. linear_map.inl R M₁ M₂ } 28 | 29 | /-- `linear_map.inl` as an `isometric_map`. -/ 30 | @[simps] def inr [decidable_eq ι] (i : ι) : QM₂ →qᵢ QM₁.prod QM₂ := 31 | { map_app' := λ x, by simp, 32 | .. linear_map.inr R M₁ M₂ } 33 | 34 | variables {QM₁ QM₂ QN₁ QN₂} 35 | 36 | /-- `pi.prod` of two isometric maps. -/ 37 | @[simps] 38 | def prod {fQM₁ gQM₁ : quadratic_form R M₁} 39 | (f : fQM₁ →qᵢ QN₁) (g : gQM₁ →qᵢ QN₂) : 40 | (fQM₁ + gQM₁) →qᵢ QN₁.prod QN₂ := 41 | { to_fun := pi.prod f g, 42 | map_app' := λ x, congr_arg2 (+) (f.map_app _) (g.map_app _), 43 | .. linear_map.prod f.to_linear_map g.to_linear_map } 44 | 45 | /-- `prod.map` of two isometric maps. -/ 46 | @[simps] 47 | def prod_map (f : QM₁ →qᵢ QN₁) (g : QM₂ →qᵢ QN₂) : 48 | QM₁.prod QM₂ →qᵢ QN₁.prod QN₂ := 49 | { map_app' := λ x, congr_arg2 (+) (f.map_app _) (g.map_app _), 50 | .. linear_map.prod_map f.to_linear_map g.to_linear_map } 51 | 52 | end prod 53 | 54 | section pi 55 | variables [fintype ι] (QM₁ : ι → quadratic_form R M₁) (QMᵢ : Π i, quadratic_form R (Mᵢ i)) 56 | 57 | /-- `linear_map.single` as an `isometric_map`. -/ 58 | @[simps] 59 | def single [decidable_eq ι] (i : ι) : QMᵢ i →qᵢ quadratic_form.pi QMᵢ := 60 | { to_fun := pi.single i, 61 | map_app' := λ x, (pi_apply QMᵢ _).trans $ begin 62 | rw ring_hom.id_apply, 63 | refine (fintype.sum_eq_single i $ λ j hij, _).trans _, 64 | { rw [pi.single_eq_of_ne hij, map_zero] }, 65 | { rw [pi.single_eq_same] } 66 | end, 67 | .. (linear_map.single i : Mᵢ i →ₗ[R] (Π i, Mᵢ i))} 68 | 69 | /-- `linear_map.pi` for `isometric_map`. -/ 70 | def pi (f : Π i, QM₁ i →qᵢ QMᵢ i) : 71 | (∑ i, QM₁ i) →qᵢ quadratic_form.pi QMᵢ := 72 | { to_fun := λ c i, f i c, 73 | map_app' := λ c, (pi_apply QMᵢ _).trans $ 74 | by simp_rw [λ i, (f i).map_app, sum_apply, ring_hom.id_apply], 75 | .. linear_map.pi (λ i, (f i).to_linear_map) } 76 | 77 | end pi 78 | 79 | end isometric_map 80 | 81 | end quadratic_form -------------------------------------------------------------------------------- /src/for_mathlib/linear_algebra/tensor_product/inner_product_space.lean: -------------------------------------------------------------------------------- 1 | import for_mathlib.linear_algebra.bilinear_form.tensor_product 2 | 3 | import analysis.inner_product_space.basic 4 | 5 | variables {V W : Type*} [normed_add_comm_group V] [normed_add_comm_group W] 6 | variables [inner_product_space ℝ V] [inner_product_space ℝ W] 7 | 8 | open_locale tensor_product 9 | 10 | lemma is_symm_bilin_form_of_real_inner : (bilin_form_of_real_inner : bilin_form ℝ V).is_symm := 11 | λ x y, real_inner_comm _ _ 12 | 13 | lemma pos_def_bilin_form_of_real_inner : 14 | (bilin_form_of_real_inner : bilin_form ℝ V).to_quadratic_form.pos_def := 15 | λ x hx, lt_of_le_of_ne' real_inner_self_nonneg (inner_self_ne_zero.mpr hx) 16 | 17 | noncomputable instance : inner_product_space.core ℝ (V ⊗[ℝ] W) := 18 | { inner := λ x y, bilin_form_of_real_inner.tmul bilin_form_of_real_inner x y, 19 | conj_symm := λ x y, 20 | bilin_form.is_symm.tmul is_symm_bilin_form_of_real_inner is_symm_bilin_form_of_real_inner y x, 21 | nonneg_re := λ x, begin 22 | simp only [is_R_or_C.re_to_real], 23 | exact (pos_def_bilin_form_of_real_inner.tmul pos_def_bilin_form_of_real_inner).nonneg _, 24 | end, 25 | definite := λ x hx, 26 | (pos_def_bilin_form_of_real_inner.tmul pos_def_bilin_form_of_real_inner).anisotropic _ hx, 27 | add_left := bilin_form.add_left, 28 | smul_left := λ _ _ _, bilin_form.bilin_smul_left _ _ _ _ } 29 | 30 | noncomputable instance : normed_add_comm_group (V ⊗[ℝ] W) := 31 | @inner_product_space.core.to_normed_add_comm_group ℝ _ _ _ _ _ 32 | 33 | noncomputable instance : inner_product_space ℝ (V ⊗[ℝ] W) := 34 | inner_product_space.of_core _ 35 | 36 | @[simp] lemma tmul_inner_tmul (v₁ : V) (w₁ : W) (v₂ : V) (w₂ : W) : 37 | @inner ℝ _ _ (v₁ ⊗ₜ[ℝ] w₁) (v₂ ⊗ₜ[ℝ] w₂) = inner v₁ v₂ * inner w₁ w₂ := 38 | bilin_form.tensor_distrib_tmul _ _ _ _ _ _ 39 | 40 | @[simp] lemma norm_tmul (v : V) (w : W) : ‖v ⊗ₜ[ℝ] w‖ = ‖v‖ * ‖w‖ := 41 | begin 42 | have := congr_arg real.sqrt (tmul_inner_tmul v w v w), 43 | simp_rw real_inner_self_eq_norm_sq at this, 44 | rw [← mul_pow, real.sqrt_sq (norm_nonneg _), 45 | real.sqrt_sq (mul_nonneg (norm_nonneg _) (norm_nonneg _))] at this, 46 | exact this, 47 | end 48 | 49 | @[simp] lemma nnnorm_tmul (v : V) (w : W) : ‖v ⊗ₜ[ℝ] w‖₊ = ‖v‖₊ * ‖w‖₊ := 50 | nnreal.eq $ norm_tmul _ _ 51 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/basic.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import linear_algebra.clifford_algebra.basic 7 | 8 | variables {R : Type*} [comm_ring R] 9 | variables {M : Type*} [add_comm_group M] [module R M] 10 | variables {Q : quadratic_form R M} 11 | 12 | notation `↑ₐ`:max x:max := algebra_map _ _ x 13 | 14 | namespace clifford_algebra 15 | 16 | -- if this fails then you have the wrong branch of mathlib 17 | example : ring (clifford_algebra Q) := infer_instance 18 | 19 | variables (Q) 20 | abbreviation clifford_hom (A : Type*) [semiring A] [algebra R A] := 21 | { f : M →ₗ[R] A // ∀ m, f m * f m = ↑ₐ(Q m) } 22 | 23 | instance {A : Type*} [ring A] [algebra R A] : 24 | has_zero (clifford_hom (0 : quadratic_form R M) A) := 25 | { zero := ⟨0, λ m, by simp⟩ } 26 | 27 | instance has_zero_of_subsingleton {A : Type*} [ring A] [algebra R A] [subsingleton A] : 28 | has_zero (clifford_hom Q A) := 29 | { zero := ⟨0, λ m, subsingleton.elim _ _⟩ } 30 | 31 | variables {Q} 32 | 33 | /-- TODO: work out what the necessary conditions are here, then make this an instance -/ 34 | example : nontrivial (clifford_algebra Q) := sorry 35 | 36 | /-- A wedge product of n vectors. Note this does not define the wedge product of arbitrary multivectors. -/ 37 | def ι_wedge (n : ℕ) [invertible (n.factorial : R)] : alternating_map R M (clifford_algebra Q) (fin n) := 38 | ⅟(n.factorial : R) • ((multilinear_map.mk_pi_algebra_fin R n _).comp_linear_map (λ i, ι Q)).alternatization 39 | 40 | end clifford_algebra 41 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/category_theory.lean: -------------------------------------------------------------------------------- 1 | import algebra.category.Algebra.basic 2 | import linear_algebra.clifford_algebra.basic 3 | import linear_algebra.exterior_algebra.basic 4 | import geometric_algebra.from_mathlib.basic 5 | import for_mathlib.linear_algebra.quadratic_form.isometric_map 6 | 7 | /-! # Category-theoretic interpretations of `clifford_algebra` 8 | 9 | ## Main definitions 10 | 11 | * `QuadraticModule R`: the category of quadratic modules 12 | * `CliffordAlgebra`: the functor from quadratic modules to algebras 13 | * `Cliff.is_initial_clifford_algebra`: the clifford algebra is initial in the category of pairs 14 | `(A, clifford_hom Q A)`. 15 | 16 | -/ 17 | 18 | open category_theory 19 | open quadratic_form 20 | open clifford_algebra 21 | 22 | instance _root_.alg_hom.has_zero_of_subsingleton (R A B : Type*) 23 | [comm_semiring R] [semiring A] [algebra R A] [semiring B] [algebra R B] [subsingleton A] : 24 | has_zero (B →ₐ[R] A) := 25 | { zero := 26 | { to_fun := 0, 27 | map_one' := subsingleton.elim _ _, 28 | map_mul' := λ _ _, subsingleton.elim _ _, 29 | commutes' := λ _, subsingleton.elim _ _, 30 | ..(0 : B →+ A) } } 31 | 32 | universes v u w 33 | 34 | set_option old_structure_cmd true 35 | 36 | variables (R : Type u) [comm_ring R] 37 | 38 | structure QuadraticModule extends Module.{v} R := 39 | (form' : quadratic_form R carrier) 40 | 41 | 42 | variables {R} 43 | 44 | namespace QuadraticModule 45 | 46 | instance : has_coe_to_sort (QuadraticModule.{v} R) (Type v) := ⟨QuadraticModule.carrier⟩ 47 | 48 | 49 | instance (V : QuadraticModule.{v} R) : add_comm_group V := V.is_add_comm_group 50 | instance (V : QuadraticModule.{v} R) : module R V := V.is_module 51 | 52 | def form (V : QuadraticModule.{v} R) : quadratic_form R V := V.form' 53 | 54 | instance category : category (QuadraticModule.{v} R) := 55 | { hom := λ M N, M.form →qᵢ N.form, 56 | id := λ M, isometric_map.id M.form, 57 | comp := λ A B C f g, g.comp f, 58 | id_comp' := λ X Y, isometric_map.id_comp, 59 | comp_id' := λ X Y, isometric_map.comp_id, 60 | assoc' := λ W X Y Z f g h, isometric_map.comp_assoc h g f } 61 | 62 | lemma comp_def {M N U : QuadraticModule.{v} R} (f : M ⟶ N) (g : N ⟶ U) : 63 | f ≫ g = g.comp f := rfl 64 | 65 | instance concrete_category : concrete_category.{v} (QuadraticModule.{v} R) := 66 | { forget := { obj := λ R, R, map := λ R S f, (f : R → S) }, 67 | forget_faithful := { } } 68 | 69 | instance has_forget_to_Module : has_forget₂ (QuadraticModule R) (Module R) := 70 | { forget₂ := 71 | { obj := λ M, Module.of R M, 72 | map := λ M₁ M₂, isometric_map.to_linear_map } } 73 | 74 | instance (M N : QuadraticModule R) : linear_map_class (M ⟶ N) R M N := 75 | { coe := λ f, f, 76 | .. isometric_map.semilinear_map_class } 77 | 78 | end QuadraticModule 79 | 80 | /-- The "clifford algebra" functor, sending a quadratic `R`-module `V` to the clifford algebra on 81 | `V`. 82 | 83 | This is `clifford_algebra.map` through the lens of category theory. -/ 84 | @[simps] 85 | def CliffordAlgebra : QuadraticModule.{u} R ⥤ Algebra.{u} R := 86 | { obj := λ M, 87 | { carrier := clifford_algebra M.form }, 88 | map := λ M N f, clifford_algebra.map _ _ f.to_linear_map f.map_app, 89 | map_id' := λ X, clifford_algebra.map_id _, 90 | map_comp' := λ M N P f g, (clifford_algebra.map_comp_map _ _ _ _ _ _ _).symm } 91 | 92 | /-- The "exterior algebra" functor, sending an `R`-module `V` to the exterior algebra on `V`. 93 | 94 | In the language of geometric algebra, `(ExteriorAlgebra R).map f` is the outermorphism. -/ 95 | @[simps] 96 | def ExteriorAlgebra : Module.{u} R ⥤ Algebra.{u} R := 97 | { obj := λ M, 98 | { carrier := exterior_algebra R M }, 99 | map := λ M N f, clifford_algebra.map _ _ f (by simp), 100 | map_id' := λ X, clifford_algebra.map_id _, 101 | map_comp' := λ M N P f g, (clifford_algebra.map_comp_map _ _ _ _ _ _ _).symm } 102 | 103 | variables {M : Type w} [add_comm_group M] [module R M] (Q : quadratic_form R M) 104 | 105 | /-- 106 | The category of pairs of algebras and `clifford_hom`s to those algebras. 107 | 108 | https://empg.maths.ed.ac.uk/Activities/Spin/Lecture1.pdf 109 | -/ 110 | structure Cliff := 111 | (alg : Algebra.{v} R) 112 | (hom : clifford_hom Q alg) 113 | 114 | namespace Cliff 115 | 116 | /-- Convert a `clifford_hom Q A` to an element of `Cliff Q`. -/ 117 | def of {A : Type v} [ring A] [algebra R A] (f : clifford_hom Q A) : Cliff.{v} Q := 118 | { alg := Algebra.of R A, hom := f } 119 | 120 | /-- `clifford_algebra Q` as an element of `Cliff Q` -/ 121 | @[reducible] protected def clifford_algebra : Cliff Q := Cliff.of Q ⟨ι Q, ι_sq_scalar Q⟩ 122 | 123 | instance : category (Cliff Q) := 124 | { hom := λ f g, {h : f.alg ⟶ g.alg // (alg_hom.to_linear_map h).comp f.hom.val = g.hom.val }, 125 | id := λ f, ⟨𝟙 _, linear_map.ext $ λ _, rfl⟩, 126 | comp := λ x y z f g, ⟨f.val ≫ g.val, 127 | by simp only [category_struct.comp, alg_hom.comp_to_linear_map, linear_map.comp_assoc, 128 | f.property, g.property]⟩, 129 | id_comp' := λ x y f, subtype.ext $ category.id_comp f, 130 | comp_id' := λ x y f, subtype.ext $ category.comp_id f, 131 | assoc' := λ w x y z f g h, subtype.ext $ category.assoc f g h } 132 | 133 | instance concrete_category : concrete_category.{v} (Cliff.{v} Q) := 134 | { forget := { obj := λ x, x.alg, map := λ x y f, (forget _).map (subtype.val f : _) }, 135 | forget_faithful := { } } 136 | 137 | instance has_forget_to_Algebra : has_forget₂ (Cliff Q) (Algebra R) := 138 | { forget₂ := 139 | { obj := λ x, x.alg, 140 | map := λ x y f, f.val } } 141 | 142 | instance unique_from (Y : Cliff Q) : unique (Cliff.clifford_algebra Q ⟶ Y) := 143 | { default := ⟨clifford_algebra.lift Q Y.hom, let ⟨A, ι, hι⟩ := Y in ι_comp_lift ι hι⟩, 144 | uniq := λ f, subtype.ext begin 145 | obtain ⟨A, ι, hι⟩ := Y, 146 | exact (clifford_algebra.lift_unique _ hι f.val).mp f.prop, 147 | end } 148 | 149 | instance unique_to (X : Cliff Q) {A : Type v} [ring A] [algebra R A] [subsingleton A] 150 | (f : clifford_hom Q A): 151 | unique (X ⟶ Cliff.of Q f) := 152 | { default := ⟨(0 : X.alg →ₐ[R] A), linear_map.ext $ λ x, @subsingleton.elim A _ _ _⟩, 153 | uniq := λ f, subtype.ext $ alg_hom.ext (λ x, @subsingleton.elim A _ _ _) } 154 | 155 | /-- The clifford algebra is the initial object in `Cliff`. -/ 156 | def is_initial_clifford_algebra : limits.is_initial (Cliff.clifford_algebra Q) := 157 | limits.is_initial.of_unique _ 158 | 159 | /-- A trivial algebra is a terminal object in `Cliff`. -/ 160 | def is_terminal_of_subsingleton 161 | {A : Type v} [ring A] [algebra R A] [subsingleton A] : 162 | limits.is_terminal (Cliff.of Q (0 : clifford_hom _ A)) := 163 | limits.is_terminal.of_unique _ 164 | 165 | end Cliff 166 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/concrete/cga.lean: -------------------------------------------------------------------------------- 1 | import linear_algebra.clifford_algebra.basic 2 | import analysis.inner_product_space.basic 3 | import geometric_algebra.from_mathlib.basic 4 | /-! 5 | # Conformal Geometric algebra 6 | 7 | This files defines the conformalized vector space `conformalize V`, and its associated geometric algebra `CGA`. 8 | 9 | A typical usage would use `CGA (euclidean_space ℝ 3)`. 10 | -/ 11 | 12 | -- the real numbers are not computable 13 | noncomputable theory 14 | 15 | variables (V : Type*) [normed_add_comm_group V] [inner_product_space ℝ V] 16 | 17 | /-! ## The conformalized space `conformalize V` -/ 18 | /-- A conformalized vector has additional $n_0$ and $n_\infty$ components -/ 19 | @[derive [add_comm_group, module ℝ]] 20 | def conformalize : Type* := V × ℝ × ℝ 21 | 22 | namespace conformalize 23 | 24 | variables {V} 25 | /-! Linear maps which extract the three components, with `c_` abbreviating 26 | "coefficient of". -/ 27 | def v : conformalize V →ₗ[ℝ] V := linear_map.fst _ _ _ 28 | def c_n0 : conformalize V →ₗ[ℝ] ℝ := (linear_map.fst _ _ _).comp (linear_map.snd _ _ _) 29 | def c_ni : conformalize V →ₗ[ℝ] ℝ := (linear_map.snd _ _ _).comp (linear_map.snd _ _ _) 30 | 31 | /-! The embedding of directions from `V` into `conformalize V`, and the two 32 | basis vectors. -/ 33 | def of_v : V →ₗ[ℝ] conformalize V := linear_map.inl _ _ _ 34 | def n0 : conformalize V := (0, 1, 0) 35 | def ni : conformalize V := (0, 0, 1) 36 | 37 | /-! Lemmas to train the simplifier about trivial compositions of the above. -/ 38 | @[simp] lemma v_of_v (x : V) : (of_v x).v = x := rfl 39 | @[simp] lemma c_n0_of_v (x : V) : (of_v x).c_n0 = 0 := rfl 40 | @[simp] lemma c_ni_of_v (x : V) : (of_v x).c_ni = 0 := rfl 41 | @[simp] lemma v_n0 : (n0 : conformalize V).v = 0 := rfl 42 | @[simp] lemma c_n0_n0 : (n0 : conformalize V).c_n0 = 1 := rfl 43 | @[simp] lemma c_ni_n0 : (n0 : conformalize V).c_ni = 0 := rfl 44 | @[simp] lemma v_ni : (ni : conformalize V).v = 0 := rfl 45 | @[simp] lemma c_n0_ni : (ni : conformalize V).c_n0 = 0 := rfl 46 | @[simp] lemma c_ni_ni : (ni : conformalize V).c_ni = 1 := rfl 47 | 48 | /-- The embedding of points from `V` to `conformalize V`. -/ 49 | def up (x : V) : conformalize V := 50 | n0 + of_v x + (1 / 2 * ‖x‖^2 : ℝ) • ni 51 | 52 | /-! ## The metric on the conformalized space -/ 53 | 54 | /-- The metric is the metric of V plus an extra term about n0 and ni. -/ 55 | def Q : quadratic_form ℝ (conformalize V) := 56 | (bilin_form_of_real_inner.comp v v).to_quadratic_form - (2 : ℝ) • quadratic_form.lin_mul_lin c_n0 c_ni 57 | 58 | /-- Show the definition is what we expect. -/ 59 | @[simp] lemma Q_apply (x : conformalize V) : Q x = ‖x.v‖^2 - 2 * (x.c_n0 * x.c_ni) := 60 | by simp [Q, inner_self_eq_norm_sq_to_K] 61 | 62 | @[simp] lemma Q_up (x : V) : Q (up x) = 0 := 63 | by simp [up, ←mul_assoc] 64 | 65 | /-! Train the simplifier how to act on components -/ 66 | @[simp] lemma Q_polar_n0_of_v (x : V) : quadratic_form.polar Q n0 (of_v x) = 0 := 67 | by simp [quadratic_form.polar] 68 | @[simp] lemma Q_polar_n0_n0 : quadratic_form.polar Q n0 (n0 : conformalize V) = 0 := 69 | by simp [quadratic_form.polar] 70 | @[simp] lemma Q_polar_n0_ni : quadratic_form.polar Q n0 (ni : conformalize V) = -2 := 71 | by simp [quadratic_form.polar] 72 | @[simp] lemma Q_polar_ni_of_v (x : V) : quadratic_form.polar Q ni (of_v x) = 0 := 73 | by simp [quadratic_form.polar] 74 | @[simp] lemma Q_polar_ni_ni : quadratic_form.polar Q ni (n0 : conformalize V) = -2 := 75 | by simp [quadratic_form.polar] 76 | @[simp] lemma Q_polar_ni_n0 : quadratic_form.polar Q ni (ni : conformalize V) = 0 := 77 | by simp [quadratic_form.polar] 78 | @[simp] lemma Q_polar_of_v_ni (x : V) : quadratic_form.polar Q (of_v x) n0 = 0 := 79 | by simp [quadratic_form.polar] 80 | @[simp] lemma Q_polar_of_v_n0 (x : V) : quadratic_form.polar Q (of_v x) ni = 0 := 81 | by simp [quadratic_form.polar] 82 | 83 | -- this one is harder than the rest 84 | @[simp] lemma Q_polar_of_v_of_v (x y : V) : quadratic_form.polar Q (of_v x) (of_v y) = 2 * inner x y := 85 | begin 86 | rw [quadratic_form.polar, Q_apply], 87 | suffices : ‖x + y‖ ^ 2 - ‖x‖ ^ 2 - ‖y‖ ^ 2 = 2 * inner x y, 88 | { simpa using this, }, 89 | simp only [@norm_sq_eq_inner ℝ, is_R_or_C.re_to_real], 90 | rw [inner_add_add_self, ←real_inner_comm y x, two_mul], 91 | abel, 92 | end 93 | 94 | /-- The c_n0 and c_ni terms cancel to give the (negated) distance -/ 95 | @[simp] lemma Q_polar_up (x y : V) : quadratic_form.polar Q (up x) (up y) = -dist x y ^ 2 := 96 | begin 97 | dunfold up, 98 | simp only [dist_eq_norm, @norm_sq_eq_inner ℝ, is_R_or_C.re_to_real, inner_sub_sub_self, ←real_inner_comm y x], 99 | simp [mul_right_comm, two_mul], 100 | abel 101 | end 102 | 103 | /-! ## The geometric algebra over that space -/ 104 | 105 | variables (V) 106 | /-- Define the Conformal Geometric Algebra over `V` . -/ 107 | abbreviation CGA := clifford_algebra (Q : quadratic_form ℝ $ conformalize V) 108 | variables {V} 109 | 110 | open clifford_algebra 111 | 112 | lemma ι_up_mul_ι_up_add_swap (x y : V) : 113 | ι Q (up x) * ι Q (up y) + ι Q (up y) * ι Q (up x) = algebra_map _ _ (-dist x y ^ 2) := 114 | by rw [ι_mul_ι_add_swap, Q_polar_up] 115 | 116 | end conformalize 117 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/concrete/default.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2021 Eric Wieser, Utensil Song. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | 7 | -- this is needed for our doc-gen instance to find these definitions 8 | import linear_algebra.clifford_algebra.equivs 9 | 10 | /-! 11 | # Specific algebras 12 | 13 | This folder contains "concrete" instantiations of algebras of interest. Note that some of 14 | the algebras in this folder have graduated to mathlib, such as: 15 | 16 | * `clifford_algebra_ring.equiv`: any ring is a clifford algebra 17 | * `clifford_algebra_complex.equiv`: the complex numbers are a clifford algebra 18 | * `clifford_algebra_quaternion.equiv`: the complex numbers are a clifford algebra 19 | -/ 20 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/concrete/pga.lean: -------------------------------------------------------------------------------- 1 | import linear_algebra.clifford_algebra.basic 2 | import data.matrix.notation 3 | import data.real.basic 4 | import analysis.inner_product_space.basic 5 | /-! 6 | # Plane-based Geometric algebra 7 | 8 | This files defines the projectivized vector space `projectivize V`, and its associated geometric algebra `CGA`. 9 | 10 | A typical usage would use `PGA (euclidean_space ℝ 3)`. 11 | 12 | This file is underdeveloped compared to one for `conformalize`, but is included as a skeleton of how to proceed. 13 | -/ 14 | 15 | -- the real numbers are not computable 16 | noncomputable theory 17 | 18 | variables (V : Type*) [normed_add_comm_group V] [inner_product_space ℝ V] 19 | 20 | /-- A projectivized vector has additional e0 component -/ 21 | @[derive [add_comm_group, module ℝ]] 22 | def projectivize : Type* := V × ℝ 23 | 24 | namespace projectivize 25 | 26 | variables {V} 27 | /-! Define linear maps to extract the new components -/ 28 | def v : projectivize V →ₗ[ℝ] V := linear_map.fst _ _ _ 29 | def c_n0 : projectivize V →ₗ[ℝ] ℝ := linear_map.snd _ _ _ 30 | 31 | /-! The metric is the metric of V with the n0 term ignored. -/ 32 | def Q : quadratic_form ℝ (projectivize V) := 33 | (bilin_form_of_real_inner.comp v v).to_quadratic_form 34 | 35 | /-- Show the definition is what we expect. -/ 36 | @[simp] lemma Q_apply (x : projectivize V) : Q x = ‖x.v‖^2 := 37 | by simp [Q, inner_self_eq_norm_sq_to_K] 38 | 39 | variables (V) 40 | /-- Define the Plane-based Geometric Algebra over V. -/ 41 | abbreviation PGA := clifford_algebra (Q : quadratic_form ℝ $ projectivize V) 42 | 43 | /-- And the embedding of the vector space into it. 44 | Note that often the dual of this result is used instead, but we do not have that in our 45 | formalization yet! -/ 46 | def up (x : V) : PGA V := 47 | clifford_algebra.ι _ (x, 1) 48 | 49 | end projectivize 50 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/conjugation.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import geometric_algebra.from_mathlib.basic 7 | import linear_algebra.clifford_algebra.conjugation 8 | import algebra.module.opposites 9 | 10 | variables {R : Type*} [comm_ring R] 11 | variables {M : Type*} [add_comm_group M] [module R M] 12 | variables {Q : quadratic_form R M} 13 | /-! 14 | # Conjugations 15 | 16 | This file contains additional lemmas about `clifford_algebra.reverse` and `clifford_algebra.involute`. 17 | 18 | As more and more goes into Mathlib, this file will become smaller and spaller. 19 | The links above will take you to the collection of mathlib theorems. 20 | -/ 21 | 22 | namespace clifford_algebra 23 | 24 | section reverse 25 | open mul_opposite 26 | 27 | /-- helper lemma for expanding the sign of reverse -/ 28 | lemma reverse_prod_sign_aux (n : ℕ) : 29 | (-1 : R)^((n + 1)*(n + 1 + 1)/2) = (-1 : R)^(n*(n + 1)/2) * (-1 : R)^(n + 1) := 30 | begin 31 | -- work with just the exponents 32 | rw ←pow_add, 33 | conv_rhs { rw neg_one_pow_eq_pow_mod_two }, 34 | conv_lhs { rw neg_one_pow_eq_pow_mod_two }, 35 | congr' 1, 36 | -- work through the ugly nat proof 37 | rw [add_mul, one_mul, mul_add _ (n + 1), mul_one, add_assoc, add_assoc n 1 1, ←add_assoc n n, ←mul_two, ←mul_two], 38 | have : 0 < 2 := by linarith, 39 | rw [nat.add_div_eq_of_add_mod_lt _, nat.add_div_eq_of_add_mod_lt _, nat.mul_div_cancel _ this, nat.mul_div_cancel _ this], 40 | -- extra goals created by `add_div_eq_of_add_mod_lt` 41 | { rw [nat.mul_mod_left, nat.mul_mod_left, zero_add], 42 | exact this }, 43 | { rw [nat.add_mod (n * 2), nat.mul_mod_left, nat.mul_mod_left, add_zero, nat.zero_mod, add_zero], 44 | exact nat.mod_lt _ this }, 45 | end 46 | 47 | /-- TODO: this needs an assumption that the vectors are othogonal -/ 48 | lemma reverse_prod_map_sign (l : list M): 49 | reverse (l.map $ ι Q).prod = ((-1 : R)^(l.length*(l.length + 1)/2)) • (l.map $ ι Q).prod := 50 | begin 51 | induction l with x xs hxs, 52 | { simp }, 53 | simp [hxs, reverse_prod_sign_aux, mul_smul], 54 | congr, 55 | sorry, -- this needs to be an assumption 56 | end 57 | 58 | end reverse 59 | 60 | end clifford_algebra 61 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/contract.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2022 Eric Wieser. All rights reserved. 3 | Released under Apache 2.0 license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | 7 | import geometric_algebra.from_mathlib.fold 8 | import linear_algebra.clifford_algebra.grading 9 | import linear_algebra.clifford_algebra.conjugation 10 | import linear_algebra.clifford_algebra.contraction 11 | import linear_algebra.exterior_algebra.basic 12 | 13 | /-! 14 | # Contraction in Clifford Algebras 15 | 16 | Most of the results are now 17 | [upstream in `linear_algebra.clifford_algebra.contraction`](https://leanprover-community.github.io/mathlib_docs/linear_algebra/clifford_algebra/contraction.html) 18 | as of https://github.com/leanprover-community/mathlib/pull/11468. 19 | -/ 20 | 21 | universes u1 u2 u3 22 | 23 | variables {R : Type u1} [comm_ring R] 24 | variables {M : Type u2} [add_comm_group M] [module R M] 25 | variables (Q : quadratic_form R M) 26 | 27 | namespace clifford_algebra 28 | 29 | variables (d d' : module.dual R M) 30 | 31 | local infix `⌋`:70 := contract_left 32 | 33 | variables {Q} 34 | 35 | variables {Q' Q'' : quadratic_form R M} {B B' : bilin_form R M} 36 | variables (h : B.to_quadratic_form = Q' - Q) (h' : B'.to_quadratic_form = Q'' - Q') 37 | 38 | /-- Theorem 24 -/ 39 | lemma change_form_reverse (d : module.dual R M) (x : clifford_algebra Q) : 40 | change_form h (reverse x) = reverse (change_form h x) := 41 | begin 42 | apply clifford_algebra.left_induction _ (λ r, _) (λ x y hx hy, _) (λ x m hx, _) x, 43 | { simp_rw [change_form_algebra_map, reverse.commutes, change_form_algebra_map] }, 44 | { rw [map_add, map_add, map_add, map_add, hx, hy] }, 45 | { simp_rw [reverse.map_mul, change_form_ι_mul, map_sub, reverse.map_mul, reverse_ι], 46 | rw ←hx, 47 | rw ←change_form_contract_left, 48 | sorry } 49 | end 50 | 51 | variables {Q} 52 | 53 | /-- The wedge product of the clifford algebra. -/ 54 | def wedge [invertible (2 : R)] (x y : clifford_algebra Q) : clifford_algebra Q := 55 | (equiv_exterior Q).symm (equiv_exterior Q x * equiv_exterior Q y) 56 | 57 | infix (name := clifford_algebra.wedge) ` ⋏ `:70 := wedge 58 | 59 | end clifford_algebra 60 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/default.lean: -------------------------------------------------------------------------------- 1 | import .basic 2 | import .conjugation 3 | /-! 4 | # Tools built on top of Mathlib's `linear_algebra.clifford_algebra` 5 | 6 | Many things here may become "generalized out" as mathlib grows, or end up being PR'd upstream 7 | -/ -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/even_odd.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | 7 | import linear_algebra.clifford_algebra.even 8 | /-! 9 | # The universal property of the even subalgebra 10 | 11 | This file is now a stub, as the results are now available upstream in 12 | [`linear_algebra/clifford_algebra/even`](https://leanprover-community.github.io/mathlib_docs/linear_algebra/clifford_algebra/even.html) 13 | -/ 14 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/even_odd_equiv.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | 7 | import linear_algebra.clifford_algebra.even_equiv 8 | /-! 9 | # The isomorphism with the even subalgebra 10 | 11 | This file is now a stub, as the results are now available upstream in 12 | [`linear_algebra/clifford_algebra/even_equiv`](https://leanprover-community.github.io/mathlib_docs/linear_algebra/clifford_algebra/even_equiv.html) 13 | -/ 14 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/fold.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2022 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import linear_algebra.clifford_algebra.fold 7 | import linear_algebra.bilinear_form 8 | import linear_algebra.tensor_product 9 | import linear_algebra.prod 10 | import linear_algebra.clifford_algebra.grading 11 | 12 | /-! 13 | # Recursive computation rules 14 | 15 | ## Main definitions 16 | 17 | * `clifford_algebra.foldr'`: a computation rule for building linear maps out of the clifford 18 | algebra. 19 | 20 | -/ 21 | 22 | universes u1 u2 u3 23 | 24 | variables {R : Type u1} [comm_ring R] 25 | variables {M : Type u2} [add_comm_group M] [module R M] 26 | variables {N : Type u3} [add_comm_group N] [module R N] 27 | variables (Q : quadratic_form R M) 28 | 29 | namespace clifford_algebra 30 | 31 | -- lemma foldr'_mul_ι (f : M →ₗ[R] clifford_algebra Q × N →ₗ[R] N) 32 | -- (hf : ∀ m x fx, f m (ι Q m * x, f m (x, fx)) = Q m • fx) (n m) (x) : 33 | -- foldr' Q f hf n (x * ι Q m) = foldr' Q f hf (f m (1, n)) x := 34 | -- begin 35 | -- dsimp [foldr'], 36 | -- rw [foldr_mul, foldr_ι, foldr'_aux_apply_apply], 37 | -- dsimp only, 38 | -- rw mul_one, 39 | -- refine congr_arg (f m) (prod.mk.eta.symm.trans _), 40 | -- congr' 1, 41 | -- apply clifford_algebra.foldr_induction _ (λ r, _) (λ x y hx hy, _) (λ m x hx, _) x, 42 | -- { simp_rw [foldr_algebra_map, prod.smul_mk, algebra.algebra_map_eq_smul_one] }, 43 | -- { rw [map_add, prod.fst_add, hx, hy] }, 44 | -- { rw [foldr_mul, foldr_ι, foldr'_aux_apply_apply, hx], }, 45 | -- end 46 | -- lemma foldr'_add 47 | -- (f g : M →ₗ[R] clifford_algebra Q × N →ₗ[R] N) 48 | -- (hfg : ∀ m x fgx, (f + g) m (ι Q m * x, (f + g) m (x, fgx)) = Q m • fgx) 49 | -- (hf : ∀ m x fx, f m (ι Q m * x, f m (x, fx)) = Q m • fx) 50 | -- (hg : ∀ m x gx, g m (ι Q m * x, g m (x, gx)) = Q m • gx) : 51 | -- foldr' Q (f + g) hfg 0 = foldr' Q f hf 0 + foldr' Q g hg 0 := 52 | -- begin 53 | -- ext x, 54 | -- rw linear_map.add_apply, 55 | -- apply clifford_algebra.foldr_induction _ (λ r, _) (λ x y hx hy, _) (λ m x hx, _) x, 56 | -- { simp_rw [foldr'_algebra_map, smul_zero, zero_add] }, 57 | -- { rw [map_add, map_add, map_add, add_add_add_comm, hx, hy] }, 58 | -- { simp_rw [foldr'_ι_mul], 59 | -- rw [hx], 60 | -- rw hx,}, 61 | -- end 62 | 63 | -- lemma foldr'_smul (c : R) 64 | -- (f : M →ₗ[R] clifford_algebra Q × N →ₗ[R] N) 65 | -- (hfg : ∀ m x fcx, (c • f) m (ι Q m * x, (c • f) m (x, fcx)) = Q m • fcx) 66 | -- (hf : ∀ m x fx, f m (ι Q m * x, f m (x, fx)) = Q m • fx) : 67 | -- foldr' Q (c • f) hfg 0 = c • foldr' Q f hf 0 := 68 | -- begin 69 | -- ext x, 70 | -- rw linear_map.smul_apply, 71 | -- apply clifford_algebra.foldr_induction _ (λ r, _) (λ x y hx hy, _) (λ m x hx, _) x, 72 | -- { simp_rw [foldr'_algebra_map, smul_zero] }, 73 | -- { rw [map_add, map_add,smul_add, hx, hy] }, 74 | -- { simp_rw [foldr'_ι_mul, line], 75 | -- rw [hx], 76 | -- rw hx,}, 77 | -- end 78 | 79 | end clifford_algebra 80 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/mathoverflow.lean: -------------------------------------------------------------------------------- 1 | import data.mv_polynomial.comm_ring 2 | import linear_algebra.finsupp 3 | import linear_algebra.clifford_algebra.basic 4 | import data.zmod.basic 5 | import data.matrix.notation 6 | import field_theory.mv_polynomial 7 | import tactic.induction 8 | import algebra.char_p.quotient 9 | import data.nat.prime 10 | import algebra.char_p.pi 11 | import algebra.char_p.two 12 | import ring_theory.mv_polynomial.ideal 13 | import ring_theory.mv_polynomial.basic 14 | import algebra.char_p.algebra 15 | import tactic.norm_fin 16 | /-! 17 | A formalization of https://mathoverflow.net/questions/60596/clifford-pbw-theorem-for-quadratic-form/87958#87958 18 | 19 | Some Zulip discussion at https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/.F0.9D.94.BD.E2.82.82.5B.CE.B1.2C.20.CE.B2.2C.20.CE.B3.5D.20.2F.20.28.CE.B1.C2.B2.2C.20.CE.B2.C2.B2.2C.20.CE.B3.C2.B2.29/near/222716333. 20 | -/ 21 | 22 | noncomputable theory 23 | 24 | open_locale big_operators 25 | 26 | section for_mathlib 27 | 28 | lemma ideal.comap_span_le {R : Type*} {S : Type*} [semiring R] [semiring S] (f : S →+* R) 29 | (g : R →+* S) (h : function.left_inverse g f) (s : set R) : 30 | ideal.comap f (ideal.span s) ≤ ideal.span (g '' s) := 31 | begin 32 | rintros x (hx : f x ∈ ideal.span s), 33 | have := ideal.apply_coe_mem_map g _ ⟨_, hx⟩, 34 | rw [ideal.map_span, subtype.coe_mk, h x] at this, 35 | exact this, 36 | end 37 | 38 | /-- `char_p.quotient'` as an `iff`. -/ 39 | lemma char_p.quotient_iff' (R : Type*) [comm_ring R] (n : ℕ) [char_p R n] (I : ideal R) : 40 | char_p (R ⧸ I) n ↔ ∀ x : ℕ, ↑x ∈ I → (x : R) = 0 := 41 | begin 42 | refine ⟨λ (i : char_p (R ⧸ I) n) x hx, _, char_p.quotient' n I⟩, 43 | resetI, 44 | have := char_p.cast_eq_zero_iff (R ⧸ I) n, 45 | rw char_p.cast_eq_zero_iff R n, 46 | refine (this _).mp _, 47 | exact (submodule.quotient.mk_eq_zero I).mpr hx, 48 | end 49 | 50 | lemma ideal.span_le_bot {R : Type*} [semiring R] (s : set R) : ideal.span s ≤ ⊥ ↔ s ≤ {0} := 51 | submodule.span_le 52 | 53 | /-- `char_p.quotient'` as an `iff`. -/ 54 | lemma char_p.quotient_iff'' (R : Type*) [comm_ring R] (n : ℕ) [char_p R n] (I : ideal R) : 55 | char_p (R ⧸ I) n ↔ I.comap (nat.cast_ring_hom R) ≤ (nat.cast_ring_hom R).ker := 56 | (char_p.quotient_iff' _ _ _).trans begin 57 | rw ring_hom.ker_eq_comap_bot, 58 | exact iff.rfl, 59 | end 60 | 61 | lemma finsupp.equiv_fun_on_finite_const {α β} [fintype α] [add_comm_monoid β] (b : β): 62 | finsupp.equiv_fun_on_finite.symm (λ _, b : α → β) = ∑ i : α, finsupp.single i b := 63 | by { ext, simp [finsupp.finset_sum_apply] } 64 | 65 | -- note; more general than `mv_polynomial.support_smul` 66 | lemma _root_.mv_polynomial.support_smul' {S R σ} [comm_semiring R] [monoid S] [distrib_mul_action S R] 67 | {r : S} {p : mv_polynomial σ R} : 68 | (r • p).support ⊆ p.support := finsupp.support_smul 69 | 70 | lemma finsupp.to_multiset_sup {α} [decidable_eq α] (f g : α →₀ ℕ) : 71 | (f ⊔ g).to_multiset = f.to_multiset ∪ g.to_multiset := 72 | begin 73 | ext, 74 | simp_rw [multiset.count_union, finsupp.count_to_multiset, finsupp.sup_apply, sup_eq_max], 75 | end 76 | 77 | lemma finsupp.to_multiset_inf {α} [decidable_eq α] (f g : α →₀ ℕ) : 78 | (f ⊓ g).to_multiset = f.to_multiset ∩ g.to_multiset := 79 | begin 80 | ext, 81 | simp_rw [multiset.count_inter, finsupp.count_to_multiset, finsupp.inf_apply, inf_eq_min], 82 | end 83 | 84 | /-- `equiv.ulift` as a `linear_equiv`. -/ 85 | @[simps] 86 | def {w u v} linear_equiv.ulift 87 | (R : Type u) (M : Type v) [semiring R] [add_comm_monoid M] [module R M]: ulift.{w} M ≃ₗ[R] M := 88 | { map_add' := λ x y, rfl, 89 | map_smul' := λ c x, rfl, 90 | .. equiv.ulift } 91 | 92 | lemma ideal.mem_span_range_iff_exists_fun {ι R} [fintype ι] [comm_semiring R] (g : ι → R) (x : R) : 93 | x ∈ ideal.span (set.range g) ↔ ∃ f : ι → R, ∑ i, f i * g i = x := 94 | mem_span_range_iff_exists_fun _ 95 | 96 | end for_mathlib 97 | 98 | namespace q60596 99 | 100 | open mv_polynomial 101 | 102 | /-- The monomial ideal generated by terms of the form $x_ix_i$. -/ 103 | def k_ideal : ideal (mv_polynomial (fin 3) (zmod 2)) := 104 | ideal.span (set.range (λ i, (X i * X i : mv_polynomial (fin 3) (zmod 2)))) 105 | 106 | lemma mem_k_ideal_iff (x : mv_polynomial (fin 3) (zmod 2)) : 107 | x ∈ k_ideal ↔ ∀ (m : fin 3 →₀ ℕ), m ∈ x.support → ∃ i, 2 ≤ m i := 108 | begin 109 | have : k_ideal = 110 | ideal.span ((λ i, monomial i (1 : zmod 2)) '' set.range (λ i, finsupp.single i 2)), 111 | { simp_rw [k_ideal, X, monomial_mul, one_mul, ←finsupp.single_add, ←set.range_comp] }, 112 | rw [this, mem_ideal_span_monomial_image], 113 | simp, 114 | end 115 | 116 | lemma X0_X1_X2_nmem_k_ideal : (X 0 * X 1 * X 2 : mv_polynomial (fin 3) (zmod 2)) ∉ k_ideal := 117 | begin 118 | intro h, 119 | simp_rw [mem_k_ideal_iff, support_mul_X, support_X, finset.map_singleton, 120 | add_right_embedding_apply, finset.mem_singleton, forall_eq, 121 | ←fin.sum_univ_three (λ i, finsupp.single i 1), ←finsupp.equiv_fun_on_finite_const, 122 | finsupp.equiv_fun_on_finite_symm_apply_to_fun] at h, 123 | obtain ⟨i, hi⟩ := h, 124 | revert hi, 125 | dec_trivial, 126 | end 127 | 128 | lemma mul_self_mem_k_ideal_of_X0_X1_X2_mul_mem {x : mv_polynomial (fin 3) (zmod 2)} 129 | (h : X 0 * X 1 * X 2 * x ∈ k_ideal) : x * x ∈ k_ideal := 130 | begin 131 | rw mem_k_ideal_iff at h, 132 | have : x ∈ ideal.span ((X : fin 3 → mv_polynomial _ (zmod 2)) '' set.univ), 133 | { rw [mem_ideal_span_X_image], 134 | intros m hm, 135 | simp_rw [mul_assoc, support_X_mul, finset.map_map, finset.mem_map, 136 | function.embedding.trans_apply, add_left_embedding_apply, exists_prop, 137 | forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, ←add_assoc, 138 | ←fin.sum_univ_three (λ i, finsupp.single i 1), ←finsupp.equiv_fun_on_finite_const, 139 | finsupp.add_apply, finsupp.equiv_fun_on_finite_symm_apply_to_fun] at h, 140 | refine (h _ hm).imp (λ i hi, ⟨set.mem_univ _, _⟩), 141 | rintro hmi, 142 | rw hmi at hi, 143 | cases nat.le_of_add_le_add_left hi }, 144 | rw [as_sum x, char_two.sum_mul_self], 145 | refine sum_mem (λ m hm, _), 146 | rw [mem_k_ideal_iff, monomial_mul], 147 | intros m' hm', 148 | obtain rfl := finset.mem_singleton.1 (support_monomial_subset hm'), 149 | rw mem_ideal_span_X_image at this, 150 | obtain ⟨i, _, hi⟩ := this m hm, 151 | refine ⟨i, nat.add_le_add _ _⟩; rwa nat.one_le_iff_ne_zero, 152 | end 153 | 154 | -- 𝔽₂[α, β, γ] / (α², β², γ²) 155 | @[derive [comm_ring, comm_semiring, ring, semiring, add_comm_group, add_comm_monoid]] 156 | def k := _ ⧸ k_ideal 157 | 158 | lemma comap_C_span_le_bot : 159 | k_ideal.comap (C : zmod 2 →+* (mv_polynomial (fin 3) (zmod 2))) ≤ ⊥ := 160 | begin 161 | refine (ideal.comap_span_le _ _ (constant_coeff_C _) _).trans _, 162 | refine (ideal.span_le_bot _).2 _, 163 | rintro x ⟨_, ⟨i, rfl⟩, rfl⟩, 164 | rw [ring_hom.map_mul, constant_coeff_X, mul_zero, set.mem_singleton_iff], 165 | end 166 | 167 | /-- `k` has characteristic 2. -/ 168 | instance k.char_p : char_p k 2 := 169 | begin 170 | dunfold k, 171 | rw char_p.quotient_iff'', 172 | have : (nat.cast_ring_hom (mv_polynomial (fin 3) (zmod 2))) = C.comp (nat.cast_ring_hom _), 173 | { ext1 r, refl }, 174 | rw [this, ←ideal.comap_comap, ←ring_hom.comap_ker], 175 | exact ideal.comap_mono (comap_C_span_le_bot.trans bot_le), 176 | end 177 | 178 | abbreviation α : k := ideal.quotient.mk _ (mv_polynomial.X 0) 179 | abbreviation β : k := ideal.quotient.mk _ (mv_polynomial.X 1) 180 | abbreviation γ : k := ideal.quotient.mk _ (mv_polynomial.X 2) 181 | 182 | /-- The elements above square to zero -/ 183 | @[simp] lemma X_sq (i : fin 3) : 184 | ideal.quotient.mk _ (mv_polynomial.X i) * ideal.quotient.mk _ (mv_polynomial.X i) = (0 : k) := 185 | begin 186 | change ideal.quotient.mk _ _ = _, 187 | rw [ideal.quotient.eq_zero_iff_mem], 188 | exact ideal.subset_span ⟨i, rfl⟩, 189 | end 190 | 191 | /-- If an element multiplied by `αβγ` is zero then it squares to zero. -/ 192 | lemma sq_zero_of_αβγ_mul {x : k} : α * β * γ * x = 0 → x * x = 0 := 193 | begin 194 | induction x using quotient.induction_on', 195 | change ideal.quotient.mk _ _ = 0 → ideal.quotient.mk _ _ = 0, 196 | rw [ideal.quotient.eq_zero_iff_mem, ideal.quotient.eq_zero_iff_mem], 197 | exact mul_self_mem_k_ideal_of_X0_X1_X2_mul_mem, 198 | end 199 | 200 | /-- Though `αβγ` is not itself zero-/ 201 | lemma αβγ_ne_zero : α * β * γ ≠ 0 := 202 | λ h, X0_X1_X2_nmem_k_ideal $ ideal.quotient.eq_zero_iff_mem.1 h 203 | 204 | @[simps] 205 | def L_func : (fin 3 → k) →ₗ[k] k := 206 | α • linear_map.proj 0 - β • linear_map.proj 1 - γ • linear_map.proj 2 207 | 208 | /-- The quotient of k^3 by the specified relation-/ 209 | @[derive [add_comm_group, module k]] 210 | def L := _ ⧸ L_func.ker 211 | 212 | def sq {ι R : Type*} [comm_ring R] (i : ι) : quadratic_form R (ι → R) := 213 | quadratic_form.sq.comp $ linear_map.proj i 214 | 215 | lemma sq_map_add_char_two {ι R : Type*} [comm_ring R] [char_p R 2] (i : ι) (a b : ι → R) : 216 | sq i (a + b) = sq i a + sq i b := 217 | char_two.add_mul_self _ _ 218 | 219 | lemma sq_map_sub_char_two {ι R : Type*} [comm_ring R] [char_p R 2] (i : ι) (a b : ι → R) : 220 | sq i (a - b) = sq i a - sq i b := 221 | begin 222 | haveI : nonempty ι := ⟨i⟩, 223 | rw [char_two.sub_eq_add, char_two.sub_eq_add, sq_map_add_char_two] 224 | end 225 | 226 | open_locale big_operators 227 | 228 | /-- The quadratic form (metric) is just euclidean -/ 229 | def Q' : quadratic_form k (fin 3 → k) := 230 | ∑ i, sq i 231 | 232 | def Q'_add (x y : fin 3 → k) : Q' (x + y) = Q' x + Q' y := 233 | by simp only [Q', quadratic_form.sum_apply, sq_map_add_char_two, finset.sum_add_distrib] 234 | 235 | def Q'_sub (x y : fin 3 → k) : Q' (x - y) = Q' x - Q' y := 236 | by simp only [Q', quadratic_form.sum_apply, sq_map_sub_char_two, finset.sum_sub_distrib] 237 | 238 | lemma Q'_apply (a : fin 3 → k) : Q' a = a 0 * a 0 + a 1 * a 1 + a 2 * a 2 := 239 | calc Q' a = a 0 * a 0 + (a 1 * a 1 + (a 2 * a 2 + 0)) : rfl 240 | ... = _ : by ring 241 | 242 | lemma Q'_apply_single (i : fin 3) (x : k) : Q' (pi.single i x) = x * x := 243 | calc Q' (pi.single i x) 244 | = ∑ j : fin 3, (pi.single i x * pi.single i x : fin 3 → k) j : by simp [Q', sq] 245 | ... = _ : by simp_rw [←pi.single_mul, finset.sum_pi_single', finset.mem_univ, if_pos] 246 | 247 | lemma Q'_zero_under_ideal (v : fin 3 → k) (hv : v ∈ L_func.ker) : Q' v = 0 := 248 | begin 249 | rw [linear_map.mem_ker, L_func_apply] at hv, 250 | have h0 : α * β * γ * v 0 = 0, 251 | { have := congr_arg ((*) (β * γ)) hv, 252 | simp only [mul_zero, mul_add, ←mul_assoc] at this, 253 | rw [mul_comm (β * γ) α, ←mul_assoc, mul_right_comm β γ β, mul_assoc β γ γ, X_sq, X_sq] at this, 254 | simpa only [mul_zero, zero_mul, add_zero, zero_add] using this }, 255 | have h1 : α * β * γ * v 1 = 0, 256 | { have := congr_arg ((*) (α * γ)) hv, 257 | simp only [mul_zero, mul_add, ←mul_assoc] at this, 258 | rw [mul_right_comm α γ α, mul_assoc α γ γ, mul_right_comm α γ β, X_sq, X_sq] at this, 259 | simpa only [mul_zero, zero_mul, add_zero, zero_add] using this }, 260 | have h2 : α * β * γ * v 2 = 0, 261 | { have := congr_arg ((*) (α * β)) hv, 262 | simp only [mul_zero, mul_add, ←mul_assoc] at this, 263 | rw [mul_right_comm α β α, mul_assoc α β β, X_sq, X_sq] at this, 264 | simpa only [mul_zero, zero_mul, add_zero, zero_add] using this }, 265 | rw [Q'_apply, sq_zero_of_αβγ_mul h0, sq_zero_of_αβγ_mul h1, sq_zero_of_αβγ_mul h2, 266 | add_zero, add_zero], 267 | end 268 | 269 | /-- `Q'`, lifted to operate on the quotient space `L`. -/ 270 | @[simps] 271 | def Q : quadratic_form k L := 272 | quadratic_form.of_polar 273 | (λ x, quotient.lift_on' x Q' $ λ a b h, begin 274 | rw submodule.quotient_rel_r_def at h, 275 | suffices : Q' (a - b) = 0, 276 | { rwa [Q'_sub, sub_eq_zero] at this, }, 277 | apply Q'_zero_under_ideal (a - b) h, 278 | end) 279 | (λ a x, begin 280 | induction x using quotient.induction_on, 281 | exact Q'.to_fun_smul a x, 282 | end) 283 | (by { rintros ⟨x⟩ ⟨x'⟩ ⟨y⟩, exact Q'.polar_add_left x x' y }) 284 | (by { rintros c ⟨x⟩ ⟨y⟩, exact Q'.polar_smul_left c x y }) 285 | 286 | open clifford_algebra 287 | 288 | /-! Shorthand for basis vectors in the Clifford algebra -/ 289 | abbreviation x' : clifford_algebra Q := ι Q $ submodule.quotient.mk (pi.single 0 1) 290 | abbreviation y' : clifford_algebra Q := ι Q $ submodule.quotient.mk (pi.single 1 1) 291 | abbreviation z' : clifford_algebra Q := ι Q $ submodule.quotient.mk (pi.single 2 1) 292 | 293 | /-- The basis vectors square to one -/ 294 | @[simp] lemma x_mul_x : x' * x' = 1 := 295 | begin 296 | dunfold x', 297 | simp_rw [clifford_algebra.ι_sq_scalar, Q_apply, ←submodule.quotient.mk'_eq_mk, 298 | quotient.lift_on'_mk', Q'_apply_single, mul_one, map_one], 299 | end 300 | 301 | /-- By virtue of the quotient, terms of this form are zero -/ 302 | lemma quot_obv : α • x' - β • y' - γ • z' = 0 := 303 | begin 304 | dunfold x' y' z', 305 | simp only [←linear_map.map_smul, ←linear_map.map_sub, ←submodule.quotient.mk_smul, 306 | ←submodule.quotient.mk_sub], 307 | convert linear_map.map_zero _ using 2, 308 | rw submodule.quotient.mk_eq_zero, 309 | norm_num [sub_zero, ideal.span, pi.single_apply], 310 | end 311 | 312 | /-- The core of the proof - scaling `1` by `α * β * γ` gives zero -/ 313 | lemma αβγ_smul_eq_zero : (α * β * γ) • (1 : clifford_algebra Q) = 0 := 314 | begin 315 | suffices : α • 1 - β • (y' * x') - γ • (z' * x') = 0, 316 | { have := congr_arg (λ x, (β * γ) • x) this, 317 | simpa [smul_sub, smul_smul, mul_assoc β γ γ, mul_right_comm β γ β, mul_right_comm β γ α, 318 | mul_comm β α] using this }, 319 | have : (α • x' - β • y' - γ • z') * x' = α • 1 - β • (y' * x') - γ • (z' * x'), 320 | { simp [sub_mul], }, 321 | rw ← this, 322 | rw [quot_obv, zero_mul], 323 | end 324 | 325 | /-- Our final result -/ 326 | lemma algebra_map_not_injective : ¬function.injective (algebra_map k $ clifford_algebra Q) := 327 | λ h, αβγ_ne_zero $ h begin 328 | rw [algebra.algebra_map_eq_smul_one, ring_hom.map_zero, αβγ_smul_eq_zero], 329 | end 330 | 331 | end q60596 332 | 333 | /- The generate statement: not every Clifford algebra has an injective algebra map -/ 334 | -- TODO: https://github.com/leanprover-community/mathlib/pull/18644/files 335 | lemma {v} clifford_algebra.not_forall_algebra_map_injective : 336 | ¬∀ (R : Type) (M : Type v) [comm_ring R] [add_comm_group M], by exactI 337 | ∀ [module R M], by exactI 338 | ∀ (Q : quadratic_form R M), 339 | function.injective (algebra_map R $ clifford_algebra Q) := 340 | λ h, q60596.algebra_map_not_injective $ λ x y hxy, begin 341 | let uQ := q60596.Q.comp (linear_equiv.ulift q60596.k _).to_linear_map, 342 | refine h q60596.k (ulift q60596.L) 343 | (q60596.Q.comp $ (linear_equiv.ulift q60596.k _).to_linear_map) _, 344 | let uC := clifford_algebra.map q60596.Q uQ 345 | (linear_equiv.ulift q60596.k q60596.L).symm.to_linear_map (λ _, rfl), 346 | simpa using uC.congr_arg hxy, 347 | end 348 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/versors.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import for_mathlib.algebra.center_submonoid 7 | import for_mathlib.algebra.filtration 8 | import for_mathlib.algebra.algebra_operations 9 | import geometric_algebra.from_mathlib.basic 10 | import geometric_algebra.from_mathlib.conjugation 11 | 12 | /-! 13 | # Versors, spinors, Multivectors, and other subspaces 14 | 15 | This file defines the `versors`, `spinors`, and `r_multivectors`. 16 | -/ 17 | 18 | variables {R : Type*} [comm_ring R] 19 | variables {M : Type*} [add_comm_group M] [module R M] 20 | variables {Q : quadratic_form R M} 21 | 22 | namespace clifford_algebra 23 | open_locale pointwise 24 | 25 | variables (Q) 26 | /-- The versors are the elements made up of products of vectors. 27 | 28 | TODO: are scalars ≠1 considered versors? -/ 29 | def versors := algebra.center_submonoid.closure R (set.range $ ι Q) 30 | 31 | variables {Q} 32 | 33 | namespace versors 34 | 35 | open algebra.center_submonoid 36 | 37 | @[simp] lemma ι_mem (m : M) : ι Q m ∈ versors Q := 38 | subset_closure R $ set.mem_range_self m 39 | 40 | /-- An induction process for the versors, proving a statement `C` about `v` given proofs that: 41 | * It holds for the scalars 42 | * It holds for the vectors 43 | * It holds for any product of two elements it holds for 44 | -/ 45 | @[elab_as_eliminator] 46 | lemma induction_on {C : versors Q → Prop} (v : versors Q) 47 | (h_grade0 : ∀ (r : R), C ⟨↑ₐr, (versors Q).algebra_map_mem r⟩) 48 | (h_grade1 : ∀ m, C ⟨ι Q m, ι_mem m⟩) 49 | (h_mul : ∀ (a b : versors Q), C a → C b → C (a * b)) : 50 | C v := 51 | subtype.cases_on v $ λ v hv, by exact 52 | submonoid.closure_induction' _ 53 | (λ x hx, by { 54 | cases hx, 55 | { obtain ⟨a, rfl⟩ := set.mem_range.mpr hx, 56 | exact h_grade0 a, }, 57 | { obtain ⟨a, rfl⟩ := set.mem_range.mpr hx, 58 | exact h_grade1 a, } }) 59 | (begin 60 | convert h_grade0 (1 : R) using 1, 61 | apply subtype.coe_injective, 62 | simpa only [ring_hom.map_one], 63 | end) 64 | (λ x hx y hy, h_mul ⟨x, hx⟩ ⟨y, hy⟩) hv 65 | 66 | meta def inv_rev_tac : tactic unit := 67 | `[apply induction_on v, 68 | { intro r, simp, }, 69 | { intro m, simp, }, 70 | { intros a b ha hb, simp [(versors Q).mul_mem, ha, hb] }] 71 | 72 | /-- Involute of a versor is a versor -/ 73 | @[simp] lemma involute_mem (v : versors Q) : involute (v : clifford_algebra Q) ∈ versors Q := 74 | by inv_rev_tac 75 | 76 | /-- Reverse of a versor is a versor -/ 77 | @[simp] lemma reverse_mem (v : versors Q) : reverse (v : clifford_algebra Q) ∈ versors Q := 78 | by inv_rev_tac 79 | 80 | /-- A versor times its reverse is a scalar 81 | 82 | TODO: Can we compute `r` constructively? -/ 83 | lemma mul_self_reverse (v : versors Q) : 84 | ∃ r : R, (v : clifford_algebra Q) * reverse (v : clifford_algebra Q) = ↑ₐr := 85 | begin 86 | with_cases { apply induction_on v }, 87 | case h_grade0 : r { 88 | refine ⟨r * r, _⟩, 89 | simp }, 90 | case h_grade1 : m { 91 | refine ⟨Q m, _⟩, 92 | simp }, 93 | case h_mul : x y { 94 | rintros ⟨qx, hx⟩ ⟨qy, hy⟩, 95 | refine ⟨qx * qy, _⟩, 96 | simp only [reverse.map_mul, submonoid.coe_mul, ring_hom.map_mul], 97 | rw [mul_assoc ↑x, ←mul_assoc ↑y, hy, algebra.commutes, ←mul_assoc, hx], } 98 | end 99 | 100 | /-- A versor's reverse times itself is a scalar 101 | 102 | TODO: Can we compute `r` constructively? -/ 103 | lemma reverse_mul_self (v : versors Q) : 104 | ∃ r : R, reverse (v : clifford_algebra Q) * (v : clifford_algebra Q) = ↑ₐr := 105 | begin 106 | obtain ⟨r, hr⟩ := mul_self_reverse ⟨reverse (v : clifford_algebra Q), reverse_mem v⟩, 107 | refine ⟨r, _⟩, 108 | simpa [reverse_involutive ↑v] using hr, 109 | end 110 | 111 | /-- The magnitude of a versor. -/ 112 | @[simps apply] 113 | def magnitude_aux : monoid_with_zero_hom (versors Q) (clifford_algebra Q) := 114 | { to_fun := λ v, (v : clifford_algebra Q) * reverse (v : clifford_algebra Q), 115 | map_mul' := λ x y, by { 116 | simp only [reverse.map_mul, submonoid.coe_mul], 117 | obtain ⟨_, hx⟩ := mul_self_reverse x, 118 | obtain ⟨_, hy⟩ := mul_self_reverse y, 119 | rw [mul_assoc ↑x, ←mul_assoc ↑y, hy, algebra.commutes, ←mul_assoc, hx], 120 | }, 121 | map_one' := by simp, 122 | map_zero' := by simp } 123 | 124 | def magnitude_aux_exists_scalar (v : versors Q) : ∃ r, magnitude_aux v = ↑ₐr := 125 | mul_self_reverse v 126 | 127 | /-- 128 | Only zero versors have zero magnitude, assuming: 129 | 130 | - The metric is anisotropic (`hqnz`). Note this is a stricter requirement 131 | than non-degeneracy; versors in CGA 𝒢(ℝ⁴⋅¹) like `n∞` and `n∞*no` are 132 | both counterexamples to this lemma. 133 | - `0` remains `0` when mapped from `R` into `clifford_algebra Q` 134 | - `R` has no zero divisors 135 | 136 | It's possible these last two requirements can be relaxed somehow. 137 | -/ 138 | lemma magnitude_aux_zero (v : versors Q) 139 | [no_zero_divisors R] 140 | (hQ : Q.anisotropic) 141 | (h0 : ∀ {r}, algebra_map R (clifford_algebra Q) r = 0 → r = 0) : 142 | magnitude_aux v = 0 ↔ v = 0 := 143 | ⟨begin 144 | apply induction_on v, 145 | { intros r hr, 146 | simp only [subtype.coe_mk, magnitude_aux_apply, reverse.commutes] at hr, 147 | ext, simp only [coe_zero, subtype.coe_mk], 148 | rw [←ring_hom.map_mul] at hr, 149 | replace hr := h0 hr, 150 | rw mul_self_eq_zero at hr, 151 | rw [hr, ring_hom.map_zero], }, 152 | { intros m hm, 153 | simp at hm, 154 | ext, simp, 155 | replace hm := hQ _ (h0 hm), 156 | rw [hm, (ι Q).map_zero], 157 | }, 158 | { intros a b ha hb hab, 159 | rw magnitude_aux.map_mul at hab, 160 | obtain ⟨ra, ha'⟩ := magnitude_aux_exists_scalar a, 161 | obtain ⟨rb, hb'⟩ := magnitude_aux_exists_scalar b, 162 | rw ha' at ha, 163 | rw hb' at hb, 164 | rw [ha', hb'] at hab, 165 | rw ←ring_hom.map_mul at hab, 166 | replace hab := h0 hab, 167 | obtain (ha'' | hb'') := mul_eq_zero.mp hab, 168 | { rw [ha'', ring_hom.map_zero] at ha, rw [ha rfl, zero_mul] }, 169 | { rw [hb'', ring_hom.map_zero] at hb, rw [hb rfl, mul_zero] } 170 | }, 171 | end, λ h, begin 172 | rw h, 173 | exact zero_mul (reverse 0), 174 | end⟩ 175 | 176 | /-- The magnitude of a versor, as a member of the subalgebra of scalars 177 | 178 | Note we can't put this in `R` unless we know `algebra_map` is injective. 179 | This is kind of annoying, because it means that even if we have `field R`, we can't invert the 180 | magnitude 181 | -/ 182 | @[simps apply] 183 | def magnitude : monoid_with_zero_hom (versors Q) (⊥ : subalgebra R $ clifford_algebra Q) := 184 | { to_fun := λ v, ⟨magnitude_aux v, 185 | let ⟨r, hr⟩ := mul_self_reverse v in algebra.mem_bot.mpr ⟨r, hr.symm⟩⟩, 186 | map_mul' := λ x y, subtype.ext $ magnitude_aux.map_mul x y, 187 | map_one' := subtype.ext $ magnitude_aux.map_one, 188 | map_zero' := subtype.ext $ magnitude_aux.map_zero } 189 | 190 | noncomputable def magnitude_R (hi : function.injective $ algebra_map R (clifford_algebra Q)) : 191 | monoid_with_zero_hom (versors Q) R := 192 | { to_fun := λ v, classical.some (magnitude_aux_exists_scalar v), 193 | map_mul' := λ x y, hi begin 194 | rw ring_hom.map_mul, 195 | rw ←classical.some_spec (magnitude_aux_exists_scalar x), 196 | rw ←classical.some_spec (magnitude_aux_exists_scalar y), 197 | rw ←classical.some_spec (magnitude_aux_exists_scalar (x * y)), 198 | exact magnitude_aux.map_mul x y, 199 | end, 200 | map_one' := hi begin 201 | rw ring_hom.map_one, 202 | rw ←classical.some_spec (magnitude_aux_exists_scalar 1), 203 | exact magnitude_aux.map_one, 204 | end, 205 | map_zero' := hi begin 206 | rw ring_hom.map_zero, 207 | rw ←classical.some_spec (magnitude_aux_exists_scalar 0), 208 | exact magnitude_aux.map_zero, 209 | end } 210 | 211 | @[simp] 212 | lemma magnitude_R_eq (hi) (v : versors Q) : (↑ₐ(magnitude_R hi v) : clifford_algebra Q) = magnitude v := begin 213 | unfold magnitude_R, 214 | simp only [submodule.coe_mk, monoid_with_zero_hom.coe_mk], 215 | have := classical.some_spec (magnitude_aux_exists_scalar v), 216 | rw ← this, 217 | simp, 218 | end 219 | 220 | section field 221 | 222 | variables {R' : Type*} [field R'] {M' : Type*} [add_comm_group M'] [module R' M'] {Q' : quadratic_form R' M'} [nontrivial (clifford_algebra Q')] 223 | 224 | /-- When `R'` is a field, we can define the inverse as `~V / (V * ~V)`. 225 | 226 | Until we resolve the problems above about getting `r` constructively, we are forced to use the axiom of choice here -/ 227 | @[simps inv] 228 | noncomputable instance : has_inv (versors Q') := 229 | { inv := λ v, (magnitude_R (algebra_map R' _).injective v)⁻¹ • ⟨reverse (v : clifford_algebra Q'), reverse_mem v⟩ } 230 | 231 | lemma inv_zero : (0 : versors Q')⁻¹ = 0 := 232 | begin 233 | rw has_inv_inv, 234 | ext, 235 | change _ • reverse 0 = 0, 236 | rw reverse.map_zero, 237 | rw smul_zero, 238 | end 239 | 240 | /-- Versors with a non-zero magnitude have an inverse -/ 241 | lemma mul_inv_cancel' (v : versors Q') (h : magnitude v ≠ 0) : v * v⁻¹ = 1 := 242 | begin 243 | rw has_inv_inv, 244 | ext, 245 | change ↑v * _ • reverse ↑v = 1, 246 | rw algebra.mul_smul_comm, 247 | rw inv_smul_eq_iff₀, 248 | { rw [algebra.smul_def, mul_one], 249 | simp only [magnitude_R_eq, ←magnitude_aux_apply, magnitude_apply, subtype.coe_mk], }, 250 | { intro h', apply h, 251 | -- TODO: the fact that we use `congr_arg` only to then use `injective` suggests that we can relax the constraints in 252 | -- magnitude_aux_zero. 253 | have := (algebra_map R' (clifford_algebra Q')).congr_arg h', 254 | rw [magnitude_R_eq, ring_hom.map_zero] at this, 255 | norm_cast at this, } 256 | end 257 | 258 | /-- If additionally the metric is anisotropic, then the inverse imparts a `group_with_zero` structure. -/ 259 | noncomputable instance [f : fact Q'.anisotropic] : 260 | group_with_zero (versors Q') := 261 | { inv_zero := inv_zero, 262 | mul_inv_cancel := λ a ha, mul_inv_cancel' a $ λ ham, ha begin 263 | refine (magnitude_aux_zero a f.out _).mp _, 264 | { intros r h, 265 | rw ←ring_hom.map_zero at h, 266 | exact (algebra_map R' _).injective h, }, 267 | { rw magnitude_apply at ham, 268 | replace ham := congr_arg (λ x : (⊥ : subalgebra R' $ clifford_algebra Q'), (x : clifford_algebra Q')) ham, 269 | simp only [submodule.coe_mk, submodule.coe_zero] at ham, 270 | exact ham } 271 | end, 272 | ..(infer_instance : nontrivial (versors Q')), 273 | ..(infer_instance : monoid_with_zero (versors Q')), 274 | ..(infer_instance : has_inv (versors Q'))} 275 | 276 | end field 277 | 278 | end versors 279 | 280 | variables (Q) 281 | /-- The spinors are the versors with an even number of factors -/ 282 | def spinors := algebra.center_submonoid.closure R (set.range (ι Q) * set.range (ι Q)) 283 | variables {Q} 284 | 285 | namespace spinors 286 | 287 | open algebra.center_submonoid 288 | 289 | /-- The spinors are versors -/ 290 | lemma subset_versors : (spinors Q).to_submonoid ≤ (versors Q).to_submonoid := 291 | begin 292 | unfold spinors versors, 293 | rw [closure_to_submonoid, closure_to_submonoid], 294 | rw submonoid.closure_union, 295 | rw submonoid.closure_union, 296 | apply sup_le_sup_left _ _, 297 | rw submonoid.closure_le, 298 | exact submonoid.mul_subset_closure (set.subset.refl _) (set.subset.refl _), 299 | end 300 | 301 | @[simp] lemma ι_mul_mem (m n : M) : ι Q m * ι Q n ∈ spinors Q := 302 | submonoid.subset_closure $ or.inr $ set.mul_mem_mul (set.mem_range_self m) (set.mem_range_self n) 303 | 304 | @[simp] lemma algebra_map_mem (r : R) : ↑ₐr ∈ spinors Q := 305 | submonoid.subset_closure $ or.inl $ set.mem_range_self r 306 | 307 | @[simp] lemma smul_mem (k : R) {v : clifford_algebra Q} (h : v ∈ spinors Q) : k • v ∈ spinors Q := 308 | begin 309 | rw algebra.smul_def, 310 | exact (spinors Q).mul_mem (algebra_map_mem k) h, 311 | end 312 | 313 | @[simp] lemma neg_mem {v : clifford_algebra Q} (h : v ∈ spinors Q) : -v ∈ spinors Q := 314 | begin 315 | rw neg_eq_neg_one_mul, 316 | rw [←(algebra_map R _).map_one, ←(algebra_map R (clifford_algebra Q)).map_neg, ←algebra.smul_def], 317 | exact smul_mem (-1) h, 318 | end 319 | 320 | /-! The spinors inherit scalar multiplication (`•`) and negation from the parent algebra -/ 321 | 322 | instance : mul_action R (spinors Q) := 323 | { smul := λ k v, ⟨k • v, smul_mem k v.prop⟩, 324 | one_smul := λ v, subtype.eq $ one_smul _ v, 325 | mul_smul := λ k₁ k₂ v, subtype.eq $ mul_smul k₁ k₂ v, } 326 | 327 | instance : has_neg (spinors Q) := 328 | { neg := λ v, ⟨-v, neg_mem v.prop⟩ } 329 | 330 | /-- An induction process for the spinors, proving a statement `C` about `v` given proofs that: 331 | * It holds for the scalars 332 | * It holds for products of two vectors 333 | * It holds for any product of two elements it holds for 334 | -/ 335 | @[elab_as_eliminator] 336 | lemma induction_on {C : spinors Q → Prop} 337 | (v : spinors Q) 338 | (h_grade0 : ∀ (r : R), C ⟨↑ₐr, algebra_map_mem r⟩) 339 | (h_grade2 : ∀ m n, C ⟨ι Q m * ι Q n, ι_mul_mem m n⟩) 340 | (h_mul : ∀ (a b : spinors Q), C a → C b → C (a * b)) : 341 | C v := 342 | subtype.cases_on v $ λ v hv, by exact 343 | submonoid.closure_induction' _ 344 | (λ x hx, by { 345 | cases hx, 346 | { obtain ⟨a, rfl⟩ := set.mem_range.mpr hx, 347 | exact h_grade0 a, }, 348 | { obtain ⟨_, _, ⟨a, rfl⟩, ⟨b, rfl⟩, rfl⟩ := set.mem_mul.mpr hx, 349 | exact h_grade2 a b, } }) 350 | (begin 351 | convert h_grade0 (1 : R) using 1, 352 | apply subtype.coe_injective, 353 | simpa only [ring_hom.map_one], 354 | end) 355 | (λ x hx y hy, h_mul ⟨x, hx⟩ ⟨y, hy⟩) hv 356 | 357 | /-- Involute of a spinor is a spinor -/ 358 | @[simp] lemma involute_mem (v : spinors Q) : involute (v : clifford_algebra Q) ∈ spinors Q := 359 | begin 360 | apply induction_on v, 361 | { intro r, simp, }, 362 | { intros m n, simp, }, 363 | { intros a b ha hb, simp [(spinors Q).mul_mem ha hb] } 364 | end 365 | 366 | /-- Reverse of a spinor is a spinor -/ 367 | @[simp] lemma reverse_mem (v : spinors Q) : reverse (v : clifford_algebra Q) ∈ spinors Q := 368 | begin 369 | apply induction_on v, 370 | { intro r, simp, }, 371 | { intro m, simp, }, 372 | { intros a b ha hb, simp [(spinors Q).mul_mem hb ha] } 373 | end 374 | 375 | end spinors 376 | 377 | @[simp] 378 | lemma involute_spinor (r : spinors Q) : involute (r : clifford_algebra Q) = r := 379 | submonoid.closure_induction r.prop 380 | (λ x hx, by { 381 | cases hx, 382 | { obtain ⟨a, rfl⟩ := set.mem_range.mpr hx, 383 | simp only [involute.commutes], }, 384 | { obtain ⟨a, b, ha, hb, rfl⟩ := set.mem_mul.mpr hx, 385 | obtain ⟨av, rfl⟩ := ha, 386 | obtain ⟨bv, rfl⟩ := hb, 387 | rw involute.map_mul, 388 | simp only [involute_ι, neg_mul_neg], } }) 389 | involute.map_one 390 | (λ x y hx hy, by rw [involute.map_mul, hx, hy]) 391 | 392 | 393 | variables (Q) 394 | private def r_multivectors.def : ℕ → submodule R (clifford_algebra Q) 395 | | 0 := 1 396 | -- union needed here so that `r_multivectors Q 0 ≤ r_multivectors Q 1` 397 | | (n + 1) := (r_multivectors.def n * (ι Q).range) ⊔ r_multivectors.def n 398 | 399 | private lemma r_multivectors.map_add {ai bi : ℕ} : 400 | r_multivectors.def Q (ai + bi) = r_multivectors.def Q ai * r_multivectors.def Q bi := 401 | begin 402 | induction bi, 403 | { ext x, 404 | simp [r_multivectors.def, algebra.of_id_apply], 405 | }, 406 | { simp [nat.succ_eq_add_one, ←nat.add_assoc, r_multivectors.def], 407 | rw submodule.mul_sup, 408 | rw [←mul_assoc, bi_ih], } 409 | end 410 | 411 | private lemma r_multivectors.mono : monotone (r_multivectors.def Q) := 412 | λ n n' h, nat.le_induction (le_of_eq rfl) (λ n hn ih, ih.trans le_sup_right) _ h 413 | 414 | /-- The elements of at most grade `n` are a filtration -/ 415 | def r_multivectors : algebra.filtration R (clifford_algebra Q) ℕ := 416 | { to_fun := r_multivectors.def Q, 417 | mono' := r_multivectors.mono Q, 418 | map_add' := λ i j, r_multivectors.map_add Q, 419 | complete' := λ x, begin 420 | induction x using clifford_algebra.induction, 421 | { use 0, simp [r_multivectors.def], }, 422 | { use 1, simp [r_multivectors.def], 423 | refine submodule.mem_sup_left _, 424 | simp, }, 425 | case h_mul : a b ha hb { 426 | obtain ⟨na, hna⟩ := ha, 427 | obtain ⟨nb, hnb⟩ := hb, 428 | use na + nb, 429 | rw r_multivectors.map_add, 430 | exact submodule.mul_mem_mul hna hnb, 431 | }, 432 | case h_add : a b ha hb { 433 | obtain ⟨na, hna⟩ := ha, 434 | obtain ⟨nb, hnb⟩ := hb, 435 | use (na ⊔ nb), 436 | replace hna := set_like.le_def.mpr (r_multivectors.mono Q le_sup_left) hna, 437 | replace hnb := set_like.le_def.mpr (r_multivectors.mono Q le_sup_right) hnb, 438 | exact submodule.add_mem _ hna hnb, 439 | } 440 | end, 441 | } 442 | variables {Q} 443 | 444 | namespace r_multivectors 445 | 446 | @[simp] lemma map_zero : r_multivectors Q 0 = 1 := rfl 447 | @[simp] lemma map_succ (n) : r_multivectors Q (n + 1) = (r_multivectors Q n * (ι Q).range) ⊔ r_multivectors Q n := rfl 448 | 449 | /-- Since the sets are monotonic, we can coerce up to a larger submodule -/ 450 | instance (n r) : has_coe_t (r_multivectors Q n) (r_multivectors Q $ n + r) := 451 | { coe := λ x, ⟨x, set_like.le_def.mpr ((r_multivectors Q).mono (nat.le_add_right n r)) x.prop⟩ } 452 | 453 | end r_multivectors 454 | 455 | end clifford_algebra 456 | -------------------------------------------------------------------------------- /src/geometric_algebra/from_mathlib/zmod_grading.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import data.zmod.basic 7 | import for_mathlib.algebra.monoid_algebra 8 | import geometric_algebra.from_mathlib.basic 9 | 10 | variables {R : Type*} [comm_ring R] 11 | variables {M : Type*} [add_comm_group M] [module R M] 12 | variables {Q : quadratic_form R M} 13 | /-! 14 | # Grading by ℤ / 2ℤ 15 | 16 | This file defines the grading by `zmod 2`, as the function `clifford_algebra.grades'`. 17 | 18 | ## Main results 19 | 20 | * `clifford_algebra.grades'_left_inverse`, `grades'` has a left-inverse, `add_monoid_algebra.sum_id`. 21 | * `clifford_algebra.grades'.map_grades'`, `grades'` is idempotent 22 | -/ 23 | 24 | namespace clifford_algebra 25 | 26 | /-- 27 | Separate an element of the clifford algebra into its `zmod 2`-graded components. 28 | 29 | This is defined as an `alg_hom` to `add_monoid_algebra` so that algebra operators can be moved 30 | before and after the mapping. 31 | 32 | This is _not_ the normal ℕ-graded definition that we usually use in GA. That definition is harder... 33 | -/ 34 | noncomputable def grades' : 35 | (clifford_algebra Q) →ₐ[R] add_monoid_algebra (clifford_algebra Q) (zmod 2) := 36 | (lift Q : _) ⟨ 37 | -- vectors are grade 1 38 | (add_monoid_algebra.lsingle 1).comp (ι Q), 39 | -- this requires 1 + 1 = 0, which is why we use `zmod 2` as our grading 40 | λ x, by { simp [add_monoid_algebra.single_mul_single], congr }⟩ 41 | 42 | /-- Recombining the grades recovers the original element-/ 43 | lemma sum_id_comp_grades' : 44 | (add_monoid_algebra.sum_id R).comp grades' = alg_hom.id R (clifford_algebra Q) := 45 | begin 46 | ext, 47 | simp [grades', add_monoid_algebra.sum_id_apply, finsupp.sum_single_index], 48 | end 49 | 50 | /-- Stated another way, `grades'` has a left-inverse and is therefore injective (via `function.left_inverse.injective`). -/ 51 | lemma grades'_left_inverse : 52 | function.left_inverse (add_monoid_algebra.sum_id R) ⇑(grades' : clifford_algebra Q →ₐ[R] _) := 53 | alg_hom.congr_fun sum_id_comp_grades' 54 | 55 | noncomputable 56 | instance : has_coe (add_monoid_algebra (clifford_algebra Q) (zmod 2)) (clifford_algebra Q) := ⟨ 57 | (add_monoid_algebra.sum_id R : add_monoid_algebra (clifford_algebra Q) (zmod 2) →ₐ[R] (clifford_algebra Q)) 58 | ⟩ 59 | 60 | @[simp, norm_cast] 61 | lemma coe_def (x : add_monoid_algebra (clifford_algebra Q) (zmod 2)) : (x : clifford_algebra Q) = add_monoid_algebra.sum_id R x := rfl 62 | 63 | 64 | /-- An element of `R` lifted with `algebra_map` has a single grade 0 element -/ 65 | lemma grades'.map_algebra_map (r : R) : 66 | grades' (algebra_map R (clifford_algebra Q) r) = finsupp.single 0 (algebra_map R _ r) := 67 | by simp 68 | 69 | /-- An element of `X` lifted with the canonical `ι R` function has a single grade 1 element -/ 70 | lemma grades'.map_ι (x : M) : 71 | grades' (ι Q x) = finsupp.single 1 (ι Q x) := 72 | by simp [grades'] 73 | 74 | -- note this is true for any `zero_hom`, not just `grades'`. Of course, then we need to repeat this 75 | -- for `add_monoid_hom`, `add_equiv`, `linear_map`, `ring_hom`, `ring_equiv`, `alg_hom`, ... 76 | private lemma map_single_apply (x : clifford_algebra Q) (i j : zmod 2) : 77 | grades' (finsupp.single i x j) = finsupp.single i (grades' x) j := 78 | by rw [finsupp.single_apply, finsupp.single_apply, apply_ite grades', grades'.map_zero] 79 | 80 | -- The grade-`i` part consists only of itself -/ 81 | @[simp] 82 | lemma grades'.map_grades' (x : clifford_algebra Q) (i : zmod 2) : 83 | grades' (grades' x i) = finsupp.single i (grades' x i) := 84 | begin 85 | induction x using clifford_algebra.induction generalizing i, 86 | case h_grade0 : { 87 | rw [grades'.map_algebra_map, map_single_apply, grades'.map_algebra_map, 88 | finsupp.single_of_single_apply], 89 | }, 90 | case h_grade1 : { 91 | rw [grades'.map_ι, map_single_apply, grades'.map_ι, 92 | finsupp.single_of_single_apply], 93 | }, 94 | case h_add : x y hx hy { 95 | rw [grades'.map_add, finsupp.add_apply, grades'.map_add, finsupp.single_add, hx, hy], 96 | }, 97 | case h_mul : f g hx hy { 98 | rw grades'.map_mul, 99 | rw add_monoid_algebra.mul_def, 100 | simp_rw [finsupp.sum_apply], 101 | 102 | -- pull the sums to the outside 103 | have : finsupp.single i = finsupp.single_add_hom i := rfl, 104 | rw this, 105 | simp_rw alg_hom.map_finsupp_sum, 106 | simp_rw add_monoid_hom.map_finsupp_sum, 107 | simp_rw finsupp.sum, 108 | congr, ext1 fi, 109 | congr, ext1 gi, 110 | rw ←this, 111 | 112 | -- this proof now resembles the other three 113 | rw [map_single_apply, grades'.map_mul, 114 | finsupp.single_of_single_apply], 115 | rw [hx, hy, add_monoid_algebra.single_mul_single], 116 | }, 117 | end 118 | 119 | end clifford_algebra 120 | -------------------------------------------------------------------------------- /src/geometric_algebra/nursery/chisolm.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Utensil Song. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Utensil Song, Eric Wieser 5 | 6 | This file is based on https://arxiv.org/abs/1205.5935 7 | -/ 8 | import algebra.hom.group 9 | import algebra.algebra.basic 10 | import data.real.basic 11 | import data.complex.basic 12 | 13 | import tactic.apply_fun 14 | import tactic 15 | 16 | universes u u₀ u₁ 17 | 18 | /- Needed for zero_pairwise_ortho_vector -/ 19 | -- lemma pairwise_of_repeat {X : Type*} {x : X} {n : ℕ} {r : X → X → Prop} (hr : r x x) : 20 | -- list.pairwise r (list.repeat x n) := 21 | -- begin 22 | -- induction n with d hd, 23 | -- { exact list.pairwise.nil}, 24 | -- { apply list.pairwise.cons _ hd, 25 | -- intros a ha, 26 | -- convert hr, 27 | -- exact list.eq_of_mem_repeat ha, 28 | -- } 29 | -- end 30 | 31 | class geometric_algebra 32 | -- Axiom 2: G contains a field G0 of characteristic zero which includes 0 and 1. 33 | (G₀ : Type*) [field G₀] 34 | -- Axiom 3: G contains a subset G1 closed under addition, 35 | -- and λ ∈ G0, v ∈ G1 implies λv = vλ ∈ G1. 36 | (G₁ : Type*) [add_comm_group G₁] [module G₀ G₁] 37 | -- Axiom 1: G is a ring with unit. 38 | -- The additive identity is called 0 and the multiplicative identity is called 1. 39 | (G : Type*) [ring G] 40 | [algebra G₀ G] 41 | := 42 | (f₁ : G₁ →+ G) 43 | -- Axiom 4: The square of every vector is a scalar. 44 | -- TODO clearly this should be nameed following "contraction rule", I'm thinking maybe `contract`? 45 | (vec_sq_scalar : ∀ v : G₁, ∃ k : G₀, f₁ v * f₁ v = algebra_map _ _ k ) 46 | 47 | namespace geometric_algebra 48 | 49 | section basic 50 | 51 | 52 | parameters 53 | {G₀ : Type u} [field G₀] 54 | {G₁ : Type u} [add_comm_group G₁] [module G₀ G₁] 55 | {G : Type u} [ring G] [algebra G₀ G] [geometric_algebra G₀ G₁ G] 56 | 57 | 58 | -- define a blade representation 59 | -- TODO: how to describe the fact that the vector argument to `graded` must be orthogonal? 60 | inductive blade : nat → Type u 61 | | scalar : G₀ → blade 0 62 | | vector : G₁ → blade 1 63 | | graded {n : ℕ} : G₁ → blade (n + 1) → blade (n + 2) 64 | namespace blade 65 | instance g0_coe : has_coe_t G₀ (blade 0) := { coe := blade.scalar } 66 | instance g1_coe : has_coe_t G₁ (blade 1) := { coe := blade.vector } 67 | 68 | -- define zero and one on the blades 69 | def zero : Π (n : ℕ), blade n 70 | | 0 := blade.scalar (0 : G₀) 71 | | 1 := blade.vector (0 : G₁) 72 | | (nat.succ $ nat.succ n) := blade.graded (0 : G₁) (zero $ nat.succ n) 73 | instance has_zero {n : ℕ} : has_zero (blade n) := { zero := zero n } 74 | instance r0_has_one : has_one (blade 0) := { one := (1 : G₀) } 75 | 76 | -- define add on the blades 77 | def r0_add (a : blade 0) (b : blade 0) : blade 0 := begin 78 | cases a with a', 79 | cases b with b', 80 | exact blade.scalar (a' + b') 81 | end 82 | instance r0_has_add : has_add (blade 0) := { add := r0_add } 83 | def r1_add (a : blade 1) (b : blade 1) : blade 1 := begin 84 | cases a, 85 | cases b, 86 | exact blade.vector (a_1 + b_1) 87 | end 88 | instance r1_has_add : has_add (blade 1) := { add := r1_add } 89 | end blade 90 | 91 | -- define a sum-of-blades representation 92 | inductive hom_mv : nat → Type u 93 | | scalar : blade 0 -> hom_mv 0 94 | | vector : blade 1 -> hom_mv 1 95 | | graded {n : ℕ} : list (blade $ nat.succ $ nat.succ n) → (hom_mv $ nat.succ $ nat.succ n) 96 | 97 | namespace hom_mv 98 | def coe : Π {n : ℕ}, (blade n) → hom_mv n 99 | | 0 := hom_mv.scalar 100 | | 1 := hom_mv.vector 101 | | (r + 2) := λ b, hom_mv.graded [b] 102 | instance has_blade_coe {r : ℕ} : has_coe (blade r) (hom_mv r) := { coe := coe } 103 | instance has_g0_coe : has_coe_t G₀ (hom_mv 0) := { coe := λ s, coe s } 104 | instance has_g1_coe : has_coe_t G₁ (hom_mv 1) := { coe := λ s, coe s } 105 | 106 | -- define zero and one on the hom_mvs 107 | instance has_zero {n : ℕ} : has_zero (hom_mv n) := { zero := (0 : blade n) } 108 | instance r0_has_one : has_one (hom_mv 0) := { one := (1 : blade 0) } 109 | 110 | def add : Π {n : ℕ}, hom_mv n → hom_mv n → hom_mv n 111 | | 0 (scalar a) (scalar b) := hom_mv.scalar (a + b) 112 | | 1 (vector a) (vector b) := hom_mv.vector (a + b) 113 | | (n + 2) (graded a) (graded b) := hom_mv.graded (a ++ b) 114 | 115 | instance has_add {n : ℕ} : has_add (hom_mv n) := { add := add } 116 | end hom_mv 117 | 118 | inductive multivector : nat → Type u 119 | | scalar : hom_mv 0 → multivector 0 120 | | augment {n : ℕ} : multivector n → hom_mv (nat.succ n) → multivector (nat.succ n) 121 | 122 | 123 | namespace mv 124 | -- define zero and one on the multivectors 125 | def mv_zero : Π (n : ℕ), multivector n 126 | | 0 := multivector.scalar (0 : G₀) 127 | | 1 := multivector.augment (mv_zero 0) 0 128 | | (nat.succ $ nat.succ n) := multivector.augment (mv_zero $ nat.succ n) (hom_mv.graded []) 129 | def mv_one : Π (n : ℕ), multivector n 130 | | 0 := multivector.scalar (1 : G₀) 131 | | 1 := multivector.augment (mv_one 0) 0 132 | | (nat.succ $ nat.succ n) := multivector.augment (mv_one $ nat.succ n) (hom_mv.graded []) 133 | instance mv_has_zero {n : ℕ} : has_zero (multivector n) := { zero := mv_zero n } 134 | instance mv_has_one {n : ℕ} : has_one (multivector n) := { one := mv_one n } 135 | 136 | -- blades are coercible to multivectors 137 | def hom_mv_coe : Π {n : ℕ}, (hom_mv n) -> (multivector n) 138 | | nat.zero := λ b, multivector.scalar b 139 | | (nat.succ n) := λ b, multivector.augment (mv_zero n) b 140 | instance has_hom_mv_coe {n : ℕ} : has_coe (hom_mv n) (multivector n) := { coe := hom_mv_coe } 141 | instance has_g0_coe_t : has_coe_t G₀ (multivector 0) := { coe := λ s, hom_mv_coe $ hom_mv.scalar $ blade.scalar s } 142 | instance has_g1_coe_t : has_coe_t G₁ (multivector 1) := { coe := λ v, hom_mv_coe $ hom_mv.vector $ blade.vector v } 143 | 144 | -- multivectors are up-coercible 145 | def augment_coe {n : ℕ} (mv : multivector n) : multivector (nat.succ n) := multivector.augment mv 0 146 | instance has_augment_coe {n : ℕ} : has_coe (multivector n) (multivector (nat.succ n)) := { coe := augment_coe } 147 | instance has_g0_coe_n {n : ℕ} : has_coe_t G₀ (multivector n) := { 148 | coe := nat.rec_on n coe $ λ n s k, s k } 149 | instance has_g1_coe_n {n : ℕ} : has_coe_t G₁ (multivector n.succ) := { 150 | coe := nat.rec_on n coe $ λ n s k, s k } 151 | 152 | def mv_add : Π {n : ℕ}, multivector n → multivector n → multivector n 153 | | 0 (multivector.scalar a) (multivector.scalar b) := multivector.scalar (a + b) 154 | | (nat.succ n) (multivector.augment a ar) (multivector.augment b br) := 155 | multivector.augment (mv_add a b) (ar + br) 156 | 157 | instance has_add {n: ℕ} : has_add (multivector n) := { add := mv_add } 158 | end mv 159 | 160 | parameter v : G₁ 161 | 162 | -- Addition! 163 | #check ((2 + v) : multivector 1) 164 | #check ((2 + v) : multivector 2) 165 | 166 | def fᵥ : G₁ →+ G := f₁ G₀ 167 | 168 | abbreviation fₛ : G₀ →+* G := algebra_map G₀ G 169 | 170 | def prod_vec (a b : G₁) : G := fᵥ a * fᵥ b 171 | 172 | local infix `*ᵥ`:75 := prod_vec 173 | 174 | def square_vec (a : G₁) := a *ᵥ a 175 | 176 | local postfix `²ᵥ`:80 := square_vec 177 | 178 | def sym_prod_vec (a b : G₁) := a *ᵥ b + b *ᵥ a 179 | 180 | local infix `*₊ᵥ`:75 := sym_prod_vec 181 | 182 | def is_orthogonal (a : G₁) (b : G₁) : Prop := sym_prod_vec a b = 0 183 | 184 | theorem zero_is_orthogonal (a : G₁) : is_orthogonal 0 a := begin 185 | unfold is_orthogonal, 186 | unfold sym_prod_vec, 187 | unfold prod_vec, 188 | simp 189 | end 190 | 191 | /-- a list of `r` orthogonal vectors, which may be non-unique -/ 192 | abbreviation pairwise_ortho_vector (r : ℕ) := {l : vector G₁ r // l.to_list.pairwise is_orthogonal} 193 | 194 | /- need this for later, can't seem to get the type inference to work if I inline it-/ 195 | -- def zero_pairwise_ortho_vector (r : ℕ) : pairwise_ortho_vector r := ⟨ 196 | -- vector.repeat (0 : G₁) r, begin 197 | -- unfold vector.repeat subtype.val, 198 | -- apply pairwise_of_repeat, 199 | -- apply zero_is_orthogonal, 200 | -- end⟩ 201 | 202 | 203 | /-- r-blades -/ 204 | def is_rblade (r : ℕ) (b : G) : Prop := 205 | -- a product of orthogonal vectors an a scalar 206 | ∃ (k : G₀) (v : pairwise_ortho_vector r), 207 | b = k • ((v : vector G₁ r).map fᵥ).to_list.prod 208 | 209 | def Bᵣ (r : ℕ) := set_of (is_rblade r) 210 | 211 | namespace Bᵣ 212 | variables {r : ℕ} 213 | 214 | lemma all_G₀_is_rblade0 (k : G₀) : is_rblade 0 (fₛ k) := begin 215 | use [k, list.pairwise.nil], 216 | simp [algebra.smul_def], 217 | end 218 | lemma all_G₁_is_rblade1 (a : G₁) : is_rblade 1 (fᵥ a) := begin 219 | use [1, ⟨vector.cons a vector.nil, list.pairwise_singleton _ a⟩], 220 | rw vector.to_list_map, 221 | simp, 222 | end 223 | 224 | instance has_coe_from_G₀ : has_coe G₀ (Bᵣ 0) := { coe := λ k, ⟨fₛ k, all_G₀_is_rblade0 k⟩} 225 | instance has_coe_from_G₁ : has_coe G₁ (Bᵣ 1) := { coe := λ a, ⟨fᵥ a, all_G₁_is_rblade1 a⟩} 226 | 227 | -- this is trivial, but maybe still needed 228 | @[simp] 229 | lemma coe_is_rblade (b : Bᵣ r) : is_rblade r b := b.prop 230 | 231 | /- todo: do we want this? -/ 232 | -- instance has_zero : has_zero (Bᵣ r) := { 233 | -- zero := ⟨(0 : G), begin 234 | -- use [0, zero_pairwise_ortho_vector r], 235 | -- simp, 236 | -- end⟩ 237 | -- } 238 | 239 | /- scalar multiple of an element of Bᵣ is also in Bᵣ -/ 240 | lemma smul_mem {b : G} {k : G₀} (hb : is_rblade r b) : is_rblade r (k • b) := begin 241 | obtain ⟨a, factors, ha_1⟩ := hb, 242 | refine ⟨k * a, factors, _⟩, 243 | rw [ha_1, mul_smul], 244 | end 245 | 246 | /- now show via trivial proofs that Bᵣ is a mul_action and has_neg -/ 247 | instance mul_action (r : ℕ) : mul_action G₀ (Bᵣ r) := 248 | { smul := λ k b, ⟨k • (b : G), smul_mem b.prop⟩, 249 | one_smul := λ b, subtype.eq $ one_smul _ b, 250 | mul_smul := λ k₁ k₂ b, subtype.eq $ mul_smul k₁ k₂ b } 251 | 252 | instance has_neg (r : ℕ) : has_neg (Bᵣ r) := { neg := λ b, (-1 : G₀) • b } 253 | 254 | end Bᵣ 255 | 256 | /-- `r`-vectors -/ 257 | def Gᵣ (r : ℕ) := add_subgroup.closure (Bᵣ r) 258 | 259 | example (r : ℕ) : add_comm_group (Gᵣ r) := by apply_instance 260 | namespace Gᵣ 261 | variables {r : ℕ} 262 | 263 | -- this is trivial, but maybe needed 264 | -- instance has_coe_from_Bᵣ : has_coe (Bᵣ r) (Gᵣ r) := { coe := λ b, ⟨b.val, add_subgroup.subset_closure b.property⟩ } 265 | 266 | -- scalar multiple of an element of Gᵣ is also in Gᵣ 267 | lemma smul_mem {v : G} {k : G₀} (hv : v ∈ Gᵣ r) : (k • v) ∈ Gᵣ r := 268 | add_subgroup.closure_induction hv 269 | (λ x hx, add_subgroup.subset_closure $ by exact Bᵣ.smul_mem hx) 270 | (by { 271 | rw smul_zero, exact (Gᵣ r).zero_mem, }) 272 | (λ a b, by { 273 | rw smul_add, exact (Gᵣ r).add_mem, }) 274 | (λ a, by { 275 | rw smul_neg, exact (Gᵣ r).neg_mem, }) 276 | 277 | -- now show via trivial proofs that Gᵣ is a module (basically a vector space) 278 | instance has_scalar (r : ℕ) : module G₀ (Gᵣ r) := 279 | { smul := λ k v, ⟨k • v, smul_mem v.prop⟩, 280 | one_smul := λ v, subtype.eq $ one_smul _ v, 281 | mul_smul := λ k₁ k₂ v, subtype.eq $ mul_smul k₁ k₂ v, 282 | smul_zero := λ v, subtype.eq $ smul_zero v, 283 | zero_smul := λ v, subtype.eq $ zero_smul _ v, 284 | add_smul := λ k₁ k₂ v, subtype.eq $ add_smul k₁ k₂ v, 285 | smul_add := λ k v₁ v₂, subtype.eq $ smul_add k v₁ v₂, 286 | zero_smul := λ v, subtype.eq $ zero_smul _ v } 287 | 288 | end Gᵣ 289 | 290 | /-- multi-vectors of at most grade `r` -/ 291 | def Mᵣ (r : ℕ) := add_subgroup.closure (⋃ (r' : fin r), (Gᵣ r').carrier) 292 | example (r : ℕ) : add_comm_group (Mᵣ r) := infer_instance 293 | 294 | abbreviation is_scalar : G → Prop := is_rblade 0 295 | 296 | /-- 297 | Symmetrised product of two vectors must be a scalar 298 | -/ 299 | lemma vec_sym_prod_scalar (a b : G₁) : is_scalar (a *₊ᵥ b) := 300 | have h1 : (a + b)²ᵥ = a²ᵥ + b²ᵥ + a *₊ᵥ b, from begin 301 | unfold square_vec sym_prod_vec prod_vec, 302 | rw fᵥ.map_add a b, 303 | rw left_distrib, 304 | repeat {rw right_distrib}, 305 | abel, 306 | end, 307 | have vec_sq_scalar : ∀ v : G₁, ∃ k : G₀, v²ᵥ = fₛ k, from 308 | λ v, geometric_algebra.vec_sq_scalar(v), 309 | begin 310 | obtain ⟨kab, hab⟩ := vec_sq_scalar (a + b), 311 | obtain ⟨ka, ha⟩ := vec_sq_scalar a, 312 | obtain ⟨kb, hb⟩ := vec_sq_scalar b, 313 | rw [hb, ha, hab] at h1, 314 | have h2 : (fₛ (kab - ka - kb : G₀) : G) = sym_prod_vec a b, by { 315 | repeat {rw ring_hom.map_sub}, 316 | rw h1, 317 | abel, 318 | }, 319 | rw ← h2, 320 | exact Bᵣ.all_G₀_is_rblade0 _, -- this feels clumsy, can I make this automatic? 321 | end 322 | 323 | end basic 324 | 325 | end geometric_algebra 326 | -------------------------------------------------------------------------------- /src/geometric_algebra/nursery/graded.lean: -------------------------------------------------------------------------------- 1 | -- Definition of a graded algebra, with no other operations defined 2 | import algebra.group.basic 3 | import linear_algebra.tensor_product 4 | import linear_algebra.dfinsupp 5 | import tactic.ring 6 | 7 | universes u 8 | 9 | -- TODO: open_locale only under namespace, never globally 10 | open_locale big_operators 11 | open_locale classical 12 | open finset 13 | 14 | -- TODO: should this have a shorter name like graded and places it under a namespace? 15 | class graded_module_components 16 | -- a type for each grade. 17 | -- TODO do we need ℤ or we can simply use ℕ 18 | -- the inductive definition of ℤ is based on ℕ 19 | -- and may add unwanted complexity to proof 20 | (A : ℤ → Type u) 21 | := 22 | -- (A 0) is the scalar type 23 | -- TODO what does zc stand for? 24 | [zc: comm_ring (A 0)] 25 | 26 | -- all the types form commutative vector spaces 27 | -- TODO change to meaningful names 28 | [b: ∀ r, add_comm_monoid (A r)] 29 | [c: ∀ r, module (A 0) (A r)] 30 | 31 | attribute [instance] graded_module_components.zc 32 | attribute [instance] graded_module_components.b 33 | attribute [instance] graded_module_components.c 34 | 35 | -- namespace graded_module_components 36 | -- -- TODO should always open a section before using variables 37 | -- variables {A : ℤ → Type u} 38 | -- /-- objects are coercible only if they have the same grade-/ 39 | -- -- TODO did it work? should we remove it? 40 | -- instance has_coe (r s : ℕ) (h: r = s) : has_coe (A r) (A s) := { coe := by {subst h, exact id}} 41 | -- end graded_module_components 42 | 43 | 44 | /-- Grade selection maps from objects in G to a finite set of components of substituent grades -/ 45 | -- TODO how about place it under namespace graded and name it has_select 46 | class has_grade_select 47 | (A : ℤ → Type u) (G: Type u) 48 | [graded_module_components A] 49 | [add_comm_group G] 50 | [module (A 0) G] := 51 | -- TODO better find a way to avoid A 0 everywhere 52 | (select : G →ₗ[A 0] (Π₀ r, A r)) 53 | 54 | /- TODO: check precedence -/ 55 | local notation `⟨`:0 g`⟩_`:0 r:100 := has_grade_select.select g r 56 | 57 | -- introducing these needs types which restrict the domain of A to `{z // z : ℤ, z %2 == 0}` 58 | -- notation `⟨`:0 g`⟩₊`:0 := has_grade_select.select_even 59 | -- notation `⟨`:0 g`⟩₋`:0 := has_grade_select.select_odd 60 | 61 | /-- A module divisible into disjoint graded modules, where the grade selectio 62 | operator is a complete and independent set of projections -/ 63 | class graded_module 64 | (A : ℤ → Type u) (G: Type u) 65 | -- TODO: we should avoid the plague of [] parameters, by bundling them? 66 | [graded_module_components A] 67 | [add_comm_group G] 68 | [module (A 0) G] 69 | extends has_grade_select A G := 70 | (to_fun : ∀{r}, A r →ₗ[A 0] G) 71 | (is_complete : ∀ g : G, ∀ f, f = select g ↔ g = f.sum (λ r, to_fun)) 72 | 73 | 74 | namespace graded_module 75 | variables {A : ℤ → Type u} {G: Type u} 76 | variables [graded_module_components A] [add_comm_group G] [module (A 0) G] 77 | variables [graded_module A G] 78 | 79 | /- locally bind the notation above to our A and G -/ 80 | -- TODO I have a feeling that this notation would not survive very long 81 | local notation (name := grade_select) `⟨`:0 g`⟩_`:0 r:100 := @has_grade_select.select A G _ _ _ _ g r 82 | 83 | /-- convert from r-vectors to multi-vectors -/ 84 | instance has_coe (r : ℤ) : has_coe (A r) G := { coe := to_fun } 85 | 86 | @[simp] 87 | lemma coe_def {r : ℤ} (v : A r) : (v : G) = to_fun v := rfl 88 | 89 | /-- An r-vector has only a single grade 90 | Discussed at https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/Expressing.20a.20sum.20with.20finitely.20many.20nonzero.20terms/near/202657281-/ 91 | lemma select_coe_is_single {r : ℤ} (v : A r) : 92 | has_grade_select.select (v : G) = dfinsupp.single r v := begin 93 | symmetry, 94 | rw is_complete (v : G) (dfinsupp.single r v), 95 | symmetry, 96 | apply dfinsupp.sum_single_index, 97 | exact linear_map.map_zero _, 98 | end 99 | 100 | def is_r_vector (r : ℤ) (a : G) := (⟨a⟩_r : G) = a 101 | 102 | /-- Chisholm 6a, ish. 103 | This says A = ⟨A}_r for r-vectors. 104 | Chisholm aditionally wants proof that A != ⟨A}_r for non-rvectors -/ 105 | lemma r_grade_of_coe {r : ℤ} (v : A r) : ⟨v⟩_r = v := begin 106 | rw select_coe_is_single, 107 | rw dfinsupp.single_apply, 108 | rw [dif_pos], 109 | refl, 110 | end 111 | 112 | /-- to_fun is injective -/ 113 | lemma to_fun_inj (r : ℤ) : function.injective (to_fun : A r → G) := begin 114 | intros a b h, 115 | rw ← r_grade_of_coe a, 116 | rw ← r_grade_of_coe b, 117 | simp only [coe_def], 118 | rw h, 119 | apply_instance, 120 | end 121 | 122 | /-- Chisholm 6b -/ 123 | lemma grade_of_sum (r : ℤ) (a b : G) : 124 | ⟨a + b⟩_r = ⟨a⟩_r + ⟨b⟩_r := 125 | by simp only [dfinsupp.add_apply, linear_map.map_add] 126 | 127 | /-- Chisholm 6c -/ 128 | lemma grade_smul (r : ℤ) (k : A 0) (a : G) : 129 | ⟨k • a⟩_r = k • ⟨a⟩_r := 130 | by simp only [dfinsupp.smul_apply, linear_map.map_smul] 131 | 132 | /-- chisholm 6d. Modifid to use `_s` instead of `_r` on the right, to keep the statement cast-free -/ 133 | lemma grade_grade (r s : ℤ) (a : G) : ⟨⟨a⟩_r⟩_s = if r = s then ⟨a⟩_s else 0 134 | := begin 135 | rw select_coe_is_single, 136 | rw dfinsupp.single_apply, 137 | split_ifs, 138 | { 139 | cases h with s, 140 | simp only [], 141 | }, 142 | simp only [eq_self_iff_true], 143 | end 144 | 145 | /-- chisholm 6e. The phrasing is made a little awkward by the construction of the finite decomposition of select --/ 146 | lemma grade_sum (g : G) : g = (has_grade_select.select g).sum (λ r, (to_fun : A r → G)) := begin 147 | apply (is_complete g (has_grade_select.select g)).1, 148 | refl, 149 | end 150 | 151 | end graded_module 152 | -------------------------------------------------------------------------------- /src/geometric_algebra/nursery/instances.lean: -------------------------------------------------------------------------------- 1 | import geometric_algebra.nursery.chisolm 2 | import data.complex.module 3 | 4 | instance field_ga (K : Type*) [field K] : geometric_algebra K K K := { 5 | f₁ := { 6 | to_fun := id, 7 | map_zero' := rfl, 8 | map_add' := begin 9 | simp only [forall_const, id.def, eq_self_iff_true] 10 | end 11 | }, 12 | vec_sq_scalar := begin 13 | intro v, 14 | use v * v, 15 | simp only [algebra.id.map_eq_self, add_monoid_hom.coe_mk, id.def], 16 | end 17 | } 18 | 19 | instance rrc_ga : geometric_algebra ℝ ℝ ℂ := { 20 | f₁ := { 21 | to_fun := λx, x, 22 | map_zero' := rfl, 23 | map_add' := begin 24 | intros x y, 25 | norm_cast, 26 | end 27 | }, 28 | vec_sq_scalar := begin 29 | intro v, 30 | use v * v, 31 | simp only [add_monoid_hom.coe_mk, ring_hom.map_mul], 32 | refl, 33 | end 34 | } 35 | 36 | -- noncomputable instance rcc_ga : geometric_algebra ℝ ℂ ℂ := { 37 | -- f₁ := { 38 | -- to_fun := id, 39 | -- map_zero' := rfl, 40 | -- map_add' := by simp, 41 | -- }, 42 | -- vec_sq_scalar := sorry /- mathematically false due to the wrong mul equiped with ℂ -/ 43 | -- } -------------------------------------------------------------------------------- /src/geometric_algebra/translations/README.md: -------------------------------------------------------------------------------- 1 | # Translations of other formalizations 2 | 3 | This folder contains some short attempts at translating definitions in other theorem proving languages to Lean. 4 | The examples here are slightly longer than the ones in our presentation, https://pygae.github.io/lean-ga/ICCA2020. 5 | -------------------------------------------------------------------------------- /src/geometric_algebra/translations/hol_light.lean: -------------------------------------------------------------------------------- 1 | import data.nat.basic 2 | import data.real.basic 3 | import data.fintype.basic 4 | import algebra.big_operators.basic 5 | import linear_algebra.basic 6 | import linear_algebra.tensor_product 7 | import order.symm_diff 8 | 9 | /-! 10 | # Derived from "Formalization of Geometric Algebra in HOL Light" 11 | 12 | This captures a fragment of [this paper](https://link.springer.com/article/10.1007/s10817-018-9498-9), 13 | and [this github repo](https://github.com/jrh13/hol-light/blob/4f2022d3b32eb791231abeb33a85ca818090ba3f/Multivariate/clifford.ml#L496-L504). 14 | 15 | This file is primarily about definitions, we're not interested in the proofs used by others so much. 16 | -/ 17 | 18 | namespace hol 19 | 20 | open_locale big_operators 21 | 22 | variables (n : ℕ) 23 | 24 | -- mapping from subsets of 1:n to coefficients 25 | abbreviation idx := finset (fin n) 26 | 27 | @[derive [add_comm_group, module ℝ]] 28 | def multivector : Type := idx n → ℝ 29 | 30 | variables {n} 31 | 32 | /-- generic product indexed by a sign function -/ 33 | def generic_prod (sgn : idx n → idx n → ℝ) (a b : multivector n) : multivector n := 34 | ∑ ai bi in finset.univ, 35 | pi.single (ai ∆ bi) ((a ai * b bi) * sgn ai bi) 36 | 37 | /-- `generic_prod sgn` is a bilinear map -/ 38 | def generic_prod.bilinear (sgn : idx n → idx n → ℝ) : 39 | multivector n →ₗ[ℝ] multivector n →ₗ[ℝ] multivector n := 40 | begin 41 | with_cases { apply linear_map.mk₂ ℝ (generic_prod sgn) }, 42 | case [H1 : a₁ a₂ b, H3 : a b₁ b₂] { all_goals { 43 | unfold generic_prod, 44 | simp [←finset.sum_add_distrib, add_mul, mul_add], 45 | dsimp only, 46 | congr, ext1, congr, ext1, convert pi.single_add _ _ _; refl 47 | } }, 48 | case [H2 : c a b, H4 : c a b] { all_goals { 49 | unfold generic_prod, 50 | simp [finset.smul_sum, add_smul, smul_add, mul_assoc, mul_left_comm _ c _], 51 | dsimp only, 52 | congr, ext1 ai, congr, ext1 bi, convert pi.single_smul' (ai ∆ bi) c _; refl 53 | } } 54 | end 55 | 56 | /-- wedge product of two multivectors-/ 57 | def wedge : multivector n → multivector n → multivector n := 58 | generic_prod $ λ ai bi, 59 | if ai ∩ bi ≠ ∅ then 0 else -- matching blades 60 | (-1) ^ ( 61 | finset.card $ (ai.product bi).filter $ λ abj, abj.1 > abj.2 62 | ) 63 | 64 | /-- `wedge` is associative -/ 65 | def wedge.assoc : associative (wedge : multivector n → multivector n → multivector n) := 66 | λ a b c, sorry 67 | 68 | end hol -------------------------------------------------------------------------------- /src/geometric_algebra/translations/ida.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser, Utensil Song. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | 7 | import data.real.basic 8 | import data.matrix.basic 9 | import algebra.algebra.basic 10 | import algebra.direct_sum.module 11 | 12 | /-! 13 | # Derived from "A New Formalization of Origami in Geometric Algebra" 14 | 15 | by Tetsuo Ida, Jacques Fleuriot, and Fadoua Ghourabi 16 | -/ 17 | 18 | namespace ida 19 | 20 | @[ext] 21 | structure multivector := 22 | (scalar : ℝ) 23 | (vector : fin 3 → ℝ) 24 | (bivec : fin 3 → ℝ) 25 | (trivec : ℝ) 26 | 27 | namespace multivector 28 | 29 | /-! The basic abelian group operations are defined component-wise. -/ 30 | instance : has_zero multivector := ⟨ 31 | { scalar := 0, vector := 0, bivec := 0, trivec := 0}⟩ 32 | instance : has_add multivector := ⟨λ x y, 33 | { scalar := x.scalar + y.scalar, 34 | vector := x.vector + y.vector, 35 | bivec := x.bivec + y.bivec, 36 | trivec := x.trivec + y.trivec}⟩ 37 | instance : has_sub multivector := ⟨λ x y, 38 | { scalar := x.scalar - y.scalar, 39 | vector := x.vector - y.vector, 40 | bivec := x.bivec - y.bivec, 41 | trivec := x.trivec - y.trivec}⟩ 42 | instance : has_neg multivector := ⟨λ x, 43 | { scalar := -x.scalar, 44 | vector := -x.vector, 45 | bivec := -x.bivec, 46 | trivec := -x.trivec}⟩ 47 | 48 | -- the original paper automates this a bit 49 | instance : add_comm_group multivector := 50 | { zero := 0, add := (+), sub := has_sub.sub, neg := has_neg.neg, 51 | add_zero := λ _, ext _ _ (add_zero _) (add_zero _) (add_zero _) (add_zero _), 52 | zero_add := λ _, ext _ _ (zero_add _) (zero_add _) (zero_add _) (zero_add _), 53 | add_assoc := λ _ _ _, ext _ _ (add_assoc _ _ _) (add_assoc _ _ _) (add_assoc _ _ _) (add_assoc _ _ _), 54 | add_comm := λ _ _, ext _ _ (add_comm _ _) (add_comm _ _) (add_comm _ _) (add_comm _ _), 55 | add_left_neg := λ _, ext _ _ (add_left_neg _) (add_left_neg _) (add_left_neg _) (add_left_neg _) } 56 | 57 | /-! scalar multiplication is also component-wise -/ 58 | instance : has_smul ℝ multivector := ⟨λ r x, 59 | { scalar := r • x.scalar, 60 | vector := r • x.vector, 61 | bivec := r • x.bivec, 62 | trivec := r • x.trivec}⟩ 63 | 64 | instance : module ℝ multivector := 65 | { smul := (•), 66 | smul_zero := λ _, ext _ _ (smul_zero _) (smul_zero _) (smul_zero _) (smul_zero _), 67 | zero_smul := λ _, ext _ _ (zero_smul _ _) (zero_smul _ _) (zero_smul _ _) (zero_smul _ _), 68 | add_smul := λ _ _ _, ext _ _ (add_smul _ _ _) (add_smul _ _ _) (add_smul _ _ _) (add_smul _ _ _), 69 | smul_add := λ _ _ _, ext _ _ (smul_add _ _ _) (smul_add _ _ _) (smul_add _ _ _) (smul_add _ _ _), 70 | one_smul := λ _, ext _ _ (one_smul _ _) (one_smul _ _) (one_smul _ _) (one_smul _ _), 71 | mul_smul := λ _ _ _, ext _ _ (mul_smul _ _ _) (mul_smul _ _ _) (mul_smul _ _ _) (mul_smul _ _ _),} 72 | 73 | open matrix 74 | 75 | instance : has_one multivector := ⟨ 76 | { scalar := 1, vector := 0, bivec := 0, trivec := 0}⟩ 77 | 78 | /-! We do not fully translate the multiplicative structure, as the paper does not contain it and their source 79 | code is no longer available. The content is trivial to reconstruct, but the results are uninteresting. 80 | 81 | We continue anyway with just the important statements which the paper makes. -/ 82 | instance : has_mul multivector := ⟨λ x y, 83 | { scalar := x.scalar * y.scalar + dot_product x.vector y.vector 84 | - dot_product x.bivec y.bivec - x.trivec * y.trivec, 85 | vector := sorry, 86 | bivec := sorry, 87 | trivec := sorry}⟩ 88 | 89 | instance : ring multivector := sorry 90 | 91 | instance : algebra ℝ multivector := sorry 92 | 93 | end multivector 94 | 95 | end ida 96 | -------------------------------------------------------------------------------- /src/geometric_algebra/translations/ida_derived.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser, Utensil Song. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser, Utensil Song 5 | -/ 6 | 7 | import data.real.basic 8 | import algebra.algebra.basic 9 | import algebra.direct_sum.module 10 | 11 | /-! 12 | # Derived from "A New Formalization of Origami in Geometric Algebra" 13 | 14 | This version is an incorrect but accidentally simpler attempt at translating what is now 15 | `ida.multivector`. It is included for completeness, but not referenced in our paper. 16 | -/ 17 | 18 | namespace ida' 19 | 20 | open_locale big_operators 21 | open_locale direct_sum 22 | 23 | -- explicitly give coordinates 24 | def rvector : fin 4 → Type 25 | | ⟨0, _⟩ := ℝ -- scalar 26 | | ⟨1, _⟩ := ℝ × ℝ × ℝ 27 | | ⟨2, _⟩ := ℝ × ℝ × ℝ 28 | | ⟨3, _⟩ := ℝ -- psuedo-scalar 29 | | ⟨n + 4, _⟩ := by linarith 30 | 31 | -- clumsy definition of addition within r-vectors 32 | instance : Π i, add_comm_group (rvector i) 33 | | ⟨0, _⟩ := by {unfold rvector, apply_instance} 34 | | ⟨1, _⟩ := by {unfold rvector, apply_instance} 35 | | ⟨2, _⟩ := by {unfold rvector, apply_instance} 36 | | ⟨3, _⟩ := by {unfold rvector, apply_instance} 37 | | ⟨n + 4, _⟩ := by linarith 38 | 39 | -- lean has all we need to define multivector composition! 40 | abbreviation multivector := ⨁ i, rvector i 41 | def grade (m : multivector) (i) : rvector i := m i 42 | def multivector.of (i) := direct_sum.of rvector i 43 | 44 | -- define multiplication elementwise - tedious 45 | def rvector_mul : Π {i j}, rvector i → rvector j → multivector 46 | | ⟨0, _⟩ ⟨0, _⟩ a b := 47 | multivector.of 0 (a * b : ℝ) 48 | | ⟨1, _⟩ ⟨1, _⟩ ⟨a₁, a₂, a₃⟩ ⟨b₁, b₂, b₃⟩ := 49 | -- euclidean dot product 50 | multivector.of 0 (a₁ * b₁ + a₂ * b₂ + a₃ * b₃ : ℝ) + 51 | -- cross product 52 | multivector.of 2 (sorry : ℝ × ℝ × ℝ) 53 | | _ _ _ _ := 54 | -- down this path lies madness or code generation 55 | sorry 56 | 57 | -- build up the algebra structure 58 | instance : has_mul multivector := ⟨λ a b, ∑ i j, rvector_mul (grade a i) (grade b j)⟩ 59 | instance : ring multivector := sorry 60 | instance : algebra ℝ multivector := sorry 61 | 62 | end ida' 63 | -------------------------------------------------------------------------------- /src/geometric_algebra/translations/laurents.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Eric Wieser. All rights reserved. 3 | Released under MIT license as described in the file LICENSE. 4 | Authors: Eric Wieser 5 | -/ 6 | import algebra.field.basic 7 | import algebra.module.prod 8 | import algebra.algebra.basic 9 | import algebra.punit_instances 10 | import data.finset.sort 11 | import data.vector 12 | import tactic 13 | 14 | /-! 15 | # Derived from "A Formalization of Grassmann-Cayley Algebra in Coq and Its Application to Theorem Proving in Projective Geometry" 16 | 17 | by Laurent Fuchs and Laurent Théry 18 | -/ 19 | 20 | namespace laurent 21 | 22 | variables (α : Type) [field α] 23 | 24 | -- vectors 25 | def Kₙ : ℕ → Type 26 | | 0 := unit 27 | | (n + 1) := α × Kₙ n 28 | -- addition and scalar multiplication 29 | instance : Π (n : ℕ), add_comm_group (Kₙ α n) 30 | | 0 := by {dunfold Kₙ, apply_instance} 31 | | (n + 1) := by {dunfold Kₙ, haveI := Kₙ.add_comm_group n, apply_instance} 32 | instance : Π n, module α (Kₙ α n) 33 | | 0 := by {dunfold Kₙ, apply_instance} 34 | | (n + 1) := by {dunfold Kₙ, haveI := Kₙ.module n, apply_instance} 35 | 36 | -- multivectors 37 | def Gₙ : ℕ → Type 38 | | 0 := α 39 | | (n + 1) := Gₙ n × Gₙ n 40 | -- addition 41 | instance : Π n, add_comm_group (Gₙ α n) 42 | | 0 := by {unfold Gₙ, apply_instance} 43 | | (n + 1) := by {unfold Gₙ, haveI := Gₙ.add_comm_group n, apply_instance} 44 | instance : Π n, module α (Gₙ α n) 45 | | 0 := by {dunfold Gₙ, apply_instance} 46 | | (n + 1) := by {dunfold Gₙ, haveI := Gₙ.module n, apply_instance} 47 | 48 | variables {α} 49 | 50 | -- coercions 51 | def coe_α : Π {n}, α → Gₙ α n 52 | | 0 k := k 53 | | (n + 1) k := (coe_α 0, coe_α k) 54 | instance has_coe_α : Π n, has_coe α (Gₙ α n) := λ n, ⟨coe_α⟩ 55 | def coe_Kₙ : Π {n}, Kₙ α n → Gₙ α n 56 | | 0 k := 0 57 | | (n + 1) ⟨x₁, x₂⟩ := (x₁, coe_Kₙ x₂) 58 | instance has_coe_Kₙ : Π n, has_coe (Kₙ α n) (Gₙ α n) := λ n, ⟨coe_Kₙ⟩ 59 | 60 | -- conjugation 61 | def conj : Π {n}, Gₙ α n → Gₙ α n 62 | | 0 x := x 63 | | (n + 1) ⟨x₁, x₂⟩ := (-conj x₁, conj x₂) 64 | def conj_d : Π {n}, Gₙ α n → Gₙ α n 65 | | 0 x := x 66 | | (n + 1) ⟨x₁, x₂⟩ := (conj_d x₁, -conj_d x₂) 67 | prefix (name := laurent.conj) `̅`:max := conj -- this unicode is probably a bad idea... 68 | notation (name := laurent.conj_d) `̅`:max x `ᵈ` := conj_d x -- this unicode is definitly a bad idea! 69 | 70 | -- vee and wedge 71 | reserve infix `⋏`:70 72 | def wedge : Π {n}, Gₙ α n → Gₙ α n → Gₙ α n 73 | | 0 x y := (x * y : α) 74 | | (n + 1) ⟨x₁, x₂⟩ ⟨y₁, y₂⟩ := let infix ` ⋏ ` := wedge in 75 | (x₁ ⋏ y₂ + ̅x₂ ⋏ y₁, x₂ ⋏ y₂) 76 | infix (name := laurent.wedge) ` ⋏ ` := wedge 77 | reserve infix `⋎`:70 78 | def vee : Π {n}, Gₙ α n → Gₙ α n → Gₙ α n 79 | | 0 x y := (x * y : α) 80 | | (n + 1) ⟨x₁, x₂⟩ ⟨y₁, y₂⟩ := let infix ` ⋎ ` := vee in 81 | (x₂ ⋎ y₂, x₁ ⋎ y₂ + x₂ ⋎ ̅y₁ᵈ) 82 | infix (name := laurent.vee) ` ⋎ ` := vee 83 | 84 | instance {n} : has_one (Gₙ α n):= ⟨(1 : α)⟩ 85 | 86 | section ring_theorems 87 | 88 | @[simp] 89 | lemma coe_α_zero : Π {n}, coe_α 0 = (0 : Gₙ α n) 90 | | 0 := rfl 91 | | (n + 1) := prod.ext coe_α_zero coe_α_zero 92 | 93 | @[simp] 94 | lemma coe_α_add : Π {n} (a b : α), coe_α (a + b) = (coe_α a + coe_α b : Gₙ α n) 95 | | 0 a b := rfl 96 | | (n + 1) a b:= prod.ext (by simp [coe_α]) (coe_α_add _ _) 97 | 98 | @[simp] 99 | lemma conj_zero : Π {n}, conj (0 : Gₙ α n) = 0 100 | | 0 := rfl 101 | | (n + 1) := prod.ext 102 | ((congr_arg has_neg.neg conj_zero).trans neg_zero) 103 | conj_zero 104 | 105 | @[simp] 106 | lemma conj_coe_α : Π {n} a, conj (coe_α a) = (coe_α a : Gₙ α n) 107 | | 0 a := rfl 108 | | (n + 1) a := prod.ext (by simp [conj, coe_α]) (conj_coe_α _) 109 | 110 | @[simp] 111 | lemma conj_one : Π {n}, conj (1 : Gₙ α n) = 1 112 | | 0 := rfl 113 | | (n + 1) := prod.ext 114 | (show -conj _ = coe_α _, by rw [coe_α_zero, conj_zero, neg_zero]) 115 | conj_one 116 | 117 | lemma conj_add : Π {n} (x y : Gₙ α n), conj (x + y) = conj x + conj y 118 | | 0 (x : α) y := rfl 119 | | (n + 1) (x₁, x₂) (y₁, y₂) := prod.ext 120 | ((congr_arg _ $ conj_add x₁ y₁).trans $ neg_add _ _) 121 | (conj_add x₂ y₂) 122 | 123 | lemma wedge_add : Π {n} (x y z : Gₙ α n), x ⋏ (y + z) = x ⋏ y + x ⋏ z 124 | | 0 (x : α) y z := mul_add x y z 125 | | (n + 1) (x₁, x₂) (y₁, y₂) (z₁, z₂) := prod.ext 126 | ((congr_arg2 (+) (wedge_add _ _ _) (wedge_add _ _ _)).trans (add_add_add_comm _ _ _ _)) 127 | (wedge_add _ _ _) 128 | 129 | lemma add_wedge : Π {n} (x y z : Gₙ α n), (x + y) ⋏ z = x ⋏ z + y ⋏ z 130 | | 0 (x : α) y z := add_mul x y z 131 | | (n + 1) (x₁, x₂) (y₁, y₂) (z₁, z₂) := prod.ext 132 | ((congr_arg2 (+) (add_wedge _ _ _) $ 133 | eq.trans (by rw [conj_add]) (add_wedge _ _ _)).trans (add_add_add_comm _ _ _ _)) 134 | (add_wedge _ _ _) 135 | 136 | @[simp] 137 | lemma wedge_zero : Π {n} (x : Gₙ α n), x ⋏ 0 = 0 138 | | 0 (x : α) := mul_zero x 139 | | (n + 1) (x₁, x₂) := prod.ext 140 | ((congr_arg2 _ (wedge_zero _) (wedge_zero _)).trans $ add_zero _) (wedge_zero _) 141 | 142 | @[simp] 143 | lemma zero_wedge : Π {n} (x : Gₙ α n), 0 ⋏ x = 0 144 | | 0 (x : α) := zero_mul x 145 | | (n + 1) (x₁, x₂) := prod.ext 146 | ((congr_arg2 (+) (zero_wedge _) 147 | (by rw [conj_zero, zero_wedge])).trans $ add_zero _) (zero_wedge _) 148 | 149 | @[simp] 150 | lemma wedge_one : Π {n} (x : Gₙ α n), x ⋏ 1 = x 151 | | 0 (x : α) := mul_one x 152 | | (n + 1) (x₁, x₂) := prod.ext 153 | (show x₁ ⋏ 1 + _ ⋏ _ = _, by rw [wedge_one, coe_α_zero, wedge_zero, add_zero]) 154 | (wedge_one _) 155 | 156 | @[simp] 157 | lemma one_wedge : Π {n} (x : Gₙ α n), 1 ⋏ x = x 158 | | 0 (x : α) := one_mul x 159 | | (n + 1) (x₁, x₂) := prod.ext 160 | (show _ ⋏ _ + (conj 1) ⋏ _ = _, by rw [conj_one, one_wedge, coe_α_zero, zero_wedge, zero_add]) 161 | (one_wedge _) 162 | 163 | instance {n} : non_assoc_ring (Gₙ α n) := 164 | { mul := (⋏), 165 | one := 1, 166 | zero_mul := zero_wedge, 167 | mul_zero := wedge_zero, 168 | one_mul := one_wedge, 169 | mul_one := wedge_one, 170 | left_distrib := wedge_add, 171 | right_distrib := add_wedge, 172 | .. (by apply_instance : add_comm_group (Gₙ α n)) } 173 | 174 | @[simp] 175 | lemma wedge_neg {n} (x y : Gₙ α n) : x ⋏ (-y) = -(x ⋏ y) := 176 | mul_neg _ _ 177 | 178 | @[simp] 179 | lemma neg_wedge {n} (x y : Gₙ α n) : (-x) ⋏ y = -(x ⋏ y) := 180 | neg_mul _ _ 181 | 182 | lemma conj_wedge : Π {n} (x y : Gₙ α n), conj (x ⋏ y) = conj x ⋏ conj y 183 | | 0 (x : α) y := by simp [wedge, conj] 184 | | (n + 1) (x₁, x₂) (y₁, y₂) := by simp [wedge, conj, conj_wedge, conj_add, add_comm] 185 | 186 | lemma wedge_assoc : Π {n} (x y z : Gₙ α n), (x ⋏ y) ⋏ z = x ⋏ (y ⋏ z) 187 | | 0 (x : α) y z := mul_assoc x y z 188 | | (n + 1) (x₁, x₂) (y₁, y₂) (z₁, z₂) := prod.ext 189 | (by simp_rw [wedge, add_wedge, wedge_add, ←wedge_assoc, add_assoc, conj_wedge]) 190 | (wedge_assoc _ _ _) 191 | 192 | lemma coe_α_wedge : Π {n} (a : α) (x : Gₙ α n), coe_α a ⋏ x = a • x 193 | | 0 a (x : α) := rfl 194 | | (n + 1) a (x₁, x₂) := prod.ext 195 | (by simp_rw [coe_α, wedge, prod.smul_fst, coe_α_zero, zero_wedge, zero_add, conj_coe_α, 196 | coe_α_wedge]) 197 | (coe_α_wedge _ _) 198 | 199 | lemma wedge_coe_α : Π {n} (x : Gₙ α n) (a : α), x ⋏ coe_α a = a • x 200 | | 0 (x : α) a := mul_comm x a 201 | | (n + 1) (x₁, x₂) a := prod.ext 202 | (by simp [coe_α, wedge, wedge_coe_α]) 203 | (by simp [coe_α, wedge, wedge_coe_α]) 204 | 205 | lemma coe_α_mul : Π {n} (a b : α), coe_α (a * b) = (coe_α a ⋏ coe_α b : Gₙ α n) 206 | | 0 a b := rfl 207 | | (n + 1) a b := prod.ext (by simp [coe_α, wedge]) (by simp [coe_α, wedge, @coe_α_mul n]) 208 | 209 | instance {n} : ring (Gₙ α n) := 210 | { mul := (⋏), 211 | one := 1, 212 | mul_assoc := wedge_assoc, 213 | .. (by apply_instance : non_assoc_ring (Gₙ α n)) } 214 | 215 | instance {n} : algebra α (Gₙ α n) := 216 | { smul := (•), 217 | to_fun := coe_α, 218 | map_one' := rfl, 219 | map_mul' := coe_α_mul, 220 | map_zero' := coe_α_zero, 221 | map_add' := coe_α_add, 222 | commutes' := λ r x, (coe_α_wedge r x).trans (wedge_coe_α _ _).symm, 223 | smul_def' := λ r x, (coe_α_wedge r x).symm } 224 | 225 | end ring_theorems 226 | 227 | section vee_theorems 228 | 229 | @[simp] 230 | lemma conj_d_zero : Π {n}, conj_d (0 : Gₙ α n) = 0 231 | | 0 := rfl 232 | | (n + 1) := prod.ext 233 | conj_d_zero 234 | ((congr_arg has_neg.neg conj_d_zero).trans neg_zero) 235 | 236 | lemma conj_d_add : Π {n} (x y : Gₙ α n), conj_d (x + y) = conj_d x + conj_d y 237 | | 0 (x : α) y := rfl 238 | | (n + 1) (x₁, x₂) (y₁, y₂) := prod.ext 239 | (conj_d_add x₁ y₁) 240 | ((congr_arg _ $ conj_d_add x₂ y₂).trans $ neg_add _ _) 241 | 242 | lemma vee_add : Π {n} (x y z : Gₙ α n), x ⋎ (y + z) = x ⋎ y + x ⋎ z 243 | | 0 (x : α) y z := (mul_add x y z :_) 244 | | (n + 1) (x₁, x₂) (y₁, y₂) (z₁, z₂) := prod.ext 245 | (vee_add _ _ _) 246 | ((congr_arg2 (+) (vee_add _ _ _) $ 247 | (congr_arg _ (conj_d_add _ _)).trans (vee_add _ _ _)).trans (add_add_add_comm _ _ _ _)) 248 | 249 | lemma add_vee : Π {n} (x y z : Gₙ α n), (x + y) ⋎ z = x ⋎ z + y ⋎ z 250 | | 0 (x : α) y z := (add_mul x y z : _) 251 | | (n + 1) (x₁, x₂) (y₁, y₂) (z₁, z₂) := prod.ext 252 | (add_vee _ _ _) 253 | (eq.trans (congr_arg2 (+) (add_vee _ _ _) (add_vee _ _ _)) (add_add_add_comm _ _ _ _)) 254 | 255 | end vee_theorems 256 | 257 | def Gₙ.coeff : Π {n}, Gₙ α n → finset (fin n) → α 258 | | 0 x s := x 259 | | (n + 1) (xi, yi) s := 260 | let s' : finset (fin n) := s.bUnion (λ i : fin n.succ, fin.cases ∅ singleton i) in 261 | (if (0 : fin n.succ) ∈ s then xi else yi).coeff s' 262 | 263 | instance has_repr [has_repr α] {n} : has_repr (Gₙ α n) := 264 | { repr := λ x, 265 | let basis : list (finset (fin n)) := 266 | (list.range (n + 1)).bind (λ k, 267 | ((list.fin_range n).sublists_len k).map list.to_finset) in 268 | let parts := basis.filter_map $ λ s, 269 | let c := repr (x.coeff s) in 270 | if c = "0" then 271 | none 272 | else 273 | some $ c ++ 274 | if s.card = 0 then 275 | "" 276 | else 277 | "•e" ++ string.join ((s.sort (≤)).map repr) in 278 | match parts with 279 | | [] := "0" 280 | | _ := string.intercalate " + " parts 281 | end } 282 | 283 | section example_3d 284 | 285 | def x : Gₙ ℚ 3 := coe_Kₙ (1, 0, 0, ()) 286 | def y : Gₙ ℚ 3 := coe_Kₙ (0, 1, 0, ()) 287 | def z : Gₙ ℚ 3 := coe_Kₙ (0, 0, 1, ()) 288 | 289 | #eval (0 : Gₙ ℚ 3) 290 | #eval [x, y, z] 291 | #eval [x ⋏ y, y ⋏ z, x ⋏ z] 292 | #eval [x ⋎ y, y ⋎ z, x ⋎ z] 293 | #eval [(x ⋏ y) ⋏ z, x ⋏ (y ⋏ z)] 294 | #eval [(x ⋏ y) ⋏ z, x ⋏ (y ⋏ z)] 295 | #eval [(x ⋎ y) ⋎ z, x ⋎ (y ⋎ z)] 296 | #eval (x + y) ⋎ (x ⋏ y) 297 | 298 | end example_3d 299 | 300 | end laurent 301 | --------------------------------------------------------------------------------