PhysLean/HepLean/SpaceTime/LorentzTensor/IndexNotation/OnlyUniqueDuals.lean
2024-08-26 10:11:49 -04:00

618 lines
25 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
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.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)
/-!
## 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
refine Iff.intro (fun h i j hj => ?_) (fun h => ?_)
· rw [@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)
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
change (l.getDual? i).bind l.getDual? = _
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
apply Option.guard_eq_some.mpr
simp
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]
refine Iff.intro (fun h => List.map_eq_map_iff.mpr fun a _ => h a) (fun h i => ?_)
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]
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
@[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⟩⟩
have hx' := x'.2
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.
-/
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
rw [mem_withUniqueDual_iff_countId_eq_two] at hi
rw [hi]
· rw [mem_withDual_iff_countId_gt_one] at hi
simp at hi
exact Nat.le_succ_of_le 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 withUniqueDual_eq_withDual_iff_countId_leq_two' :
l.withUniqueDual = l.withDual ↔ ∀ I, l.countId I ≤ 2 := by
rw [withUniqueDual_eq_withDual_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⟩
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
· exact Or.inl h0
· by_cases h1 : l.countId (l.val.get i) = 1
· exact Or.inr (Or.inl h1)
· have h2 : l.countId (l.val.get i) ≤ 2 := by
rw [withUniqueDual_eq_withDual_iff_countId_leq_two] at h
exact h i
omega
section filterID
/-! TODO: Move this section. -/
lemma filter_id_of_countId_eq_zero {i : Fin l.length} (h1 : l.countId (l.val.get i) = 0) :
l.val.filter (fun J => (l.val.get i).id = J.id) = [] := by
rw [countId_eq_length_filter, List.length_eq_zero] at h1
exact h1
lemma filter_id_of_countId_eq_zero' {I : Index X} (h1 : l.countId I = 0) :
l.val.filter (fun J => I.id = J.id) = [] := by
rw [countId_eq_length_filter, List.length_eq_zero] at h1
exact h1
lemma filter_id_of_countId_eq_one {i : Fin l.length} (h1 : l.countId (l.val.get i) = 1) :
l.val.filter (fun J => (l.val.get i).id = J.id) = [l.val.get i] := by
rw [countId_eq_length_filter, List.length_eq_one] at h1
obtain ⟨J, hJ⟩ := h1
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]
exact List.getElem_mem l.val (↑i) i.isLt
rw [hJ] at hme
simp only [List.get_eq_getElem, List.mem_singleton] at hme
erw [hJ]
simp only [List.get_eq_getElem, List.cons.injEq, and_true]
exact id (Eq.symm hme)
lemma filter_id_of_countId_eq_one_mem {I : Index X} (hI : I ∈ l.val) (h : l.countId I = 1) :
l.val.filter (fun J => I.id = J.id) = [I] := by
rw [countId_eq_length_filter, List.length_eq_one] at h
obtain ⟨J, hJ⟩ := h
have hme : I ∈ List.filter (fun J => decide (I.id = J.id)) l.val := by
simp only [List.mem_filter, decide_True, and_true]
exact hI
rw [hJ] at hme
simp only [List.mem_singleton] at hme
erw [hJ]
simp only [List.cons.injEq, and_true]
exact id (Eq.symm hme)
lemma filter_id_of_countId_eq_two {i : Fin l.length}
(h : l.countId (l.val.get i) = 2) :
l.val.filter (fun J => (l.val.get i).id = J.id) =
[l.val.get i, l.val.get ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))]
l.val.filter (fun J => (l.val.get i).id = J.id) =
[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))
· apply Or.inl
symm
apply List.Sublist.eq_of_length
· have h1 : [l.val.get i, l.val.get
((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))].filter
(fun J => (l.val.get i).id = J.id) = [l.val.get i, l.val.get
((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))] := by
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]
change l.idMap i = l.idMap ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))
simp
rw [← h1]
refine List.Sublist.filter (fun (J : Index X) => ((l.val.get i).id = J.id)) ?_
rw [List.sublist_iff_exists_fin_orderEmbedding_get_eq]
refine ⟨⟨⟨![i, (l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h)], ?_⟩, ?_⟩, ?_⟩
· 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
· 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)
simp only [AreDualInSelf] at h1
have h2 := h1.1
omega
apply Or.inr
symm
apply List.Sublist.eq_of_length
· have h1 : [l.val.get ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h)),
l.val.get i].filter (fun J => (l.val.get i).id = J.id) = [l.val.get
((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h)), l.val.get i,] := by
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
· change l.idMap i = l.idMap ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))
simp
· simp only [List.not_mem_nil, false_implies, implies_true, and_self]
rw [← h1]
refine List.Sublist.filter (fun (J : Index X) => ((l.val.get i).id = J.id)) ?_
rw [List.sublist_iff_exists_fin_orderEmbedding_get_eq]
refine ⟨⟨⟨![(l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h), i], ?_⟩, ?_⟩, ?_⟩
· 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
/-- Given an index `I` such that there is one index in `l` with the same `id` as `I`.
This is that index. -/
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?`. -/
@[simp]
lemma consDual_id {I : Index X} (hI : l.countId I = 1) :
(l.consDual hI).id = I.id := by
change (l.cons I).idMap ((((l.cons I).getDual? ⟨0, by simp⟩).get
((l.cons I).getDual?_isSome_of_countId_eq_two (by simpa [countId] using hI)))) = _
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]
lemma consDual_mem {I : Index X} (hI : l.countId I = 1) :
l.consDual hI ∈ l.val := by
let Di := (((l.cons I).getDual? ⟨0, by simp⟩).get (by
rw [← zero_mem_withUniqueDual_of_cons_iff_countId_one] at hI; exact
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
rw [← zero_mem_withUniqueDual_of_cons_iff_countId_one] at hI;
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
rw [Fin.ne_iff_vne] at hDiz
exact hDiz
omega
change (l.cons I).val.get Di ∈ l.val
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
apply congrArg
rw [Fin.ext_iff]
exact id (Eq.symm Dim1)
simp only [List.length_cons, cons_length, Fin.eta, List.get_eq_getElem,
List.getElem_cons_succ] at h1
rw [h1]
exact List.getElem_mem l.val _ _
lemma consDual_filter {I : Index X} (hI : l.countId I = 1) :
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]
simp only [List.cons.injEq, and_true]
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
lemma consDual_iff {I : Index X} (hI : l.countId I = 1)
(I' : Index X) : I' = l.consDual hI ↔ I' ∈ l.val ∧ I'.id = I.id := by
refine Iff.intro (fun h => ?_) (fun h => ?_)
· subst h
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]
rw [l.consDual_filter hI] at hI'
simpa using hI'
lemma filter_of_constDual {I : Index X} (hI : l.countId I = 1) :
(l.cons I).val.filter (fun J => (l.consDual hI).id = J.id) = [I, l.consDual hI] := by
simp only [consDual_id, cons_val, decide_True, List.filter_cons_of_pos, List.cons.injEq, true_and]
exact consDual_filter l hI
end filterID
lemma withUniqueDual_eq_withDual_iff_countId_mem_le_two :
l.withUniqueDual = l.withDual ↔
∀ 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)
lemma withUniqueDual_eq_withDual_iff_all_countId_le_two :
l.withUniqueDual = l.withDual ↔
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) :
(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]
· rw [withUniqueDual_eq_withDual_iff_countId_mem_le_two] at hl
exact hl I' hI'
· simpa using hII'
lemma withUniqueDual_eq_withDual_of_cons {I : Index X}
(hl : (l.cons I).withUniqueDual = (l.cons I).withDual) :
l.withUniqueDual = l.withDual := by
rw [withUniqueDual_eq_withDual_iff_countId_mem_le_two] at hl ⊢
intro I' hI'
have hImem : I' ∈ (l.cons I).val := by
simp [hI']
have h1 : List.countP (fun J => decide (I'.id = J.id)) l.val ≤
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)
lemma withUniqueDual_eq_withDual_cons_iff' (I : Index X) :
(l.cons I).withUniqueDual = (l.cons I).withDual ↔
l.withUniqueDual = l.withDual ∧ l.countId I ≤ 1 := by
refine Iff.intro (fun h => ?_) (fun h => ?_)
· have h1 : l.withUniqueDual = l.withDual := by
exact withUniqueDual_eq_withDual_of_cons l h
apply And.intro h1 ((withUniqueDual_eq_withDual_cons_iff l I h1).mp h)
· rw [withUniqueDual_eq_withDual_cons_iff]
· exact h.2
· exact h.1
/-!
## withUniqueDualInOther equal to withDualInOther append conditions
-/
lemma withUniqueDualInOther_eq_withDualInOther_append_of_symm'
(h : (l ++ l2).withUniqueDualInOther l3 = (l ++ l2).withDualInOther l3) :
(l2 ++ l).withUniqueDualInOther l3 = (l2 ++ l).withDualInOther l3 := by
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]
simpa only [mem_withInDualOther_iff_isSome, getDualInOther?_append_of_inl,
getDualInOther?_append_of_inr] using h (appendEquiv (Sum.inr k))
| Sum.inr k =>
rw [← mem_append_withUniqueDualInOther_symm]
simpa only [mem_withInDualOther_iff_isSome, getDualInOther?_append_of_inr,
getDualInOther?_append_of_inl] using h (appendEquiv (Sum.inl k))
lemma withUniqueDualInOther_eq_withDualInOther_append_of_symm :
(l ++ l2).withUniqueDualInOther l3 = (l ++ l2).withDualInOther l3 ↔
(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)
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) ↔
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)
/-!
## 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
= l2.withDual l2.withDualInOther l := by
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
(h : (l ++ l2).withUniqueDual = (l ++ l2).withDual) :
l.withUniqueDualInOther l2 = l.withDualInOther l2 := by
rw [Finset.ext_iff]
intro i
refine Iff.intro (fun h' => ?_) (fun h' => ?_)
· simp only [mem_withInDualOther_iff_isSome, h', mem_withUniqueDualInOther_isSome]
· have hn : appendEquiv (Sum.inl i) ∈ (l ++ l2).withUniqueDual := by
rw [h]
simp_all only [mem_withInDualOther_iff_isSome, mem_withDual_iff_isSome,
getDual?_isSome_append_inl_iff, or_true, mem_withUniqueDual_isSome]
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
(h : (l ++ l2).withUniqueDual = (l ++ l2).withDual) :
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
· intro h
exact ⟨append_withDual_eq_withUniqueDual_inl l l2 h,
append_withDual_eq_withUniqueDual_inr l l2 h,
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)⟩
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]
lemma append_withDual_eq_withUniqueDual_contr_left
(h1 : (l ++ l2).withUniqueDual = (l ++ l2).withDual) :
(l.contrIndexList ++ l2).withUniqueDual = (l.contrIndexList ++ l2).withDual := by
rw [withUniqueDual_eq_withDual_iff_all_countId_le_two] at h1 ⊢
simp only [append_val, countId_append, List.all_append, Bool.and_eq_true, List.all_eq_true,
decide_eq_true_eq]
simp at h1
apply And.intro
· intro I hI
have hIl := h1.1 I (List.mem_of_mem_filter hI)
have ht : l.contrIndexList.countId I ≤ l.countId I :=
countId_contrIndexList_le_countId l I
omega
· intro I hI
have hIl2 := h1.2 I hI
have ht : l.contrIndexList.countId I ≤ l.countId I :=
countId_contrIndexList_le_countId l I
omega
end IndexList
end IndexNotation