PhysLean/HepLean/Tensors/IndexNotation/IndexList/OnlyUniqueDuals.lean
2024-09-06 07:08:08 -04:00

176 lines
5.5 KiB
Text

/-
Copyright (c) 2024 Joseph Tooby-Smith. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joseph Tooby-Smith
-/
import HepLean.Tensors.IndexNotation.IndexList.CountId
import HepLean.Tensors.IndexNotation.IndexList.Contraction
import Mathlib.Algebra.Order.Ring.Nat
import Mathlib.Data.Finset.Sort
/-!
# withDuals equal to withUniqueDuals
In a permissible list of indices every index which has a dual has a unique dual.
This corresponds to the condition that `l.withDual = l.withUniqueDual`.
We prove lemmas relating to this condition.
-/
namespace IndexNotation
namespace IndexList
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
variable (l l2 l3 : IndexList X)
/-- The conditon on an index list which is true if and only if for every index with a dual,
that dual is unique. -/
def OnlyUniqueDuals : Prop := l.withUniqueDual = l.withDual
namespace OnlyUniqueDuals
variable {l l2 l3 : IndexList X}
omit [IndexNotation X] [Fintype X]
omit [DecidableEq X] in
lemma iff_unique_forall :
l.OnlyUniqueDuals ↔
∀ (i : l.withDual) j, l.AreDualInSelf i j → j = l.getDual? i := by
refine Iff.intro (fun h i j hj => ?_) (fun h => ?_)
· rw [OnlyUniqueDuals, @Finset.ext_iff] at h
simp only [withUniqueDual, mem_withDual_iff_isSome, Finset.mem_filter, Finset.mem_univ,
true_and, and_iff_left_iff_imp] at h
refine h i ?_ j hj
exact withDual_isSome l i
· refine Finset.ext (fun i => ?_)
refine Iff.intro (fun hi => mem_withDual_of_mem_withUniqueDual l i hi) (fun hi => ?_)
· simp only [withUniqueDual, mem_withDual_iff_isSome, Finset.mem_filter, Finset.mem_univ,
true_and]
exact And.intro ((mem_withDual_iff_isSome l i).mp hi) (fun j hj => h ⟨i, hi⟩ j hj)
omit [DecidableEq X] in
lemma iff_countId_leq_two :
l.OnlyUniqueDuals ↔ ∀ i, l.countId (l.val.get i) ≤ 2 := by
refine Iff.intro (fun h i => ?_) (fun h => ?_)
· by_cases hi : i ∈ l.withDual
· rw [← h, mem_withUniqueDual_iff_countId_eq_two] at hi
rw [hi]
· rw [mem_withDual_iff_countId_gt_one] at hi
exact Nat.le_of_not_ge hi
· refine Finset.ext (fun i => ?_)
rw [mem_withUniqueDual_iff_countId_eq_two, mem_withDual_iff_countId_gt_one]
have hi := h i
omega
lemma iff_countId_leq_two' : l.OnlyUniqueDuals ↔ ∀ I, l.countId I ≤ 2 := by
rw [iff_countId_leq_two]
refine Iff.intro (fun h I => ?_) (fun h i => h (l.val.get i))
by_cases hI : l.countId I = 0
· rw [hI]
exact Nat.zero_le 2
· obtain ⟨I', hI1', hI2'⟩ := countId_neq_zero_mem l I hI
rw [countId_congr _ hI2']
have hi : List.indexOf I' l.val < l.length := List.indexOf_lt_length.mpr hI1'
have hI' : I' = l.val.get ⟨List.indexOf I' l.val, hi⟩ := (List.indexOf_get hi).symm
rw [hI']
exact h ⟨List.indexOf I' l.val, hi⟩
/-!
## On appended lists
-/
lemma inl (h : (l ++ l2).OnlyUniqueDuals) : l.OnlyUniqueDuals := by
rw [iff_countId_leq_two'] at h ⊢
intro I
have hI := h I
rw [countId_append] at hI
exact Nat.le_of_add_right_le hI
lemma inr (h : (l ++ l2).OnlyUniqueDuals) : l2.OnlyUniqueDuals := by
rw [iff_countId_leq_two'] at h ⊢
intro I
have hI := h I
rw [countId_append] at hI
exact le_of_add_le_right hI
lemma symm' (h : (l ++ l2).OnlyUniqueDuals) : (l2 ++ l).OnlyUniqueDuals := by
rw [iff_countId_leq_two'] at h ⊢
intro I
have hI := h I
rw [countId_append] at hI
simp only [countId_append, ge_iff_le]
omega
lemma symm : (l ++ l2).OnlyUniqueDuals ↔ (l2 ++ l).OnlyUniqueDuals := by
refine Iff.intro symm' symm'
lemma swap (h : (l ++ l2 ++ l3).OnlyUniqueDuals) : (l2 ++ l ++ l3).OnlyUniqueDuals := by
rw [iff_countId_leq_two'] at h ⊢
intro I
have hI := h I
simp only [countId_append] at hI
simp only [countId_append, ge_iff_le]
omega
/-!
## Contractions
-/
lemma contrIndexList (h : l.OnlyUniqueDuals) : l.contrIndexList.OnlyUniqueDuals := by
rw [iff_countId_leq_two'] at h ⊢
exact fun I => Nat.le_trans (countId_contrIndexList_le_countId l I) (h I)
lemma contrIndexList_left (h1 : (l ++ l2).OnlyUniqueDuals) :
(l.contrIndexList ++ l2).OnlyUniqueDuals := by
rw [iff_countId_leq_two'] at h1 ⊢
intro I
have hI := h1 I
simp only [countId_append] at hI
simp only [countId_append, ge_iff_le]
have h1 := countId_contrIndexList_le_countId l I
exact add_le_of_add_le_right hI h1
lemma contrIndexList_right (h1 : (l ++ l2).OnlyUniqueDuals) :
(l ++ l2.contrIndexList).OnlyUniqueDuals := by
rw [symm] at h1 ⊢
exact contrIndexList_left h1
lemma contrIndexList_append (h1 : (l ++ l2).OnlyUniqueDuals) :
(l.contrIndexList ++ l2.contrIndexList).OnlyUniqueDuals := by
rw [iff_countId_leq_two'] at h1 ⊢
intro I
have hI := h1 I
simp only [countId_append] at hI
simp only [countId_append, ge_iff_le]
have h1 := countId_contrIndexList_le_countId l I
have h2 := countId_contrIndexList_le_countId l2 I
omega
end OnlyUniqueDuals
omit [IndexNotation X] [Fintype X] in
lemma countId_of_OnlyUniqueDuals (h : l.OnlyUniqueDuals) (I : Index X) :
l.countId I ≤ 2 := by
rw [OnlyUniqueDuals.iff_countId_leq_two'] at h
exact h I
omit [IndexNotation X] [Fintype X] in
lemma countId_eq_two_ofcontrIndexList_left_of_OnlyUniqueDuals
(h : (l ++ l2).OnlyUniqueDuals) (I : Index X) (h' : (l.contrIndexList ++ l2).countId I = 2) :
(l ++ l2).countId I = 2 := by
simp only [countId_append]
have h1 := countId_contrIndexList_le_countId l I
have h3 := countId_of_OnlyUniqueDuals _ h I
simp only [countId_append] at h3 h'
omega
end IndexList
end IndexNotation