feat: Relationship between indices and countP
This commit is contained in:
parent
778373f135
commit
d376632751
6 changed files with 355 additions and 152 deletions
|
@ -5,6 +5,8 @@ Authors: Joseph Tooby-Smith
|
|||
-/
|
||||
import Mathlib.Data.Set.Finite
|
||||
import Mathlib.Logic.Equiv.Fin
|
||||
import Mathlib.Data.Finset.Sort
|
||||
import Mathlib.Tactic.FinCases
|
||||
/-!
|
||||
|
||||
# Index notation for a type
|
||||
|
@ -392,6 +394,73 @@ lemma colorMap_sumELim (l1 l2 : IndexList X) :
|
|||
|
||||
end append
|
||||
|
||||
/-!
|
||||
|
||||
## countP on id
|
||||
|
||||
-/
|
||||
|
||||
lemma countP_id_neq_zero (i : Fin l.length) :
|
||||
l.val.countP (fun J => (l.val.get i).id = J.id) ≠ 0 := by
|
||||
rw [List.countP_eq_length_filter]
|
||||
by_contra hn
|
||||
rw [List.length_eq_zero] at hn
|
||||
have hm : l.val.get i ∈ List.filter (fun J => decide ((l.val.get i).id = J.id)) l.val := by
|
||||
simpa using List.getElem_mem l.val i.1 i.isLt
|
||||
rw [hn] at hm
|
||||
simp at hm
|
||||
|
||||
|
||||
/-! TODO: Replace with Mathlib lemma. -/
|
||||
lemma filter_sort_comm {n : ℕ} (s : Finset (Fin n)) (p : Fin n → Prop) [DecidablePred p] :
|
||||
List.filter p (Finset.sort (fun i j => i ≤ j) s) =
|
||||
Finset.sort (fun i j => i ≤ j) (Finset.filter p s) := by
|
||||
simp [Finset.filter, Finset.sort]
|
||||
have : ∀ (m : Multiset (Fin n)), List.filter p (Multiset.sort (fun i j => i ≤ j) m) =
|
||||
Multiset.sort (fun i j => i ≤ j) (Multiset.filter p m) := by
|
||||
apply Quot.ind
|
||||
intro m
|
||||
simp [List.mergeSort]
|
||||
have h1 : List.Sorted (fun i j => i ≤ j) (List.filter (fun b => decide (p b))
|
||||
(List.mergeSort (fun i j => i ≤ j) m)) := by
|
||||
simp [List.Sorted]
|
||||
rw [List.pairwise_filter]
|
||||
rw [@List.pairwise_iff_get]
|
||||
intro i j h1 _ _
|
||||
have hs : List.Sorted (fun i j => i ≤ j) (List.mergeSort (fun i j => i ≤ j) m) := by
|
||||
exact List.sorted_mergeSort (fun i j => i ≤ j) m
|
||||
simp [List.Sorted] at hs
|
||||
rw [List.pairwise_iff_get] at hs
|
||||
exact hs i j h1
|
||||
have hp1 : (List.mergeSort (fun i j => i ≤ j) m).Perm m := by
|
||||
exact List.perm_mergeSort (fun i j => i ≤ j) m
|
||||
have hp2 : (List.filter (fun b => decide (p b)) ((List.mergeSort (fun i j => i ≤ j) m))).Perm
|
||||
(List.filter (fun b => decide (p b)) m) := by
|
||||
exact List.Perm.filter (fun b => decide (p b)) hp1
|
||||
have hp3 : (List.filter (fun b => decide (p b)) m).Perm
|
||||
(List.mergeSort (fun i j => i ≤ j) (List.filter (fun b => decide (p b)) m)) := by
|
||||
exact List.Perm.symm (List.perm_mergeSort (fun i j => i ≤ j)
|
||||
(List.filter (fun b => decide (p b)) m))
|
||||
have hp4 := hp2.trans hp3
|
||||
refine List.eq_of_perm_of_sorted hp4 h1 ?_
|
||||
exact List.sorted_mergeSort (fun i j => i ≤ j) (List.filter (fun b => decide (p b)) m)
|
||||
exact this s.val
|
||||
|
||||
lemma filter_id_eq_sort (i : Fin l.length) : l.val.filter (fun J => (l.val.get i).id = J.id) =
|
||||
List.map l.val.get (Finset.sort (fun i j => i ≤ j)
|
||||
(Finset.filter (fun j => l.idMap i = l.idMap j) Finset.univ)) := by
|
||||
have h1 := (List.finRange_map_get l.val).symm
|
||||
have h2 : l.val = List.map l.val.get (Finset.sort (fun i j => i ≤ j) Finset.univ) := by
|
||||
nth_rewrite 1 [h1, (Fin.sort_univ l.val.length).symm]
|
||||
rfl
|
||||
nth_rewrite 3 [h2]
|
||||
rw [List.filter_map]
|
||||
apply congrArg
|
||||
rw [← filter_sort_comm]
|
||||
apply List.filter_congr
|
||||
intro x _
|
||||
simp [idMap]
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
||||
|
|
|
@ -299,14 +299,6 @@ open IndexList TensorColor
|
|||
|
||||
instance : Coe (ColorIndexList 𝓒) (IndexList 𝓒.Color) := ⟨fun l => l.toIndexList⟩
|
||||
|
||||
/-! TODO: Define an induction principal on `ColorIndexList`. -/
|
||||
|
||||
/-- The `ColorIndexList` whose underlying list of indices is empty. -/
|
||||
def empty : ColorIndexList 𝓒 where
|
||||
val := ∅
|
||||
unique_duals := rfl
|
||||
dual_color := rfl
|
||||
|
||||
/-- The colorMap of a `ColorIndexList` as a `𝓒.ColorMap`.
|
||||
This is to be compared with `colorMap` which is a map `Fin l.length → 𝓒.Color`. -/
|
||||
def colorMap' : 𝓒.ColorMap (Fin l.length) :=
|
||||
|
@ -336,6 +328,28 @@ lemma orderEmbOfFin_univ (n m : ℕ) (h : n = m) :
|
|||
|
||||
/-!
|
||||
|
||||
## Cons for `ColorIndexList`
|
||||
|
||||
-/
|
||||
|
||||
/-! TODO: Define `cons` for `ColorIndexList`. Will need conditions unlike for `IndexList`. -/
|
||||
|
||||
/-!
|
||||
|
||||
## Induction for `ColorIndexList`
|
||||
|
||||
-/
|
||||
|
||||
/-! TODO: Define an induction principal on `ColorIndexList`. -/
|
||||
|
||||
/-- The `ColorIndexList` whose underlying list of indices is empty. -/
|
||||
def empty : ColorIndexList 𝓒 where
|
||||
val := ∅
|
||||
unique_duals := rfl
|
||||
dual_color := rfl
|
||||
|
||||
/-!
|
||||
|
||||
## Contracting an `ColorIndexList`
|
||||
|
||||
-/
|
||||
|
|
|
@ -69,115 +69,16 @@ lemma withDual_union_withoutDual : l.withDual ∪ l.withoutDual = Finset.univ :=
|
|||
· simp at h
|
||||
simp [withoutDual, Finset.mem_filter, Finset.mem_univ, h]
|
||||
|
||||
lemma mem_withoutDual_iff_count :
|
||||
(fun i => (i ∈ l.withoutDual : Bool)) =
|
||||
(fun (i : Index X) => (l.val.countP (fun j => i.id = j.id) = 1 : Bool)) ∘ l.val.get := by
|
||||
funext x
|
||||
simp [withoutDual, getDual?]
|
||||
rw [Fin.find_eq_none_iff]
|
||||
simp [AreDualInSelf]
|
||||
apply Iff.intro
|
||||
· intro h
|
||||
have h1 : ¬ l.val.Duplicate l.val[↑x] := by
|
||||
by_contra hn
|
||||
rw [List.duplicate_iff_exists_distinct_get] at hn
|
||||
obtain ⟨i, j, h1, h2, h3⟩ := hn
|
||||
have h4 := h i
|
||||
have h5 := h j
|
||||
simp [idMap] at h4 h5
|
||||
by_cases hi : i = x
|
||||
<;> by_cases hj : j = x
|
||||
· subst hi hj
|
||||
simp at h1
|
||||
· subst hi
|
||||
exact h5 (fun a => hj (id (Eq.symm a))) (congrArg Index.id h3)
|
||||
· subst hj
|
||||
exact h4 (fun a => hi (id (Eq.symm a))) (congrArg Index.id h2)
|
||||
· exact h5 (fun a => hj (id (Eq.symm a))) (congrArg Index.id h3)
|
||||
rw [List.duplicate_iff_two_le_count] at h1
|
||||
simp at h1
|
||||
by_cases hx : List.count l.val[↑x] l.val = 0
|
||||
· rw [List.count_eq_zero] at hx
|
||||
have hl : l.val[↑x] ∈ l.val := by
|
||||
simp only [Fin.getElem_fin]
|
||||
exact List.getElem_mem l.val (↑x) (Fin.val_lt_of_le x (le_refl l.length))
|
||||
exact False.elim (h x (fun _ => hx hl) rfl)
|
||||
have hln : List.count l.val[↑x] l.val = 1 := by
|
||||
rw [@Nat.lt_succ] at h1
|
||||
rw [@Nat.le_one_iff_eq_zero_or_eq_one] at h1
|
||||
simp at hx
|
||||
simpa [hx] using h1
|
||||
rw [← hln, List.count]
|
||||
refine (List.countP_congr ?_)
|
||||
intro xt hxt
|
||||
let xid := l.val.indexOf xt
|
||||
have h2 := List.indexOf_lt_length.mpr hxt
|
||||
have h3 : xt = l.val.get ⟨xid, h2⟩ := by
|
||||
exact Eq.symm (List.indexOf_get h2)
|
||||
simp only [decide_eq_true_eq, Fin.getElem_fin, beq_iff_eq]
|
||||
by_cases hxtx : ⟨xid, h2⟩ = x
|
||||
· rw [h3, hxtx]
|
||||
simp only [List.get_eq_getElem]
|
||||
refine Iff.intro (fun h' => False.elim (h x (fun _ => ?_) rfl)) (fun h' => ?_)
|
||||
· exact h ⟨xid, h2⟩ (fun a => hxtx (id (Eq.symm a))) (by rw [h3] at h'; exact h')
|
||||
· rw [h']
|
||||
· intro h
|
||||
intro i hxi
|
||||
by_contra hn
|
||||
by_cases hxs : x < i
|
||||
· let ls := [l.val[x], l.val[i]]
|
||||
have hsub : ls.Sublist l.val := by
|
||||
rw [List.sublist_iff_exists_fin_orderEmbedding_get_eq]
|
||||
let fs : Fin ls.length ↪o Fin l.val.length := {
|
||||
toFun := ![x, i],
|
||||
inj' := by
|
||||
intro a b
|
||||
fin_cases a <;>
|
||||
fin_cases b
|
||||
<;> simp [hxi]
|
||||
exact fun a => hxi (id (Eq.symm a)),
|
||||
map_rel_iff' := by
|
||||
intro a b
|
||||
fin_cases a <;>
|
||||
fin_cases b
|
||||
<;> simp [hxs]
|
||||
omega}
|
||||
use fs
|
||||
intro a
|
||||
fin_cases a <;> rfl
|
||||
have h1 := List.Sublist.countP_le (fun (j : Index X) => decide (l.val[↑x].id = j.id)) hsub
|
||||
simp only [Fin.getElem_fin, decide_True, List.countP_cons_of_pos, h, add_le_iff_nonpos_left,
|
||||
nonpos_iff_eq_zero, ls] at h1
|
||||
rw [@List.countP_eq_zero] at h1
|
||||
simp at h1
|
||||
exact h1 hn
|
||||
have hxs' : i < x := by omega
|
||||
let ls := [l.val[i], l.val[x]]
|
||||
have hsub : ls.Sublist l.val := by
|
||||
rw [List.sublist_iff_exists_fin_orderEmbedding_get_eq]
|
||||
let fs : Fin ls.length ↪o Fin l.val.length := {
|
||||
toFun := ![i, x],
|
||||
inj' := by
|
||||
intro a b
|
||||
fin_cases a <;>
|
||||
fin_cases b
|
||||
<;> simp [hxi]
|
||||
exact fun a => hxi (id (Eq.symm a)),
|
||||
map_rel_iff' := by
|
||||
intro a b
|
||||
fin_cases a <;>
|
||||
fin_cases b
|
||||
<;> simp [hxs']
|
||||
omega}
|
||||
use fs
|
||||
intro a
|
||||
fin_cases a <;> rfl
|
||||
have h1 := List.Sublist.countP_le (fun (j : Index X) => decide (l.val[↑x].id = j.id)) hsub
|
||||
simp [h, ls, hn,] at h1
|
||||
rw [List.countP_cons_of_pos] at h1
|
||||
· simp at h1
|
||||
simp [idMap] at hn
|
||||
simp [hn]
|
||||
lemma mem_withoutDual_iff_countP (i : Fin l.length) :
|
||||
i ∈ l.withoutDual ↔ l.val.countP (fun j => (l.val.get i).id = j.id) = 1 := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· exact countP_of_not_mem_withDual l i (l.not_mem_withDual_of_mem_withoutDual i h)
|
||||
· by_contra hn
|
||||
have h : i ∈ l.withDual := by
|
||||
simp [withoutDual] at hn
|
||||
simpa using Option.ne_none_iff_isSome.mp hn
|
||||
rw [mem_withDual_iff_countP] at h
|
||||
omega
|
||||
|
||||
/-- An equivalence from `Fin l.withoutDual.card` to `l.withoutDual` determined by
|
||||
the order on `l.withoutDual` inherted from `Fin`. -/
|
||||
|
@ -194,41 +95,8 @@ lemma list_ofFn_withoutDualEquiv_eq_sort :
|
|||
|
||||
lemma withoutDual_sort_eq_filter : l.withoutDual.sort (fun i j => i ≤ j) =
|
||||
(List.finRange l.length).filter (fun i => i ∈ l.withoutDual) := by
|
||||
have h1 {n : ℕ} (s : Finset (Fin n)) (p : Fin n → Prop) [DecidablePred p] :
|
||||
List.filter p (Finset.sort (fun i j => i ≤ j) s) =
|
||||
Finset.sort (fun i j => i ≤ j) (Finset.filter p s) := by
|
||||
simp [Finset.filter, Finset.sort]
|
||||
have : ∀ (m : Multiset (Fin n)), List.filter p (Multiset.sort (fun i j => i ≤ j) m) =
|
||||
Multiset.sort (fun i j => i ≤ j) (Multiset.filter p m) := by
|
||||
apply Quot.ind
|
||||
intro m
|
||||
simp [List.mergeSort]
|
||||
have h1 : List.Sorted (fun i j => i ≤ j) (List.filter (fun b => decide (p b))
|
||||
(List.mergeSort (fun i j => i ≤ j) m)) := by
|
||||
simp [List.Sorted]
|
||||
rw [List.pairwise_filter]
|
||||
rw [@List.pairwise_iff_get]
|
||||
intro i j h1 _ _
|
||||
have hs : List.Sorted (fun i j => i ≤ j) (List.mergeSort (fun i j => i ≤ j) m) := by
|
||||
exact List.sorted_mergeSort (fun i j => i ≤ j) m
|
||||
simp [List.Sorted] at hs
|
||||
rw [List.pairwise_iff_get] at hs
|
||||
exact hs i j h1
|
||||
have hp1 : (List.mergeSort (fun i j => i ≤ j) m).Perm m := by
|
||||
exact List.perm_mergeSort (fun i j => i ≤ j) m
|
||||
have hp2 : (List.filter (fun b => decide (p b)) ((List.mergeSort (fun i j => i ≤ j) m))).Perm
|
||||
(List.filter (fun b => decide (p b)) m) := by
|
||||
exact List.Perm.filter (fun b => decide (p b)) hp1
|
||||
have hp3 : (List.filter (fun b => decide (p b)) m).Perm
|
||||
(List.mergeSort (fun i j => i ≤ j) (List.filter (fun b => decide (p b)) m)) := by
|
||||
exact List.Perm.symm (List.perm_mergeSort (fun i j => i ≤ j)
|
||||
(List.filter (fun b => decide (p b)) m))
|
||||
have hp4 := hp2.trans hp3
|
||||
refine List.eq_of_perm_of_sorted hp4 h1 ?_
|
||||
exact List.sorted_mergeSort (fun i j => i ≤ j) (List.filter (fun b => decide (p b)) m)
|
||||
exact this s.val
|
||||
rw [withoutDual]
|
||||
rw [← h1]
|
||||
rw [← filter_sort_comm]
|
||||
simp only [Option.isNone_iff_eq_none, Finset.mem_filter, Finset.mem_univ, true_and]
|
||||
apply congrArg
|
||||
exact Fin.sort_univ l.length
|
||||
|
@ -274,7 +142,9 @@ lemma contrIndexList_eq_contrIndexList' : l.contrIndexList = l.contrIndexList' :
|
|||
let f1 : Index X → Bool := fun (i : Index X) => l.val.countP (fun j => i.id = j.id) = 1
|
||||
let f2 : (Fin l.length) → Bool := fun i => i ∈ l.withoutDual
|
||||
change List.filter f1 l.val = List.map l.val.get (List.filter f2 (List.finRange l.length))
|
||||
have hf : f2 = f1 ∘ l.val.get := mem_withoutDual_iff_count l
|
||||
have hf : f2 = f1 ∘ l.val.get := by
|
||||
funext i
|
||||
simp only [mem_withoutDual_iff_countP l, List.get_eq_getElem, Function.comp_apply, f2, f1]
|
||||
rw [hf, ← List.filter_map]
|
||||
apply congrArg
|
||||
simp [length]
|
||||
|
|
|
@ -5,6 +5,7 @@ Authors: Joseph Tooby-Smith
|
|||
-/
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.WithUniqueDual
|
||||
import Mathlib.Algebra.Order.Ring.Nat
|
||||
import Mathlib.Data.Finset.Sort
|
||||
/-!
|
||||
|
||||
# withDuals equal to withUniqueDuals
|
||||
|
@ -123,6 +124,78 @@ lemma withUnqiueDual_eq_withDual_of_empty (h : l.withDual = ∅) :
|
|||
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_countP :
|
||||
l.withUniqueDual = l.withDual ↔
|
||||
∀ i, l.val.countP (fun J => (l.val.get i).id = J.id) ≤ 2 := by
|
||||
refine Iff.intro (fun h i => ?_) (fun h => ?_)
|
||||
· by_cases hi : i ∈ l.withDual
|
||||
· rw [← h] at hi
|
||||
rw [mem_withUniqueDual_iff_countP] at hi
|
||||
rw [hi]
|
||||
· rw [mem_withDual_iff_countP] at hi
|
||||
simp at hi
|
||||
exact Nat.le_succ_of_le hi
|
||||
· refine Finset.ext (fun i => ?_)
|
||||
rw [mem_withUniqueDual_iff_countP, mem_withDual_iff_countP]
|
||||
have hi := h i
|
||||
omega
|
||||
|
||||
lemma withUniqueDual_eq_withDual_iff_countP_mem_le_two :
|
||||
l.withUniqueDual = l.withDual ↔
|
||||
∀ I (_ : I ∈ l.val), l.val.countP (fun J => I.id = J.id) ≤ 2 := by
|
||||
rw [withUniqueDual_eq_withDual_iff_countP]
|
||||
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_countP_le_two :
|
||||
l.withUniqueDual = l.withDual ↔
|
||||
l.val.all (fun I => l.val.countP (fun J => I.id = J.id) ≤ 2) := by
|
||||
rw [withUniqueDual_eq_withDual_iff_countP_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.val.countP (fun J => I.id = J.id) ≤ 1 := by
|
||||
rw [withUniqueDual_eq_withDual_iff_all_countP_le_two]
|
||||
simp
|
||||
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_countP_mem_le_two] at hl
|
||||
exact hl I' hI'
|
||||
· simpa using hII'
|
||||
|
||||
/-!
|
||||
|
||||
## withUniqueDualInOther equal to withDualInOther append conditions
|
||||
|
|
|
@ -5,6 +5,7 @@ Authors: Joseph Tooby-Smith
|
|||
-/
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.GetDual
|
||||
import Mathlib.Algebra.Order.Ring.Nat
|
||||
import Mathlib.Tactic.FinCases
|
||||
/-!
|
||||
|
||||
# Indices with duals.
|
||||
|
@ -72,6 +73,98 @@ lemma mem_withDual_iff_exists : i ∈ l.withDual ↔ ∃ j, l.AreDualInSelf i j
|
|||
|
||||
/-!
|
||||
|
||||
## Relationship between membership of withDual and countP on id.
|
||||
|
||||
-/
|
||||
|
||||
lemma countP_of_mem_withDual (i : Fin l.length) (h : i ∈ l.withDual) :
|
||||
1 < l.val.countP (fun J => (l.val.get i).id = J.id) := by
|
||||
rw [mem_withDual_iff_exists] at h
|
||||
obtain ⟨j, hj⟩ := h
|
||||
simp [AreDualInSelf, idMap] at hj
|
||||
by_contra hn
|
||||
have hn' := l.countP_id_neq_zero i
|
||||
have hl : 2 ≤ l.val.countP (fun J => (l.val.get i).id = J.id) := by
|
||||
by_cases hij : i < j
|
||||
· have hsub : List.Sublist [l.val.get i, l.val.get j] l.val := by
|
||||
rw [List.sublist_iff_exists_fin_orderEmbedding_get_eq]
|
||||
refine ⟨⟨⟨![i, j], ?_⟩, ?_⟩, ?_⟩
|
||||
· refine List.nodup_ofFn.mp ?_
|
||||
simpa using Fin.ne_of_lt hij
|
||||
· intro a b
|
||||
fin_cases a, b
|
||||
<;> simp [hij]
|
||||
exact Fin.le_of_lt hij
|
||||
· intro a
|
||||
fin_cases a <;> rfl
|
||||
simpa [hj.2] using List.Sublist.countP_le
|
||||
(fun (j : Index X) => decide (l.val[i].id = j.id)) hsub
|
||||
· have hij' : j < i := by omega
|
||||
have hsub : List.Sublist [l.val.get j, l.val.get i] l.val := by
|
||||
rw [List.sublist_iff_exists_fin_orderEmbedding_get_eq]
|
||||
refine ⟨⟨⟨![j, i], ?_⟩, ?_⟩, ?_⟩
|
||||
· refine List.nodup_ofFn.mp ?_
|
||||
simpa using Fin.ne_of_lt hij'
|
||||
· intro a b
|
||||
fin_cases a, b
|
||||
<;> simp [hij']
|
||||
exact Fin.le_of_lt hij'
|
||||
· intro a
|
||||
fin_cases a <;> rfl
|
||||
simpa [hj.2] using List.Sublist.countP_le
|
||||
(fun (j : Index X) => decide (l.val[i].id = j.id)) hsub
|
||||
omega
|
||||
|
||||
lemma countP_of_not_mem_withDual (i : Fin l.length)(h : i ∉ l.withDual) :
|
||||
l.val.countP (fun J => (l.val.get i).id = J.id) = 1 := by
|
||||
rw [mem_withDual_iff_exists] at h
|
||||
simp [AreDualInSelf] at h
|
||||
have h1 : ¬ l.val.Duplicate (l.val.get i) := by
|
||||
by_contra hn
|
||||
rw [List.duplicate_iff_exists_distinct_get] at hn
|
||||
obtain ⟨k, j, h1, h2, h3⟩ := hn
|
||||
by_cases hi : k = i
|
||||
<;> by_cases hj : j = i
|
||||
· subst hi hj
|
||||
simp at h1
|
||||
· subst hi
|
||||
exact h j (fun a => hj (id (Eq.symm a))) (congrArg Index.id h3)
|
||||
· subst hj
|
||||
exact h k (fun a => hi (id (Eq.symm a))) (congrArg Index.id h2)
|
||||
· exact h j (fun a => hj (id (Eq.symm a))) (congrArg Index.id h3)
|
||||
rw [List.duplicate_iff_two_le_count] at h1
|
||||
simp at h1
|
||||
by_cases hx : List.count l.val[i] l.val = 0
|
||||
· rw [List.count_eq_zero] at hx
|
||||
refine False.elim (h i (fun _ => hx ?_) rfl)
|
||||
exact List.getElem_mem l.val (↑i) (Fin.val_lt_of_le i (le_refl l.length))
|
||||
· have hln : List.count l.val[i] l.val = 1 := by
|
||||
rw [Nat.lt_succ, Nat.le_one_iff_eq_zero_or_eq_one] at h1
|
||||
simp at hx
|
||||
simpa [hx] using h1
|
||||
rw [← hln, List.count]
|
||||
refine (List.countP_congr (fun xt hxt => ?_))
|
||||
let xid := l.val.indexOf xt
|
||||
have h2 := List.indexOf_lt_length.mpr hxt
|
||||
simp only [decide_eq_true_eq, Fin.getElem_fin, beq_iff_eq]
|
||||
by_cases hxtx : ⟨xid, h2⟩ = i
|
||||
· rw [(List.indexOf_get h2).symm, hxtx]
|
||||
simp only [List.get_eq_getElem]
|
||||
· refine Iff.intro (fun h' => False.elim (h i (fun _ => ?_) rfl)) (fun h' => ?_)
|
||||
· exact h ⟨xid, h2⟩ (fun a => hxtx (id (Eq.symm a))) (by
|
||||
rw [(List.indexOf_get h2).symm] at h'; exact h')
|
||||
· rw [h']
|
||||
rfl
|
||||
|
||||
lemma mem_withDual_iff_countP (i : Fin l.length) :
|
||||
i ∈ l.withDual ↔ 1 < l.val.countP (fun J => (l.val.get i).id = J.id) := by
|
||||
refine Iff.intro (fun h => countP_of_mem_withDual l i h) (fun h => ?_)
|
||||
by_contra hn
|
||||
have hn' := countP_of_not_mem_withDual l i hn
|
||||
omega
|
||||
|
||||
/-!
|
||||
|
||||
## Basic properties of withDualInOther
|
||||
|
||||
-/
|
||||
|
|
|
@ -911,6 +911,90 @@ lemma getDualInOtherEquiv_cast {l1 l2 l1' l2' : IndexList X} (h : l1 = l1') (h2
|
|||
subst h h2
|
||||
rfl
|
||||
|
||||
/-!
|
||||
|
||||
## Membership of withUniqueDual and countP on id
|
||||
|
||||
-/
|
||||
|
||||
lemma finset_filter_id_mem_withUniqueDual (i : Fin l.length) (h : i ∈ l.withUniqueDual) :
|
||||
Finset.filter (fun j => l.idMap i = l.idMap j) Finset.univ =
|
||||
{i, (l.getDual? i).get (l.mem_withUniqueDual_isSome i h)} := by
|
||||
refine Finset.ext (fun j => ?_)
|
||||
simp
|
||||
rw [← propext (eq_getDual?_get_of_withUniqueDual_iff l i j h)]
|
||||
simp only [AreDualInSelf, ne_eq]
|
||||
refine Iff.intro (fun h => ?_) (fun h=> ?_)
|
||||
· simp_all only [and_true]
|
||||
exact Or.symm (Decidable.not_or_of_imp fun h => h.symm)
|
||||
· cases h with
|
||||
| inl h =>
|
||||
subst h
|
||||
simp_all only
|
||||
| inr h => simp_all only
|
||||
|
||||
lemma mem_withUniqueDual_of_finset_filter (i : Fin l.length) (h : i ∈ l.withDual)
|
||||
(hf : Finset.filter (fun j => l.idMap i = l.idMap j) Finset.univ =
|
||||
{i, (l.getDual? i).get ((mem_withDual_iff_isSome l i).mp h)}) :
|
||||
i ∈ l.withUniqueDual := by
|
||||
simp only [withUniqueDual, mem_withDual_iff_isSome, Finset.mem_filter, Finset.mem_univ, true_and]
|
||||
apply And.intro
|
||||
· simpa using h
|
||||
· intro j hj
|
||||
simp only [AreDualInSelf, ne_eq] at hj
|
||||
have hj' : j ∈ Finset.filter (fun j => l.idMap i = l.idMap j) Finset.univ := by
|
||||
simpa using hj.2
|
||||
rw [hf] at hj'
|
||||
simp at hj'
|
||||
rcases hj' with hj' | hj'
|
||||
· simp_all
|
||||
· rw [hj']
|
||||
simp
|
||||
|
||||
lemma mem__withUniqueDual_iff_finset_filter (i : Fin l.length) (h : i ∈ l.withDual) :
|
||||
i ∈ l.withUniqueDual ↔ Finset.filter (fun j => l.idMap i = l.idMap j) Finset.univ =
|
||||
{i, (l.getDual? i).get ((mem_withDual_iff_isSome l i).mp h)} :=
|
||||
Iff.intro (fun h' => finset_filter_id_mem_withUniqueDual l i h')
|
||||
(fun h' => mem_withUniqueDual_of_finset_filter l i h h')
|
||||
|
||||
/-! TODO: Move -/
|
||||
lemma card_finset_self_dual (i : Fin l.length) (h : i ∈ l.withDual) :
|
||||
({i, (l.getDual? i).get ((mem_withDual_iff_isSome l i).mp h)} : Finset (Fin l.length)).card = 2 := by
|
||||
rw [Finset.card_eq_two]
|
||||
use i, (l.getDual? i).get ((mem_withDual_iff_isSome l i).mp h)
|
||||
simp
|
||||
have h1 : l.AreDualInSelf i ((l.getDual? i).get ((mem_withDual_iff_isSome l i).mp h)) := by
|
||||
simp
|
||||
exact h1.1
|
||||
|
||||
lemma countP_of_mem_withUniqueDual (i : Fin l.length) (h : i ∈ l.withUniqueDual) :
|
||||
l.val.countP (fun J => (l.val.get i).id = J.id) = 2 := by
|
||||
rw [List.countP_eq_length_filter, filter_id_eq_sort]
|
||||
simp only [List.length_map, Finset.length_sort]
|
||||
erw [l.finset_filter_id_mem_withUniqueDual i h]
|
||||
refine l.card_finset_self_dual i (mem_withDual_of_mem_withUniqueDual l i h)
|
||||
|
||||
lemma mem_withUniqueDual_of_countP (i : Fin l.length)
|
||||
(h : l.val.countP (fun J => (l.val.get i).id = J.id) = 2) : i ∈ l.withUniqueDual := by
|
||||
have hw : i ∈ l.withDual := by
|
||||
rw [mem_withDual_iff_countP, h]
|
||||
exact Nat.one_lt_two
|
||||
rw [l.mem__withUniqueDual_iff_finset_filter i hw]
|
||||
rw [List.countP_eq_length_filter, filter_id_eq_sort] at h
|
||||
simp at h
|
||||
have hsub : {i, (l.getDual? i).get ((mem_withDual_iff_isSome l i).mp hw)} ⊆
|
||||
Finset.filter (fun j => l.idMap i = l.idMap j) Finset.univ := by
|
||||
rw [Finset.insert_subset_iff]
|
||||
simp
|
||||
refine ((Finset.subset_iff_eq_of_card_le ?_).mp hsub).symm
|
||||
erw [h]
|
||||
rw [l.card_finset_self_dual i hw]
|
||||
|
||||
lemma mem_withUniqueDual_iff_countP (i : Fin l.length) :
|
||||
i ∈ l.withUniqueDual ↔ l.val.countP (fun J => (l.val.get i).id = J.id) = 2 :=
|
||||
Iff.intro (fun h => l.countP_of_mem_withUniqueDual i h)
|
||||
(fun h => l.mem_withUniqueDual_of_countP i h)
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue