Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7bcd49c
wip
eric-wieser Aug 7, 2023
b14cba2
wip
eric-wieser Aug 17, 2023
4ad432b
update
eric-wieser Aug 17, 2023
71a9111
cleanup
eric-wieser Aug 17, 2023
301236d
add import
eric-wieser Aug 17, 2023
1133939
fix
eric-wieser Aug 17, 2023
4f85ca3
helper lemma
eric-wieser Aug 17, 2023
0e1ef11
Update Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean
eric-wieser Aug 18, 2023
89fef2c
feat: base change of Clifford algebras
eric-wieser Aug 25, 2023
4b75e62
Merge remote-tracking branch 'origin/master' into eric-wieser/Cliffor…
eric-wieser Aug 25, 2023
570460e
a bit closer to fixed
eric-wieser Aug 25, 2023
9c091cd
missing functorial lemmas
eric-wieser Aug 25, 2023
3eb6233
expose implementation details of 'reverse'
eric-wieser Aug 25, 2023
9012171
wip
eric-wieser Aug 25, 2023
f7c2b81
chore(LinearAlgebra/TensorProduct/Tower): missing functorial lemmas
eric-wieser Aug 25, 2023
88c111b
refactor(LinearAlgebra/CliffordAlgebra/Conjugation): expose implement…
eric-wieser Aug 25, 2023
d4ad602
Merge remote-tracking branch 'origin/eric-wieser/Clifford.reverseOp' …
eric-wieser Aug 25, 2023
deff414
Merge remote-tracking branch 'origin/eric-wieser/tensor-functorial' i…
eric-wieser Aug 25, 2023
f758ce7
docstring
eric-wieser Aug 25, 2023
f678bc8
add AlgHom versions too
eric-wieser Aug 25, 2023
1468963
fix build
eric-wieser Aug 25, 2023
203739a
Merge branch 'eric-wieser/tensor-functorial' into eric-wieser/Cliffor…
eric-wieser Aug 25, 2023
c97d835
partial fix
eric-wieser Aug 25, 2023
48d407a
Merge remote-tracking branch 'origin/master' into eric-wieser/Cliffor…
eric-wieser Sep 8, 2023
49c3410
Merge remote-tracking branch 'origin/master' into eric-wieser/Cliffor…
eric-wieser Sep 8, 2023
5e46b50
fix docstrings
eric-wieser Sep 8, 2023
45ba2ac
Merge remote-tracking branch 'origin/master' into eric-wieser/Cliffor…
eric-wieser Sep 11, 2023
40489e9
sorry-free but messy
eric-wieser Sep 12, 2023
6d5d036
style fixes
eric-wieser Sep 13, 2023
08115ab
fix Mathlib order
eric-wieser Sep 13, 2023
934d0ec
Merge remote-tracking branch 'origin/master' into eric-wieser/Cliffor…
eric-wieser Sep 14, 2023
a17529c
minor statement golf
eric-wieser Sep 14, 2023
f37187c
golf
eric-wieser Sep 14, 2023
8b34aec
helper lemmas
eric-wieser Sep 14, 2023
20e4ec3
golf
eric-wieser Sep 14, 2023
48985e9
even more golf
eric-wieser Sep 14, 2023
248ba57
Merge remote-tracking branch 'origin/master' into eric-wieser/Cliffor…
eric-wieser Sep 16, 2023
9e29226
golf slightly, and make more readable
eric-wieser Sep 16, 2023
8467a30
fix docstring
eric-wieser Sep 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Mathlib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,7 @@ import Mathlib.LinearAlgebra.BilinearForm.TensorProduct
import Mathlib.LinearAlgebra.BilinearMap
import Mathlib.LinearAlgebra.Charpoly.Basic
import Mathlib.LinearAlgebra.Charpoly.ToMatrix
import Mathlib.LinearAlgebra.CliffordAlgebra.BaseChange
import Mathlib.LinearAlgebra.CliffordAlgebra.Basic
import Mathlib.LinearAlgebra.CliffordAlgebra.Conjugation
import Mathlib.LinearAlgebra.CliffordAlgebra.Contraction
Expand Down
201 changes: 201 additions & 0 deletions Mathlib/LinearAlgebra/CliffordAlgebra/BaseChange.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/-
Copyright (c) 2023 Eric Wieser. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Eric Wieser
-/
import Mathlib.Data.Complex.Module
import Mathlib.LinearAlgebra.QuadraticForm.TensorProduct
import Mathlib.LinearAlgebra.CliffordAlgebra.Conjugation
import Mathlib.LinearAlgebra.TensorProduct.Opposite
import Mathlib.RingTheory.TensorProduct

