PhysLean/HepLean/SpaceTime/LorentzTensor/IndexNotation/OnlyUniqueDuals.lean

567 lines
23 KiB
Text
Raw Normal View History

2024-08-15 10:16:42 -04:00
/-
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.SpaceTime.LorentzTensor.IndexNotation.WithUniqueDual
import Mathlib.Algebra.Order.Ring.Nat
import Mathlib.Data.Finset.Sort
2024-08-15 10:16:42 -04:00
/-!
# withDuals equal to withUniqueDuals
2024-08-15 12:39:52 -04:00
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.
2024-08-15 10:16:42 -04:00
-/
namespace IndexNotation
namespace IndexList
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
variable (l l2 l3 : IndexList X)
/-!
## withDual equal to withUniqueDual
-/
lemma withUnqiueDual_eq_withDual_iff_unique_forall :
l.withUniqueDual = l.withDual ↔
∀ (i : l.withDual) j, l.AreDualInSelf i j → j = l.getDual? i := by
2024-08-20 14:38:29 -04:00
refine Iff.intro (fun h i j hj => ?_) (fun h => ?_)
· rw [@Finset.ext_iff] at h
2024-08-15 10:42:11 -04:00
simp only [withUniqueDual, mem_withDual_iff_isSome, Finset.mem_filter, Finset.mem_univ,
true_and, and_iff_left_iff_imp] at h
2024-08-15 10:16:42 -04:00
refine h i ?_ j hj
exact withDual_isSome l i
2024-08-20 14:38:29 -04:00
· 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,
2024-08-15 10:42:11 -04:00
true_and]
2024-08-20 14:38:29 -04:00
exact And.intro ((mem_withDual_iff_isSome l i).mp hi) (fun j hj => h ⟨i, hi⟩ j hj)
2024-08-15 10:16:42 -04:00
lemma withUnqiueDual_eq_withDual_iff :
l.withUniqueDual = l.withDual ↔
∀ i, (l.getDual? i).bind l.getDual? = Option.guard (fun i => i ∈ l.withDual) i := by
apply Iff.intro
· intro h i
by_cases hi : i ∈ l.withDual
· have hii : i ∈ l.withUniqueDual := by
simp_all only
2024-08-15 10:53:30 -04:00
change (l.getDual? i).bind l.getDual? = _
2024-08-15 10:16:42 -04:00
simp [hii]
symm
rw [Option.guard_eq_some]
exact ⟨rfl, mem_withUniqueDual_isSome l i hii⟩
· simp at hi
simp [Option.guard, hi]
· intro h
rw [withUnqiueDual_eq_withDual_iff_unique_forall]
intro i j hj
rcases l.getDual?_of_areDualInSelf hj with hi | hi | hi
· have hj' := h j
rw [hi] at hj'
simp at hj'
rw [hj']
symm
rw [Option.guard_eq_some, hi]
exact ⟨rfl, rfl⟩
· exact hi.symm
· have hj' := h j
rw [hi] at hj'
rw [h i] at hj'
have hi : Option.guard (fun i => i ∈ l.withDual) ↑i = some i := by
2024-08-15 10:53:30 -04:00
apply Option.guard_eq_some.mpr
simp
2024-08-15 10:16:42 -04:00
rw [hi] at hj'
simp at hj'
have hj'' := Option.guard_eq_some.mp hj'.symm
have hj''' := hj''.1
rw [hj'''] at hj
simp at hj
lemma withUnqiueDual_eq_withDual_iff_list_apply :
l.withUniqueDual = l.withDual ↔
(Fin.list l.length).map (fun i => (l.getDual? i).bind l.getDual?) =
(Fin.list l.length).map (fun i => Option.guard (fun i => i ∈ l.withDual) i) := by
rw [withUnqiueDual_eq_withDual_iff]
2024-08-20 14:38:29 -04:00
refine Iff.intro (fun h => List.map_eq_map_iff.mpr fun a _ => h a) (fun h i => ?_)
2024-08-15 10:16:42 -04:00
simp only [List.map_inj_left] at h
have h1 {n : } (m : Fin n) : m ∈ Fin.list n := by
have h1' : (Fin.list n)[m] = m := Fin.getElem_list _ _
exact h1' ▸ List.getElem_mem _ _ _
exact h i (h1 i)
/-- A boolean which is true for an index list `l` if for every index in `l` with a dual,
that dual is unique. -/
def withUnqiueDualEqWithDualBool : Bool :=
if (Fin.list l.length).map (fun i => (l.getDual? i).bind l.getDual?) =
(Fin.list l.length).map (fun i => Option.guard (fun i => i ∈ l.withDual) i) then
true
else
false
lemma withUnqiueDual_eq_withDual_iff_list_apply_bool :
l.withUniqueDual = l.withDual ↔ l.withUnqiueDualEqWithDualBool := by
rw [withUnqiueDual_eq_withDual_iff_list_apply]
2024-08-20 14:38:29 -04:00
refine Iff.intro (fun h => ?_) (fun h => ?_)
· simp only [withUnqiueDualEqWithDualBool, h, mem_withDual_iff_isSome, ↓reduceIte]
· simpa only [mem_withDual_iff_isSome, List.map_inj_left, withUnqiueDualEqWithDualBool,
Bool.if_false_right, Bool.and_true, decide_eq_true_eq] using h
2024-08-15 10:16:42 -04:00
@[simp]
lemma withUnqiueDual_eq_withDual_of_empty (h : l.withDual = ∅) :
l.withUniqueDual = l.withDual := by
rw [h, Finset.eq_empty_iff_forall_not_mem]
intro x
by_contra hx
have x' : l.withDual := ⟨x, l.mem_withDual_of_withUniqueDual ⟨x, hx⟩⟩
2024-08-15 10:53:30 -04:00
have hx' := x'.2
2024-08-15 10:16:42 -04:00
simp [h] at hx'
lemma withUniqueDual_eq_withDual_iff_sort_eq :
l.withUniqueDual = l.withDual ↔
l.withUniqueDual.sort (fun i j => i ≤ j) = l.withDual.sort (fun i j => i ≤ j) := by
refine Iff.intro (fun h => ?_) (fun h => ?_)
· rw [h]
· have h1 := congrArg Multiset.ofList h
rw [Finset.sort_eq, Finset.sort_eq] at h1
exact Eq.symm ((fun {α} {s t} => Finset.val_inj.mp) (id (Eq.symm h1)))
/-!
# withUniqueDual equal to withDual and count conditions.
-/
2024-08-23 15:37:14 -04:00
lemma withUniqueDual_eq_withDual_iff_countId_leq_two :
l.withUniqueDual = l.withDual ↔ ∀ 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] at hi
2024-08-23 15:37:14 -04:00
rw [mem_withUniqueDual_iff_countId_eq_two] at hi
rw [hi]
2024-08-23 15:37:14 -04:00
· rw [mem_withDual_iff_countId_gt_one] at hi
simp at hi
exact Nat.le_succ_of_le hi
· refine Finset.ext (fun i => ?_)
2024-08-23 15:37:14 -04:00
rw [mem_withUniqueDual_iff_countId_eq_two, mem_withDual_iff_countId_gt_one]
have hi := h i
omega
2024-08-23 15:37:14 -04:00
lemma withUniqueDual_eq_withDual_countId_cases (h : l.withUniqueDual = l.withDual)
(i : Fin l.length) : l.countId (l.val.get i) = 0
l.countId (l.val.get i) = 1 l.countId (l.val.get i) = 2 := by
by_cases h0 : l.countId (l.val.get i)= 0
2024-08-23 09:29:39 -04:00
· exact Or.inl h0
2024-08-23 15:37:14 -04:00
· by_cases h1 : l.countId (l.val.get i) = 1
2024-08-23 09:29:39 -04:00
· exact Or.inr (Or.inl h1)
2024-08-23 15:37:14 -04:00
· have h2 : l.countId (l.val.get i) ≤ 2 := by
rw [withUniqueDual_eq_withDual_iff_countId_leq_two] at h
2024-08-23 09:29:39 -04:00
exact h i
omega
section filterID
2024-08-23 11:14:48 -04:00
2024-08-23 15:37:14 -04:00
lemma filter_id_of_countId_eq_zero {i : Fin l.length} (h1 : l.countId (l.val.get i) = 0) :
2024-08-23 09:29:39 -04:00
l.val.filter (fun J => (l.val.get i).id = J.id) = [] := by
2024-08-23 15:37:14 -04:00
rw [countId_eq_length_filter, List.length_eq_zero] at h1
2024-08-23 11:14:48 -04:00
exact h1
2024-08-23 15:37:14 -04:00
lemma filter_id_of_countId_eq_one {i : Fin l.length} (h1 : l.countId (l.val.get i) = 1) :
2024-08-23 09:29:39 -04:00
l.val.filter (fun J => (l.val.get i).id = J.id) = [l.val.get i] := by
2024-08-23 15:37:14 -04:00
rw [countId_eq_length_filter, List.length_eq_one] at h1
2024-08-23 09:29:39 -04:00
obtain ⟨J, hJ⟩ := h1
2024-08-23 09:49:16 -04:00
have hme : (l.val.get i) ∈ List.filter (fun J => decide ((l.val.get i).id = J.id)) l.val := by
simp only [List.get_eq_getElem, List.mem_filter, decide_True, and_true]
2024-08-23 09:29:39 -04:00
exact List.getElem_mem l.val (↑i) i.isLt
rw [hJ] at hme
2024-08-23 09:49:16 -04:00
simp only [List.get_eq_getElem, List.mem_singleton] at hme
2024-08-23 09:29:39 -04:00
erw [hJ]
2024-08-23 09:49:16 -04:00
simp only [List.get_eq_getElem, List.cons.injEq, and_true]
2024-08-23 09:29:39 -04:00
exact id (Eq.symm hme)
2024-08-23 15:37:14 -04:00
lemma filter_id_of_countId_eq_two {i : Fin l.length}
(h : l.countId (l.val.get i) = 2) :
2024-08-23 09:29:39 -04:00
l.val.filter (fun J => (l.val.get i).id = J.id) =
2024-08-23 15:37:14 -04:00
[l.val.get i, l.val.get ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))]
2024-08-23 09:29:39 -04:00
l.val.filter (fun J => (l.val.get i).id = J.id) =
2024-08-23 15:37:14 -04:00
[l.val.get ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h)), l.val.get i] := by
have hc := l.countId_eq_two_of_mem_withUniqueDual i
((mem_withUniqueDual_iff_countId_eq_two l i).mpr h)
rw [countId_eq_length_filter] at hc
by_cases hi : i < ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))
2024-08-23 09:29:39 -04:00
· apply Or.inl
symm
apply List.Sublist.eq_of_length
2024-08-23 09:49:16 -04:00
· have h1 : [l.val.get i, l.val.get
2024-08-23 15:37:14 -04:00
((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))].filter
2024-08-23 09:49:16 -04:00
(fun J => (l.val.get i).id = J.id) = [l.val.get i, l.val.get
2024-08-23 15:37:14 -04:00
((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))] := by
2024-08-23 09:49:16 -04:00
simp only [List.get_eq_getElem, decide_True, List.filter_cons_of_pos, List.cons.injEq,
List.filter_eq_self, List.mem_singleton, decide_eq_true_eq, forall_eq, true_and]
2024-08-23 15:37:14 -04:00
change l.idMap i = l.idMap ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))
2024-08-23 09:29:39 -04:00
simp
rw [← h1]
2024-08-23 09:49:16 -04:00
refine List.Sublist.filter (fun (J : Index X) => ((l.val.get i).id = J.id)) ?_
2024-08-23 09:29:39 -04:00
rw [List.sublist_iff_exists_fin_orderEmbedding_get_eq]
2024-08-23 15:37:14 -04:00
refine ⟨⟨⟨![i, (l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h)], ?_⟩, ?_⟩, ?_⟩
2024-08-23 09:29:39 -04:00
· refine List.nodup_ofFn.mp ?_
simpa using Fin.ne_of_lt hi
· intro a b
fin_cases a, b
<;> simp [hi]
exact Fin.le_of_lt hi
· intro a
fin_cases a <;> rfl
· rw [hc]
simp
2024-08-23 15:37:14 -04:00
· have hi' : ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h)) < i := by
have h1 := l.getDual?_get_areDualInSelf i (getDual?_isSome_of_countId_eq_two l h)
2024-08-23 09:29:39 -04:00
simp only [AreDualInSelf] at h1
have h2 := h1.1
omega
apply Or.inr
symm
apply List.Sublist.eq_of_length
2024-08-23 15:37:14 -04:00
· have h1 : [l.val.get ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h)),
2024-08-23 09:49:16 -04:00
l.val.get i].filter (fun J => (l.val.get i).id = J.id) = [l.val.get
2024-08-23 15:37:14 -04:00
((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h)), l.val.get i,] := by
2024-08-23 09:49:16 -04:00
simp only [List.get_eq_getElem, List.filter_eq_self, List.mem_cons, List.mem_singleton,
decide_eq_true_eq, forall_eq_or_imp, forall_eq, and_true]
apply And.intro
2024-08-23 15:37:14 -04:00
· change l.idMap i = l.idMap ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))
2024-08-23 09:49:16 -04:00
simp
· simp only [List.not_mem_nil, false_implies, implies_true, and_self]
2024-08-23 09:29:39 -04:00
rw [← h1]
2024-08-23 09:49:16 -04:00
refine List.Sublist.filter (fun (J : Index X) => ((l.val.get i).id = J.id)) ?_
2024-08-23 09:29:39 -04:00
rw [List.sublist_iff_exists_fin_orderEmbedding_get_eq]
2024-08-23 15:37:14 -04:00
refine ⟨⟨⟨![(l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h), i], ?_⟩, ?_⟩, ?_⟩
2024-08-23 09:29:39 -04:00
· refine List.nodup_ofFn.mp ?_
simp only [List.get_eq_getElem, List.length_singleton, Nat.succ_eq_add_one, Nat.reduceAdd,
List.length_nil, List.ofFn_succ, Fin.isValue, Matrix.cons_val_zero, Matrix.cons_val_succ,
Matrix.cons_val_fin_one, List.ofFn_zero, List.nodup_cons, List.mem_singleton,
List.not_mem_nil, not_false_eq_true, List.nodup_nil, and_self, and_true]
exact Fin.ne_of_lt hi'
· intro a b
fin_cases a, b
<;> simp [hi']
exact Fin.le_of_lt hi'
· intro a
fin_cases a <;> rfl
· rw [hc]
simp
2024-08-23 09:49:16 -04:00
/-- Given an index `I` such that there is one index in `l` with the same `id` as `I`.
This is that index. -/
2024-08-23 15:37:14 -04:00
def consDual {I : Index X} (hI : l.countId I = 1) : Index X :=
(l.cons I).val.get (((l.cons I).getDual? ⟨0, by simp⟩).get
((l.cons I).getDual?_isSome_of_countId_eq_two (by simpa [countId] using hI)))
/-! TODO: Relate `consDual` to `getDualInOther?`. -/
2024-08-23 09:29:39 -04:00
@[simp]
2024-08-23 15:37:14 -04:00
lemma consDual_id {I : Index X} (hI : l.countId I = 1) :
2024-08-23 09:29:39 -04:00
(l.consDual hI).id = I.id := by
change (l.cons I).idMap ((((l.cons I).getDual? ⟨0, by simp⟩).get
2024-08-23 15:37:14 -04:00
((l.cons I).getDual?_isSome_of_countId_eq_two (by simpa [countId] using hI)))) = _
2024-08-23 09:29:39 -04:00
simp only [cons, Fin.zero_eta, getDual?_get_id]
simp only [idMap, List.get_eq_getElem, List.length_cons, Fin.val_zero, List.getElem_cons_zero]
@[simp]
2024-08-23 15:37:14 -04:00
lemma consDual_mem {I : Index X} (hI : l.countId I = 1) :
2024-08-23 09:29:39 -04:00
l.consDual hI ∈ l.val := by
let Di := (((l.cons I).getDual? ⟨0, by simp⟩).get (by
2024-08-23 15:37:14 -04:00
rw [← zero_mem_withUniqueDual_of_cons_iff_countId_one] at hI; exact
2024-08-23 09:29:39 -04:00
mem_withUniqueDual_isSome (l.cons I) ⟨0, _⟩ hI))
have hDiz : Di ≠ ⟨0, by simp⟩ := by
have hd : (l.cons I).AreDualInSelf ⟨0, by simp⟩ Di := by
simp [Di]
symm
exact (l.cons I).getDual?_get_areDualInSelf ⟨0, by simp⟩ (by
2024-08-23 15:37:14 -04:00
rw [← zero_mem_withUniqueDual_of_cons_iff_countId_one] at hI;
2024-08-23 09:29:39 -04:00
exact mem_withUniqueDual_isSome (l.cons I) ⟨0, _⟩ hI)
simp [AreDualInSelf] at hd
have hd2 := hd.1
exact fun a => hd2 (id (Eq.symm a))
have Dim1 : (Di.1-1) + 1 = Di.1 := by
have : Di.1 ≠ 0 := by
2024-08-23 09:49:16 -04:00
rw [Fin.ne_iff_vne] at hDiz
2024-08-23 09:29:39 -04:00
exact hDiz
omega
change (l.cons I).val.get Di ∈ l.val
2024-08-23 09:49:16 -04:00
simp only [cons_val, List.get_eq_getElem, List.length_cons]
have h1 : (I :: l.val).get ⟨Di.1, Di.isLt⟩ = (I :: l.val).get
⟨(Di.1-1) + 1, by rw [Dim1]; exact Di.isLt⟩ := by
2024-08-23 09:29:39 -04:00
apply congrArg
rw [Fin.ext_iff]
exact id (Eq.symm Dim1)
2024-08-23 09:49:16 -04:00
simp only [List.length_cons, cons_length, Fin.eta, List.get_eq_getElem,
List.getElem_cons_succ] at h1
2024-08-23 09:29:39 -04:00
rw [h1]
exact List.getElem_mem l.val _ _
2024-08-23 15:37:14 -04:00
lemma consDual_filter {I : Index X} (hI : l.countId I = 1) :
2024-08-23 09:29:39 -04:00
l.val.filter (fun J => I.id = J.id) = [l.consDual hI] := by
have h1 : (l.val.filter (fun J => I.id = J.id)).length = 1 := by
rw [← List.countP_eq_length_filter]
exact hI
rw [List.length_eq_one] at h1
obtain ⟨a, ha⟩ := h1
rw [ha]
2024-08-23 09:49:16 -04:00
simp only [List.cons.injEq, and_true]
2024-08-23 09:29:39 -04:00
have haI : l.consDual hI ∈ l.val.filter (fun J => I.id = J.id) := by
simp
rw [ha] at haI
simp at haI
exact haI.symm
2024-08-23 15:37:14 -04:00
lemma consDual_iff {I : Index X} (hI : l.countId I = 1)
2024-08-23 09:29:39 -04:00
(I' : Index X) : I' = l.consDual hI ↔ I' ∈ l.val ∧ I'.id = I.id := by
refine Iff.intro (fun h => ?_) (fun h => ?_)
· subst h
2024-08-23 09:49:16 -04:00
simp only [consDual_mem, consDual_id, and_self]
· have hI' : I' ∈ l.val.filter (fun J => I.id = J.id) := by
simp only [List.mem_filter, h, decide_True, and_self]
2024-08-23 09:29:39 -04:00
rw [l.consDual_filter hI] at hI'
simpa using hI'
2024-08-23 15:37:14 -04:00
lemma filter_of_constDual {I : Index X} (hI : l.countId I = 1) :
2024-08-23 09:29:39 -04:00
(l.cons I).val.filter (fun J => (l.consDual hI).id = J.id) = [I, l.consDual hI] := by
2024-08-23 09:49:16 -04:00
simp only [consDual_id, cons_val, decide_True, List.filter_cons_of_pos, List.cons.injEq, true_and]
2024-08-23 09:29:39 -04:00
exact consDual_filter l hI
end filterID
2024-08-23 15:37:14 -04:00
lemma withUniqueDual_eq_withDual_iff_countId_mem_le_two :
l.withUniqueDual = l.withDual ↔
2024-08-23 15:37:14 -04:00
∀ I (_ : I ∈ l.val), l.countId I ≤ 2 := by
rw [withUniqueDual_eq_withDual_iff_countId_leq_two]
refine Iff.intro (fun h I hI => ?_) (fun h i => ?_)
· let i := l.val.indexOf I
have hi : i < l.length := List.indexOf_lt_length.mpr hI
have hIi : I = l.val.get ⟨i, hi⟩ := (List.indexOf_get hi).symm
rw [hIi]
exact h ⟨i, hi⟩
· exact h (l.val.get i) (List.getElem_mem l.val (↑i) i.isLt)
2024-08-23 15:37:14 -04:00
lemma withUniqueDual_eq_withDual_iff_all_countId_le_two :
l.withUniqueDual = l.withDual ↔
2024-08-23 15:37:14 -04:00
l.val.all (fun I => l.countId I ≤ 2) := by
rw [withUniqueDual_eq_withDual_iff_countId_mem_le_two]
simp only [List.all_eq_true, decide_eq_true_eq]
/-!
## Relationship with cons
-/
lemma withUniqueDual_eq_withDual_cons_iff (I : Index X) (hl : l.withUniqueDual = l.withDual) :
2024-08-23 15:37:14 -04:00
(l.cons I).withUniqueDual = (l.cons I).withDual ↔ l.countId I ≤ 1 := by
rw [withUniqueDual_eq_withDual_iff_all_countId_le_two]
simp only [cons_val, countId, List.all_cons, decide_True, List.countP_cons_of_pos,
Nat.reduceLeDiff, Bool.and_eq_true, decide_eq_true_eq, List.all_eq_true, and_iff_left_iff_imp]
intro h I' hI'
by_cases hII' : I'.id = I.id
· rw [List.countP_cons_of_pos]
· rw [hII']
omega
· simpa using hII'
· rw [List.countP_cons_of_neg]
2024-08-23 15:37:14 -04:00
· rw [withUniqueDual_eq_withDual_iff_countId_mem_le_two] at hl
exact hl I' hI'
· simpa using hII'
2024-08-23 09:29:39 -04:00
lemma withUniqueDual_eq_withDual_of_cons {I : Index X}
(hl : (l.cons I).withUniqueDual = (l.cons I).withDual) :
l.withUniqueDual = l.withDual := by
2024-08-23 15:37:14 -04:00
rw [withUniqueDual_eq_withDual_iff_countId_mem_le_two] at hl ⊢
2024-08-23 09:29:39 -04:00
intro I' hI'
have hImem : I' ∈ (l.cons I).val := by
simp [hI']
2024-08-23 09:49:16 -04:00
have h1 : List.countP (fun J => decide (I'.id = J.id)) l.val ≤
2024-08-23 09:29:39 -04:00
List.countP (fun J => decide (I'.id = J.id)) (I :: l.val) := by
by_cases hII' : I'.id = I.id
· rw [List.countP_cons_of_pos _ l.val]
· simp
· simpa using hII'
· rw [List.countP_cons_of_neg _ l.val]
simpa using hII'
exact Nat.le_trans h1 (hl I' hImem)
2024-08-23 09:49:16 -04:00
lemma withUniqueDual_eq_withDual_cons_iff' (I : Index X) :
2024-08-23 09:29:39 -04:00
(l.cons I).withUniqueDual = (l.cons I).withDual ↔
2024-08-23 15:37:14 -04:00
l.withUniqueDual = l.withDual ∧ l.countId I ≤ 1 := by
2024-08-23 09:29:39 -04:00
refine Iff.intro (fun h => ?_) (fun h => ?_)
· have h1 : l.withUniqueDual = l.withDual := by
exact withUniqueDual_eq_withDual_of_cons l h
2024-08-23 09:49:16 -04:00
apply And.intro h1 ((withUniqueDual_eq_withDual_cons_iff l I h1).mp h)
2024-08-23 09:29:39 -04:00
· rw [withUniqueDual_eq_withDual_cons_iff]
· exact h.2
· exact h.1
2024-08-15 10:16:42 -04:00
/-!
## withUniqueDualInOther equal to withDualInOther append conditions
-/
lemma withUniqueDualInOther_eq_withDualInOther_append_of_symm'
(h : (l ++ l2).withUniqueDualInOther l3 = (l ++ l2).withDualInOther l3) :
2024-08-15 10:53:30 -04:00
(l2 ++ l).withUniqueDualInOther l3 = (l2 ++ l).withDualInOther l3 := by
2024-08-15 10:16:42 -04:00
rw [Finset.ext_iff] at h ⊢
intro j
obtain ⟨k, hk⟩ := appendEquiv.surjective j
subst hk
match k with
| Sum.inl k =>
rw [mem_append_withUniqueDualInOther_symm]
2024-08-15 10:42:11 -04:00
simpa only [mem_withInDualOther_iff_isSome, getDualInOther?_append_of_inl,
getDualInOther?_append_of_inr] using h (appendEquiv (Sum.inr k))
2024-08-15 10:16:42 -04:00
| Sum.inr k =>
rw [← mem_append_withUniqueDualInOther_symm]
2024-08-15 10:42:11 -04:00
simpa only [mem_withInDualOther_iff_isSome, getDualInOther?_append_of_inr,
getDualInOther?_append_of_inl] using h (appendEquiv (Sum.inl k))
2024-08-15 10:16:42 -04:00
lemma withUniqueDualInOther_eq_withDualInOther_append_of_symm :
(l ++ l2).withUniqueDualInOther l3 = (l ++ l2).withDualInOther l3 ↔
2024-08-20 14:38:29 -04:00
(l2 ++ l).withUniqueDualInOther l3 = (l2 ++ l).withDualInOther l3 :=
Iff.intro
(l.withUniqueDualInOther_eq_withDualInOther_append_of_symm' l2 l3)
(l2.withUniqueDualInOther_eq_withDualInOther_append_of_symm' l l3)
2024-08-15 10:16:42 -04:00
lemma withUniqueDualInOther_eq_withDualInOther_of_append_symm'
(h : l.withUniqueDualInOther (l2 ++ l3) = l.withDualInOther (l2 ++ l3)) :
l.withUniqueDualInOther (l3 ++ l2) = l.withDualInOther (l3 ++ l2) := by
rw [Finset.ext_iff] at h ⊢
intro j
rw [mem_withUniqueDualInOther_symm]
rw [h j]
simp only [mem_withInDualOther_iff_isSome, getDualInOther?_isSome_of_append_iff]
exact Or.comm
lemma withUniqueDualInOther_eq_withDualInOther_of_append_symm :
l.withUniqueDualInOther (l2 ++ l3) = l.withDualInOther (l2 ++ l3) ↔
2024-08-20 14:38:29 -04:00
l.withUniqueDualInOther (l3 ++ l2) = l.withDualInOther (l3 ++ l2) :=
Iff.intro
(l.withUniqueDualInOther_eq_withDualInOther_of_append_symm' l2 l3)
(l.withUniqueDualInOther_eq_withDualInOther_of_append_symm' l3 l2)
2024-08-15 10:16:42 -04:00
/-!
## withDual equal to withUniqueDual append conditions
-/
lemma append_withDual_eq_withUniqueDual_iff :
(l ++ l2).withUniqueDual = (l ++ l2).withDual ↔
((l.withUniqueDual ∩ (l.withDualInOther l2)ᶜ) l.withUniqueDualInOther l2)
= l.withDual l.withDualInOther l2
∧ (l2.withUniqueDual ∩ (l2.withDualInOther l)ᶜ) l2.withUniqueDualInOther l
2024-08-15 10:53:30 -04:00
= l2.withDual l2.withDualInOther l := by
2024-08-15 10:16:42 -04:00
rw [append_withUniqueDual_disjSum, withDual_append_eq_disjSum]
simp only [Equiv.finsetCongr_apply, Finset.map_inj]
have h (s s' : Finset (Fin l.length)) (t t' : Finset (Fin l2.length)) :
s.disjSum t = s'.disjSum t' ↔ s = s' ∧ t = t' := by
simp [Finset.ext_iff]
exact h _ _ _ _
lemma append_withDual_eq_withUniqueDual_symm :
(l ++ l2).withUniqueDual = (l ++ l2).withDual ↔
(l2 ++ l).withUniqueDual = (l2 ++ l).withDual := by
rw [append_withDual_eq_withUniqueDual_iff, append_withDual_eq_withUniqueDual_iff]
exact And.comm
@[simp]
lemma append_withDual_eq_withUniqueDual_inl (h : (l ++ l2).withUniqueDual = (l ++ l2).withDual) :
l.withUniqueDual = l.withDual := by
rw [Finset.ext_iff]
intro i
refine Iff.intro (fun h' => ?_) (fun h' => ?_)
· exact mem_withDual_of_mem_withUniqueDual l i h'
· have hn : appendEquiv (Sum.inl i) ∈ (l ++ l2).withUniqueDual := by
rw [h]
simp_all
refine l.mem_withUniqueDual_of_inl l2 i hn ?_
exact (mem_withDual_iff_isSome l i).mp h'
@[simp]
lemma append_withDual_eq_withUniqueDual_inr (h : (l ++ l2).withUniqueDual = (l ++ l2).withDual) :
l2.withUniqueDual = l2.withDual := by
rw [append_withDual_eq_withUniqueDual_symm] at h
exact append_withDual_eq_withUniqueDual_inl l2 l h
@[simp]
lemma append_withDual_eq_withUniqueDual_withUniqueDualInOther_inl
2024-08-15 10:53:30 -04:00
(h : (l ++ l2).withUniqueDual = (l ++ l2).withDual) :
2024-08-15 10:16:42 -04:00
l.withUniqueDualInOther l2 = l.withDualInOther l2 := by
rw [Finset.ext_iff]
intro i
refine Iff.intro (fun h' => ?_) (fun h' => ?_)
2024-08-15 10:42:11 -04:00
· simp only [mem_withInDualOther_iff_isSome, h', mem_withUniqueDualInOther_isSome]
2024-08-15 10:16:42 -04:00
· have hn : appendEquiv (Sum.inl i) ∈ (l ++ l2).withUniqueDual := by
rw [h]
2024-08-15 10:42:11 -04:00
simp_all only [mem_withInDualOther_iff_isSome, mem_withDual_iff_isSome,
getDual?_isSome_append_inl_iff, or_true, mem_withUniqueDual_isSome]
2024-08-15 10:16:42 -04:00
refine l.mem_withUniqueDualInOther_of_inl_withDualInOther l2 i hn ?_
exact (mem_withInDualOther_iff_isSome l l2 i).mp h'
@[simp]
lemma append_withDual_eq_withUniqueDual_withUniqueDualInOther_inr
2024-08-15 10:53:30 -04:00
(h : (l ++ l2).withUniqueDual = (l ++ l2).withDual) :
2024-08-15 10:16:42 -04:00
l2.withUniqueDualInOther l = l2.withDualInOther l := by
rw [append_withDual_eq_withUniqueDual_symm] at h
exact append_withDual_eq_withUniqueDual_withUniqueDualInOther_inl l2 l h
lemma append_withDual_eq_withUniqueDual_iff' :
(l ++ l2).withUniqueDual = (l ++ l2).withDual ↔
l.withUniqueDual = l.withDual ∧ l2.withUniqueDual = l2.withDual
∧ l.withUniqueDualInOther l2 = l.withDualInOther l2 ∧
l2.withUniqueDualInOther l = l2.withDualInOther l := by
apply Iff.intro
2024-08-20 14:38:29 -04:00
· intro h
2024-08-21 06:45:09 -04:00
exact ⟨append_withDual_eq_withUniqueDual_inl l l2 h,
append_withDual_eq_withUniqueDual_inr l l2 h,
2024-08-20 14:38:29 -04:00
append_withDual_eq_withUniqueDual_withUniqueDualInOther_inl l l2 h,
append_withDual_eq_withUniqueDual_withUniqueDualInOther_inr l l2 h⟩
· intro h
rw [append_withDual_eq_withUniqueDual_iff]
rw [h.1, h.2.1, h.2.2.1, h.2.2.2]
have h1 : l.withDual ∩ (l.withDualInOther l2)ᶜ = l.withDual := by
rw [Finset.inter_eq_left, Finset.subset_iff, ← h.1, ← h.2.2.1]
intro i hi
simp only [withUniqueDualInOther, mem_withDual_iff_isSome, Bool.not_eq_true,
Option.not_isSome, Option.isNone_iff_eq_none, mem_withInDualOther_iff_isSome,
Finset.compl_filter, not_and, not_forall, Finset.mem_filter, Finset.mem_univ, true_and]
intro hn
simp_all
have h2 : l2.withDual ∩ (l2.withDualInOther l)ᶜ = l2.withDual := by
rw [Finset.inter_eq_left, Finset.subset_iff, ← h.2.1, ← h.2.2.2]
intro i hi
simp only [withUniqueDualInOther, mem_withDual_iff_isSome, Bool.not_eq_true,
Option.not_isSome, Option.isNone_iff_eq_none, mem_withInDualOther_iff_isSome,
Finset.compl_filter, not_and, not_forall, Finset.mem_filter, Finset.mem_univ, true_and]
intro hn
simp_all
exact ⟨congrFun (congrArg Union.union h1) (l.withDualInOther l2),
congrFun (congrArg Union.union h2) (l2.withDualInOther l)⟩
2024-08-15 10:16:42 -04:00
lemma append_withDual_eq_withUniqueDual_swap :
(l ++ l2 ++ l3).withUniqueDual = (l ++ l2 ++ l3).withDual
↔ (l2 ++ l ++ l3).withUniqueDual = (l2 ++ l ++ l3).withDual := by
rw [append_withDual_eq_withUniqueDual_iff']
rw [append_withDual_eq_withUniqueDual_iff' (l2 ++ l) l3]
rw [append_withDual_eq_withUniqueDual_symm]
rw [withUniqueDualInOther_eq_withDualInOther_of_append_symm]
rw [withUniqueDualInOther_eq_withDualInOther_append_of_symm]
end IndexList
end IndexNotation