Imports
/- Copyright (c) 2025 Joseph Tooby-Smith. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joseph Tooby-Smith -/ module public import Physlib.Relativity.Tensors.ComponentIdx.Single public import Physlib.Relativity.Tensors.Contraction.SuccSuccAbove public import Mathlib.Topology.Algebra.Module.ModuleTopology public import Mathlib.Analysis.RCLike.Basic public import Mathlib.Tactic.Cases public import Mathlib.GroupTheory.Perm.Fin

Reindexing of tensor components

In this file we give results related to the reindexing of tensors. If a tensor has indices specified by a list of colors c : Fin n → C, then reindexing the tensor corresponds to a bijection σ : Fin m → Fin n such that c ∘ σ = c1 for some other list of colors c1 : Fin m → C. A reindexing might take a tensor ψⁱⱼ to a tensor ψʲᵢ by reordering the indices, or it might take a tensor ψⁱⱼᵏ to a tensor ψⁱᵏ.

We are interested in the interaction of reindexing with the following operations on tensors:

    Fin.append corresponds to the product of tensors.

    Fin.succAbove corresponds to the evaluation of a tensor at a given index.

    Fin.succSuccAbove corresponds to the contraction of a tensor at two given indices.

@[expose] public section

Index maps

The finite index maps out of which the reindexings below are built: Fin.append for products and Fin.succAbove for a deleted slot. The lemmas on Fin.succSuccAbove, for a deleted pair, are in Physlib.Relativity.Tensors.Contraction.SuccSuccAbove.

Splitting Fin (m + n) into its two blocks and reassembling them is the identity.

lemma append_castAdd_natAdd_eq_id {m n : } : Fin.append (Fin.castAdd n) (Fin.natAdd m) = (id : Fin (m + n) Fin (m + n)) := m:n:append (castAdd n) (natAdd m) = id All goals completed! 🐙

Moving slot i to the end is the cycle [i, last]: the block map that lists the i.succAbove survivors in order and then i is Fin.cycleIcc i (Fin.last n).

All goals completed! 🐙

Given two lists of indices c : Fin n → C and c1 : Fin m → C a map σ : Fin m → Fin n satisfies the condition IsReindexing c c1 σ if it is:

    A bijection

    Forms a commutative triangle with c and c1.

def IsReindexing {n m : } (c : Fin n C) (c1 : Fin m C) (σ : Fin m Fin n) : Prop := Function.Bijective σ i, c (σ i) = c1 i

Properties of the underlying function

lemma injective {n m : } {c : Fin n C} {c1 : Fin m C} {σ : Fin m Fin n} (h : IsReindexing c c1 σ) : Function.Injective σ := h.1.1lemma surjective {n m : } {c : Fin n C} {c1 : Fin m C} {σ : Fin m Fin n} (h : IsReindexing c c1 σ) : Function.Surjective σ := h.1.2lemma auto {n m : } {c : Fin n C} {c1 : Fin m C} {σ : Fin m Fin n} (h : IsReindexing c c1 σ := by {simp [IsReindexing]; try decide}) : IsReindexing c c1 σ := h@[simp] lemma on_id {n : } {c c1 : Fin n C} : IsReindexing c c1 (id : Fin n Fin n) i, c i = c1 i := C:Typen:c:Fin n Cc1:Fin n CIsReindexing c c1 id (i : Fin n), c i = c1 i All goals completed! 🐙lemma on_id_symm {n : } {c c1 : Fin n C} (h : IsReindexing c1 c id) : IsReindexing c c1 (id : Fin n Fin n) := C:Typen:c:Fin n Cc1:Fin n Ch:IsReindexing c1 c idIsReindexing c c1 id C:Typen:c:Fin n Cc1:Fin n Ch: (i : Fin n), c1 i = c i (i : Fin n), c i = c1 i All goals completed! 🐙

For a map σ satisfying IsReindexing c c1 σ, the inverse of that map.

def inv {n m : } {c : Fin n C} {c1 : Fin m C} (σ : Fin m Fin n) (h : IsReindexing c c1 σ) : Fin n Fin m := Fintype.bijInv h.1

For a map σ : Fin m → Fin n satisfying IsReindexing c c1 σ, that map lifted to an equivalence between Fin n and Fin m.

def toEquiv {n m : } {c : Fin n C} {c1 : Fin m C} {σ : Fin m Fin n} (h : IsReindexing c c1 σ) : Fin n Fin m where toFun := inv σ h invFun := σ left_inv := Fintype.rightInverse_bijInv h.1 right_inv := Fintype.leftInverse_bijInv h.1
lemma apply_inv_apply {n m : } {c : Fin n C} {c1 : Fin m C} (σ : Fin m Fin n) (h : IsReindexing c c1 σ) (x : Fin m) : h.inv σ (σ x) = x := C:Typen:m:c:Fin n Cc1:Fin m Cσ:Fin m Fin nh:IsReindexing c c1 σx:Fin minv σ h (σ x) = x C:Typen:m:c:Fin n Cc1:Fin m Cσ:Fin m Fin nh:IsReindexing c c1 σx:Fin mh.toEquiv (h.toEquiv.symm x) = x All goals completed! 🐙lemma inv_apply_apply {n m : } {c : Fin n C} {c1 : Fin m C} (σ : Fin m Fin n) (h : IsReindexing c c1 σ) (x : Fin n) : σ (h.inv σ x) = x := C:Typen:m:c:Fin n Cc1:Fin m Cσ:Fin m Fin nh:IsReindexing c c1 σx:Fin nσ (inv σ h x) = x C:Typen:m:c:Fin n Cc1:Fin m Cσ:Fin m Fin nh:IsReindexing c c1 σx:Fin nh.toEquiv.symm (h.toEquiv x) = x All goals completed! 🐙All goals completed! 🐙C:Typen:m:c:Fin n Cc1:Fin m Cσ:Fin m Fin nh:IsReindexing c c1 σx:Fin m(c σ) x = c (h.toEquiv.symm x) All goals completed! 🐙C:Typen:m:c:Fin n Cc1:Fin m Cσ:Fin m Fin nh:IsReindexing c c1 σx:Fin nc (h.toEquiv.symm (h.toEquiv x)) = (c σ) (h.toEquiv x) All goals completed! 🐙

