/- 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