/-!
# The base change of a clifford algebra

In this file we show the isomorphism

* `CliffordAlgebra.equivBaseChange A Q` :
`CliffordAlgebra (Q.baseChange A) ≃ₐ[A] (A ⊗[R] CliffordAlgebra Q)`
with forward direction `CliffordAlgebra.toBasechange A Q` and reverse direction
`CliffordAlgebra.ofBasechange A Q`.

This covers a more general case of the complexification of clifford algebras (as described in §2.2
of https://empg.maths.ed.ac.uk/Activities/Spin/Lecture2.pdf), where ℂ and ℝ are replaced by an
`R`-algebra `A` (where `2 : R` is invertible).

We show the additional results:

* `CliffordAlgebra.toBasechange_ι`: the effect of base-changing pure vectors.
* `CliffordAlgebra.ofBasechange_tmul_ι`: the effect of un-base-changing a tensor of a pure vectors.
* `CliffordAlgebra.toBasechange_involute`: the effect of base-changing an involution.
* `CliffordAlgebra.toBasechange_reverse`: the effect of base-changing a reversal.
-/

variable {R A V : Type*}
variable [CommRing R] [CommRing A] [AddCommGroup V]
variable [Algebra R A] [Module R V] [Module A V] [IsScalarTower R A V]
variable [Invertible (2 : R)]

open scoped TensorProduct

namespace CliffordAlgebra

variable (A)

/-- Auxiliary construction: note this is really just a heterobasic `CliffordAlgebra.map`. -/
def ofBaseChangeAux (Q : QuadraticForm R V) :
CliffordAlgebra Q →ₐ[R] CliffordAlgebra (Q.baseChange A) :=
CliffordAlgebra.lift Q <| by
refine ⟨(ι (Q.baseChange A)).restrictScalars R ∘ₗ TensorProduct.mk R A V 1, fun v => ?_⟩
refine (CliffordAlgebra.ι_sq_scalar (Q.baseChange A) (1 ⊗ₜ v)).trans ?_
rw [QuadraticForm.baseChange_tmul, one_mul, ←Algebra.algebraMap_eq_smul_one,
←IsScalarTower.algebraMap_apply]

@[simp] theorem ofBaseChangeAux_ι (Q : QuadraticForm R V) (v : V) :
ofBaseChangeAux A Q (ι Q v) = ι (Q.baseChange A) (1 ⊗ₜ v) :=
CliffordAlgebra.lift_ι_apply _ _ v

/-- Convert from the base-changed clifford algebra to the clifford algebra over a base-changed
module. -/
def ofBaseChange (Q : QuadraticForm R V) :
A ⊗[R] CliffordAlgebra Q →ₐ[A] CliffordAlgebra (Q.baseChange A) :=
Algebra.TensorProduct.algHomOfLinearMapTensorProduct
(TensorProduct.AlgebraTensorModule.lift <|
let f : A →ₗ[A] _ := (Algebra.lsmul A A (CliffordAlgebra (Q.baseChange A))).toLinearMap
LinearMap.flip <| LinearMap.flip (({
toFun := fun f : CliffordAlgebra (Q.baseChange A) →ₗ[A] CliffordAlgebra (Q.baseChange A) =>
LinearMap.restrictScalars R f
map_add' := fun f g => LinearMap.ext fun x => rfl
map_smul' := fun (c : A) g => LinearMap.ext fun x => rfl
} : _ →ₗ[A] _) ∘ₗ f) ∘ₗ (ofBaseChangeAux A Q).toLinearMap)
(fun z₁ z₂ b₁ b₂ =>
show (z₁ * z₂) • ofBaseChangeAux A Q (b₁ * b₂)
= z₁ • ofBaseChangeAux A Q b₁ * z₂ • ofBaseChangeAux A Q b₂
by rw [map_mul, smul_mul_smul])
(fun r =>
show r • ofBaseChangeAux A Q 1 = algebraMap A (CliffordAlgebra (Q.baseChange A)) r
by rw [map_one, Algebra.algebraMap_eq_smul_one])

@[simp] theorem ofBaseChange_tmul_ι (Q : QuadraticForm R V) (z : A) (v : V) :
ofBaseChange A Q (z ⊗ₜ ι Q v) = ι (Q.baseChange A) (z ⊗ₜ v) := by
show z • ofBaseChangeAux A Q (ι Q v) = ι (Q.baseChange A) (z ⊗ₜ[R] v)
rw [ofBaseChangeAux_ι, ←map_smul, TensorProduct.smul_tmul', smul_eq_mul, mul_one]

@[simp] theorem ofBaseChange_tmul_one (Q : QuadraticForm R V) (z : A) :
ofBaseChange A Q (z ⊗ₜ 1) = algebraMap _ _ z := by
show z • ofBaseChangeAux A Q 1 = _
rw [map_one, ←Algebra.algebraMap_eq_smul_one]

/-- Convert from the clifford algebra over a base-changed module to the base-changed clifford
algebra. -/
def toBaseChange (Q : QuadraticForm R V) :
CliffordAlgebra (Q.baseChange A) →ₐ[A] A ⊗[R] CliffordAlgebra Q :=
CliffordAlgebra.lift _ <| by
refine ⟨TensorProduct.AlgebraTensorModule.map (LinearMap.id : A →ₗ[A] A) (ι Q), ?_⟩
letI : Invertible (2 : A) := (Invertible.map (algebraMap R A) 2).copy 2 (map_ofNat _ _).symm
letI : Invertible (2 : A ⊗[R] CliffordAlgebra Q) :=
(Invertible.map (algebraMap R _) 2).copy 2 (map_ofNat _ _).symm
suffices hpure_tensor : ∀ v w, (1 * 1) ⊗ₜ[R] (ι Q v * ι Q w) + (1 * 1) ⊗ₜ[R] (ι Q w * ι Q v) =
QuadraticForm.polarBilin (Q.baseChange A) (1 ⊗ₜ[R] v) (1 ⊗ₜ[R] w) ⊗ₜ[R] 1 by
-- the crux is that by converting to a statement about linear maps instead of quadratic forms,
-- we then have access to all the partially-applied `ext` lemmas.
rw [CliffordAlgebra.forall_mul_self_eq_iff (isUnit_of_invertible _)]
refine TensorProduct.AlgebraTensorModule.curry_injective ?_
ext v w
exact hpure_tensor v w
intros v w
rw [← TensorProduct.tmul_add, CliffordAlgebra.ι_mul_ι_add_swap,
QuadraticForm.polarBilin_baseChange, BilinForm.baseChange_tmul, one_mul,
TensorProduct.smul_tmul, Algebra.algebraMap_eq_smul_one, QuadraticForm.polarBilin_apply]

@[simp] theorem toBaseChange_ι (Q : QuadraticForm R V) (z : A) (v : V) :
toBaseChange A Q (ι (Q.baseChange A) (z ⊗ₜ v)) = z ⊗ₜ ι Q v :=
CliffordAlgebra.lift_ι_apply _ _ _

theorem toBaseChange_comp_involute (Q : QuadraticForm R V) :
(toBaseChange A Q).comp (involute : CliffordAlgebra (Q.baseChange A) →ₐ[A] _) =
(Algebra.TensorProduct.map (AlgHom.id _ _) involute).comp (toBaseChange A Q) := by
ext v
show toBaseChange A Q (involute (ι (Q.baseChange A) (1 ⊗ₜ[R] v)))
= (Algebra.TensorProduct.map (AlgHom.id _ _) involute :
A ⊗[R] CliffordAlgebra Q →ₐ[A] _)
(toBaseChange A Q (ι (Q.baseChange A) (1 ⊗ₜ[R] v)))
rw [toBaseChange_ι, involute_ι, map_neg (toBaseChange A Q), toBaseChange_ι,
Algebra.TensorProduct.map_tmul, AlgHom.id_apply, involute_ι, TensorProduct.tmul_neg]

/-- The involution acts only on the right of the tensor product. -/
theorem toBaseChange_involute (Q : QuadraticForm R V) (x : CliffordAlgebra (Q.baseChange A)) :
toBaseChange A Q (involute x) =
TensorProduct.map LinearMap.id (involute.toLinearMap) (toBaseChange A Q x) :=
FunLike.congr_fun (toBaseChange_comp_involute A Q) x

open MulOpposite

/-- Auxiliary theorem used to prove `toBaseChange_reverse` without needing induction. -/
theorem toBaseChange_comp_reverseOp (Q : QuadraticForm R V) :
(toBaseChange A Q).op.comp (reverseOp) =
((Algebra.TensorProduct.opAlgEquiv R A A (CliffordAlgebra Q)).toAlgHom.comp <|
(Algebra.TensorProduct.map
(AlgEquiv.toOpposite A A).toAlgHom (reverseOp (Q := Q))).comp
(toBaseChange A Q)) := by
ext v
show op (toBaseChange A Q (reverse (ι (Q.baseChange A) (1 ⊗ₜ[R] v)))) =
Algebra.TensorProduct.opAlgEquiv R A A (CliffordAlgebra Q)
(Algebra.TensorProduct.map (AlgEquiv.toOpposite A A).toAlgHom (reverseOp (Q := Q))
(toBaseChange A Q (ι (Q.baseChange A) (1 ⊗ₜ[R] v))))
rw [toBaseChange_ι, reverse_ι, toBaseChange_ι, Algebra.TensorProduct.map_tmul,
Algebra.TensorProduct.opAlgEquiv_tmul, reverseOp_ι]
rfl

/-- `reverse` acts only on the right of the tensor product. -/
theorem toBaseChange_reverse (Q : QuadraticForm R V) (x : CliffordAlgebra (Q.baseChange A)) :
toBaseChange A Q (reverse x) =
TensorProduct.map LinearMap.id reverse (toBaseChange A Q x) := by
have := FunLike.congr_fun (toBaseChange_comp_reverseOp A Q) x
refine (congr_arg unop this).trans ?_; clear this
refine (LinearMap.congr_fun (TensorProduct.AlgebraTensorModule.map_comp _ _ _ _).symm _).trans ?_
rw [reverse, ←AlgEquiv.toLinearMap, ←AlgEquiv.toLinearEquiv_toLinearMap,
AlgEquiv.toLinearEquiv_toOpposite]
simp
rfl

attribute [ext] TensorProduct.ext

theorem toBaseChange_comp_ofBaseChange (Q : QuadraticForm R V) :
(toBaseChange A Q).comp (ofBaseChange A Q) = AlgHom.id _ _ := by
ext z : 2
· change toBaseChange A Q (ofBaseChange A Q (z ⊗ₜ[R] 1)) = z ⊗ₜ[R] 1
rw [ofBaseChange_tmul_one, AlgHom.commutes, Algebra.TensorProduct.algebraMap_apply,
Algebra.id.map_eq_self]
· ext v : 1
change toBaseChange A Q (ofBaseChange A Q (1 ⊗ₜ[R] ι Q v)) = 1 ⊗ₜ[R] ι Q v
rw [ofBaseChange_tmul_ι, toBaseChange_ι]

@[simp] theorem toBaseChange_ofBaseChange (Q : QuadraticForm R V) (x : A ⊗[R] CliffordAlgebra Q) :
toBaseChange A Q (ofBaseChange A Q x) = x :=
AlgHom.congr_fun (toBaseChange_comp_ofBaseChange A Q : _) x

theorem ofBaseChange_comp_toBaseChange (Q : QuadraticForm R V) :
(ofBaseChange A Q).comp (toBaseChange A Q) = AlgHom.id _ _ := by
ext x
show ofBaseChange A Q (toBaseChange A Q (ι (Q.baseChange A) (1 ⊗ₜ[R] x)))
= ι (Q.baseChange A) (1 ⊗ₜ[R] x)
rw [toBaseChange_ι, ofBaseChange_tmul_ι]

@[simp] theorem ofBaseChange_toBaseChange
(Q : QuadraticForm R V) (x : CliffordAlgebra (Q.baseChange A)) :
ofBaseChange A Q (toBaseChange A Q x) = x :=
AlgHom.congr_fun (ofBaseChange_comp_toBaseChange A Q : _) x

/-- Base-changing the vector space of a clifford algebra is isomorphic as an A-algebra to
base-changing the clifford algebra itself; <|Cℓ(A ⊗_R V, Q_A) ≅ A ⊗_R Cℓ(V, Q)<|.

This is `CliffordAlgebra.toBaseChange` and `CliffordAlgebra.ofBaseChange` as an equivalence. -/
@[simps!]
def equivBaseChange (Q : QuadraticForm R V) :
CliffordAlgebra (Q.baseChange A) ≃ₐ[A] A ⊗[R] CliffordAlgebra Q :=
AlgEquiv.ofAlgHom (toBaseChange A Q) (ofBaseChange A Q)
(toBaseChange_comp_ofBaseChange A Q)
(ofBaseChange_comp_toBaseChange A Q)

end CliffordAlgebra
32 changes: 26 additions & 6 deletions Mathlib/LinearAlgebra/CliffordAlgebra/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,36 @@ theorem induction {C : CliffordAlgebra Q → Prop}
exact Subtype.prop (lift Q of a)
#align clifford_algebra.induction CliffordAlgebra.induction

/-- The symmetric product of vectors is a scalar -/
theorem ι_mul_ι_add_swap (a b : M) :
ι Q a * ι Q b + ι Q b * ι Q a = algebraMap R _ (QuadraticForm.polar Q a b) :=
theorem mul_add_swap_eq_polar_of_forall_mul_self_eq {A : Type*} [Ring A] [Algebra R A]
(f : M →ₗ[R] A) (hf : ∀ x, f x * f x = algebraMap _ _ (Q x)) (a b : M) :
f a * f b + f b * f a = algebraMap R _ (QuadraticForm.polar Q a b) :=
calc
ι Q a * ι Q b + ι Q b * ι Q a = ι Q (a + b) * ι Q (a + b) - ι Q a * ι Q a - ι Q b * ι Q b := by
rw [(ι Q).map_add, mul_add, add_mul, add_mul]; abel
f a * f b + f b * f a = f (a + b) * f (a + b) - f a * f a - f b * f b := by
rw [f.map_add, mul_add, add_mul, add_mul]; abel
_ = algebraMap R _ (Q (a + b)) - algebraMap R _ (Q a) - algebraMap R _ (Q b) := by
rw [ι_sq_scalar, ι_sq_scalar, ι_sq_scalar]
rw [hf, hf, hf]
_ = algebraMap R _ (Q (a + b) - Q a - Q b) := by rw [← RingHom.map_sub, ← RingHom.map_sub]
_ = algebraMap R _ (QuadraticForm.polar Q a b) := rfl

/-- An alternative way to provide the argument to `CliffordAlgebra.lift` when `2` is invertible.

To show a function squares to the quadratic form, it suffices to show that
`f x * f y + f y * f x = algebraMap _ _ (polar Q x y)` -/
theorem forall_mul_self_eq_iff {A : Type*} [Ring A] [Algebra R A] (h2 : IsUnit (2 : A))
(f : M →ₗ[R] A) :
(∀ x, f x * f x = algebraMap _ _ (Q x)) ↔
(LinearMap.mul R A).compl₂ f ∘ₗ f + (LinearMap.mul R A).flip.compl₂ f ∘ₗ f =
Q.polarBilin.toLin.compr₂ (Algebra.linearMap R A) := by
simp_rw [FunLike.ext_iff]
refine ⟨mul_add_swap_eq_polar_of_forall_mul_self_eq _, fun h x => ?_⟩
change ∀ x y : M, f x * f y + f y * f x = algebraMap R A (QuadraticForm.polar Q x y) at h
apply h2.mul_left_cancel
rw [two_mul, two_mul, h x x, QuadraticForm.polar_self, two_mul, map_add]

/-- The symmetric product of vectors is a scalar -/
theorem ι_mul_ι_add_swap (a b : M) :
ι Q a * ι Q b + ι Q b * ι Q a = algebraMap R _ (QuadraticForm.polar Q a b) :=
mul_add_swap_eq_polar_of_forall_mul_self_eq _ (ι_sq_scalar _) _ _
#align clifford_algebra.ι_mul_ι_add_swap CliffordAlgebra.ι_mul_ι_add_swap

theorem ι_mul_comm (a b : M) :
Expand Down