Imports
/-
Copyright (c) 2026 Robert Sneiderman. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Robert Sneiderman
-/
module
public import Physlib.Mathematics.KroneckerDelta.Basic
public import Mathlib.LinearAlgebra.Matrix.PermutationThe Levi-Civita symbol in general dimension
i. Overview
This module defines the Levi-Civita symbol leviCivitaSymbol on a general finite index
type ι: for g : ι → ι it is the sign of g when g is a permutation and 0
otherwise. Taking ι = Fin d gives the Levi-Civita symbol ε_{i₁ ⋯ i_d} in dimension
d, normalized by ε_{0 1 ⋯ (d-1)} = 1.
The definition is the generalizedKroneckerDelta of g against the identity, i.e. the
determinant of the matrix of Kronecker deltas δ[g i, j], so the basic properties are
inherited from the determinant: the value 1 on the identity, antisymmetry under
transposition of two indices, vanishing on repeated indices, and the sign of a
permutation via Matrix.det_permutation.
ii. Key results
leviCivitaSymbol : the Levi-Civita symbol on a finite index type, valued in ℤ.
leviCivitaSymbol_id : the normalization ε_{0 1 ⋯ (d-1)} = 1.
leviCivitaSymbol_perm : on a permutation σ the symbol is the sign of σ.
leviCivitaSymbol_comp_swap : antisymmetry under transposition of two indices.
leviCivitaSymbol_swap_comp : antisymmetry under transposition of two index values.
leviCivitaSymbol_eq_zero_iff : the symbol vanishes exactly on repeated indices.
iii. Table of contents
A. Definition
B. Value on permutations
C. Antisymmetry
D. Vanishing on repeated indices
iv. References
https://en.wikipedia.org/wiki/Levi-Civita_symbol
@[expose] public sectionA. Definition
The Levi-Civita symbol on a finite index type ι: leviCivitaSymbol g is the sign
of g when g : ι → ι is a permutation, and 0 otherwise. It is the generalized
Kronecker delta of g against the identity, i.e. the determinant of the matrix of
Kronecker deltas δ[g i, j].
For ι = Fin d this is the Levi-Civita symbol ε_{i₁ ⋯ i_d} in dimension d,
normalized by ε_{0 1 ⋯ (d-1)} = 1.
def leviCivitaSymbol (g : ι → ι) : ℤ :=
generalizedKroneckerDelta g (id : ι → ι)
The Levi-Civita symbol as the determinant of the matrix of Kronecker deltas
δ[g i, j].
lemma leviCivitaSymbol_eq_det (g : ι → ι) :
leviCivitaSymbol g = Matrix.det (fun i j => ((kroneckerDelta (g i) j : ℕ) : ℤ)) :=
rfl
The Levi-Civita symbol of the identity, i.e. ε_{0 1 ⋯ (d-1)}, is 1.
ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ι⊢ Matrix.det 1 = 1
exact Matrix.det_one All goals completed! 🐙B. Value on permutations
The Levi-Civita symbol of a permutation σ is the sign of σ.
@[simp]
lemma leviCivitaSymbol_perm (σ : Equiv.Perm ι) :
leviCivitaSymbol ⇑σ = (Equiv.Perm.sign σ : ℤ) := by ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ι⊢ leviCivitaSymbol ⇑σ = ↑(Equiv.Perm.sign σ)
rw [leviCivitaSymbol_eq_det, ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ι⊢ (Matrix.det fun i j => ↑δ[σ i,j]) = ↑(Equiv.Perm.sign σ) ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ι⊢ (Equiv.Perm.permMatrix ℤ σ).det = ↑(Equiv.Perm.sign σ) show (fun i j => ((kroneckerDelta (σ i) j : ℕ) : ℤ))
= σ.permMatrix ℤ from funext fun i => funext fun j => by ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ιi:ιj:ι⊢ ↑δ[σ i,j] = Equiv.Perm.permMatrix ℤ σ i j ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ι⊢ (Equiv.Perm.permMatrix ℤ σ).det = ↑(Equiv.Perm.sign σ)
simp [kroneckerDelta, PEquiv.toMatrix_apply, Equiv.toPEquiv_apply, eq_comm] All goals completed! 🐙 ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ι⊢ (Equiv.Perm.permMatrix ℤ σ).det = ↑(Equiv.Perm.sign σ)] ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ι⊢ (Equiv.Perm.permMatrix ℤ σ).det = ↑(Equiv.Perm.sign σ)
exact Matrix.det_permutation σ All goals completed! 🐙C. Antisymmetry
The Levi-Civita symbol is antisymmetric under transposition of two of its indices: precomposing with the swap of two distinct index positions negates it.
lemma leviCivitaSymbol_comp_swap (g : ι → ι) {i j : ι} (hij : i ≠ j) :
leviCivitaSymbol (g ∘ Equiv.swap i j) = - leviCivitaSymbol g :=
generalizedKroneckerDelta_swap g id hijThe Levi-Civita symbol is antisymmetric under transposition of two index values: postcomposing with the swap of two distinct values exchanges those two values wherever they occur and negates it.
lemma leviCivitaSymbol_swap_comp (g : ι → ι) {i j : ι} (hij : i ≠ j) :
leviCivitaSymbol (Equiv.swap i j ∘ g) = - leviCivitaSymbol g := by ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ j⊢ leviCivitaSymbol (⇑(Equiv.swap i j) ∘ g) = -leviCivitaSymbol g
have h : (fun a b => ((kroneckerDelta ((Equiv.swap i j ∘ g) a) b : ℕ) : ℤ))
= Matrix.submatrix (fun a b => ((kroneckerDelta (g a) b : ℕ) : ℤ)) id (Equiv.swap i j) :=
funext fun a => funext fun b => by ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ ja:ιb:ι⊢ ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b] = Matrix.submatrix (fun a b => ↑δ[g a,b]) id (⇑(Equiv.swap i j)) a b ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ leviCivitaSymbol (⇑(Equiv.swap i j) ∘ g) = -leviCivitaSymbol g simp [kroneckerDelta, Equiv.swap_apply_eq_iff] ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ leviCivitaSymbol (⇑(Equiv.swap i j) ∘ g) = -leviCivitaSymbol g ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ leviCivitaSymbol (⇑(Equiv.swap i j) ∘ g) = -leviCivitaSymbol g
rw [leviCivitaSymbol_eq_det, ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ (Matrix.det fun i_1 j_1 => ↑δ[(⇑(Equiv.swap i j) ∘ g) i_1,j_1]) = -leviCivitaSymbol g ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ ↑↑(-1) * leviCivitaSymbol g = -leviCivitaSymbol g h, ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ (Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)).det = -leviCivitaSymbol g ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ ↑↑(-1) * leviCivitaSymbol g = -leviCivitaSymbol g Matrix.det_permute', ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ (↑↑(Equiv.Perm.sign (Equiv.swap i j)) * Matrix.det fun a b => ↑δ[g a,b]) = -leviCivitaSymbol g ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ ↑↑(-1) * leviCivitaSymbol g = -leviCivitaSymbol g Equiv.Perm.sign_swap hij, ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ (↑↑(-1) * Matrix.det fun a b => ↑δ[g a,b]) = -leviCivitaSymbol g ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ ↑↑(-1) * leviCivitaSymbol g = -leviCivitaSymbol g
← leviCivitaSymbol_eq_det ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ ↑↑(-1) * leviCivitaSymbol g = -leviCivitaSymbol g ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ ↑↑(-1) * leviCivitaSymbol g = -leviCivitaSymbol g] ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:(fun a b => ↑δ[(⇑(Equiv.swap i j) ∘ g) a,b]) = Matrix.submatrix (fun a b => ↑δ[g a,b]) id ⇑(Equiv.swap i j)⊢ ↑↑(-1) * leviCivitaSymbol g = -leviCivitaSymbol g
simp All goals completed! 🐙D. Vanishing on repeated indices
The Levi-Civita symbol vanishes on a repeated index: if two distinct index positions
i ≠ j carry the same value, the symbol is zero.
lemma leviCivitaSymbol_eq_zero_of_eq {g : ι → ι} {i j : ι} (hij : i ≠ j) (h : g i = g j) :
leviCivitaSymbol g = 0 := by ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:g i = g j⊢ leviCivitaSymbol g = 0
rw [leviCivitaSymbol_eq_det ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:g i = g j⊢ (Matrix.det fun i j => ↑δ[g i,j]) = 0 ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:g i = g j⊢ (Matrix.det fun i j => ↑δ[g i,j]) = 0] ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:g i = g j⊢ (Matrix.det fun i j => ↑δ[g i,j]) = 0
exact Matrix.det_zero_of_row_eq hij (funext fun c => by ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:g i = g jc:ι⊢ ↑δ[g i,c] = ↑δ[g j,c] rw [h ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhij:i ≠ jh:g i = g jc:ι⊢ ↑δ[g j,c] = ↑δ[g j,c] All goals completed! 🐙] All goals completed! 🐙)The Levi-Civita symbol vanishes on maps which are not injective.
lemma leviCivitaSymbol_eq_zero_of_not_injective {g : ι → ι} (h : ¬ Function.Injective g) :
leviCivitaSymbol g = 0 := by ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιh:¬Function.Injective g⊢ leviCivitaSymbol g = 0
simp only [Function.Injective, not_forall] at h ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιh:∃ x x_1, ∃ (_ : g x = g x_1), ¬x = x_1⊢ leviCivitaSymbol g = 0
obtain ⟨i, j, hgij, hij⟩ := h ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιi:ιj:ιhgij:g i = g jhij:¬i = j⊢ leviCivitaSymbol g = 0
exact leviCivitaSymbol_eq_zero_of_eq hij hgij All goals completed! 🐙The Levi-Civita symbol vanishes exactly on maps with a repeated index, i.e. on maps which are not injective.
lemma leviCivitaSymbol_eq_zero_iff {g : ι → ι} :
leviCivitaSymbol g = 0 ↔ ¬ Function.Injective g := by ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ι⊢ leviCivitaSymbol g = 0 ↔ ¬Function.Injective g
refine ⟨fun h hinj => ?_, leviCivitaSymbol_eq_zero_of_not_injective⟩ ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ιg:ι → ιh:leviCivitaSymbol g = 0hinj:Function.Injective g⊢ False
obtain ⟨σ, rfl⟩ : ∃ σ : Equiv.Perm ι, ⇑σ = g :=
⟨Equiv.ofBijective g (Finite.injective_iff_bijective.mp hinj), rfl⟩ ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ιh:leviCivitaSymbol ⇑σ = 0hinj:Function.Injective ⇑σ⊢ False
rw [leviCivitaSymbol_perm ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ιh:↑(Equiv.Perm.sign σ) = 0hinj:Function.Injective ⇑σ⊢ False ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ιh:↑(Equiv.Perm.sign σ) = 0hinj:Function.Injective ⇑σ⊢ False] at h ι:Typeinst✝¹:DecidableEq ιinst✝:Fintype ισ:Equiv.Perm ιh:↑(Equiv.Perm.sign σ) = 0hinj:Function.Injective ⇑σ⊢ False
exact Units.ne_zero (Equiv.Perm.sign σ) h All goals completed! 🐙