Constructors

lemma swap {n : } {c : Fin n C} (i j : Fin n) : IsReindexing c (c Equiv.swap i j) (Equiv.swap i j) := C:Typen:c:Fin n Ci:Fin nj:Fin nIsReindexing c (c (Equiv.swap i j)) (Equiv.swap i j) All goals completed! 🐙

The inverse of a map satisfying IsReindexing c c1 σ is a reindexing of c1 by c.

lemma symm {n m : } {c : Fin n C} {c1 : Fin m C} {σ : Fin m Fin n} (h : IsReindexing c c1 σ) : IsReindexing c1 c (h.inv σ) := h.toEquiv.bijective, h.inv_perserve_color
lemma symm_of_id {n : } {c c1 : Fin n C} (h : IsReindexing c c1 id) : IsReindexing c1 c id := C:Typen:c:Fin n Cc1:Fin n Ch:IsReindexing c c1 idIsReindexing c1 c id C:Typen:c:Fin n Cc1:Fin n Ch: (i : Fin n), c i = c1 i (i : Fin n), c1 i = c i All goals completed! 🐙

The composition of two maps satisfying IsReindexing also satisfies the IsReindexing.

lemma comp {n n1 n2 : } {c : Fin n C} {c1 : Fin n1 C} {c2 : Fin n2 C} {σ : Fin n1 Fin n} {σ2 : Fin n2 Fin n1} (h : IsReindexing c c1 σ) (h2 : IsReindexing c1 c2 σ2) : IsReindexing c c2 (σ σ2) := h.1.comp h2.1, fun x => (h.2 (σ2 x)).trans (h2.2 x)
C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σheq:append (castAdd n2 σ) (natAdd n) = (finSumFinEquiv.symm.trans (((Equiv.ofBijective σ ).sumCongr (Equiv.refl (Fin n2))).trans finSumFinEquiv))Function.Bijective (finSumFinEquiv.symm.trans (((Equiv.ofBijective σ ).sumCongr (Equiv.refl (Fin n2))).trans finSumFinEquiv)) All goals completed! 🐙 C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n' + n2)append c c2 (append (castAdd n2 σ) (natAdd n) i) = append c' c2 i C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n' + n2)a:Fin n'append c c2 (append (castAdd n2 σ) (natAdd n) (castAdd n2 a)) = append c' c2 (castAdd n2 a)C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n' + n2)a:Fin n2append c c2 (append (castAdd n2 σ) (natAdd n) (natAdd n' a)) = append c' c2 (natAdd n' a) C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n' + n2)a:Fin n'append c c2 (append (castAdd n2 σ) (natAdd n) (castAdd n2 a)) = append c' c2 (castAdd n2 a)C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n' + n2)a:Fin n2append c c2 (append (castAdd n2 σ) (natAdd n) (natAdd n' a)) = append c' c2 (natAdd n' a) All goals completed! 🐙C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σheq:append (castAdd n) (natAdd n2 σ) = (finSumFinEquiv.symm.trans (((Equiv.refl (Fin n2)).sumCongr (Equiv.ofBijective σ )).trans finSumFinEquiv))Function.Bijective (finSumFinEquiv.symm.trans (((Equiv.refl (Fin n2)).sumCongr (Equiv.ofBijective σ )).trans finSumFinEquiv)) All goals completed! 🐙 C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n2 + n')append c2 c (append (castAdd n) (natAdd n2 σ) i) = append c2 c' i C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n2 + n')a:Fin n2append c2 c (append (castAdd n) (natAdd n2 σ) (castAdd n' a)) = append c2 c' (castAdd n' a)C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n2 + n')a:Fin n'append c2 c (append (castAdd n) (natAdd n2 σ) (natAdd n2 a)) = append c2 c' (natAdd n2 a) C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n2 + n')a:Fin n2append c2 c (append (castAdd n) (natAdd n2 σ) (castAdd n' a)) = append c2 c' (castAdd n' a)C:Typen:n':n2:c:Fin n Cc':Fin n' Cσ:Fin n' Fin nc2:Fin n2 Ch:IsReindexing c c' σi:Fin (n2 + n')a:Fin n'append c2 c (append (castAdd n) (natAdd n2 σ) (natAdd n2 a)) = append c2 c' (natAdd n2 a) All goals completed! 🐙C:Typen:c:Fin n Cc1:Fin 0 CP: (i : Fin (n + 0)), c i = append c c1 i (i : Fin n), c i = append c c1 i All goals completed! 🐙C:Typen:n2:c:Fin n Cc2:Fin n2 Cheq:append (natAdd n) (castAdd n2) = (finSumFinEquiv.symm.trans ((Equiv.sumComm (Fin n2) (Fin n)).trans finSumFinEquiv))Function.Bijective (finSumFinEquiv.symm.trans ((Equiv.sumComm (Fin n2) (Fin n)).trans finSumFinEquiv)) All goals completed! 🐙 C:Typen:n2:c:Fin n Cc2:Fin n2 Ci:Fin (n2 + n)append c c2 (append (natAdd n) (castAdd n2) i) = append c2 c i C:Typen:n2:c:Fin n Cc2:Fin n2 Ci:Fin (n2 + n)a:Fin n2append c c2 (append (natAdd n) (castAdd n2) (castAdd n a)) = append c2 c (castAdd n a)C:Typen:n2:c:Fin n Cc2:Fin n2 Ci:Fin (n2 + n)a:Fin nappend c c2 (append (natAdd n) (castAdd n2) (natAdd n2 a)) = append c2 c (natAdd n2 a) C:Typen:n2:c:Fin n Cc2:Fin n2 Ci:Fin (n2 + n)a:Fin n2append c c2 (append (natAdd n) (castAdd n2) (castAdd n a)) = append c2 c (castAdd n a)C:Typen:n2:c:Fin n Cc2:Fin n2 Ci:Fin (n2 + n)a:Fin nappend c c2 (append (natAdd n) (castAdd n2) (natAdd n2 a)) = append c2 c (natAdd n2 a) All goals completed! 🐙lemma append_assoc_right {n1 n2 n3 : } {c : Fin n1 C} {c2 : Fin n2 C} {c3 : Fin n3 C} : IsReindexing (Fin.append c (Fin.append c2 c3)) (Fin.append (Fin.append c c2) c3) (Fin.cast (k:Typeinst✝⁵:CommRing kC:TypeG:Typeinst✝⁴:Group GV:C Typeinst✝³:(c : C) AddCommGroup (V c)inst✝²:(c : C) Module k (V c)basisIdx:C Typeinst✝¹:(c : C) Fintype (basisIdx c)inst✝:(c : C) DecidableEq (basisIdx c)rep:(c : C) Representation k G (V c)b:(c : C) Basis (basisIdx c) k (V c)S:TensorSpecies k C G V basisIdx rep bn1:n2:n3:c:Fin n1 Cc2:Fin n2 Cc3:Fin n3 Cn1 + n2 + n3 = n1 + (n2 + n3) All goals completed! 🐙)) := (finCongr (C:Typen1:n2:n3:c:Fin n1 Cc2:Fin n2 Cc3:Fin n3 Cn1 + n2 + n3 = n1 + (n2 + n3) All goals completed! 🐙)).bijective, fun i => (congrFun (Fin.append_assoc c c2 c3) i).symmlemma append_assoc_left {n1 n2 n3 : } {c : Fin n1 C} {c2 : Fin n2 C} {c3 : Fin n3 C} : IsReindexing (Fin.append (Fin.append c c2) c3) (Fin.append c (Fin.append c2 c3)) (Fin.cast (k:Typeinst✝⁵:CommRing kC:TypeG:Typeinst✝⁴:Group GV:C Typeinst✝³:(c : C) AddCommGroup (V c)inst✝²:(c : C) Module k (V c)basisIdx:C Typeinst✝¹:(c : C) Fintype (basisIdx c)inst✝:(c : C) DecidableEq (basisIdx c)rep:(c : C) Representation k G (V c)b:(c : C) Basis (basisIdx c) k (V c)S:TensorSpecies k C G V basisIdx rep bn1:n2:n3:c:Fin n1 Cc2:Fin n2 Cc3:Fin n3 Cn1 + (n2 + n3) = n1 + n2 + n3 All goals completed! 🐙)) := (finCongr (C:Typen1:n2:n3:c:Fin n1 Cc2:Fin n2 Cc3:Fin n3 Cn1 + (n2 + n3) = n1 + n2 + n3 All goals completed! 🐙)).bijective, fun i => congrFun (Fin.append_assoc c c2 c3) _C:Typen:n1:c:Fin n Cc1:Fin (n1 + 1) Ci:Fin (n1 + 1)x:Fin (n + n1)a:Fin n1hidx:(natAdd n i).succAbove (natAdd n a) = natAdd n (i.succAbove a)append c c1 ((natAdd n i).succAbove (natAdd n a)) = append c (c1 i.succAbove) (natAdd n a) All goals completed! 🐙C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Ci:Fin (n + 1)y:Fin (n + (n1 + 1))a:Fin (n1 + 1)hidx:(castAdd (n1 + 1) i).succAbove (Fin.cast (natAdd n a)) = natAdd (n + 1) aappend c c1 ((castAdd (n1 + 1) i).succAbove (Fin.cast (natAdd n a))) = append (c i.succAbove) c1 (natAdd n a) All goals completed! 🐙

Removing two entries from the right component of Fin.append c1 c commutes with the append: removing the i-th and j-th entries of c and then appending c1 matches removing the corresponding entries of Fin.append c1 c, via the identity permutation. This is used for the commutation of taking a product of tensors with contraction of indices.

lemma append_succSuccAbove_natAdd {n n1 : } {c : Fin (n + 1 + 1) C} {c1 : Fin n1 C} (i j : Fin (n + 1 + 1)) : IsReindexing (Fin.append c1 c (Fin.natAdd n1 i).succSuccAbove (Fin.natAdd n1 j)) (Fin.append c1 (c i.succSuccAbove j)) id := C:Typen:n1:c:Fin (n + 1 + 1) Cc1:Fin n1 Ci:Fin (n + 1 + 1)j:Fin (n + 1 + 1)IsReindexing (append c1 c (natAdd n1 i).succSuccAbove (natAdd n1 j)) (append c1 (c i.succSuccAbove j)) id C:Typen:n1:c:Fin (n + 1 + 1) Cc1:Fin n1 Ci:Fin (n + 1 + 1)j:Fin (n + 1 + 1) (i_1 : Fin (n1 + n)), (append c1 c (natAdd n1 i).succSuccAbove (natAdd n1 j)) (id i_1) = append c1 (c i.succSuccAbove j) i_1 All goals completed! 🐙

Given a reindexing of c by c1 via σ for which the index i is sent to 0, removing the i-th entry of c1 and the first entry of c yields a reindexing of c ∘ Fin.succ by c1 ∘ i.succAbove via the map sending j to the predecessor of σ (i.succAbove j).

C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i = 0k:Fin n a, σ (i.succAbove a) = k.succ C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i = 0k:Fin nj:Fin (n1 + 1)hj:σ j = k.succ a, σ (i.succAbove a) = k.succ C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i = 0k:Fin nj:Fin (n1 + 1)hj:σ j = k.succ¬j = i All goals completed! 🐙 C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i = 0 (i_1 : Fin n1), (c succ) ((fun j => (σ (i.succAbove j)).pred ) i_1) = (c1 i.succAbove) i_1 C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i = 0x:Fin n1(c succ) ((fun j => (σ (i.succAbove j)).pred ) x) = (c1 i.succAbove) x All goals completed! 🐙

Given a reindexing of c by c1 via σ for which the index i is not sent to 0, removing the i-th entry of c1 and the (σ i)-th entry of c yields a reindexing of c ∘ (σ i).succAbove by c1 ∘ i.succAbove via the map (σ i).pred.predAbove ∘ σ ∘ i.succAbove.

C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i 0hpr:σ i = ((σ i).pred hi).succhne: (x : Fin n1), σ (i.succAbove x) σ ik:Fin n a, σ (i.succAbove a) = (σ i).succAbove k C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i 0hpr:σ i = ((σ i).pred hi).succhne: (x : Fin n1), σ (i.succAbove x) σ ik:Fin nj:Fin (n1 + 1)hj:σ j = (σ i).succAbove k a, σ (i.succAbove a) = (σ i).succAbove k C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i 0hpr:σ i = ((σ i).pred hi).succhne: (x : Fin n1), σ (i.succAbove x) σ ik:Fin nj:Fin (n1 + 1)hj:σ j = (σ i).succAbove k¬j = i C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)h:IsReindexing c c1 σk:Fin nj:Fin (n1 + 1)hi:σ j 0hpr:σ j = ((σ j).pred hi).succhne: (x : Fin n1), σ (j.succAbove x) σ jhj:σ j = (σ j).succAbove kFalse All goals completed! 🐙 C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i 0hpr:σ i = ((σ i).pred hi).succhne: (x : Fin n1), σ (i.succAbove x) σ i (i_1 : Fin n1), (c (σ i).succAbove) ((((σ i).pred hi).predAbove σ i.succAbove) i_1) = (c1 i.succAbove) i_1 C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i 0hpr:σ i = ((σ i).pred hi).succhne: (x : Fin n1), σ (i.succAbove x) σ ix:Fin n1(c (σ i).succAbove) ((((σ i).pred hi).predAbove σ i.succAbove) x) = (c1 i.succAbove) x C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i 0hpr:σ i = ((σ i).pred hi).succhne: (x : Fin n1), σ (i.succAbove x) σ ix:Fin n1c ((σ i).succAbove (((σ i).pred hi).predAbove (σ (i.succAbove x)))) = c (σ (i.succAbove x)) C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i 0hpr:σ i = ((σ i).pred hi).succhne: (x : Fin n1), σ (i.succAbove x) σ ix:Fin n1(σ i).succAbove (((σ i).pred hi).predAbove (σ (i.succAbove x))) = σ (i.succAbove x) conv_lhs => C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i 0hpr:σ i = ((σ i).pred hi).succhne: (x : Fin n1), σ (i.succAbove x) σ ix:Fin n1| σ i; C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i 0hpr:σ i = ((σ i).pred hi).succhne: (x : Fin n1), σ (i.succAbove x) σ ix:Fin n1| ((σ i).pred hi).succ All goals completed! 🐙

Given a reindexing of c by c1 via σ, removing the i-th entry of c1 and the (σ i)-th entry of c yields a reindexing of c ∘ (σ i).succAbove by c1 ∘ i.succAbove. This unifies succAbove_of_eq_zero and succAbove_of_neq_zero via a case split on whether σ i = 0. This is used for the commutation of permutation of indices with evaluation of indices.

lemma succAbove {n n1 : } {c : Fin (n + 1) C} {c1 : Fin (n1 + 1) C} {σ : Fin (n1 + 1) Fin (n + 1)} (i : Fin (n1 + 1)) (h : IsReindexing c c1 σ) : IsReindexing (c (σ i).succAbove) (c1 i.succAbove) (if hi : σ i = 0 then fun j => (σ (i.succAbove j)).pred (k:Typeinst✝⁵:CommRing kC:TypeG:Typeinst✝⁴:Group GV:C Typeinst✝³:(c : C) AddCommGroup (V c)inst✝²:(c : C) Module k (V c)basisIdx:C Typeinst✝¹:(c : C) Fintype (basisIdx c)inst✝:(c : C) DecidableEq (basisIdx c)rep:(c : C) Representation k G (V c)b:(c : C) Basis (basisIdx c) k (V c)S:TensorSpecies k C G V basisIdx rep bn:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i = 0j:Fin n1σ (i.succAbove j) 0 All goals completed! 🐙) else (Fin.pred (σ i) hi).predAbove σ i.succAbove) := C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σIsReindexing (c (σ i).succAbove) (c1 i.succAbove) (if hi : σ i = 0 then fun j => (σ (i.succAbove j)).pred else ((σ i).pred hi).predAbove σ i.succAbove) C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i = 0IsReindexing (c (σ i).succAbove) (c1 i.succAbove) (if hi : σ i = 0 then fun j => (σ (i.succAbove j)).pred else ((σ i).pred hi).predAbove σ i.succAbove)C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:¬σ i = 0IsReindexing (c (σ i).succAbove) (c1 i.succAbove) (if hi : σ i = 0 then fun j => (σ (i.succAbove j)).pred else ((σ i).pred hi).predAbove σ i.succAbove) C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:σ i = 0IsReindexing (c (σ i).succAbove) (c1 i.succAbove) (if hi : σ i = 0 then fun j => (σ (i.succAbove j)).pred else ((σ i).pred hi).predAbove σ i.succAbove) All goals completed! 🐙 C:Typen:n1:c:Fin (n + 1) Cc1:Fin (n1 + 1) Cσ:Fin (n1 + 1) Fin (n + 1)i:Fin (n1 + 1)h:IsReindexing c c1 σhi:¬σ i = 0IsReindexing (c (σ i).succAbove) (c1 i.succAbove) (if hi : σ i = 0 then fun j => (σ (i.succAbove j)).pred else ((σ i).pred hi).predAbove σ i.succAbove) All goals completed! 🐙

The conclusion of succAbove from an explicit survivor relabelling: if σ' fills the square (σ i).succAbove ∘ σ' = σ ∘ i.succAbove, carrying the complement of i to the complement of σ i, then it is a reindexing of the two shortened colour lists. The square forces σ' to be injective, hence bijective, so no bijectivity hypothesis is needed; this is why the statement is restricted to equal lengths.

Where succAbove builds the relabelling from σ as a dite composite, the map here is the caller's, which is what lets it stand in the statement of a lemma the caller instantiates.

All goals completed! 🐙)) C:Typen:c:Fin (n + 1) Cc1:Fin (n + 1) Cσ:Fin (n + 1) Fin (n + 1)σ':Fin n Fin ni:Fin (n + 1)h:IsReindexing c c1 σhσ':(σ i).succAbove σ' = σ i.succAbovekey: (a : Fin n), (σ i).succAbove (σ' a) = σ (i.succAbove a)a:Fin n(c (σ i).succAbove) (σ' a) = (c1 i.succAbove) a All goals completed! 🐙

Given a reindexing of c by c1 via σ and two distinct indices i ≠ j, removing the i-th and j-th entries of c1 and the (σ i)-th and (σ j)-th entries of c yields a reindexing of c ∘ (σ i).succSuccAbove (σ j) by c1 ∘ i.succSuccAbove j. This is used for the commutation of permutation of indices with contraction of indices.

lemma succSuccAbove {n n1 : } {c : Fin (n + 1 + 1) C} {c1 : Fin (n1 + 1 + 1) C} (i j : Fin (n1 + 1 + 1)) (hij : i j) {σ : Fin (n1 + 1 + 1) Fin (n + 1 + 1)} ( : IsReindexing c c1 σ) : IsReindexing (c (σ i).succSuccAbove (σ j)) (c1 i.succSuccAbove j) (i.funPredPredAbove j hij σ .1) := C:Typen:n1:c:Fin (n + 1 + 1) Cc1:Fin (n1 + 1 + 1) Ci:Fin (n1 + 1 + 1)j:Fin (n1 + 1 + 1)hij:i jσ:Fin (n1 + 1 + 1) Fin (n + 1 + 1):IsReindexing c c1 σIsReindexing (c (σ i).succSuccAbove (σ j)) (c1 i.succSuccAbove j) (i.funPredPredAbove j hij σ ) C:Typen:n1:c:Fin (n + 1 + 1) Cc1:Fin (n1 + 1 + 1) Ci:Fin (n1 + 1 + 1)j:Fin (n1 + 1 + 1)hij:i jσ:Fin (n1 + 1 + 1) Fin (n + 1 + 1):IsReindexing c c1 σFunction.Bijective (i.funPredPredAbove j hij σ )C:Typen:n1:c:Fin (n + 1 + 1) Cc1:Fin (n1 + 1 + 1) Ci:Fin (n1 + 1 + 1)j:Fin (n1 + 1 + 1)hij:i jσ:Fin (n1 + 1 + 1) Fin (n + 1 + 1):IsReindexing c c1 σ (i_1 : Fin n1), (c (σ i).succSuccAbove (σ j)) (i.funPredPredAbove j hij σ i_1) = (c1 i.succSuccAbove j) i_1 C:Typen:n1:c:Fin (n + 1 + 1) Cc1:Fin (n1 + 1 + 1) Ci:Fin (n1 + 1 + 1)j:Fin (n1 + 1 + 1)hij:i jσ:Fin (n1 + 1 + 1) Fin (n + 1 + 1):IsReindexing c c1 σFunction.Bijective (i.funPredPredAbove j hij σ ) All goals completed! 🐙 C:Typen:n1:c:Fin (n + 1 + 1) Cc1:Fin (n1 + 1 + 1) Ci:Fin (n1 + 1 + 1)j:Fin (n1 + 1 + 1)hij:i jσ:Fin (n1 + 1 + 1) Fin (n + 1 + 1):IsReindexing c c1 σ (i_1 : Fin n1), (c (σ i).succSuccAbove (σ j)) (i.funPredPredAbove j hij σ i_1) = (c1 i.succSuccAbove j) i_1 C:Typen:n1:c:Fin (n + 1 + 1) Cc1:Fin (n1 + 1 + 1) Ci:Fin (n1 + 1 + 1)j:Fin (n1 + 1 + 1)hij:i jσ:Fin (n1 + 1 + 1) Fin (n + 1 + 1):IsReindexing c c1 σm:Fin n1(c (σ i).succSuccAbove (σ j)) (i.funPredPredAbove j hij σ m) = (c1 i.succSuccAbove j) m All goals completed! 🐙

Removing two pairs of entries from c in either order gives the same colour list: removing the i1-th and j1-th entries and then the (shifted) i2-th and j2-th entries matches removing the i2-th and j2-th entries first and then the (shifted) i1-th and j1-th entries, via the identity permutation. This is used for the commutation of two contractions.

C:Typen:c:Fin (n + 1 + 1 + 1 + 1) Ci1:Fin (n + 1 + 1 + 1 + 1)j1:Fin (n + 1 + 1 + 1 + 1)i2:Fin (n + 1 + 1)j2:Fin (n + 1 + 1)hij1:i1 j1hij2:i2 j2i:Fin ni1 j1C:Typen:c:Fin (n + 1 + 1 + 1 + 1) Ci1:Fin (n + 1 + 1 + 1 + 1)j1:Fin (n + 1 + 1 + 1 + 1)i2:Fin (n + 1 + 1)j2:Fin (n + 1 + 1)hij1:i1 j1hij2:i2 j2i:Fin ni2 j2 C:Typen:c:Fin (n + 1 + 1 + 1 + 1) Ci1:Fin (n + 1 + 1 + 1 + 1)j1:Fin (n + 1 + 1 + 1 + 1)i2:Fin (n + 1 + 1)j2:Fin (n + 1 + 1)hij1:i1 j1hij2:i2 j2i:Fin ni1 j1 All goals completed! 🐙 C:Typen:c:Fin (n + 1 + 1 + 1 + 1) Ci1:Fin (n + 1 + 1 + 1 + 1)j1:Fin (n + 1 + 1 + 1 + 1)i2:Fin (n + 1 + 1)j2:Fin (n + 1 + 1)hij1:i1 j1hij2:i2 j2i:Fin ni2 j2 All goals completed! 🐙
lemma succSuccAbove_succAbove_comm {n : } {c : Fin (n + 1 + 1 + 1) C} (k : Fin (n + 1)) (i j : Fin (n + 1 + 1 + 1)) : -- The corresponding position of k in the full list. let k' := Fin.succSuccAbove i j k let k'' := Fin.predAbove 0 k' -- The position of i after removing k' let i' := k''.predAbove i -- The position of j after removing k' let j' := k''.predAbove j IsReindexing ((c k'.succAbove) i'.succSuccAbove j') ((c i.succSuccAbove j) k.succAbove) id := C:Typen:c:Fin (n + 1 + 1 + 1) Ck:Fin (n + 1)i:Fin (n + 1 + 1 + 1)j:Fin (n + 1 + 1 + 1)let k' := i.succSuccAbove j k; let k'' := predAbove 0 k'; let i' := k''.predAbove i; let j' := k''.predAbove j; IsReindexing ((c k'.succAbove) i'.succSuccAbove j') ((c i.succSuccAbove j) k.succAbove) id C:Typen:c:Fin (n + 1 + 1 + 1) Ck:Fin (n + 1)i:Fin (n + 1 + 1 + 1)j:Fin (n + 1 + 1 + 1)m:Fin n((c (i.succSuccAbove j k).succAbove) ((predAbove 0 (i.succSuccAbove j k)).predAbove i).succSuccAbove ((predAbove 0 (i.succSuccAbove j k)).predAbove j)) (id m) = ((c i.succSuccAbove j) k.succAbove) m C:Typen:c:Fin (n + 1 + 1 + 1) Ck:Fin (n + 1)i:Fin (n + 1 + 1 + 1)j:Fin (n + 1 + 1 + 1)m:Fin nc ((i.succSuccAbove j k).succAbove (((predAbove 0 (i.succSuccAbove j k)).predAbove i).succSuccAbove ((predAbove 0 (i.succSuccAbove j k)).predAbove j) m)) = c (i.succSuccAbove j (k.succAbove m)) C:Typen:c:Fin (n + 1 + 1 + 1) Ck:Fin (n + 1)i:Fin (n + 1 + 1 + 1)j:Fin (n + 1 + 1 + 1)m:Fin n(i.succSuccAbove j k).succAbove (((predAbove 0 (i.succSuccAbove j k)).predAbove i).succSuccAbove ((predAbove 0 (i.succSuccAbove j k)).predAbove j) m) = i.succSuccAbove j (k.succAbove m) C:Typen:c:Fin (n + 1 + 1 + 1) Ck:Fin (n + 1)i:Fin (n + 1 + 1 + 1)j:Fin (n + 1 + 1 + 1)m:Fin n((i.succSuccAbove j k).succAbove (((predAbove 0 (i.succSuccAbove j k)).predAbove i).succSuccAbove ((predAbove 0 (i.succSuccAbove j k)).predAbove j) m)) = (i.succSuccAbove j (k.succAbove m)) C:Typen:c:Fin (n + 1 + 1 + 1) Ck:Fin (n + 1)i:Fin (n + 1 + 1 + 1)j:Fin (n + 1 + 1 + 1)m:Fin n(if (if (m < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < i then (i.pred ) else (i.castLT )) m < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < j then (j.pred ) else (j.castLT ) then m else if (m + 1 < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < i then (i.pred ) else (i.castLT )) (if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < j then (j.pred ) else (j.castLT )) m then m + 1 else if (if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < i then (i.pred ) else (i.castLT )) m m + 1 < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < j then (j.pred ) else (j.castLT ) then m + 1 else m + 2) < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then if (m < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < i then (i.pred ) else (i.castLT )) m < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < j then (j.pred ) else (j.castLT ) then m else if (m + 1 < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < i then (i.pred ) else (i.castLT )) (if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < j then (j.pred ) else (j.castLT )) m then m + 1 else if (if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < i then (i.pred ) else (i.castLT )) m m + 1 < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < j then (j.pred ) else (j.castLT ) then m + 1 else m + 2 else (if (m < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < i then (i.pred ) else (i.castLT )) m < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < j then (j.pred ) else (j.castLT ) then m else if (m + 1 < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < i then (i.pred ) else (i.castLT )) (if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < j then (j.pred ) else (j.castLT )) m then m + 1 else if (if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < i then (i.pred ) else (i.castLT )) m m + 1 < if h : (if h : 0 < if k < i k < j then k else if k + 1 < i j k then k + 1 else if i k k + 1 < j then k + 1 else k + 2 then ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).pred ) else ((if k < i k < j then k, else if k + 1 < i j k then k + 1, else if i k k + 1 < j then k + 1, else k + 2, ).castLT )) < j then (j.pred ) else (j.castLT ) then m + 1 else m + 2) + 1) = if (if m < k then m else m + 1) < i (if m < k then m else m + 1) < j then if m < k then m else m + 1 else if (if m < k then m else m + 1) + 1 < i j if m < k then m else m + 1 then (if m < k then m else m + 1) + 1 else if (i if m < k then m else m + 1) (if m < k then m else m + 1) + 1 < j then (if m < k then m else m + 1) + 1 else (if m < k then m else m + 1) + 2 All goals completed! 🐙

