Tensors and index notation 🚧
Note Authors: Joseph Tooby-Smith
These notes are created using an interactive theorem
prover called Lean.
Lean formally checks definitions, theorems and proofs for correctness.
These notes are part of a much larger project called
PhysLean, which aims to digitalize
physics into Lean. Please consider contributing to this project.
Please provide feedback or suggestions for improvements by creating a GitHub issue
here.
Table of content
1. Introduction
2. Tensor Species
2.1. Example: Complex Lorentz tensors
3. Tensor trees
3.1. Node identities
4. Elaboration
5. Example use: Pauli matrices
1. Introduction
This note is related to: https://arxiv.org/pdf/2411.07667, and concerns the implmentation of tensors and index notation into PhysLean, and its mathematical structure.
This note is not intended to be a first-introduction to tensors and index notation.
2. Tensor Species
The structure TensorSpecies
contains the necessary structure needed to define
a system of tensors with index notation. Examples of TensorSpecies
include real Lorentz tensors,
complex Lorentz tensors, and ordinary Euclidean tensors.
Show Lean code:
structure TensorSpecies where
/-- The commutative ring over which we want to consider the tensors to live in,
usually `ℝ` or `ℂ`. -/
k : Type
/-- An instance of `k` as a commutative ring. -/
k_commRing : CommRing k
/-- The symmetry group acting on these tensor e.g. the Lorentz group or SL(2,ℂ). -/
G : Type
/-- An instance of `G` as a group. -/
G_group : Group G
/-- The colors of indices e.g. up or down. -/
C : Type
/-- A functor from `C` to `Rep k G` giving our building block representations.
Equivalently a function `C → Re k G`. -/
FD : Discrete C ⥤ Rep k G
/-- A specification of the dimension of each color in C. This will be used for explicit
evaluation of tensors. -/
repDim : C → ℕ
/-- repDim is not zero for any color. This allows casting of `ℕ` to `Fin (S.repDim c)`. -/
repDim_neZero (c : C) : NeZero (repDim c)
/-- A basis for each Module, determined by the evaluation map. -/
basis : (c : C) → Basis (Fin (repDim c)) k (FD.obj (Discrete.mk c)).V
/-- A map from `C` to `C`. An involution. -/
τ : C → C
/-- The condition that `τ` is an involution. -/
τ_involution : Function.Involutive τ
/-- The natural transformation describing contraction. -/
contr : OverColor.Discrete.pairτ FD τ ⟶ 𝟙_ (Discrete C ⥤ Rep k G)
/-- Contraction is symmetric with respect to duals. -/
contr_tmul_symm (c : C) (x : FD.obj (Discrete.mk c))
(y : FD.obj (Discrete.mk (τ c))) :
(contr.app (Discrete.mk c)).hom (x ⊗ₜ[k] y) = (contr.app (Discrete.mk (τ c))).hom
(y ⊗ₜ (FD.map (Discrete.eqToHom (τ_involution c).symm)).hom x)
/-- The natural transformation describing the unit. -/
unit : 𝟙_ (Discrete C ⥤ Rep k G) ⟶ OverColor.Discrete.τPair FD τ
/-- The unit is symmetric. -/
unit_symm (c : C) :
((unit.app (Discrete.mk c)).hom (1 : k)) =
((FD.obj (Discrete.mk (τ (c)))) ◁
(FD.map (Discrete.eqToHom (τ_involution c)))).hom
((β_ (FD.obj (Discrete.mk (τ (τ c)))) (FD.obj (Discrete.mk (τ (c))))).hom.hom
((unit.app (Discrete.mk (τ c))).hom (1 : k)))
/-- Contraction with unit leaves invariant. -/
contr_unit (c : C) (x : FD.obj (Discrete.mk (c))) :
(λ_ (FD.obj (Discrete.mk (c)))).hom.hom
(((contr.app (Discrete.mk c)) ▷ (FD.obj (Discrete.mk (c)))).hom
((α_ _ _ (FD.obj (Discrete.mk (c)))).inv.hom
(x ⊗ₜ[k] (unit.app (Discrete.mk c)).hom (1 : k)))) = x
/-- The natural transformation describing the metric. -/
metric : 𝟙_ (Discrete C ⥤ Rep k G) ⟶ OverColor.Discrete.pair FD
/-- On contracting metrics we get back the unit. -/
contr_metric (c : C) :
(β_ (FD.obj (Discrete.mk c)) (FD.obj (Discrete.mk (τ c)))).hom.hom
(((FD.obj (Discrete.mk c)) ◁ (λ_ (FD.obj (Discrete.mk (τ c)))).hom).hom
(((FD.obj (Discrete.mk c)) ◁ ((contr.app (Discrete.mk c)) ▷
(FD.obj (Discrete.mk (τ c))))).hom
(((FD.obj (Discrete.mk c)) ◁ (α_ (FD.obj (Discrete.mk (c)))
(FD.obj (Discrete.mk (τ c))) (FD.obj (Discrete.mk (τ c)))).inv).hom
((α_ (FD.obj (Discrete.mk (c))) (FD.obj (Discrete.mk (c)))
(FD.obj (Discrete.mk (τ c)) ⊗ FD.obj (Discrete.mk (τ c)))).hom.hom
((metric.app (Discrete.mk c)).hom (1 : k) ⊗ₜ[k]
(metric.app (Discrete.mk (τ c))).hom (1 : k))))))
= (unit.app (Discrete.mk c)).hom (1 : k)
2.1. Example: Complex Lorentz tensors
3. Tensor trees
A syntax tree for tensor expressions.
Show Lean code:
inductive TensorTree (S : TensorSpecies) : {n : ℕ} → (Fin n → S.C) → Type where
/-- A general tensor node. -/
| tensorNode {n : ℕ} {c : Fin n → S.C} (T : S.F.obj (OverColor.mk c)) : TensorTree S c
/-- A node corresponding to the scalar multiple of a tensor by a element of the field. -/
| smul {n : ℕ} {c : Fin n → S.C} : S.k → TensorTree S c → TensorTree S c
/-- A node corresponding to negation of a tensor. -/
| neg {n : ℕ} {c : Fin n → S.C} : TensorTree S c → TensorTree S c
/-- A node corresponding to the addition of two tensors. -/
| add {n : ℕ} {c : Fin n → S.C} : TensorTree S c → TensorTree S c → TensorTree S c
/-- A node corresponding to the action of a group element on a tensor. -/
| action {n : ℕ} {c : Fin n → S.C} : S.G → TensorTree S c → TensorTree S c
/-- A node corresponding to the permutation of indices of a tensor. -/
| perm {n m : ℕ} {c : Fin n → S.C} {c1 : Fin m → S.C}
(σ : (OverColor.mk c) ⟶ (OverColor.mk c1)) (t : TensorTree S c) : TensorTree S c1
/-- A node corresponding to the product of two tensors. -/
| prod {n m : ℕ} {c : Fin n → S.C} {c1 : Fin m → S.C}
(t : TensorTree S c) (t1 : TensorTree S c1) : TensorTree S (Sum.elim c c1 ∘ finSumFinEquiv.symm)
/-- A node corresponding to the contraction of indices of a tensor. -/
| contr {n : ℕ} {c : Fin n.succ.succ → S.C} : (i : Fin n.succ.succ) →
(j : Fin n.succ) → (h : c (i.succAbove j) = S.τ (c i)) → TensorTree S c →
TensorTree S (c ∘ i.succAbove ∘ j.succAbove)
/-- A node corresponding to the evaluation of an index of a tensor. -/
| eval {n : ℕ} {c : Fin n.succ → S.C} : (i : Fin n.succ) → (x : ℕ) → TensorTree S c →
TensorTree S (c ∘ i.succAbove)
The underlying tensor a tensor tree corresponds to.
Show Lean code:
def tensor {n : ℕ} {c : Fin n → S.C} : TensorTree S c → S.F.obj (OverColor.mk c) := fun
| tensorNode t => t
| smul a t => a • t.tensor
| neg t => - t.tensor
| add t1 t2 => t1.tensor + t2.tensor
| action g t => (S.F.obj (OverColor.mk _)).ρ g t.tensor
| perm σ t => (S.F.map σ).hom t.tensor
| prod t1 t2 => (S.F.map (OverColor.equivToIso finSumFinEquiv).hom).hom
((Functor.LaxMonoidal.μ S.F _ _).hom (t1.tensor ⊗ₜ t2.tensor))
| contr i j h t => (S.contrMap _ i j h).hom t.tensor
| eval i e t => (S.evalMap i (Fin.ofNat' _ e)) t.tensor