176 lines
5.5 KiB
Text
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
|