Removing two single entries from c in either order gives the same colour list: removing the k1-th entry and then the (shifted) k2-th entry matches removing the k2-th entry first and then the (shifted) k1-th entry, via the identity permutation. This is used for the commutation of two evaluations of indices.

lemma succAbove_succAbove_comm {n : } {c : Fin (n + 1 + 1) C} (k1 : Fin (n + 1 + 1)) (k2 : Fin (n + 1)) : let k2' := k1.succAbove k2; let k1' := k2.predAbove k1; IsReindexing ((c k2'.succAbove) k1'.succAbove) ((c k1.succAbove) k2.succAbove) id := C:Typen:c:Fin (n + 1 + 1) Ck1:Fin (n + 1 + 1)k2:Fin (n + 1)let k2' := k1.succAbove k2; let k1' := k2.predAbove k1; IsReindexing ((c k2'.succAbove) k1'.succAbove) ((c k1.succAbove) k2.succAbove) id C:Typen:c:Fin (n + 1 + 1) Ck1:Fin (n + 1 + 1)k2:Fin (n + 1)k2':Fin (n + 1 + 1) := k1.succAbove k2k1':Fin (n + 1) := k2.predAbove k1IsReindexing ((c k2'.succAbove) k1'.succAbove) ((c k1.succAbove) k2.succAbove) id C:Typen:c:Fin (n + 1 + 1) Ck1:Fin (n + 1 + 1)k2:Fin (n + 1)k2':Fin (n + 1 + 1) := k1.succAbove k2k1':Fin (n + 1) := k2.predAbove k1m:Fin n((c k2'.succAbove) k1'.succAbove) (id m) = ((c k1.succAbove) k2.succAbove) m C:Typen:c:Fin (n + 1 + 1) Ck1:Fin (n + 1 + 1)k2:Fin (n + 1)k2':Fin (n + 1 + 1) := k1.succAbove k2k1':Fin (n + 1) := k2.predAbove k1m:Fin nc (k2'.succAbove (k1'.succAbove m)) = c (k1.succAbove (k2.succAbove m)) C:Typen:c:Fin (n + 1 + 1) Ck1:Fin (n + 1 + 1)k2:Fin (n + 1)k2':Fin (n + 1 + 1) := k1.succAbove k2k1':Fin (n + 1) := k2.predAbove k1m:Fin nk2'.succAbove (k1'.succAbove m) = k1.succAbove (k2.succAbove m) All goals completed! 🐙

Splitting a list of colours c : Fin (n + 1) → C into its first n entries and its last entry recovers c: the identity permutation matches Fin.append (c ∘ (Fin.last n).succAbove) ![c (Fin.last n)] with c.

C:Typen:c:Fin (n + 1) C (i : Fin (n + Nat.succ 0)), append (c castSucc) ![c (last n)] i = c i C:Typen:c:Fin (n + 1) Ci:Fin nappend (c castSucc) ![c (last n)] (castAdd (Nat.succ 0) i) = c (castAdd (Nat.succ 0) i)C:Typen:c:Fin (n + 1) Ci:Fin (Nat.succ 0)append (c castSucc) ![c (last n)] (natAdd n i) = c (natAdd n i) C:Typen:c:Fin (n + 1) Ci:Fin nappend (c castSucc) ![c (last n)] (castAdd (Nat.succ 0) i) = c (castAdd (Nat.succ 0) i) C:Typen:c:Fin (n + 1) Ci:Fin nc i.castSucc = c (castAdd (Nat.succ 0) i); All goals completed! 🐙 C:Typen:c:Fin (n + 1) Ci:Fin (Nat.succ 0)append (c castSucc) ![c (last n)] (natAdd n i) = c (natAdd n i) C:Typen:c:Fin (n + 1) Cappend (c castSucc) ![c (last n)] (natAdd n ((fun i => i) 0, )) = c (natAdd n ((fun i => i) 0, )); C:Typen:c:Fin (n + 1) Cc (last n) = c (natAdd n 0, ); All goals completed! 🐙

Splitting a list of colours c : Fin (n + 1) → C at an arbitrary slot i, rather than at the last one as in append_succ_last: the block map that lists the i.succAbove survivors and then i itself matches c with the survivors of i followed by the surviving entry c1 1 of a rank-two list c1 whose second entry is slot i's colour.

C:Typen:c:Fin (n + 1) Cc1:Fin 2 Ci:Fin (n + 1)hc:c i = c1 1Function.Bijective (i.cycleIcc (last n)) All goals completed! 🐙, fun x => C:Typen:c:Fin (n + 1) Cc1:Fin 2 Ci:Fin (n + 1)hc:c i = c1 1x:Fin (n + 1)c (append i.succAbove (fun x => i) x) = append (c i.succAbove) (c1 Fin.succAbove 0) x C:Typen:c:Fin (n + 1) Cc1:Fin 2 Ci:Fin (n + 1)hc:c i = c1 1x:Fin (n + 1)a:Fin nc (append i.succAbove (fun x => i) (castAdd 1 a)) = append (c i.succAbove) (c1 Fin.succAbove 0) (castAdd 1 a)C:Typen:c:Fin (n + 1) Cc1:Fin 2 Ci:Fin (n + 1)hc:c i = c1 1x:Fin (n + 1)a:Fin 1c (append i.succAbove (fun x => i) (natAdd n a)) = append (c i.succAbove) (c1 Fin.succAbove 0) (natAdd n a) C:Typen:c:Fin (n + 1) Cc1:Fin 2 Ci:Fin (n + 1)hc:c i = c1 1x:Fin (n + 1)a:Fin nc (append i.succAbove (fun x => i) (castAdd 1 a)) = append (c i.succAbove) (c1 Fin.succAbove 0) (castAdd 1 a) All goals completed! 🐙 C:Typen:c:Fin (n + 1) Cc1:Fin 2 Ci:Fin (n + 1)hc:c i = c1 1x:Fin (n + 1)a:Fin 1c (append i.succAbove (fun x => i) (natAdd n a)) = append (c i.succAbove) (c1 Fin.succAbove 0) (natAdd n a) C:Typen:c:Fin (n + 1) Cc1:Fin 2 Ci:Fin (n + 1)hc:c i = c1 1x:Fin (n + 1)c (append i.succAbove (fun x => i) (natAdd n ((fun i => i) 0, ))) = append (c i.succAbove) (c1 Fin.succAbove 0) (natAdd n ((fun i => i) 0, )) All goals completed! 🐙

Updating slot i of c to d and then back to e = c i returns c, no other slot moving: the colour cast a round trip of two contractions at slot i generates.

lemma update_update_of_eq {n : } {c : Fin n C} {d e : C} (i : Fin n) (he : c i = e) : IsReindexing c (Function.update (Function.update c i d) i e) (id : Fin n Fin n) := on_id.mpr (fun j => C:Typen:c:Fin n Cd:Ce:Ci:Fin nhe:c i = ej:Fin nc j = Function.update (Function.update c i d) i e j C:Typen:c:Fin n Cd:Ce:Ci:Fin nhe:c i = ej:Fin nh:j = ic j = Function.update (Function.update c i d) i e jC:Typen:c:Fin n Cd:Ce:Ci:Fin nhe:c i = ej:Fin nh:¬j = ic j = Function.update (Function.update c i d) i e j C:Typen:c:Fin n Cd:Ce:Ci:Fin nhe:c i = ej:Fin nh:j = ic j = Function.update (Function.update c i d) i e jC:Typen:c:Fin n Cd:Ce:Ci:Fin nhe:c i = ej:Fin nh:¬j = ic j = Function.update (Function.update c i d) i e j All goals completed! 🐙)

Splitting a list of colours c : Fin (n + 1) → C into its first entry and its remaining n entries recovers c: the canonical reindexing Fin (1 + n) ≃ Fin (n + 1) matches Fin.append ![c 0] (c ∘ Fin.succAbove 0) with c.

lemma append_of_first {n : } (c : Fin (n + 1) C) : IsReindexing (Fin.append ![c 0] (c Fin.succAbove 0)) c (Fin.cast (k:Typeinst✝⁵:CommRing kC:TypeG:Typeinst✝⁴:Group GV:C Typeinst✝³:(c : C) AddCommGroup (V c)inst✝²:(c : C) Module k (V c)basisIdx:C Typeinst✝¹:(c : C) Fintype (basisIdx c)inst✝:(c : C) DecidableEq (basisIdx c)rep:(c : C) Representation k G (V c)b:(c : C) Basis (basisIdx c) k (V c)S:TensorSpecies k C G V basisIdx rep bn:c:Fin (n + 1) Cn + 1 = Nat.succ 0 + n All goals completed! 🐙)) := C:Typen:c:Fin (n + 1) CIsReindexing (append ![c 0] (c Fin.succAbove 0)) c (Fin.cast ) refine (finCongr (C:Typen:c:Fin (n + 1) Cn + 1 = Nat.succ 0 + n All goals completed! 🐙)).bijective, fun i => ?_ C:Typen:c:Fin (n + 1) Cappend ![c 0] (c Fin.succAbove 0) (Fin.cast 0) = c 0C:Typen:c:Fin (n + 1) Ci:Fin nappend ![c 0] (c Fin.succAbove 0) (Fin.cast i.succ) = c i.succ C:Typen:c:Fin (n + 1) Cappend ![c 0] (c Fin.succAbove 0) (Fin.cast 0) = c 0 All goals completed! 🐙 C:Typen:c:Fin (n + 1) Ci:Fin nappend ![c 0] (c Fin.succAbove 0) (Fin.cast i.succ) = c i.succ simpa using congrArg (Fin.append ![c 0] (c Fin.succ)) (a₁ := Fin.cast _ i.succ) (a₂ := Fin.natAdd 1 i) (C:Typen:c:Fin (n + 1) Ci:Fin nFin.cast i.succ = natAdd 1 i C:Typen:c:Fin (n + 1) Ci:Fin n(Fin.cast i.succ) = (natAdd 1 i); All goals completed! 🐙)

Casting the domain along an equality n1 = n of lengths is a reindexing of c by c ∘ Fin.cast h.

lemma fin_cast_isReindexing (n n1 : ) {c : Fin n C} (h : n1 = n) : IsReindexing c (c Fin.cast h) (Fin.cast h) := C:Typen:n1:c:Fin n Ch:n1 = nIsReindexing c (c Fin.cast h) (Fin.cast h) C:Typen:n1:c:Fin n Ch:n1 = nFunction.Bijective (Fin.cast h)C:Typen:n1:c:Fin n Ch:n1 = n (i : Fin n1), c (Fin.cast h i) = (c Fin.cast h) i C:Typen:n1:c:Fin n Ch:n1 = nFunction.Bijective (Fin.cast h) All goals completed! 🐙 C:Typen:n1:c:Fin n Ch:n1 = n (i : Fin n1), c (Fin.cast h i) = (c Fin.cast h) i C:Typen:n1:c:Fin n Ch:n1 = ni:Fin n1c (Fin.cast h i) = (c Fin.cast h) i All goals completed! 🐙